Aetheria/Assets/Plugins/Celestial Body/Scripts/Shaders/PostProcessing/OceanEffect.shader

124 lines
3.8 KiB
Text
Raw Normal View History

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
}
}
}