Hi, I have a shader that uses complex calculations to create normals. I’d like it to be in the deferred part of a shader because the object is obscured quite a lot, so I don’t want it to waste time rendering something when it will finally be obscured. I expect this will be on unity 5.
Is there a way of doing this?
I presume I’ll need a way of identifying the object from everything else in the deferred part, and divert the renderer to use my shader whenever it’s seen. But there is no ID tag in the g-buffers, as far as I see.
Thanks,
Dave.
Objects rendered in forward path are actually depth culled as well, since unity sorts opaque objects front to back. So if the object using your expensive shader is behind an opaque wall, no fragment shader invocations will be made. The issue with the forward path is when the object is visible and lit by multiple lights. Because unity uses multi pass shading, it’s going to redo all your nasty computations for every light. The way to prevent this is to edit the shader to compute the lighting for all the lights at once. I’m sure the forums and the wiki will be of great help if you choose to do so.
Hi, thanks for the reply.
So I can’t identify an object and use my own shader to pixel render it, unless it’s in th first pass?
I’m rendering a fractal landscape like the following I did in OpenGL
It uses fractal maths on a pixel level using deferred rendering, where there is grass on the ground the pixels are not rendered with the fractal shader. The same with the trees on other examples.
I’d like to transfer this engine to Unity.
For the sake of efficiency, is it possible to render the normal Unity terrain as the last object in the scene? It will then be obscured by the z-buffer discards. I need it to be the last opaque thing to be rendered.
Thanks again.
Dave.
What do you mean identify an object? You can provide a custom shader for both the main pass (1 pixel light + 4 vertex lights + ambient) and the ‘add’ pass (1 extra pixel light) for the forward rendering path. If you don’t implement the add pass, only the main pass will be called, which you can use with up to 4 lights at once I think. Otherwise, if you don’t want to suffer from multiple passes, go deferred.
About grass, that depends. If it’s transparent, you’re out of luck, since it doesn’t technically occlude anything and doesn’t write into the z-buffer. If it’s alpha tested though, it can be done. You just need to change the “Queue” tag of your terrain shader to something like “AlphaTest+1”. That should make it render after all the opaque and alpha tested objects.
It comes with a cost though… everything that would normally be depth culled by the terrain will be shaded. To prevent that, I guess you’d need to somehow manually implement a depth prepass just for the terrain… One way to do that is to call Camera.RenderWithShader() with a shader that renders just the terrain’s depth (no pixel shader) before the camera renders the scene and then edit the main shader to run only on ZTest Equal. That’s gonna double your draw calls for the terrain obviously, but it should still be a major win, unless you’re cpu bound. This will also further cull terrain pixels that are occluded by the terrain itself, which I think is quite a significant amount. Basically you get a guarantee that only pixels you can actually see on the screen will be shaded.