【步兵 shader】扫光

来源:互联网 发布:linux输入中文 编辑:程序博客网 时间:2024/04/20 19:25

【步兵 shader】扫光 By EOS.

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


实现方式

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

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

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

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

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

因为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_ESprecision mediump float;#endifvarying 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~
之前
真爱无价,欢迎打赏~
打赏码

原创粉丝点击