我正在为unity3d编写着色器。着色器使用多个渲染目标来渲染后期处理效果。
然而,我遇到了一个有趣的问题。
当Unity3d在direct3d模式下运行时,默认情况下,所有标准着色器仅将数据写入第一个颜色缓冲区(即索引为0)。即如果我将3个颜色缓冲区附加到相机,则调用Camera.Render
颜色缓冲区(索引0)将包含渲染场景,并且所有其他缓冲区将保持不变,除非某些着色器专门写入它们。我的着色器利用了这种行为(我使用索引为1和2的缓冲区来累积后期处理效果所需的数据)。
但是,在OpenGL模式下,标准unity3d着色器一次写入所有颜色缓冲区。即如果我将多个渲染缓冲区附加到摄像机,则调用Camera.Render
所有3个缓冲区将包含渲染场景的副本。
在OpenGL模式下破坏了我的着色器。
我该如何解决?我需要一次渲染整个场景,只有具有特定着色器的对象才能修改其他颜色缓冲区。
我需要一次渲染场景,因为使用图层蒙版会导致统一重新计算所有灯光的投影机阴影,我需要阴影才能正确。
么?
答案 0 :(得分:1)
可悲的是,事实证明“不写入其中一个渲染目标”是opengl中未记录的行为。编译为正向渲染路径时,标准的统一着色器会生成gl_FragData[0] = ...;
赋值并仅写入一个缓冲区,从而触发未记录的行为并导致混乱。
为了解决这个问题,我需要统一将数据写入标准着色器中的其他渲染目标。不幸的是,这是无法做到的,因为没有“入口点”来“挂钩”标准着色器并将其他数据写入其他颜色缓冲区。最接近的是"finalcolor"修饰符,但它实际上不允许通过CG着色器写入额外的缓冲区(需要额外的数据来自片段着色器,这是从表面着色器无法访问的),它只能是修改一种颜色。
我决定重写着色器的一部分(因此它不会在OpenGL中触发未记录的行为)并放弃在效果中支持统一阴影贴图。据我所知,除了修改统一引擎(需要“特殊安排”和源代码访问)或用我自己的替换整个照明系统外,没有其他选择。