扫光这个需求很常见,一是给界面添加些许生气,二则是让界面上的重点突出出来。
往往 一个静止的界面中 突然有东西动了,就会很容易引起人的注意。
扫光的实现方式有很多中,各有优缺点,可能你觉得shader实现是最高大上的,可能在美术眼里,
这种表现效果却是最low的,所以还是一切以最终要的效果为基准来定制策略。
帧动画【spine或其他】
优点:效果丰富、程序使用简单
缺点:帧数多资源大,占用内存多,每个不同形状要特效
单张图片+裁剪+叠加模式
优点:颜色和扫光形状替换简单、且扫光边缘过度自然、无视形状
缺点:不同效果需要不同图片、且使用时要指定裁剪图片和扫光图片略微复杂
ps:我目前用的是这种用的较多,最大的一个特点就是他是通过图片的移动来扫光的,
所以可以通过相对位置计算,不同控件的起始位置重合,一起移动,从而实现跨空间扫光的效果。
这是个很cool的效果,有机会你们可以试试。
因为shader的核心是利用直线方程的移动,已经计算两条直线方程的距离来实现。
所以边缘自然是直线,所以没有方案2中的美术来控制行转和透明度的效果好,
但曝光效果由于是计算出来的所以也有它的独到之处。
上边也说了,核心就是直线方程,至于代码中看不懂的公式请自行查询。
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日常开发中用的不多,但这个功能依然为不常之中的最常,值得学习。
我也是网上临摹,然后封装了一下,然后、、众萌新可以拿去装逼了,不过直接搬运之前,
希望能学习几分代码或说封装的技巧,本人实战派,如果讲的不够精彩还望见谅,哈哈哈哈~