Search Unity

Depth blended shader in second camera reflection

Discussion in 'Shaders' started by Koksny, Apr 7, 2019.

  1. Koksny

    Koksny

    Joined:
    Nov 15, 2017
    Posts:
    15
    Hey, i'm using depth blended shader as water surface shader (for the edge blending), and i'm trying to render it as reflection (using second camera and code based on Unity MirrorReflection4 script, basically doing inverted culling and custom projection matrix).

    It works fine in main camera, however no matter what i do - the depth blending fails in reflected space/texture. I'm using shader replacements for other camera, and i'm feeding custom depth buffer sampler to the surface shader (instead of using _CameraDepthBuffer), but it still doesn't work.

    Do i need to multiply some matrices? Feed custom clipping space position?

    Depth blended shader:
    Code (CSharp):
    1.  [/SIZE]
    2.             VertexOutput vert (VertexInput v) {
    3.                 VertexOutput o = (VertexOutput)0;
    4.                 o.uv0 = v.texcoord0;
    5.                 o.pos = UnityObjectToClipPos( v.vertex );
    6.                 o.projPos = ComputeScreenPos (o.pos);
    7.                 COMPUTE_EYEDEPTH(o.projPos.z);
    8.                 return o;
    9.             }
    10.             float4 frag(VertexOutput i) : COLOR {
    11.                 float sceneZ = max(0,LinearEyeDepth (UNITY_SAMPLE_DEPTH(tex2Dproj(_CameraDepthTexture, UNITY_PROJ_COORD(i.projPos)))) - _ProjectionParams.g);
    12.                 float partZ = max(0,i.projPos.z - _ProjectionParams.g);
    13.                 float4 _WaterTexture_var = tex2D(_WaterTexture,TRANSFORM_TEX(i.uv0, _WaterTexture));
    14.                 float3 emissive = saturate(( _WaterTexture_var.rgb > 0.5 ? (1.0-(1.0-2.0*(_WaterTexture_var.rgb-0.5))*(1.0-_WaterColor.rgb)) : (2.0*_WaterTexture_var.rgb*_WaterColor.rgb) ));
    15.                 float3 finalColor = emissive;
    16.                 return fixed4(finalColor,(_WaterTexture_var.a*saturate((sceneZ-partZ)/_WaterFeather)));
    17.             }
    18.        
    Mirror reflection script:
    Code (CSharp):
    1.  [/SIZE]   private static void CAT_MirrorReflectionCalculateMatrix(ref Matrix4x4 reflectionMat, Vector4 plane)
    2.     {
    3.         reflectionMat.m00 = (1F - 2F * plane[0] * plane[0]);
    4.         reflectionMat.m01 = (-2F * plane[0] * plane[1]);
    5.         reflectionMat.m02 = (-2F * plane[0] * plane[2]);
    6.         reflectionMat.m03 = (-2F * plane[3] * plane[0]);
    7.  
    8.         reflectionMat.m10 = (-2F * plane[1] * plane[0]);
    9.         reflectionMat.m11 = (1F - 2F * plane[1] * plane[1]);
    10.         reflectionMat.m12 = (-2F * plane[1] * plane[2]);
    11.         reflectionMat.m13 = (-2F * plane[3] * plane[1]);
    12.  
    13.         reflectionMat.m20 = (-2F * plane[2] * plane[0]);
    14.         reflectionMat.m21 = (-2F * plane[2] * plane[1]);
    15.         reflectionMat.m22 = (1F - 2F * plane[2] * plane[2]);
    16.         reflectionMat.m23 = (-2F * plane[3] * plane[2]);
    17.  
    18.         reflectionMat.m30 = 0F;
    19.         reflectionMat.m31 = 0F;
    20.         reflectionMat.m32 = 0F;
    21.         reflectionMat.m33 = 1F;
    22.     }
    23.        
    24.     private Vector4 CAT_MirrorReflectionCameraSpacePlane(Camera cam, Vector3 pos, Vector3 normal, float sideSign)
    25.     {
    26.         Vector3 offsetPos = pos + normal * CAT_MirrorReflectionClipPlaneOffset;
    27.         Matrix4x4 m = cam.worldToCameraMatrix;
    28.         Vector3 cpos = m.MultiplyPoint3x4(offsetPos);
    29.         Vector3 cnormal = m.MultiplyVector(normal).normalized * sideSign;
    30.         return new Vector4(cnormal.x, cnormal.y, cnormal.z, -Vector3.Dot(cpos, cnormal));
    31.     }
    32.  
    33.     // Use this for initialization
    34.     void OnEnable () {
    35.  
    36.         Shader.SetGlobalTexture ("_MirrorReflectionTexture", CAT_MirrorReflectionDepthRTT);
    37.         CAT_MirrorReflectionCamera.transform.SetPositionAndRotation (transform.position, transform.rotation);
    38.         CAT_MirrorReflectionCamera.SetReplacementShader (CAT_UIController.instance.CAT_ReflectionCameraShader, "Mirrorable");
    39.         CAT_MirrorReflectionCamera.depthTextureMode = DepthTextureMode.DepthNormals;
    40.         CAT_MirrorReflectionCamera.SetTargetBuffers(CAT_MirrorReflectionRTT.colorBuffer, CAT_MirrorReflectionDepthRTT.depthBuffer);
    41.         CAT_MirrorReflectionPlaneWorldPosition = transform.position;
    42.         CAT_MirrorReflectionPlaneNormal = transform.up;
    43.         CAT_MirrorReflectionMagicalFloat = -Vector3.Dot (CAT_MirrorReflectionPlaneNormal, CAT_MirrorReflectionPlaneWorldPosition) - CAT_MirrorReflectionClipPlaneOffset;
    44.         CAT_MirrorReflectionMatrix = new Matrix4x4 ();
    45.         CAT_MirrorReflectionCalculateMatrix (ref CAT_MirrorReflectionMatrix, new Vector4 (CAT_MirrorReflectionPlaneNormal.x, CAT_MirrorReflectionPlaneNormal.y, CAT_MirrorReflectionPlaneNormal.z, CAT_MirrorReflectionMagicalFloat));
    46.         CAT_MirrorReflectionMaterial.SetTexture("_ReflectionTex", CAT_MirrorReflectionRTT);
    47.     }
    48.  
    49.     public void OnWillRenderObject() {
    50.  
    51.             // Get data
    52. //            Vector3 MirrorReflectionOldCameraPosition = CAT_XriumActiveCamera.transform.position;
    53.             CAT_MirrorReflectionCamera.fieldOfView = CAT_XriumActiveCamera.fieldOfView;
    54.             CAT_MirrorReflectionCamera.worldToCameraMatrix = CAT_XriumActiveCamera.worldToCameraMatrix * CAT_MirrorReflectionMatrix;
    55.  
    56.             // Set some wiglly-woggly-jiggly-shiggly matrix magic
    57.             Vector4 MirroReflectionClipPlane = CAT_MirrorReflectionCameraSpacePlane (CAT_MirrorReflectionCamera, CAT_MirrorReflectionPlaneWorldPosition, CAT_MirrorReflectionPlaneNormal, 0.1f);
    58.             CAT_MirrorReflectionCamera.projectionMatrix = CAT_XriumActiveCamera.CalculateObliqueMatrix (MirroReflectionClipPlane);
    59.  
    60.             // Render
    61.             GL.invertCulling = true;
    62.  
    63.             Vector3 MirrorReflectionActiveCameraRotationEuler = CAT_XriumActiveCamera.transform.eulerAngles;
    64.             CAT_MirrorReflectionCamera.transform.position = CAT_MirrorReflectionMatrix.MultiplyPoint3x4 (CAT_XriumActiveCamera.transform.position);
    65.             CAT_MirrorReflectionCamera.transform.eulerAngles = new Vector3 (0, MirrorReflectionActiveCameraRotationEuler.y, MirrorReflectionActiveCameraRotationEuler.z);
    66.             if (!CAT_MirrorReflectionCamera.orthographic && CAT_MirrorReflectionCamera.rect.size.sqrMagnitude > 0)
    67.                 CAT_MirrorReflectionCamera.Render ();
    68. //            CAT_MirrorReflectionCamera.transform.position = MirrorReflectionOldCameraPosition;
    69.             GL.invertCulling = false;
    70.  
    71.             CAT_XriumController.CAT_XriumUpdateMirrorsTickets--;
    72.     }
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    Have you confirmed there even is anything in the camera depth texture for the reflected view, or that it is the correct depth texture? You might try using _LastCameraDepthTexture instead to see if that gives you something. I also don't know how depth textures work with custom projection matricies, so you might be getting bad data elsewhere for converting the non-linear depth texture value into linear depth.
     
  3. Koksny

    Koksny

    Joined:
    Nov 15, 2017
    Posts:
    15
    I did, i can project the depth texture alone onto the reflection plane and it's rendered properly. Unfortunately, after some more digging i've discovered it's basically a variation of "Fog not working in water reflection" issue ( https://answers.unity.com/questions/681123/water-4-advanced-fog-missing-from-reflections.html , https://forum.unity.com/threads/fog-not-reflecting-properly-on-water-surface.284812/ ) , and it has not been solved so far.

    Thanks for checking it out, but it seems i can only wait until LWRP/HDRP solves somehow this issue.
     
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    Unfortunately the LWRP calculates fog exactly the same way as the built in rendering paths, so fog on custom projections are still broken. I think the HDRP does proper radial fog, so it might actually work there.

    Either way, the depth texture should still work at least to some degree as the depth texture and the z depth will still match.