Shader  特效越跑越慢

发布时间 2023-06-27 14:55:15作者: 皮斯卡略夫

Shader  特效越跑越慢问题的排查

问题

某屏幕特效 shader 逻辑是呈现自上而下或自左而右的扫描线效果,其核心
逻辑大致如下

float t = fract(time/3.6);
t = (t-0.5)*4.0-1.0;
t = abs(x-t);
t = 1.0-smoothstep(0.005,0.008,t) + (1.0-smoothstep(0.002,0.04,t))*0.4;

out_color.rgb = vec3(0.8, 0.6, 0.8);
out_color.a = t;

问题现象为:在运行一段时间后,出现卡顿表现,原本连续运动的扫描线
呈现出一种间断性步进的效果,而非平滑地移动。

分析与解决

面对此问题,首先需要确认是否是渲染帧率下降,经简单的代码内 Fps 计
算得整体 Fps 保持在 60 无误。使用相关的帧率监控 profiler 也能得到
一致的结果。为确认帧率,使用 System trace 工具抓帧查看,确认每帧
绘制时间并无 delay, 整体渲染并无问题。

排除帧率因素,那么渲染卡顿原因可能来自逻辑错误,而非性能不足,即
计算出现误差而呈现出卡顿或间断性移动的现象。由于在 shader 内对平
移的计算主要使用 time 时间这个数值来计算,而这个数值在 CPU 端一直
累加,数值持续变大,有理由怀疑该浮点数值足够大时会产生误差。

根据对代码分析和试验,最终找到误差的来源是下面这一行代码

float t = fract(time/3.6);

当 time 较大,除以 3.6 再取小数,会带来较大的误差。这里误差的来源
必须是除法和取小数共存,若直接取小数 fract(time) 则其并无较大误差。

针对这个问题,目前的解决方法是 time 的更新以 90 秒为一个循环,在 0-90
之间循环,避免出现较大的浮点数。