Unity 6 HLSL调色板替换Shader随机噪点消除求助
Unity 6调色板替换Shader噪点问题解决思路
问题根源分析
- 精确颜色匹配的精度误差:GPU浮点运算和纹理采样存在精度损耗,用
all(mainTex == 采样颜色)的精确相等判断会出现匹配失效或误匹配,产生随机噪点。 - 多Pass渲染逻辑不一致:Shader包含3个渲染Pass,但仅最后一个
UniversalForwardPass实现了调色板替换,前两个Pass(光照、法线渲染)仍使用原始纹理颜色,多Pass输出叠加导致画面异常。 - 调色板采样的UV精度问题:循环中计算调色板UV时的浮点除法误差,可能导致采样到相邻的调色板颜色。
具体修复步骤
1. 替换精确颜色匹配为容差匹配
将UnlitFragment中的精确相等判断改为基于颜色距离的容差匹配,避免精度误差影响:
float4 UnlitFragment(Varyings i) : SV_Target { float4 mainTex = i.color * SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv); // 遍历调色板,用颜色距离做容差匹配 for(int x = 0; x < _Palette_TexelSize.z; x++) { // 用TexelFetch直接按索引采样,避免UV计算误差 float4 paletteColor = TexelFetch(_Palette, int2(x, 0), 0); // 只比较RGB通道,忽略Alpha(如果调色板Alpha不参与匹配) float colorDistance = distance(mainTex.rgb, paletteColor.rgb); // 容差值可根据实际需求调整,0.01适合大多数场景 if(colorDistance < 0.01) { float4 swapColor = TexelFetch(_Swap, int2(x, 0), 0); mainTex.rgb = swapColor.rgb; // 找到匹配后跳出循环,避免多次替换 break; } } #if defined(DEBUG_DISPLAY) // 保留原有调试代码 SurfaceData2D surfaceData; InputData2D inputData; half4 debugColor = 0; InitializeSurfaceData(mainTex.rgb, mainTex.a, surfaceData); InitializeInputData(i.uv, inputData); SETUP_DEBUG_TEXTURE_DATA_2D_NO_TS(inputData, i.positionWS, i.positionCS, _MainTex); if(CanDebugOverrideOutputColor(surfaceData, inputData, debugColor)) { return debugColor; } #endif return mainTex; }
2. 统一所有Pass的调色板替换逻辑
在另外两个Pass中加入相同的调色板替换代码:
- CombinedShapeLightFragment:获取
main变量后立即执行调色板替换,再进行光照计算 - NormalsRenderingFragment:获取
mainTex变量后执行调色板替换,再处理法线渲染
3. 优化纹理采样设置
- 给
_Palette和_Swap纹理设置Point Filter(点过滤),关闭MipMap,避免线性插值导致的颜色模糊或误采样 - 确保所有纹理使用无压缩格式(如RGBA32),减少压缩导致的颜色精度损失
4. 循环优化(可选)
如果调色板尺寸固定,可以提前将调色板颜色存入Shader数组,避免循环中重复采样纹理,提升性能的同时减少采样误差。
内容的提问来源于stack exchange,提问作者Brad Jones
相关产品推荐
相关产品推荐

