在片段着色器中写入RWTexture2D后物体黑屏的问题排查
问题排查与解决方案
核心问题根源
你遇到的问题是同一片段着色器Pass内读写RWTexture2D的同步冲突:GPU的片段着色器线程是并行执行的,同一帧内写入RWTexture2D后,无法保证当前线程能立刻读取到刚写入的数据——甚至可能因为资源状态未同步,读取到的是纹理初始值(0)。另外还有几个细节可能触发这个问题:
具体修复步骤
拆分读写到不同Pass
不要在同一个Pass里既写又读RWTexture2D,分成两个独立Pass:- 第一个Pass:仅负责写入可见性数据到
_VisibilityBuffer,不需要输出有效颜色 - 第二个Pass:读取
_VisibilityBuffer的值,结合_Color计算最终输出颜色
示例代码结构:
// Pass 1: 写入可见性缓冲区 Pass { HLSLPROGRAM #pragma vertex Vertex #pragma fragment WriteVisibility RWTexture2D<float> _VisibilityBuffer : register(u1); float4 WriteVisibility(Interpolators input) : SV_Target { // 显式转换为int2,避免浮点精度问题 _VisibilityBuffer[int2(input.texelCoords)] = input.visibility; return float4(0,0,0,0); // 仅完成写入,无需显示内容 } ENDHLSL } // Pass 2: 读取缓冲区并渲染 Pass { HLSLPROGRAM #pragma vertex Vertex #pragma fragment Fragment Texture2D<float> _VisibilityBuffer : register(t1); // 读取用普通Texture2D即可 SamplerState sampler_VisibilityBuffer; float4 Fragment(Interpolators input) : SV_Target { // 若用Sample需传入归一化坐标,用Load则保持int2转换 float visibility = _VisibilityBuffer.Load(int3(input.texelCoords, 0)); return _Color * visibility; } ENDHLSL }- 第一个Pass:仅负责写入可见性数据到
检查纹理资源配置
- 在Unity中,
_VisibilityBuffer必须是启用随机读写的RenderTexture:创建时勾选Enable Random Write,格式选择匹配的类型(比如R32_FLOAT) - ShaderLab中需正确声明纹理属性:
Properties { _VisibilityBuffer ("Visibility Buffer", 2D) = "white" {} }
- 在Unity中,
修正texelCoords的类型
RWTexture2D的下标要求是int2类型,如果input.texelCoords是float2,必须显式转换(比如int2(input.texelCoords)),否则浮点精度误差会导致访问错误的纹理单元,返回0值。确认寄存器绑定无冲突
确保register(u1)没有被其他资源(如其他纹理、缓冲区)占用,避免资源绑定错误导致读写失效。
内容的提问来源于stack exchange,提问作者phal5
相关产品推荐
相关产品推荐

