diff --git a/crest/Assets/Crest/Crest/Shaders/OceanInputs/AnimWavesAddFromTex.shader b/crest/Assets/Crest/Crest/Shaders/OceanInputs/AnimWavesAddFromTex.shader index 493690bea..8197f42a3 100644 --- a/crest/Assets/Crest/Crest/Shaders/OceanInputs/AnimWavesAddFromTex.shader +++ b/crest/Assets/Crest/Crest/Shaders/OceanInputs/AnimWavesAddFromTex.shader @@ -9,15 +9,14 @@ Shader "Crest/Inputs/Animated Waves/Add From Texture" _MainTex("Texture", 2D) = "white" {} _Strength( "Strength", float ) = 1 [Toggle] _HeightsOnly("Heights Only", Float) = 1 + [Toggle] _GenerateDisplacementsFromHeights("Generate Displacements From Heights", Float) = 0 + _GenerateDisplacementStrength("Generate Displacement Strength", Range(0, 10)) = 1 [Toggle] _SSSFromAlpha("Sub Surface Scattering (SSS) from Alpha", Float) = 0 _SSSStrength("SSS Strength", Float) = 0.5 } SubShader { - // base simulation runs on the Geometry queue, before this shader. - // this shader adds interaction forces on top of the simulation result. - Tags { "Queue" = "Transparent" } Blend One One Pass @@ -28,15 +27,16 @@ Shader "Crest/Inputs/Animated Waves/Add From Texture" #pragma shader_feature _HEIGHTSONLY_ON #pragma shader_feature _SSSFROMALPHA_ON + #pragma shader_feature _GENERATEDISPLACEMENTSFROMHEIGHTS_ON #include "UnityCG.cginc" sampler2D _MainTex; float4 _MainTex_ST; - + float4 _MainTex_TexelSize; float _Strength; float _SSSStrength; - + float _GenerateDisplacementStrength; float _Weight; struct Attributes @@ -48,13 +48,15 @@ Shader "Crest/Inputs/Animated Waves/Add From Texture" struct Varyings { float4 positionCS : SV_POSITION; - float2 uv : TEXCOORD0; + float3 positionWS : TEXCOORD0; + float2 uv : TEXCOORD1; }; Varyings Vert(Attributes input) { Varyings o; o.positionCS = UnityObjectToClipPos(input.positionOS); + o.positionWS = mul(unity_ObjectToWorld, float4(input.positionOS, 1.0)).xyz; o.uv = TRANSFORM_TEX(input.uv, _MainTex); return o; } @@ -67,16 +69,30 @@ Shader "Crest/Inputs/Animated Waves/Add From Texture" half4 texSample = tex2D(_MainTex, input.uv); #if _HEIGHTSONLY_ON - displacement.y = texSample.x * _Strength; + // Texture represents heights, not 3D displacements + displacement.y = texSample.x; + +#if _GENERATEDISPLACEMENTSFROMHEIGHTS_ON + // Generate horizontal displacement from derivatives of height + + // These derivatives aren't strictly correct - they assume there is a roughly 1:1 correspondance between + // texture sampling density (via _MainTex_TexelSize.x) and output sampling density (via ddx(input.positionWS.x)). + // I couldn't find a nice/cheap way to compute texel density (i.e. maintex texel size in world), so i'll leave + // it to a scale factor. + float height_x = tex2D(_MainTex, input.uv + float2(_MainTex_TexelSize.x, 0.0)); + float height_z = tex2D(_MainTex, input.uv + float2(0.0, _MainTex_TexelSize.y)); + displacement.x = _GenerateDisplacementStrength * (height_x - displacement.y) / ddx(input.positionWS.x); + displacement.z = _GenerateDisplacementStrength * (height_z - displacement.y) / ddy(input.positionWS.z); +#endif #else - displacement.xyz = texSample.xyz * _Strength; + displacement.xyz = texSample.xyz; #endif #if _SSSFROMALPHA_ON sss = texSample.x * _SSSStrength; #endif - return _Weight * half4(displacement, sss); + return _Weight * half4(_Strength * displacement, sss); } ENDCG