- Home /
Custom vertex shader doesn't write to camera depth normals texture.
I'm attempting to write a custom vertex shader, but I'm finding that unlike the standard shader, my shader does not write to the camera depth normals texture. (UpdateDepthNormalsTexture step in the frame debugger)
It is my understanding that the UpdateDepthNormalsTexture works using a built-in replacement shader called "Hidden/Internal-DepthNormalsTexture" Looking at that built-in shader I see that it has a subshader with Tags { "RenderType"="Opaque" } My subshader has the same RenderType, so I would expect it to work with the replacement shader.
The DepthNormalsTexture is used by the SSAO script so the SSAO ends up ignoring objects in front of the camera using my custom shader.
My question is, how can I get my custom shader to render to the depth normals texture?
Shader:
Shader "Custom/WrappedDiffuse" {
Properties {
_Tint ("Tint", Color) = (1, 1, 1, 1)
_MainTex ("Texture", 2D) = "white" {}
_WrapTex("Wrap Texture", 2D) = "white" {}
_WrapShift("Wrap Shift", Range(-1, 1)) = 0
_BumpMap("Normals", 2D) = "bump" {}
_BumpScale("Bump Scale", Float) = 1
}
SubShader {
Pass {
Tags {
"RenderType" = "Opaque"
"Queue" = "Geometry"
"LightMode" = "ForwardBase"
}
CGPROGRAM
#pragma vertex MyVertexProgram
#pragma fragment MyFragmentProgram
#include "UnityPBSLighting.cginc"
float4 _Tint;
float _BumpScale;
sampler2D _MainTex;
sampler2D _WrapTex;
float _WrapShift;
sampler2D _BumpMap;
float4 _MainTex_ST;
struct VertexData {
float4 position : POSITION;
float3 normal : NORMAL;
float2 uv : TEXCOORD0;
};
struct Interpolators {
float4 position : SV_POSITION;
float2 uv : TEXCOORD0;
float3 normal : TEXCOORD1;
};
Interpolators MyVertexProgram (VertexData v) {
Interpolators i;
i.position = mul(UNITY_MATRIX_MVP, v.position);
i.normal = UnityObjectToWorldNormal(v.normal);
i.uv = TRANSFORM_TEX(v.uv, _MainTex);
return i;
}
float3 InitializeFragmentNormal(inout Interpolators i) {
float3 texNormal;
texNormal.xy = tex2D(_BumpMap, i.uv).wy * 2 - 1;
texNormal.xy *= _BumpScale;
texNormal.z = sqrt(1 - saturate(dot(texNormal.xy, texNormal.xy)));
texNormal = UnpackScaleNormal(tex2D(_BumpMap, i.uv), _BumpScale);
texNormal = texNormal.xzy;
texNormal = normalize(texNormal);
return texNormal;
}
float4 MyFragmentProgram (Interpolators i) : SV_TARGET {
i.normal = i.normal + InitializeFragmentNormal(i);
float3 lightDir = _WorldSpaceLightPos0.xyz;
float3 lightColor = _LightColor0.rgb;
float3 albedo = tex2D(_MainTex, i.uv).rgb * _Tint.rgb;
float dotProd = dot(lightDir, i.normal);
dotProd = (dotProd + 1) / 2;
dotProd += _WrapShift;
dotProd = max(0.05, dotProd);
dotProd = min(0.95, dotProd);
float2 wrapPosition = float2(dotProd, 0);
float3 wrap = tex2D(_WrapTex, wrapPosition).rgb;
float3 diffuse =
albedo * lightColor * wrap;
return float4(diffuse, 1);
}
ENDCG
}
}
Fallback "Diffuse"
}
Answer by markv12 · Feb 13, 2017 at 08:21 AM
It seems that as of Unity 5.5, when using a replacement shader you not only need a subshader with a matching RenderType, the material the shader is applied to also has to have a RenderType tag set to the proper value. To do this, go to a material in the inspector and change the inspector to "Debug" mode. Each material will have a "String Tag Map" list that allows you to specify a set of key value pairs for the material. Add a tag with the key "RenderType" and the value "Opaque" or whatever RebderType your shader is meant for. The material should now work properly with replacement shaders like the one used to render the depth-normals texture.
If you don't want to have to do this for every material that uses your shader, you can write a custom view for your shader that sets the RenderType automatically. If you look at the editor for the standard shader you'll notice at the top a "Rendering Mode" drop-down menu. This drop-down adds and removes tags from the String Tag Map for you and has a default value. Your custom view could work like that.
That was the fastest I've ever solved a problem in Unity. First post on the forums I came to had the right answer. Thank you so much!
I've been working with Unity professionally for the better part of 10 years, and this is the first I learn about this whole thing.
I can't believe this wasn't like one of the first things that's mentioned when using certain post processing effects like SSAO.
Would never have figured this out, as we were stuck in our shader scratching our heads.