2015-05-09 158 views
3

我正在为unity3d编写着色器。着色器使用多个渲染目标来呈现后期处理效果。Unity3d,多个渲染目标 - Direct3D/OpenGl中的不同行为

但是,我遇到了一个有趣的问题。

当Unity3d运行在Direct3D模式,默认情况下所有的标准着色器将数据写入到仅第一颜色缓冲液(即,具有索引0)。即如果我将3个颜色缓冲区添加到相机,请拨打Camera.Render带索引0的颜色缓冲区将包含渲染场景,除非某些着色器专门写入,否则所有其他缓冲区都将保持不变。我的着色器利用这种行为(我使用缓冲区索引1和2来累积后期处理效果所需的数据)。

然而,在OpenGL模式下的标准unity3d着色器中的所有颜色缓冲区写一次。即如果我将多个渲染缓冲区附加到相机上,请致电Camera.Render,所有3个缓冲区都将包含渲染场景的副本。

这打破了我在OpenGL模式下的着色器。

我该如何解决这个问题?我需要一次渲染整个场景,只有具有特定着色器的对象才能修改其他颜色缓冲区。

我需要渲染的场景一气呵成,因为使用图层蒙版,使团结重新计算投影阴影的所有灯光,我需要的阴影是正确的。

建议?

+0

您是否尝试过在相机上手动操作命令缓冲区? http://docs.unity3d.com/ScriptReference/Camera.GetCommandBuffers.html –

+0

@MaxYankov:不,如果你更具体,它会有所帮助。我发现我可以在那里插入额外的命令,但我不知道我该怎么处理缓冲区。我不记得D3D/OGL是否在任何地方记录默认的MRT行为。基本上,如果着色器只写入第一个缓冲区,则在D3D上,二级缓冲区不变。在OGL上他们从第一缓冲区接收信息的副本。这是标准的统一着色器。 – SigTerm

+0

我希望我可以更具体一些,但我认为我没有足够的经验。但是,如果我遇到这个问题,这是我可以挖掘的地方。 –

回答

1

可悲的是,事实证明,“不写入渲染目标之一”,是在OpenGL无证行为。当为正向渲染路径编译时,标准统一着色器产生gl_FragData[0] = ...;赋值并且只写入一个缓冲区,这会触发未记录的行为并导致混乱。

为了解决这个问题,我需要作出统一写入数据明确纳入标准着色器附加渲染目标。不幸的是,这是无法完成的,因为没有“入口点”来“挂钩”标准着色器并将其他数据写入其他颜色缓冲区。最接近的是"finalcolor"修饰符,但它实际上不允许通过CG着色器写入额外的缓冲区(这需要额外的数据来自片段着色器,这是从表面着色器不可访问的),但只能修改一种颜色。

我决定重写着色器的一部分(所以它不会引发在OpenGL无证行为),并放弃了其在效合一阴影贴图的支持。据我所知,没有其他选择没有修改统一引擎(需要“特殊安排”和源代码访问)或用我自己的替换整个照明系统。