Unity3d, multiple render targets - different behavior in Direct3D / OpenGl

I am writing a shader for unity3d. The shader uses multiple render targets to render the post-processing effect.

However, I ran into an interesting problem.

When Unity3d is run in direct3d mode, by default all standard shaders write data only to the first color buffer (i.e. index 0). That is, if I connect 3 color buffers to the camera, call the color buffer Camera.Render

with index 0, it will contain the rendered scene, and all other buffers will remain intact, unless some shader is written to them. My shader uses this behavior (I use buffers with indices 1 and 2 to collect the data needed for the post-process effect).

However, in OpenGL mode, the standard single3d shaders write to ALL color buffers simultaneously. That is, if I attach multiple render buffers to the camera, call Camera.Render

all 3 buffers will contain a copy of the scene rendering.

This breaks my shader in OpenGL mode.

How can I fix this? I need to render the entire scene in one go, and only objects that have a specific shader need to modify the additional color buffers.

I need to render the scene in one go because using layer masks results in unity to recalculate the projector shadows for ALL lights and I need the shadows to be correct.



source to share

1 answer

Unfortunately, it turns out that "don't write to one of the render targets" is an undocumented behavior in opengl. The standard unit shader, when compiled for the direct render path, creates an gl_FragData[0] = ...;

assignment and write to only one buffer, which causes undocumented behavior and causes a mess.

To fix this problem, I would need to make the data writer explicitly into the additional render targets in the standard shaders. Unfortunately, this cannot be done because there is no "starting point" to "intercept" the standard shader and write additional data to other color buffers. The closest thing to this is the "finalcolor" modifier , but in fact it does not allow writing to additional buffers through the CG shader (which requires additional data to be from the fragment shader, which is not available for the surface shader), you can only change one color.

I decided to rewrite part of the shader (so that it doesn't trigger undocumented behavior in OpenGL) and dropped support for shadowmap support in unity. As far as I know, there are no other options other than modifying the unity mechanism (requires "special devices" and access to the source code) or replacing the entire lighting system with my own.



All Articles