Replaced Shader not Rendering Objects in Correct Depth Order

Hello everyone,

In one of my shaders I require the surface normals of all opaque geometry in the scene. I can not simply use “_CameraNormalsTexture” as my shader uses the “PrePassBase” and “PrePassFinal” passes for the deferred lighting. As I need these surface normals in the the “PrePassBase” pass _CameraNormalsTexture has not yet been created.

Because of this I have created a simple replaced shader that interpolates the scenes vertex normals to a separate render texture and then pass that render texture in to my other shader. To test the output of the replacement shader I am temporarily passing the replaced shader texture to my color output. This is when I can see that the normals are correctly being rendered but there is an issue with the rendered objects not following the rules of the ZWrite setting, and thus my objects are popping in front and behind one another as the camera moves.

Here’s a couple images to show whats occurring:


This is what the scene looks when normally rendered.


This is what the scene looks like when rendered with the replaced shader.

I have also included the simple scene normal shader though I have also tested with a basic surface shader and get the exact same results.

Shader "0xDC/SceneNormals"{
	SubShader{
		Tags {"Queue"="Geometry" "RenderType"="Opaque"}
		
		Fog {Mode Off}
		ZWrite On
		Cull Back
		ZTest Less

		Pass{		
			CGPROGRAM
			#pragma vertex vert_main
			#pragma fragment frag_main
			#pragma target 2.0
			#pragma fragmentoption ARB_precision_hint_fastest
			#pragma debug
			#include "UnityCG.cginc"

			struct v2f{
				float4 pos		: SV_POSITION;
				float3 normal	: TEXCOORD0;
			};
			v2f vert_main(appdata_full v){
				v2f o;
				o.pos	= mul(UNITY_MATRIX_MVP, v.vertex);
				o.normal	= v.normal;
				return o;
			}
			fixed4 frag_main(v2f IN) : COLOR{
				fixed4 res;
				res.rgb = (normalize(IN.normal) * 0.5f + 0.5f);
				res.a = 1.0f;
				return res;
			}
			ENDCG
		}
	}
	FallBack "None"
}

Below is some of the code to show how I set up the camera and render each frame:

    private static bool InitCamera()
    {
        //Setup the sceneNormal shader
        ms_SceneNormalShader = Shader.Find(SCENE_NORMAL_SHADER_NAME);
        if (ms_SceneNormalShader == null)
        {
            Debug.Log("Could not find " + SCENE_NORMAL_SHADER_NAME);
            return false;
        }

        //Setup the Decal Camera.
        if (ms_DecalCamera == null)
            ms_DecalCamera = GameObject.Find(DECAL_SYSTEM);

        ms_DecalCamera.camera.CopyFrom(Camera.main);
        ms_DecalCamera.camera.enabled = false;

        //Setup the sceneNormals renderTexture.
        if (ms_RTSceneNormals != null)
        {
            RenderTexture.ReleaseTemporary(ms_RTSceneNormals);
            ms_RTSceneNormals = null;
        }
    
        ms_RTSceneNormals = RenderTexture.GetTemporary(Screen.width, Screen.height);
        ms_RTSceneNormals.SetGlobalShaderProperty("_SceneNormalMap");

        return true;
    }

And this is what I call each frame from within LateUpdate()

    public static void RenderSceneNormals()
    {
        ms_DecalCamera.camera.CopyFrom(Camera.main);
        ms_DecalCamera.camera.targetTexture = ms_RTSceneNormals;
        ms_DecalCamera.camera.RenderWithShader(ms_SceneNormalShader, "RenderType");
    }

If anyone can see what might be the issue that would be awesome.

Cheers,
0xDEADCODE

Well figured this one out myself again… I love it when it’s just a simple little fix, but man can it make you feel stupid for missing it…

OK so the whole problem was that when I was creating my Temporary Render Texture I forgot to set the depth value so it was defaulted to 0!!

So all I needed to do was change

ms_RTSceneNormals = RenderTexture.GetTemporary(Screen.width, Screen.height);

to

ms_RTSceneNormals = RenderTexture.GetTemporary(Screen.width, Screen.height, 16);

Man I feel dumb…but relieved!!

3 Likes

Well done, glad to hear its working .

Good,But how to do that use renderWithShader to render the object which you wanted? I can not get it … this is my thread,hope your help~
http://forum.unity3d.com/threads/167116-How-can-give-the-depth-texture-to-other-pass-use

Good find! I was looking through your code for things that would cause depth issues, but missed the RenderTexture initialization. It’s worth noting that the reason it seems “exactly wrong” is because Unity renders opaque objects from nearest to farthest in the hopes of getting as many discarded fragments as possible. In the case where there is no depth buffer at all, however, you get your objects appearing in reverse order.


I test the depth use replaceWithShader,But got 2 problem:
1.the objec.t sort is invert.
2.the depth texture seems not work

someBody resolve this ?

below is the project:

1170152–44833–$depthReplaceTest.unitypackage (48.5 KB)

Anybody help?

BUMP…

Dreamerflyer, this has already been resolved in this thread by 0xDEADCODE. Stop posting again and again in different threads.

Here is the fix again, quoted from the original post;

hi Farfarer, thanks your reply,can you see my attatchment? I also do that,but not work ,hope your test,thanks.

What you want is something else and not related to depth sorting problems as i recall from your original forum post, what you want requires a custom shader(s) and its very time consuming although ive shown you how to write one, you havent shown any effort to write your own, i guess.

yes,this problem found when i want to make VOLUMTRIC OBJECT .when i want to render object’s back and front depth texture with renderWithShader,I found that problem.I DO NOT understand:

  1. why the render order is invert .
    2.why the render texture _repalceDepthTexture and _CameraDepthTexture decode is not the same color.
    3.How to use grabPass for the depth not for the screean snap picture.

I try many many method.include use different material for cull frond and cull back in one object .use 2 camera to render.but not work.you can test my above attachment.buffer =RenderTexture.GetTemporary ((int)Camera.main.pixelWidth , (int)Camera.main.pixelHeight,16);.I have done the same as 0xDEADCODE.but you can see ,the render order is invert.so I ask for this here many times.

OK, GOT IT~~, when USE CULL ,NEED ZWRITE ,ZTEST correct~.