Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Shader "Custom/Waves" {
- Properties {
- _Color("Color", Color) = (1,1,1,1)
- _GradientMap ("Gradient Map", 2D) = "white" {}
- _MainTex ("Albedo (RGB)", 2D) = "white" {}
- _DistortTex ("Distortion (displacement)", 2D) = "white" {}
- _DistortScale("Distortion Scale", Range(-100, 100)) = 100
- // Red is the amount of Y variance in the vertex position.
- // Blue is the amount by which the color is pushed towards white.
- _WaterInteractionTex ("Object interaction", 2D) = "white" {}
- _WaterInteractionScale ("Interaction scale factor", Range(-100, 100)) = 10
- _Glossiness ("Smoothness", Range(0,1)) = 0.5
- _Metallic ("Metallic", Range(0,1)) = 0.0
- _WaveA ("Wave A (dir, steepness, wavelength)", Vector) = (1,0,0.5,10)
- _WaveB ("Wave B", Vector) = (0,1,0.25,20)
- _WaveC ("Wave C", Vector) = (1,1,0.15,10)
- _WaveSpeed ("Wave scroll speed factor", Range(0,1)) = .5
- _MaxTessellationDistance("Max tessellation distance", float) = 100
- _Tessellation("Tessellation", Range(1.0, 128.0)) = 1.0
- }
- SubShader {
- Tags { "RenderType"="Opaque" }
- LOD 200
- CGPROGRAM
- #pragma surface surf Standard fullforwardshadows vertex:vert tessellate:tessDistance addshadow
- #include "Tessellation.cginc"
- #pragma require tessellation tessHW
- #pragma target 4.6
- sampler2D _MainTex;
- sampler2D _DistortTex;
- float4 _DistortTex_ST;
- float _DistortScale;
- sampler2D _WaterInteractionTex;
- float _WaterInteractionScale;
- sampler2D _GradientMap;
- float3 _InteractorPosition;
- uniform float _OrthographicCamSize;
- struct Input {
- float2 uv_MainTex;
- float3 worldPos;
- // HACK: we override the alpha channel to be the amount we push the color towards white.
- float4 color : COLOR;
- };
- half _Glossiness;
- half _Metallic;
- float _WaveSpeed;
- fixed4 _Color;
- float4 _WaveA, _WaveB, _WaveC;
- float _MaxTessellationDistance;
- float _Tessellation;
- float4 tessDistance (appdata_full v0, appdata_full v1, appdata_full v2) {
- float minDist = 10.0;
- float maxDist = _MaxTessellationDistance;
- return UnityDistanceBasedTess(v0.vertex, v1.vertex, v2.vertex, minDist, maxDist, _Tessellation);
- }
- float3 GerstnerWave (
- float4 wave, float3 p, inout float3 tangent, inout float3 binormal
- ) {
- float steepness = wave.z;
- float wavelength = wave.w;
- float k = 2 * UNITY_PI / wavelength;
- float c = sqrt(9.8 / k);
- float2 d = normalize(wave.xy);
- float f = k * (dot(d, p.xz) - c * _Time.y * _WaveSpeed);
- float a = steepness / k;
- tangent += float3(
- -d.x * d.x * (steepness * sin(f)),
- d.x * (steepness * cos(f)),
- -d.x * d.y * (steepness * sin(f))
- );
- binormal += float3(
- -d.x * d.y * (steepness * sin(f)),
- d.y * (steepness * cos(f)),
- -d.y * d.y * (steepness * sin(f))
- );
- return float3(
- d.x * (a * cos(f)),
- a * sin(f),
- d.y * (a * cos(f))
- );
- }
- float scaleRipple(float2 rippleUV) {
- // Fade out ripples based on distance from center of the render texture,
- // so there aren't weird behaviors when we hit the edges (and values get clamped)
- float dx = 2 * (rippleUV.x - .5); // Range -1 to 1
- float dy = 2 * (rippleUV.y - .5); // Range -1 to 1
- float distSq = (dx * dx) + (dy * dy); // Range 0-2
- float rippleScale = saturate(1 - sqrt(distSq)); // Range 0-1
- return rippleScale;
- }
- void vert(inout appdata_full vertexData){
- float3 tangent = float3(1, 0, 0);
- float3 binormal = float3(0, 0, 1);
- // Use world position coordinates for the wave calculations
- // so that our ocean tiles tile smoothly.
- float3 worldPos = mul(unity_ObjectToWorld, vertexData.vertex).xyz;
- // Distort the world position using some noise, to break up the
- // waves a bit.
- float4 worldOffset = tex2Dlod(_DistortTex, vertexData.texcoord1) * _DistortScale;
- float3 offsetWorldPos = worldPos;
- offsetWorldPos.xz += float2(worldOffset.x, worldOffset.y);
- float3 offset = float3(0, 0, 0);
- offset += GerstnerWave(_WaveA, offsetWorldPos, tangent, binormal);
- offset += GerstnerWave(_WaveB, offsetWorldPos, tangent, binormal);
- offset += GerstnerWave(_WaveC, offsetWorldPos, tangent, binormal);
- // Scale down wave size when they're further from the camera.
- float scale = distance(_WorldSpaceCameraPos.xyz, worldPos);
- /// Distance < 100 -> scale = 1. Distance = 1100 -> scale = 0.
- scale = saturate((1100 - scale) / 1000);
- float3 p = vertexData.vertex.xyz + offset * scale;
- // Apply distortions from the _WaterInteractionTex. Red is vertical
- // displacement, blue is how much we push the color towards white.
- // Adjust vertical portion of vertex position based on nearby objects
- // See https://www.patreon.com/posts/24192529
- float4 rippleUV = float4(0, 0, 0, 0);
- rippleUV.xy += (worldPos.xz - _InteractorPosition.xz) / (_OrthographicCamSize * 2) + .5;
- float4 rippleSample = tex2Dlod(_WaterInteractionTex, rippleUV);
- rippleSample *= scaleRipple(rippleUV);
- float rippleY = rippleSample.r * _WaterInteractionScale;
- p.y += rippleY;
- vertexData.normal = normalize(cross(binormal, tangent));
- vertexData.vertex.xyz = p;
- // Brightest colors only come from ripple effects.
- vertexData.color = _Color * saturate(.5 + rippleY / _WaterInteractionScale);
- // Push color towards white based on the blue channel of the ripple texture.
- // See HACK note in the struct definition.
- vertexData.color.a = rippleSample.b;
- }
- void surf (Input IN, inout SurfaceOutputStandard o) {
- // Arbitrary fiddle factor to make things look decent.
- float depth = 1 - (IN.worldPos.y / 400);
- fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * tex2D(_GradientMap, float2(depth, 0)) * IN.color;
- // See HACK note in the Input struct definition.
- c = saturate(c + float4(1,1,1,1) * IN.color.a * 3);
- c.a = 1;
- o.Albedo = c.rgb;
- o.Metallic = _Metallic;
- o.Smoothness = _Glossiness;
- o.Alpha = c.a;
- }
- ENDCG
- }
- FallBack "Diffuse"
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement