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