COMPUTE_VIEW_NORMAL is for transforming vertex normals from object space to view space, and the normals stored in the camera depth normals texture are already in view space. The normals “changing” as it pans across the screen is the correct behavior for a perspective camera as you’re seeing different parts of the sphere as it pans across.
What you seem to want is normals relative to the pixel’s view direction, accounting for perspective.
I wrote a little something for that here for applying that to a matcap shader, but you’d have to figure out how to apply this to the depth normals texture yourself (you have to calculate the view space position of each pixel from the depth).
I am basically going to remake the edge shader to outline backfaces.
So trying to project normals on the viewing direction, using the below code:
 float fov = 3.14/3; //assumed here fov = 60 deg;
float3 vDir = normalize(float3(-tan(fov/2)*
(i.pos.x/_MainTex_TexelSize.w-0.5*_MainTex_TexelSize.z/_MainTex_TexelSize.w),
-tan(fov/2)*(i.pos.y/_MainTex_TexelSize.w-0.5),1)); //viewDir
float3 proj = normalize(dot(Normal0,vDir)*vDir); //normal projected on vievDir
half4 newcolor = tex2D(_CameraDepthNormalsTexture, i.uv[0].xy);
//normals - lower half of the screen
if ((i.pos.y/_MainTex_TexelSize.w-0.5)>0) newcolor.xy = EncodeViewNormalStereo(proj);
//normals projected on viewing dir - upper half of the screen
return newcolor;
I have achieved this:
The artifacts on the sphere edges show there must some error in the calculated viewing direction.
But I have found another, much simpler way to edge around backfaces, that is to just to use VFACE and encode two “normal” colors into Internal-DepthNormals shader and use the standard Legacy edge effect.
If you’re just trying to detect backfaces it is literally impossible to do accurately as part of the image effect. The only way to do it by modifying the Internal-DepthNormals using VFACE. And you’re not encoding two normals at that point, you’re still just encoding one, you’re just encoding the correct normal for unculled, two sided shaders.
Yes. thanks.
That works great, but I got disappointed, because I was hoping to get it to work in conjunction with clipping shaders on object.
But unfortunately, the depthNormal texture gets rendered before the objects get clipped.
Clipped how? Via a custom shader? You need to add a custom tagged pass to the Internal-DepthNormals shader and set your clipped shader to use the same tag.
Thanks again.
That worked well. But I still must be missing something: My changes made to the Internal-DepthNormals shader do not bring any effect in the deferred lighting mode.
Because deferred doesn’t use that replacement shader, it just uses the gbuffers. If you use an opaque shader without a deferred pass, they won’t work properly with any post process that relies on normals as they do not render their normals into the gbuffers. Unity renders forward opaque objects into the gbuffers using the shadowcaster pass, which just renders black into the albedo gbuffer and depth buffer. I suspect that’s what’s happening here.
If the surface shader is already handling backface normal flipping, is using the standard lighting model, and is not disabling the deferred pass generation, then you shouldn’t have to do anything.