Consider this water shader. I takes the distance from the water surface to the depth buffer and tints the image from transparent, to clear teal, to dark teal. The further the darker/more opaque. (in the case of the camera being underwater I place a quad in front of the camera so that it looks exactly the same as looking from above the water)
The issue is that in the screenshoot I am looking from under water towards the sky, if I were to raycast from the camera, the ray would leave the water quite early, that is to say, there is very little water between the camera and the tunnel ceiling.
The issue is that my shader don’t take that into consideration.
My current solution that does not work is as follow:
Have a ‘water back’ mesh that uses a shader that writes it’s position to the depth buffer, so that when the water shader reads the depth buffer, it reads a lower depth value and thus does not darken the image as much as it does right now, the closer the camera being to the ‘water back’ mesh, the more transparent the water is.
The issue is that I can’t get it to work, I’ve tried quite a few variations of the following shader but none seem to work and I am not sure what I am doing wrong.
Shader "Custom/InvisibleMask" {
Properties{
}
SubShader
{
Tags { "RenderType"="Opaque" "Queue"="Geometry-1"} //actually rendering at 2999 that is 1 less than the water in the material
LOD 100
ColorMask 0
Pass{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _CameraDepthTexture;
struct appdata{
float4 vertex : POSITION;
};
struct v2f{
float4 vertex : SV_POSITION;
float4 screenPos : TEXCOORD0;
};
v2f vert (appdata v){
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.screenPos = ComputeScreenPos(o.vertex);
return o;
}
float frag (v2f i) : SV_Depth{
float4 screenPos = float4(i.screenPos.xyz, i.screenPos.w + 0.00000000001);
float4 screenPosNorm = screenPos / screenPos.w;
screenPosNorm.z = (UNITY_NEAR_CLIP_VALUE >= 0) ? screenPosNorm.z : screenPosNorm.z * 0.5 + 0.5;
float screenDepth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, screenPosNorm.xy);
return .92375;//this value either completely removes the water or the water is completely unaffected by it
//returning neither screenPosNorm.z nor screenDepth gave the intended effect, it either did nothing or deleted the water
}
ENDCG
}
}
}