- Home /
Unity 5: Water Shader and Fog Not Rendering
Apparently fog in Unity 5 has been changed, and as a result fog on water doesn't render properly on the 'horizon.'
I'm using the old 'Water Pro' shader from Unity 4.
I've been following the advice of this thread for how to implement fog rendering for the water shader. However, I've ran into difficulties. The fog shows up on the surface of the water, but with a bizarre behavior based off of the camera's rotation.
Here's how the fog *should* look based off of the same scene in Unity 4. Disregard the particle effects, those don't work either ;)
Here's a video showing what no fog looks like.
Here is a video showing the current shader glitch.
Any idea how to fix this? I've been struggling for hours and there is practically no documentation on this.
Thank you very much!!!
Here's the edited shader so far:
Shader "FX/Water" {
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)
_Fresnel ("Fresnel (A) ", 2D) = "gray" {}
_BumpMap ("Normalmap ", 2D) = "bump" {}
WaveSpeed ("Wave speed (map1 x,y; map2 x,y)", Vector) = (19,9,-16,-7)
_ReflectiveColor ("Reflective color (RGB) fresnel (A) ", 2D) = "" {}
_ReflectiveColorCube ("Reflective color cube (RGB) fresnel (A)", Cube) = "" { TexGen CubeReflect }
_HorizonColor ("Simple water horizon color", COLOR) = ( .172, .463, .435, 1)
_MainTex ("Fallback texture", 2D) = "" {}
_ReflectionTex ("Internal Reflection", 2D) = "" {}
_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 fragmentoption ARB_precision_hint_fastest
#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
#include "UnityCG.cginc"
uniform float4 _WaveScale4;
uniform float4 _WaveOffset;
#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 vertex : SV_POSITION;
#if defined(HAS_REFLECTION) || defined(HAS_REFRACTION)
float4 ref : TEXCOORD0;
float2 bumpuv0 : TEXCOORD1;
float2 bumpuv1 : TEXCOORD2;
float3 viewDir : TEXCOORD3;
#else
float2 bumpuv0 : TEXCOORD0;
float2 bumpuv1 : TEXCOORD1;
float3 viewDir : TEXCOORD2;
#endif
UNITY_FOG_COORDS(5)
};
v2f vert(appdata v)
{
v2f o;
o.vertex = mul (UNITY_MATRIX_MVP, v.vertex);
UNITY_TRANSFER_FOG(o,o.vertex);
// scroll bump waves
float4 temp;
temp.xyzw = v.vertex.xzxz * _WaveScale4 / 1.0 + _WaveOffset;
o.bumpuv0 = temp.xy;
o.bumpuv1 = temp.wz;
// object space view direction (will normalize per pixel)
o.viewDir.xzy = ObjSpaceViewDir(v.vertex);
#if defined(HAS_REFLECTION) || defined(HAS_REFRACTION)
o.ref = ComputeScreenPos(o.vertex);
#endif
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;
half4 frag( v2f i ) : COLOR
{
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
UNITY_APPLY_FOG(i.fogCoord, color);
return color;
}
ENDCG
}
}
// -----------------------------------------------------------
// Old cards
// three texture, cubemaps
Subshader {
Tags { "WaterMode"="Simple" "RenderType"="Opaque" }
Pass {
Color (0.5,0.5,0.5,0.5)
SetTexture [_MainTex] {
Matrix [_WaveMatrix]
combine texture * primary
}
SetTexture [_MainTex] {
Matrix [_WaveMatrix2]
combine texture * primary + previous
}
SetTexture [_ReflectiveColorCube] {
combine texture +- previous, primary
Matrix [_Reflection]
}
}
}
// dual texture, cubemaps
Subshader {
Tags { "WaterMode"="Simple" "RenderType"="Opaque" }
Pass {
Color (0.5,0.5,0.5,0.5)
SetTexture [_MainTex] {
Matrix [_WaveMatrix]
combine texture
}
SetTexture [_ReflectiveColorCube] {
combine texture +- previous, primary
Matrix [_Reflection]
}
}
}
// single texture
Subshader {
Tags { "WaterMode"="Simple" "RenderType"="Opaque" }
Pass {
Color (0.5,0.5,0.5,0)
SetTexture [_MainTex] {
Matrix [_WaveMatrix]
combine texture, primary
}
}
}
}
UPDATE:
So I essentially wrote Unity's buggy code independently in the above code.... I took the following code directly from the FXWaterPro shader file after upgrading my standard assets. The bug still exists.
The code also has an uncanny resemblance to mine. Can somebody run a diff as a sanity check between this code, and the FXWaterPro shader code??
Shader "FX/Water" {
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" {}
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
#include "UnityCG.cginc"
uniform float4 _WaveScale4;
uniform float4 _WaveOffset;
#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;
#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 (_Object2World, v.vertex);
temp.xyzw = wpos.xzxz * _WaveScale4 + _WaveOffset;
o.bumpuv0 = temp.xy;
o.bumpuv1 = temp.wz;
// 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;
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
UNITY_APPLY_FOG(i.fogCoord, color);
return color;
}
ENDCG
}
}
}
Answer by screenname_taken · Mar 13, 2015 at 03:54 PM
Import the water from the new Standard Shader pack for Unity 5.
I can't actually find the water shader in Standard Shader pack...
You download it from here correct? Or is there a different source?
Also, the standard assets on the Unity asset store are only 4.6. Is there a Unity 5 version?
Go to "Assets", then Import Package -> Environment, and then scroll to find the Waters. I think Water(Basic) is the one similar to the water that was in unity free.
Imports aren't showing up; probably a configuration issue. But I'll try that, thank you!
Just as a followup: I imported the new standard assets; but the bug is still there.
It only happens when the water is incredibly large, however (greater than 512 scale). However, this can be mitigated by using multiple water prefabs and a horizon prefab, as I've found out.
Your answer
Follow this Question
Related Questions
Unity 5 Fog not working on Standard Shader Objects 3 Answers
Fog Mode Off Functionality 1 Answer
Represent Land 3D Area End 0 Answers