I have hacked the WavingDoublePass shader for various reasons and, in combination with an Image Effect using the _CameraDepthTexture, found a problem that I need some help sorting out. Attached is a scene which demonstrates the problem.
Put simply, when disabling the vertex displacement in WavingDoublePass, the _CameraDepthTexture continues to display displaced/waving grass. I’d like to know why this is happening, as it suggests that the waving motion is being calculated twice (which is fine, I suppose), but I don’t know where the second location is so I can make the relevant changes there as well.
Please let me know if you have any questions. The package does require Unity Pro.
Test Package: 1157860–44194–$WavingGrassDepthTest.unitypackage (2.91 MB)
And the Shader code:
Shader "Hidden/TerrainEngine/Details/WavingDoublePass" {
Properties {
_WavingTint ("Fade Color", Color) = (.7,.6,.5, 0)
_MainTex ("Base (RGB) Alpha (A)", 2D) = "white" {}
_WaveAndDistance ("Wave and distance", Vector) = (12, 3.6, 1, 1)
_Cutoff ("Cutoff", float) = 0.5
}
SubShader {
Tags {
"Queue" = "Geometry+200"
"IgnoreProjector"="True"
"RenderType"="Grass"
}
Cull Off
LOD 200
ColorMask RGB
CGPROGRAM
#pragma surface surf Lambert vertex:WavingGrassVertCopy addshadow
#pragma exclude_renderers flash
#include "TerrainEngine.cginc"
sampler2D _MainTex;
fixed _Cutoff;
float _grassMovementOn;
fixed4 TerrainWaveGrassCopy (inout float4 vertex, float waveAmount, fixed4 color)
{
float4 _waveXSize = float4(0.012, 0.02, 0.06, 0.024) * _WaveAndDistance.y;
float4 _waveZSize = float4 (0.006, .02, 0.02, 0.05) * _WaveAndDistance.y;
float4 waveSpeed = float4 (0.3, .5, .4, 1.2) * 4;
float4 _waveXmove = float4(0.012, 0.02, -0.06, 0.048) * 2;
float4 _waveZmove = float4 (0.006, .02, -0.02, 0.1);
float4 waves;
waves = vertex.x * _waveXSize;
waves += vertex.z * _waveZSize;
// Add in time to model them over time
waves += _WaveAndDistance.x * waveSpeed;
float4 s, c;
waves = frac (waves);
FastSinCos (waves, s,c);
s = s * s;
s = s * s;
float lighting = dot (s, normalize (float4 (1,1,.4,.2))) * .7;
s = s * waveAmount;
float3 waveMove = float3 (0,0,0);
waveMove.x = dot (s, _waveXmove);
waveMove.z = dot (s, _waveZmove);
// ---------- LOOK HERE ----------
// This line has been conditionalized
// to show that the depth texture
// is waving the vertices in another
// location. Adding it back in will
// show that the same algorithm is
// being used twice. Where is the
// other implementation?
if (_grassMovementOn == 1)
{
vertex.xz -= waveMove.xz * _WaveAndDistance.z;
}
// -------------------------------
// apply color animation
fixed3 waveColor = lerp (fixed3(0.5,0.5,0.5), _WavingTint.rgb, lighting);
// Fade the grass out before detail distance.
// Saturate because Radeon HD drivers on OS X 10.4.10 don't saturate vertex colors properly.
float3 offset = vertex.xyz - _CameraPosition.xyz;
color.a = saturate (2 * (_WaveAndDistance.w - dot (offset, offset)) * _CameraPosition.w);
return fixed4(2 * waveColor * color.rgb, color.a);
}
struct Input {
float2 uv_MainTex;
fixed4 color : COLOR;
};
void WavingGrassVertCopy (inout appdata_full v)
{
// MeshGrass v.color.a: 1 on top vertices, 0 on bottom vertices
// _WaveAndDistance.z == 0 for MeshLit
float waveAmount = v.color.a * _WaveAndDistance.z;
v.color = TerrainWaveGrassCopy (v.vertex, waveAmount, v.color);
}
void surf (Input IN, inout SurfaceOutput o) {
fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * IN.color;
o.Albedo = c.rgb;
o.Alpha = c.a;
clip (o.Alpha - _Cutoff);
o.Alpha *= IN.color.a;
}
ENDCG
}
SubShader {
Tags {
"Queue" = "Geometry+200"
"IgnoreProjector"="True"
"RenderType"="Grass"
}
Cull Off
LOD 200
ColorMask RGB
Pass {
Tags { "LightMode" = "Vertex" }
Material {
Diffuse (1,1,1,1)
Ambient (1,1,1,1)
}
Lighting On
ColorMaterial AmbientAndDiffuse
AlphaTest Greater [_Cutoff]
SetTexture [_MainTex] { combine texture * primary DOUBLE, texture }
}
Pass {
Tags { "LightMode" = "VertexLMRGBM" }
AlphaTest Greater [_Cutoff]
BindChannels {
Bind "Vertex", vertex
Bind "texcoord1", texcoord0 // lightmap uses 2nd uv
Bind "texcoord", texcoord1 // main uses 1st uv
}
SetTexture [unity_Lightmap] {
matrix [unity_LightmapMatrix]
combine texture * texture alpha DOUBLE
}
SetTexture [_MainTex] { combine texture * previous QUAD, texture }
}
}
Fallback Off
}
Shader "Custom/Depth"
{
Properties
{
_MainTex ("Base (RGB)", 2D) = "black" {}
}
CGINCLUDE
#include "UnityCG.cginc"
float4x4 _frustumCorners;
float4 _cameraPos;
float _showDepth;
float _depthScale;
uniform sampler2D _CameraDepthTexture;
uniform sampler2D _MainTex;
uniform float4 _MainTex_TexelSize;
struct VertexShaderOutput
{
float4 pos : POSITION;
float2 uv : TEXCOORD0;
float2 uv_depth : TEXCOORD1;
float4 interpolatedRay : TEXCOORD2;
};
VertexShaderOutput VertexShaderFunction( appdata_img input )
{
VertexShaderOutput output;
half index = input.vertex.z;
input.vertex.z = 0.1;
output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
output.uv = input.texcoord.xy;
output.uv_depth = input.texcoord.xy;
#if SHADER_API_D3D9
if (_MainTex_TexelSize.y < 0)
{
output.uv.y = 1 - output.uv.y;
}
#endif
output.interpolatedRay = _frustumCorners[(int)index];
output.interpolatedRay.w = index;
return output;
}
float4 FragmentShaderFunction(VertexShaderOutput input) : COLOR
{
// unpack depth from Camera Depth Texture
float depth = Linear01Depth(UNITY_SAMPLE_DEPTH(tex2D(_CameraDepthTexture, input.uv_depth)));
depth = pow(depth, _depthScale);
// lerp half of it with the screen texture
return lerp(tex2D(_MainTex, input.uv), depth, _showDepth);
}
ENDCG
// Main shader
SubShader
{
Pass
{
ZTest Always Cull Off ZWrite Off
Fog { Mode off }
CGPROGRAM
#pragma vertex VertexShaderFunction
#pragma fragment FragmentShaderFunction
#pragma fragmentoption ARB_precision_hint_fastest
#pragma target 3.0
ENDCG
}
}
Fallback off
}