【步兵 shader】扫光

【步兵 shader】扫光 By EOS.

扫光这个需求很常见,一是给界面添加些许生气,二则是让界面上的重点突出出来。
往往 一个静止的界面中 突然有东西动了,就会很容易引起人的注意。


实现方式

扫光的实现方式有很多中,各有优缺点,可能你觉得shader实现是最高大上的,可能在美术眼里,
这种表现效果却是最low的,所以还是一切以最终要的效果为基准来定制策略。

  1. 帧动画【spine或其他】
    优点:效果丰富、程序使用简单
    缺点:帧数多资源大,占用内存多,每个不同形状要特效

  2. 单张图片+裁剪+叠加模式
    优点:颜色和扫光形状替换简单、且扫光边缘过度自然、无视形状
    缺点:不同效果需要不同图片、且使用时要指定裁剪图片和扫光图片略微复杂

ps:我目前用的是这种用的较多,最大的一个特点就是他是通过图片的移动来扫光的,
所以可以通过相对位置计算,不同控件的起始位置重合,一起移动,从而实现跨空间扫光的效果。
这是个很cool的效果,有机会你们可以试试。

  1. shader实现
    优点:无视图片大小,无需资源,能达到自然的曝光效果
    缺点:不易控制,边缘过于生硬。

因为shader的核心是利用直线方程的移动,已经计算两条直线方程的距离来实现。
所以边缘自然是直线,所以没有方案2中的美术来控制行转和透明度的效果好,
但曝光效果由于是计算出来的所以也有它的独到之处。


效果图

从左往右扫
【步兵 shader】扫光_第1张图片
从上往下扫
【步兵 shader】扫光_第2张图片
看也看过了,接下来重点来了!!!


shader扫光源码

上边也说了,核心就是直线方程,至于代码中看不懂的公式请自行查询。
A/B 主要控制斜率, dx、dy 主要控制移动速度。
radius是控制直线的距离,shineFactor则控制曝光度。

下边为源码,至于使用方式,请结合前文中的ShaderTools。
见前文:【步兵 shader】封装篇

---------------Flash_START---------------
def.shader.FlashFunc = function (sp, state)
    if state.__params then
        for k,v in pairs(state.__params) do
            state:setUniformFloat(k,v)
        end
    else
        state:setUniformFloat("A", 1.0)
        state:setUniformFloat("B", 0.5)
        state:setUniformFloat("dx", 1)
        state:setUniformFloat("dy", 0)
        state:setUniformFloat("radius", 0.25)
        state:setUniformFloat("shineFactor", 1.75)
    end
    sp:registerScriptHandler(function(state)
        if state == "cleanup" then
            gm.scheduler:unscheduleScriptEntry(sp._shader_update_id)
        end
    end)


    local tt = 0
    local function shader_Logic (dt)
        tt = tt + dt
        tt = tt % 5
        state:setUniformFloat("time", tt)
        state:setUniformFloat("opacity", sp:getOpacity()/255)
    end
    sp._shader_update_id = gm.scheduler:scheduleScriptFunc(shader_Logic, 1/60, false)
end

-- 初始位置直线方程 Ax+By=0
-- dx, dy 每秒直线移动位移
-- radius 半径
-- shineFactor 亮度增加倍数
def.shader.FlashFS = 
[[#ifdef GL_ES
precision mediump float;
#endif

varying vec4 v_fragmentColor;
varying vec2 v_texCoord;

uniform float time;
uniform float opacity;

uniform float A,B;
uniform float dx,dy;
uniform float radius;
uniform float shineFactor;

void main(void)
{
    float nowLineC = -A*(dx*time) - B*(dy*time);

    float x = v_texCoord.x;
    float y = v_texCoord.y;
    float allLineC = -A*x - B*y;

    float dist = abs(allLineC - nowLineC) / sqrt(A*A + B*B);

    vec4 c = texture2D(CC_Texture0, v_texCoord);
    float multi = 1.0;
    float factor = 1.0 - dist/radius;
    if (dist < radius) {
        multi = multi + (shineFactor - 1.0) * factor;
        gl_FragColor.xyz = vec3(c.r, c.g, c.b)*opacity*multi;
    } else {
        gl_FragColor.xyz = vec3(c.r, c.g, c.b)*opacity;
    }
    gl_FragColor.w = c.w * opacity;
}
]]
---------------Frost_ENDED---------------

使用方法:

 stl.set(dog.show.model, def.shader.flash) --默认横扫

 --自定义参数
 stl.set(dog.show.model, def.shader.flash, function (sp, state)
    state.__params = {
          A = 0.5, B = 1.0, dx = 0, dy = 0.8, radius = 0.15, shineFactor = 1.4
      }
      def.shader.FlashFunc(sp, state)
  end)

总结

shader日常开发中用的不多,但这个功能依然为不常之中的最常,值得学习。
我也是网上临摹,然后封装了一下,然后、、众萌新可以拿去装逼了,不过直接搬运之前,
希望能学习几分代码或说封装的技巧,本人实战派,如果讲的不够精彩还望见谅,哈哈哈哈~

好了就这么多!(ps:虽然从来无人打赏=、=)
See Again~
之前
真爱无价,欢迎打赏~
【步兵 shader】扫光_第3张图片

你可能感兴趣的:(shader,shader,扫光)