124 lines
3.8 KiB
Text
124 lines
3.8 KiB
Text
|
|
Shader "Hidden/Ocean"
|
||
|
|
{
|
||
|
|
Properties
|
||
|
|
{
|
||
|
|
_MainTex ("Texture", 2D) = "white" {}
|
||
|
|
}
|
||
|
|
SubShader
|
||
|
|
{
|
||
|
|
// No culling or depth
|
||
|
|
Cull Off ZWrite Off ZTest Always
|
||
|
|
|
||
|
|
Pass
|
||
|
|
{
|
||
|
|
CGPROGRAM
|
||
|
|
#pragma vertex vert
|
||
|
|
#pragma fragment frag
|
||
|
|
|
||
|
|
#include "UnityCG.cginc"
|
||
|
|
#include "../Includes/Math.cginc"
|
||
|
|
#include "../Includes/Triplanar.cginc"
|
||
|
|
|
||
|
|
struct appdata {
|
||
|
|
float4 vertex : POSITION;
|
||
|
|
float2 uv : TEXCOORD0;
|
||
|
|
};
|
||
|
|
|
||
|
|
struct v2f {
|
||
|
|
float4 pos : SV_POSITION;
|
||
|
|
float2 uv : TEXCOORD0;
|
||
|
|
float3 viewVector : TEXCOORD1;
|
||
|
|
};
|
||
|
|
|
||
|
|
v2f vert (appdata v) {
|
||
|
|
v2f output;
|
||
|
|
output.pos = UnityObjectToClipPos(v.vertex);
|
||
|
|
output.uv = v.uv;
|
||
|
|
// Camera space matches OpenGL convention where cam forward is -z. In unity forward is positive z.
|
||
|
|
// (https://docs.unity3d.com/ScriptReference/Camera-cameraToWorldMatrix.html)
|
||
|
|
float3 viewVector = mul(unity_CameraInvProjection, float4(v.uv * 2 - 1, 0, -1));
|
||
|
|
output.viewVector = mul(unity_CameraToWorld, float4(viewVector,0));
|
||
|
|
return output;
|
||
|
|
}
|
||
|
|
|
||
|
|
float4 colA;
|
||
|
|
float4 colB;
|
||
|
|
float4 specularCol;
|
||
|
|
float depthMultiplier;
|
||
|
|
float alphaMultiplier;
|
||
|
|
float smoothness;
|
||
|
|
|
||
|
|
|
||
|
|
sampler2D waveNormalA;
|
||
|
|
sampler2D waveNormalB;
|
||
|
|
float waveStrength;
|
||
|
|
float waveNormalScale;
|
||
|
|
float waveSpeed;
|
||
|
|
|
||
|
|
sampler2D _MainTex;
|
||
|
|
sampler2D _CameraDepthTexture;
|
||
|
|
float4 params;
|
||
|
|
|
||
|
|
float planetScale;
|
||
|
|
float3 oceanCentre;
|
||
|
|
float oceanRadius;
|
||
|
|
float3 dirToSun;
|
||
|
|
|
||
|
|
fixed4 frag (v2f i) : SV_Target
|
||
|
|
{
|
||
|
|
|
||
|
|
fixed4 originalCol = tex2D(_MainTex, i.uv);
|
||
|
|
|
||
|
|
float3 rayPos = _WorldSpaceCameraPos;
|
||
|
|
float viewLength = length(i.viewVector);
|
||
|
|
float3 rayDir = i.viewVector / viewLength;
|
||
|
|
|
||
|
|
float nonlin_depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv);
|
||
|
|
float sceneDepth = LinearEyeDepth(nonlin_depth) * viewLength;
|
||
|
|
|
||
|
|
float2 hitInfo = raySphere(oceanCentre, oceanRadius, rayPos, rayDir);
|
||
|
|
float dstToOcean = hitInfo.x;
|
||
|
|
float dstThroughOcean = hitInfo.y;
|
||
|
|
float3 rayOceanIntersectPos = rayPos + rayDir * dstToOcean - oceanCentre;
|
||
|
|
|
||
|
|
// dst that view ray travels through ocean (before hitting terrain / exiting ocean)
|
||
|
|
float oceanViewDepth = min(dstThroughOcean, sceneDepth - dstToOcean);
|
||
|
|
|
||
|
|
|
||
|
|
if (oceanViewDepth > 0) {
|
||
|
|
float3 clipPlanePos = rayPos + i.viewVector * _ProjectionParams.y;
|
||
|
|
|
||
|
|
float dstAboveWater = length(clipPlanePos - oceanCentre) - oceanRadius;
|
||
|
|
|
||
|
|
float t = 1 - exp(-oceanViewDepth / planetScale * depthMultiplier);
|
||
|
|
float alpha = 1-exp(-oceanViewDepth / planetScale * alphaMultiplier);
|
||
|
|
float4 oceanCol = lerp(colA, colB, t);
|
||
|
|
|
||
|
|
float3 oceanSphereNormal = normalize(rayOceanIntersectPos);
|
||
|
|
|
||
|
|
float2 waveOffsetA = float2(_Time.x * waveSpeed, _Time.x * waveSpeed * 0.8);
|
||
|
|
float2 waveOffsetB = float2(_Time.x * waveSpeed * - 0.8, _Time.x * waveSpeed * -0.3);
|
||
|
|
float3 waveNormal = triplanarNormal(rayOceanIntersectPos, oceanSphereNormal, waveNormalScale / planetScale, waveOffsetA, waveNormalA);
|
||
|
|
waveNormal = triplanarNormal(rayOceanIntersectPos, waveNormal, waveNormalScale / planetScale, waveOffsetB, waveNormalB);
|
||
|
|
waveNormal = normalize(lerp(oceanSphereNormal, waveNormal, waveStrength));
|
||
|
|
//return float4(oceanNormal * .5 + .5,1);
|
||
|
|
float diffuseLighting = saturate(dot(oceanSphereNormal, dirToSun));
|
||
|
|
float specularAngle = acos(dot(normalize(dirToSun - rayDir), waveNormal));
|
||
|
|
float specularExponent = specularAngle / (1 - smoothness);
|
||
|
|
float specularHighlight = exp(-specularExponent * specularExponent);
|
||
|
|
|
||
|
|
oceanCol *= diffuseLighting;
|
||
|
|
oceanCol += specularHighlight * (dstAboveWater > 0) * specularCol;
|
||
|
|
|
||
|
|
//return float4(oceanSphereNormal,1);
|
||
|
|
float4 finalCol = originalCol * (1-alpha) + oceanCol * alpha;
|
||
|
|
return float4(finalCol.xyz, params.x);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
return originalCol;
|
||
|
|
}
|
||
|
|
ENDCG
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|