Three.js昼夜模拟Shader出现闪烁问题求助
昼夜模拟Shader闪烁问题排查思路
常见诱因及排查步骤
数值精度损耗
太阳方向计算若依赖GPU端浮点运算,可能因float精度不足出现帧间方向突变。检查GetSunDirection函数:- 小时转角度的运算(如
hour * 15.0)是否因浮点误差导致帧间角度跳变,可尝试将角度计算移至CPU端,传递归一化后的方向向量给Shader - 三角函数(
sin/cos)计算是否存在精度丢失,可对角度值做取整或平滑处理
- 小时转角度的运算(如
帧间数值跳变
检查GMT小时数的更新逻辑:- 是否在整数边界(如23→0、12→13)时出现瞬间跳变,导致太阳方向突变?给小时数添加平滑过渡(如
Mathf.Lerp缓动更新) - 是否存在多线程异步更新小时数的情况?确保数值读取线程安全,避免帧间数值不一致
- 是否在整数边界(如23→0、12→13)时出现瞬间跳变,导致太阳方向突变?给小时数添加平滑过渡(如
Shader非法运算警告
若警告包含以下内容,优先处理:- 未指定精度的
precision警告:跨平台精度差异可能引发闪烁 NaN/Inf或除零警告:检查太阳方向计算中是否存在非法运算,这类错误会导致帧间方向变为无效值
- 未指定精度的
光照空间转换错误
若使用URP/HDRP,确认太阳方向是否正确适配管线的光照空间(世界/视图空间),空间转换错误会导致视角变化时出现闪烁;同时检查阴影采样是否与主光照方向一致,阴影方向不匹配也会引发闪烁
代码验证建议
提取GetSunDirection核心逻辑在CPU端测试,连续输出帧间方向差值:
public Vector3 GetSunDirection(float gmtHour) { float angle = gmtHour * 15f; // 每小时对应15度 float rad = angle * Mathf.Deg2Rad; float x = Mathf.Sin(rad); float y = Mathf.Cos(rad) * 0.6f; // 限制太阳高度角 float z = Mathf.Cos(rad); return new Vector3(x, y, z).normalized; }
若差值突然增大,说明是数值跳变导致闪烁;若差值稳定仍闪烁,需排查Shader端方向的使用逻辑
截图对比排查
对比闪烁帧与正常帧的太阳向量值,查看是否存在:
- 分量突然正负反转
- 向量未归一化(长度异常)
- 光照强度瞬间跳变
内容的提问来源于stack exchange,提问作者Pablo Escobar
相关产品推荐
相关产品推荐

