Unity 5.5 I have a problem with calculating depth in a shader

Hi everyone,

Firstly thanks to everyone to posts on this forum - its an amazing resource, I use it so often for the problems I encounter. This time however I cant seem to find a solution so was hoping some clever person can let me know what Im doing wrong.

Basically an adaption of the unity FXwaterpro shader to render my water with small waves at the shoreline. I found this on another thread. It was working great but after undating to unity 5.5 the depth comparison doesnt seem to work correctly in this instance. Here is the original shader:

Shader “FX/WaterFoam” {
Properties {
_WaveScale (“Wave scale”, Range (0.02,0.15)) = 0.063
_ReflDistort (“Reflection distort”, Range (0,1.5)) = 0.44
_RefrDistort (“Refraction distort”, Range (0,1.5)) = 0.40
_RefrColor (“Refraction color”, COLOR) = ( .34, .85, .92, 1)
[NoScaleOffset] _Fresnel ("Fresnel (A) ", 2D) = “gray” {}
[NoScaleOffset] _BumpMap ("Normalmap ", 2D) = “bump” {}
[NoScaleOffset] _Foam (“Foam texture”, 2D) = “white” {}
[NoScaleOffset] _FoamGradient ("Foam gradient ", 2D) = “white” {}
_FoamStrength (“Foam strength”, Range (0, 10.0)) = 1.0

WaveSpeed (“Wave speed (map1 x,y; map2 x,y)”, Vector) = (19,9,-16,-7)
[NoScaleOffset] _ReflectiveColor ("Reflective color (RGB) fresnel (A) ", 2D) = “” {}
_HorizonColor (“Simple water horizon color”, COLOR) = ( .172, .463, .435, 1)
[HideInInspector] _ReflectionTex (“Internal Reflection”, 2D) = “” {}
[HideInInspector] _RefractionTex (“Internal Refraction”, 2D) = “” {}
}

// -----------------------------------------------------------
// Fragment program cards

Subshader {
Tags { “WaterMode”=“Refractive” “RenderType”=“Opaque” }
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fog
#pragma multi_compile WATER_REFRACTIVE WATER_REFLECTIVE WATER_SIMPLE
#if defined (WATER_REFLECTIVE) || defined (WATER_REFRACTIVE)
#define HAS_REFLECTION 1
#endif
#if defined (WATER_REFRACTIVE)
#define HAS_REFRACTION 1
#endif

#if defined(HAS_REFLECTION) || defined(HAS_REFRACTION)
#define HAS_FOAM
#endif

#include “UnityCG.cginc”

uniform float4 _WaveScale4;
uniform float4 _WaveOffset;

#if defined(HAS_FOAM)
uniform float _FoamStrength;
uniform sampler2D _CameraDepthTexture; //Depth Texture
#endif

#if HAS_REFLECTION
uniform float _ReflDistort;
#endif
#if HAS_REFRACTION
uniform float _RefrDistort;
#endif

struct appdata {
float4 vertex : POSITION;
float3 normal : NORMAL;
};

struct v2f {
float4 pos : SV_POSITION;
#if defined(HAS_REFLECTION) || defined(HAS_REFRACTION)
float4 ref : TEXCOORD0;
float2 bumpuv0 : TEXCOORD1;
float2 bumpuv1 : TEXCOORD2;
float3 viewDir : TEXCOORD3;
#if defined(HAS_FOAM)
float2 foamuv : TEXCOORD5;
#endif
#else
float2 bumpuv0 : TEXCOORD0;
float2 bumpuv1 : TEXCOORD1;
float3 viewDir : TEXCOORD2;
#endif

UNITY_FOG_COORDS(4)
};

v2f vert(appdata v)
{
v2f o;
o.pos = mul (UNITY_MATRIX_MVP, v.vertex);

// scroll bump waves
float4 temp;
float4 wpos = mul (unity_ObjectToWorld, v.vertex);
temp.xyzw = wpos.xzxz * _WaveScale4 + _WaveOffset;
o.bumpuv0 = temp.xy;
o.bumpuv1 = temp.wz;

#if defined(HAS_FOAM)
o.foamuv = 7.0f * wpos.xz + 0.05 * float2(_SinTime.w, _SinTime.w);
//o.edgeuv = wpos.xz;
#endif

// object space view direction (will normalize per pixel)
o.viewDir.xzy = WorldSpaceViewDir(v.vertex);

#if defined(HAS_REFLECTION) || defined(HAS_REFRACTION)
o.ref = ComputeScreenPos(o.pos);
#endif

UNITY_TRANSFER_FOG(o,o.pos);
return o;
}

#if defined (WATER_REFLECTIVE) || defined (WATER_REFRACTIVE)
sampler2D _ReflectionTex;
#endif
#if defined (WATER_REFLECTIVE) || defined (WATER_SIMPLE)
sampler2D _ReflectiveColor;
#endif
#if defined (WATER_REFRACTIVE)
sampler2D _Fresnel;
sampler2D _RefractionTex;
uniform float4 _RefrColor;
#endif
#if defined (WATER_SIMPLE)
uniform float4 _HorizonColor;
#endif
sampler2D _BumpMap;

#if defined(HAS_FOAM)
sampler2D _Foam;
sampler2D _FoamGradient;
#endif

half4 frag( v2f i ) : SV_Target
{
i.viewDir = normalize(i.viewDir);

// combine two scrolling bumpmaps into one
half3 bump1 = UnpackNormal(tex2D( _BumpMap, i.bumpuv0 )).rgb;
half3 bump2 = UnpackNormal(tex2D( _BumpMap, i.bumpuv1 )).rgb;
half3 bump = (bump1 + bump2) * 0.5;

// fresnel factor
half fresnelFac = dot( i.viewDir, bump );

// perturb reflection/refraction UVs by bumpmap, and lookup colors
#if HAS_REFLECTION
float4 uv1 = i.ref; uv1.xy += bump * _ReflDistort;
half4 refl = tex2Dproj( _ReflectionTex, UNITY_PROJ_COORD(uv1) );
#endif
#if HAS_REFRACTION
float4 uv2 = i.ref; uv2.xy -= bump * _RefrDistort;
half4 refr = tex2Dproj( _RefractionTex, UNITY_PROJ_COORD(uv2) ) * _RefrColor;
#endif

// final color is between refracted and reflected based on fresnel
half4 color;

#if defined(WATER_REFRACTIVE)
half fresnel = UNITY_SAMPLE_1CHANNEL( _Fresnel, float2(fresnelFac,fresnelFac) );
color = lerp( refr, refl, fresnel);
#endif

#if defined(WATER_REFLECTIVE)
half4 water = tex2D( _ReflectiveColor, float2(fresnelFac,fresnelFac) );
color.rgb = lerp( water.rgb, refl.rgb, water.a );
color.a = refl.a * water.a;
#endif

#if defined(WATER_SIMPLE)
half4 water = tex2D( _ReflectiveColor, float2(fresnelFac,fresnelFac) );
color.rgb = lerp( water.rgb, _HorizonColor.rgb, water.a );
color.a = _HorizonColor.a;
#endif

#if defined(HAS_FOAM)
float sceneZ = LinearEyeDepth (tex2Dproj(_CameraDepthTexture, UNITY_PROJ_COORD(i.ref)).r);
float objectZ = i.ref.z;
float intensityFactor = 1 - saturate((sceneZ - objectZ) / _FoamStrength);
half3 foamGradient = 1 - tex2D(_FoamGradient, float2(intensityFactor - _Time.y*0.2, 0) + bump.xy * 0.15);
float2 foamDistortUV = bump.xy * 0.2;
half3 foamColor = tex2D(_Foam, i.foamuv + foamDistortUV).rgb;
color.rgb += foamGradient * intensityFactor * foamColor;

#endif

UNITY_APPLY_FOG(i.fogCoord, color);

return color;
}
ENDCG

}
}
}

I have been researching LinearEyeDepth and Linear01Depth and have tried a number of different things but with no luck.

Has something changed in unity 5.5 which is affecting how this works ?

Many thanks in advance,

Sam

So I’ve been trying to fix this all day and then 30 mins after I post I find the answer.

For anyone else with a similar issue, I resolved this by changing the following like near the end of the shader (in the #if defined(HAS_FOAM) section)

old line (not working for me): float objectZ = i.ref.z;
new working line: float objectZ = i.ref.w;

If anyone could possible enlighten me on what’s going on here I would love to know.

Anyway, here’s hoping that thiis helps someone else.

Thanks everyone :slight_smile:

1 Like

Thank you so much! I’ve spent days looking for a solution. I wish I could tell you why it works, but I’m as confused as you are!