Files
beyond/Assets/ThirdParty/Lux URP Essentials/Shaders/Water/Lux URP Water.shader
2024-11-20 15:21:28 +01:00

675 lines
32 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// NOTE: Based on URP Lighting.hlsl which replaced some half3 with floats to avoid lighting artifacts on mobile
Shader "Lux URP/Water"
{
Properties
{
[HeaderHelpLuxURP_URL(pwa0yoxc3z5m)]
[Header(Surface Options)]
[Space(5)]
[Enum(Off,0,On,1)]_ZWrite ("ZWrite", Float) = 1.0
[Enum(UnityEngine.Rendering.CompareFunction)] _ZTest("ZTest", Float) = 4 // "LessEqual"
// [Enum(UnityEngine.Rendering.CullMode)] _Culling ("Culling", Float) = 0
[Enum(UnityEngine.Rendering.BlendMode)] _DstBlend("Dest BlendMode", Float) = 0
[ToggleOff(_RECEIVE_SHADOWS_OFF)]
_ReceiveShadows ("Receive Shadows", Float) = 1.0
[Toggle(ORTHO_SUPPORT)]
_OrthoSpport ("Enable Orthographic Support", Float) = 0
[Header(Surface Inputs)]
[Space(5)]
_BumpMap ("Water Normal Map", 2D) = "bump" {}
_BumpScale ("Normal Scale", Float) = 1.0
[LuxURPVectorTwoDrawer]
_Speed ("Speed (UV)", Vector) = (0.1, 0, 0, 0)
[LuxURPVectorFourDrawer]
_SecondaryTilingSpeedRefractBump("Secondary Bump", Vector) = (2, 2.3, 0.1, 1)
[LuxURPHelpDrawer] _Help ("Tiling (X) Speed (Y) Refraction (Z) Bump Scale (W)", Float) = 1
[Space(5)]
_Smoothness ("Smoothness", Range(0.0, 1.0)) = 0.5
_SpecColor ("Specular", Color) = (0.2, 0.2, 0.2)
[Space(5)]
_EdgeBlend ("Edge Blending", Range(0.1, 10.0)) = 2.0
[Space(5)]
[Toggle(_REFRACTION)]
_EnableRefraction ("Enable Refraction", Float) = 1
_Refraction (" Refraction", Range(0, 1)) = .25
_ReflectionBumpScale ("Reflection Bump Scale", Range(0.1, 1.0)) = 0.3
[Header(Underwater Fog)]
[Space(5)]
_Color ("Fog Color", Color) = (.2,.8,.9,1)
_Density ("Density", Float) = 1.0
[Header(Foam)]
[Space(5)]
[Toggle(_FOAM)] _Foam ("Enable Foam", Float) = 1.0
[NoScaleOffset] _FoamMap ("Foam Albedo (RGB) Mask (A)", 2D) = "bump" {}
_FoamTiling ("Foam Tiling", Float) = 2
[LuxURPVectorTwoDrawer]
_FoamSpeed ("Foam Speed (UV)", Vector) = (0.1, 0, 0, 0)
_FoamScale ("Foam Scale", Float) = 4
_FoamSoftIntersectionFactor ("Foam Edge Blending", Range(0.1, 3.0)) = 0.5
_FoamSlopStrength ("Foam Slope Strength", Range(0.0, 1.0)) = 0.85
_FoamSmoothness ("Foam Smoothness", Range(0.0, 1.0)) = 0.3
[Header(Advanced)]
[Space(5)]
[ToggleOff] _SpecularHighlights ("Enable Specular Highlights", Float) = 1.0
[ToggleOff]
_EnvironmentReflections ("Environment Reflections", Float) = 1.0
}
SubShader
{
Tags
{
"RenderPipeline" = "UniversalPipeline"
"RenderType"="Transparent"
"Queue"="Transparent"
}
LOD 300
Pass
{
Tags {"LightMode" = "UniversalForward"}
// Blend SrcAlpha OneMinusSrcAlpha
Blend One [_DstBlend]
Cull Back
ZTest [_ZTest]
ZWrite [_ZWrite]
HLSLPROGRAM
// Required to compile gles 2.0 with standard srp library
#pragma prefer_hlslcc gles
#pragma exclude_renderers d3d11_9x
#pragma target 2.0
// -------------------------------------
// Lightweight Pipeline keywords
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
#pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS
#pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS
#pragma multi_compile _ _SHADOWS_SOFT
#pragma multi_compile _ _MIXED_LIGHTING_SUBTRACTIVE
#pragma shader_feature _SPECULARHIGHLIGHTS_OFF
#pragma shader_feature _ENVIRONMENTREFLECTIONS_OFF
#pragma shader_feature _RECEIVE_SHADOWS_OFF
#pragma shader_feature_local _FOAM
#pragma shader_feature_local ORTHO_SUPPORT
#pragma shader_feature_local _REFRACTION
// #define _ADDITIONAL_LIGHTS_VERTEX
// -------------------------------------
// Unity defined keywords
#pragma multi_compile _ DIRLIGHTMAP_COMBINED
#pragma multi_compile _ LIGHTMAP_ON
#pragma multi_compile_fog
//--------------------------------------
// GPU Instancing
#pragma multi_compile_instancing
#define _SPECULAR_SETUP 1
#define _NORMALMAP 1
#pragma vertex vert
#pragma fragment frag
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
// defines a bunch of helper functions (like lerpwhiteto)
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl"
// defines SurfaceData, textures and the functions Alpha, SampleAlbedoAlpha, SampleNormal, SampleEmission
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/SurfaceInput.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/UnityInstancing.hlsl"
struct VertexInput
{
float4 positionOS : POSITION;
float3 normalOS : NORMAL;
float4 tangentOS : TANGENT;
float2 texcoord : TEXCOORD0;
float2 lightmapUV : TEXCOORD1;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct VertexOutput
{
float4 positionCS : SV_POSITION;
float4 uv : TEXCOORD0; // xy textccord, zw water
DECLARE_LIGHTMAP_OR_SH(lightmapUV, vertexSH, 1);
float3 positionWS : TEXCOORD2;
#ifdef _NORMALMAP
half4 normalWS : TEXCOORD3; // xyz: normal, w: viewDir.x
half4 tangentWS : TEXCOORD4; // xyz: tangent, w: viewDir.y
half4 bitangentWS : TEXCOORD5; // xyz: bitangent, w: viewDir.z
#else
half3 normalWS : TEXCOORD3;
half3 viewDirWS : TEXCOORD4;
#endif
half4 fogFactorAndVertexLight : TEXCOORD6; // x: fogFactor, yzw: vertex light
#if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR)
float4 shadowCoord : TEXCOORD7;
#endif
UNITY_VERTEX_INPUT_INSTANCE_ID
UNITY_VERTEX_OUTPUT_STEREO
};
CBUFFER_START(UnityPerMaterial)
float _Alpha;
half3 _SpecColor;
half _Smoothness;
half _EdgeBlend;
float2 _Speed;
half _BumpScale;
float4 _SecondaryTilingSpeedRefractBump;
half4 _Color;
half _Density;
half _FresnelPower;
half _Refraction;
half _ReflectionBumpScale;
half _FoamScale;
half _FoamTiling;
half2 _FoamSpeed;
half _FoamSoftIntersectionFactor;
half _FoamSlopStrength;
half _FoamSmoothness;
float4 _BumpMap_ST;
CBUFFER_END
// Defined in SurfaceInput.hlsl
// TEXTURE2D(_BaseMap); SAMPLER(sampler_BaseMap);
#if defined(SHADER_API_GLES)
TEXTURE2D(_CameraDepthTexture); SAMPLER(sampler_CameraDepthTexture);
//TEXTURE2D(_CameraOpaqueTexture); SAMPLER(sampler_CameraOpaqueTexture);
#else
// URP 7.1.5.
TEXTURE2D_X_FLOAT(_CameraDepthTexture);
//SAMPLER(sampler_PointClamp); // Using Load means no sampling or filtering anyway
#endif
TEXTURE2D_X(_CameraOpaqueTexture);
SAMPLER(sampler_LinearClamp);
SAMPLER(sampler_PointClamp);
float4 _CameraDepthTexture_TexelSize;
float4 _CameraOpaqueTexture_TexelSize;
float4 _CameraOpaqueTexture_ST;
TEXTURE2D(_FoamMap); SAMPLER(sampler_FoamMap); float4 _FoamMap_TexelSize;
VertexOutput vert (VertexInput input)
{
VertexOutput output = (VertexOutput)0;
UNITY_SETUP_INSTANCE_ID(input);
UNITY_TRANSFER_INSTANCE_ID(input, output);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
//o.positionWS = TransformObjectToWorld(input.positionOS.xyz); // mul(UNITY_MATRIX_M, input.vertex).xyz;
//o.positionCS = TransformWorldToHClip(o.positionWS.xyz); // TransformObjectToHClip(input.positionOS.xyz);
VertexPositionInputs vertexInput = GetVertexPositionInputs(input.positionOS.xyz);
output.positionWS = vertexInput.positionWS;
output.positionCS = vertexInput.positionCS;
VertexNormalInputs normalInput = GetVertexNormalInputs(input.normalOS, input.tangentOS);
#if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR)
output.shadowCoord = GetShadowCoord(vertexInput);
#endif
#ifdef _NORMALMAP
float3 viewDirWS = GetCameraPositionWS() - output.positionWS;
output.normalWS = half4(normalInput.normalWS, viewDirWS.x);
output.tangentWS = half4(normalInput.tangentWS, viewDirWS.y);
output.bitangentWS = half4(normalInput.bitangentWS, viewDirWS.z);
#else
output.normalWS.xyz = NormalizeNormalPerVertex(normalInput.normalWS);
output.viewDirWS = GetCameraPositionWS() - o.positionWS;
#endif
half fogFactor = ComputeFogFactor(output.positionCS.z);
half3 vertexLight = VertexLighting(output.positionWS, output.normalWS.xyz);
OUTPUT_LIGHTMAP_UV(input.lightmapUV, unity_LightmapST, output.lightmapUV);
OUTPUT_SH(output.normalWS.xyz, output.vertexSH);
output.fogFactorAndVertexLight = half4(fogFactor, vertexLight);
output.uv.xy = TRANSFORM_TEX(input.texcoord, _BumpMap) + _Time.xx * _Speed;
// Water
// see: ComputeGrabScreenPos
float4 screenUV = ComputeScreenPos(output.positionCS);
output.uv.zw = screenUV.xy; //waterDepth.xx;
return output;
}
// ------------------------------------------------------------------
// Helper functions to handle orthographic / perspective projection
inline float GetOrthoDepthFromZBuffer (float rawDepth) {
#if defined(UNITY_REVERSED_Z)
// Needed to handle openGL
#if UNITY_REVERSED_Z == 1
rawDepth = 1.0f - rawDepth;
#endif
#endif
return lerp(_ProjectionParams.y, _ProjectionParams.z, rawDepth);
}
inline float GetProperEyeDepth (float rawDepth) {
#if defined(ORTHO_SUPPORT)
float perspectiveSceneDepth = LinearEyeDepth(rawDepth, _ZBufferParams);
float orthoSceneDepth = GetOrthoDepthFromZBuffer(rawDepth);
return lerp(perspectiveSceneDepth, orthoSceneDepth, unity_OrthoParams.w);
#else
return LinearEyeDepth(rawDepth, _ZBufferParams);
#endif
}
half4 frag (VertexOutput input) : SV_Target
{
UNITY_SETUP_INSTANCE_ID(input);
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
//half3 albedo = 0;
//half metallic = 0;
half3 specular = _SpecColor;
half smoothness = _Smoothness;
half occlusion = 1;
half emission = 0;
half alpha = 1;
half3 normalTS = half3(0,0,1);
half3 refraction = 0;
#if defined(ORTHO_SUPPORT)
float surfaceEyeDepth = GetProperEyeDepth(input.positionCS.z); // LinearEyeDepth(input.positionCS.z, _ZBufferParams);
#else
float surfaceEyeDepth = input.positionCS.w;
#endif
// We have to reset i.grabUV.w as otherwise texture projection does not work
#if defined(ORTHO_SUPPORT)
input.positionCS.w = lerp(input.positionCS.w, 1.0f, unity_OrthoParams.w);
#endif
float2 screenUV = input.uv.zw / input.positionCS.w;
// Fix screenUV for Single Pass Stereo Rendering
#if defined(UNITY_SINGLE_PASS_STEREO)
screenUV.xy = UnityStereoTransformScreenSpaceTex(screenUV.xy);
#endif
half4 normalSample = SAMPLE_TEXTURE2D(_BumpMap, sampler_BumpMap, input.uv.xy);
// ////////////
// Get the normals
#if BUMP_SCALE_NOT_SUPPORTED
normalTS = UnpackNormal(normalSample);
normalSample = SAMPLE_TEXTURE2D(_BumpMap, sampler_BumpMap, input.uv.xy * _SecondaryTilingSpeedRefractBump.x + _Time.xx * _Speed * _SecondaryTilingSpeedRefractBump.y + normalTS.xz * _SecondaryTilingSpeedRefractBump.z );
half3 detailNormal = UnpackNormal(normalSample);
normalTS = normalize(half3(normalTS.xy + detailNormal.xy, normalTS.z * detailNormal.z));
#else
normalTS = UnpackNormalScale(normalSample, _BumpScale);
normalSample = SAMPLE_TEXTURE2D(_BumpMap, sampler_BumpMap, input.uv.xy * _SecondaryTilingSpeedRefractBump.x + _Time.xx * _Speed * _SecondaryTilingSpeedRefractBump.y + normalTS.xz * _SecondaryTilingSpeedRefractBump.z );
half3 detailNormal = UnpackNormalScale(normalSample, _SecondaryTilingSpeedRefractBump.w);
normalTS = normalize(half3(normalTS.xy + detailNormal.xy, normalTS.z * detailNormal.z));
#endif
// World space normal - as we need it for view space normal (skipped)
half3 normalWS = TransformTangentToWorld(normalTS, half3x3(input.tangentWS.xyz, input.bitangentWS.xyz, input.normalWS.xyz));
normalWS = NormalizeNormalPerPixel(normalWS);
// ////////////
// Refraction
// Skipped view space normal and went with tangent space instead
//half3 viewNormal = mul((float3x3)GetWorldToHClipMatrix(), -normalWS).xyz;
//float2 offset = viewNormal.xz * _Refraction;
float distanceFadeFactor = input.positionCS.z * _ZBufferParams.z;
// OpenGL Core
#if UNITY_REVERSED_Z != 1
distanceFadeFactor = input.positionCS.z / input.positionCS.w;
#endif
// Somehow handle orthographic projection
#if defined(ORTHO_SUPPORT)
distanceFadeFactor = (unity_OrthoParams.w) ? 1.0f / unity_OrthoParams.x : distanceFadeFactor;
#endif
#if defined(_REFRACTION)
float2 offset = normalTS.xy * _Refraction * distanceFadeFactor;
#else
float2 offset = 0;
#endif
// URP 7.1.5.: We have to use saturate(screenUV + offset) and saturate(offset)
// GLES 2.0 does not support LOAD_TEXTURE2D_X. LOAD_TEXTURE2D_X does not clamp even if we use saturate? * 0.9999f solves this.
#if defined(SHADER_API_GLES)
float refractedSceneDepth = SAMPLE_DEPTH_TEXTURE_LOD(_CameraDepthTexture, sampler_CameraDepthTexture, screenUV + offset, 0);
#else
float refractedSceneDepth = LOAD_TEXTURE2D_X(_CameraDepthTexture, _CameraDepthTexture_TexelSize.zw * saturate(screenUV + offset) * 0.9999f ).x;
//float refractedSceneDepth = SAMPLE_TEXTURE2D_X(_CameraDepthTexture, sampler_PointClamp, saturate(screenUV + offset)).x;
#endif
refractedSceneDepth = GetProperEyeDepth(refractedSceneDepth);
float viewDepth = refractedSceneDepth - surfaceEyeDepth;
// Do not refract pixel of the foreground
#if defined(_REFRACTION)
offset = screenUV + offset * saturate(viewDepth);
#if defined(SHADER_API_GLES)
refractedSceneDepth = SAMPLE_DEPTH_TEXTURE_LOD(_CameraDepthTexture, sampler_CameraDepthTexture, offset, 0);
#else
refractedSceneDepth = LOAD_TEXTURE2D_X(_CameraDepthTexture, (_CameraDepthTexture_TexelSize.zw * saturate(offset) * 0.9999f )).x;
//refractedSceneDepth = SAMPLE_TEXTURE2D_X(_CameraDepthTexture, sampler_PointClamp, saturate(offset)).x;
#endif
refractedSceneDepth = GetProperEyeDepth(refractedSceneDepth);
refraction = SAMPLE_TEXTURE2D_X(_CameraOpaqueTexture, sampler_LinearClamp, saturate(offset)).rgb;
viewDepth = refractedSceneDepth - surfaceEyeDepth;
// In case we use HDR refraction may get way too bright.
refraction = saturate(refraction);
#endif
// Final blend value
alpha = saturate ( _EdgeBlend * viewDepth );
// ////////////
// Underwater fog
// Calculate Attenuation along viewDirection
float viewAtten = saturate( 1.0 - exp( -viewDepth * _Density) );
float underwaterFogDensity = viewAtten;
// ////////////
// Foam
#if defined(_FOAM)
/*
// We might do a 3rd unrefracted sample here - but it indroduces some kind of ghosting.
#if defined(SHADER_API_GLES)
refractedSceneDepth = SAMPLE_DEPTH_TEXTURE_LOD(_CameraDepthTexture, sampler_CameraDepthTexture, screenUV, 0);
#else
refractedSceneDepth = LOAD_TEXTURE2D_X(_CameraDepthTexture, _CameraDepthTexture_TexelSize.zw * screenUV).x;
#endif
refractedSceneDepth = GetProperEyeDepth(refractedSceneDepth);
viewDepth = refractedSceneDepth - surfaceEyeDepth;
*/
half FoamSoftIntersection = saturate( _FoamSoftIntersectionFactor * (viewDepth ));
half FoamThreshold = normalTS.z * 2 - 1;
// Get shoreline foam mask
float shorelineFoam = saturate(-FoamSoftIntersection * (1 + FoamThreshold) + 1 );
shorelineFoam = shorelineFoam * saturate(1 * FoamSoftIntersection - FoamSoftIntersection * FoamSoftIntersection );
half4 rawFoamSample = SAMPLE_TEXTURE2D(_FoamMap, sampler_FoamMap, input.uv.xy * _FoamTiling + normalTS.xy * 0.02 + _Time.xx * _FoamSpeed);
// Add foam on slopes
shorelineFoam += saturate(1 - input.normalWS.y) * _FoamSlopStrength;
// Combine sample and distribution(shorelineFoam)
rawFoamSample.a = saturate(rawFoamSample.a * shorelineFoam * _FoamScale * ( 1 - (normalTS.x + normalTS.y) * 4) );
// Errode foam
rawFoamSample.a = rawFoamSample.a * smoothstep( 0.8 - rawFoamSample.a, 1.6 - rawFoamSample.a, rawFoamSample.a );
// Adjust smoothess to foam
smoothness = lerp(smoothness, _FoamSmoothness, rawFoamSample.a);
#endif
// ////////////
// Transfer all to world space and prepare inputData (for convenience)
InputData inputData = (InputData)0;
inputData.positionWS = input.positionWS;
#ifdef _NORMALMAP
inputData.normalWS = normalWS;
inputData.viewDirectionWS = SafeNormalize( float3(input.normalWS.w, input.tangentWS.w, input.bitangentWS.w) );
#else
inputData.normalWS = input.normalWS.xyz; // no normal map
inputData.viewDirectionWS = SafeNormalize(input.viewDirWS);
#endif
// Refract shadows / * input.positionCS.w because unity will divide
/*
#if defined(_MAIN_LIGHT_SHADOWS)
#if SHADOWS_SCREEN
#if defined(_REFRACTION)
inputData.shadowCoord = float4(offset * input.positionCS.w, input.shadowCoord.zw);
#else
inputData.shadowCoord = float4(screenUV * input.positionCS.w, input.shadowCoord.zw);
#endif
#else
inputData.shadowCoord = input.shadowCoord;
#endif
#else
inputData.shadowCoord = float4(0, 0, 0, 0);
#endif
*/
// No refracted shadows any more...
#if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR)
inputData.shadowCoord = input.shadowCoord;
#elif defined(MAIN_LIGHT_CALCULATE_SHADOWS)
inputData.shadowCoord = TransformWorldToShadowCoord(inputData.positionWS);
#else
inputData.shadowCoord = float4(0, 0, 0, 0);
#endif
// Fix shadowCoord for Single Pass Stereo Rendering
#if defined(UNITY_SINGLE_PASS_STEREO)
#if SHADOWS_SCREEN
// Shadows perform : UnityStereoTransformScreenSpaceTex(shadowCoord.xy) after perspective division;
// We do it manually:
inputData.shadowCoord.xy = inputData.shadowCoord.xy / inputData.shadowCoord.w;
inputData.shadowCoord.w = 1.0f;
// inputData.shadowCoord.x = screenUV.x;
// Then we reset shadowCoord.w and unity_StereoScaleOffset so it does not get applied twice
unity_StereoScaleOffset[0] = float4(1,1,0,0);
unity_StereoScaleOffset[1] = float4(1,1,0,0);
#endif
#endif
inputData.fogCoord = input.fogFactorAndVertexLight.x;
inputData.vertexLighting = input.fogFactorAndVertexLight.yzw;
inputData.bakedGI = SAMPLE_GI(input.lightmapUV, input.vertexSH, inputData.normalWS);
// /////////
// Apply lighting
half4 color = 1;
half3 origRefraction = refraction;
// Get fog
real fogFactor = input.fogFactorAndVertexLight.x;
#if defined(FOG_LINEAR) || defined(FOG_EXP) || defined(FOG_EXP2)
#if defined(FOG_EXP)
fogFactor = saturate(exp2(-fogFactor));
#elif defined(FOG_EXP2)
fogFactor = saturate(exp2(-fogFactor*fogFactor));
#endif
#endif
// Prepare missing Inputs
half reflectivity = ReflectivitySpecular(specular);
half oneMinusReflectivity = 1.0 - reflectivity;
half perceptualRoughness = PerceptualSmoothnessToPerceptualRoughness(smoothness);
half roughness = PerceptualRoughnessToRoughness(perceptualRoughness);
half roughness2 = roughness * roughness;
half normalizationTerm = roughness * 4.0h + 2.0h;
// Get light
Light mainLight = GetMainLight(inputData.shadowCoord);
half3 lightColorAndAttenuation = mainLight.color * (mainLight.distanceAttenuation * mainLight.shadowAttenuation);
half3 shad = lightColorAndAttenuation;
MixRealtimeAndBakedGI(mainLight, inputData.normalWS, inputData.bakedGI, half4(0, 0, 0, 0));
#ifdef _ADDITIONAL_LIGHTS
int pixelLightCount = GetAdditionalLightsCount();
#endif
half NdotL = saturate(dot( inputData.normalWS, mainLight.direction));
half3 VertexAndGILighting = input.fogFactorAndVertexLight.yzw + inputData.bakedGI;
// Diffuse underwater lighting
half diffuse_nl = saturate(dot(half3(0,1,0), mainLight.direction));
//half3 diffuseUnderwaterLighting = _Color * (lightColorAndAttenuation * diffuse_nl + VertexAndGILighting);
// Shadows are sampled at the bottom surface. So we attenuate them by underwaterFogDensity. Just a hack but it looks better than not doing anything here.
half3 diffuseUnderwaterLighting = _Color.rgb * (VertexAndGILighting + (diffuse_nl *
mainLight.color * mainLight.distanceAttenuation *
lerp( mainLight.shadowAttenuation, 1 , underwaterFogDensity )
)
);
// Add foam
#if defined(_FOAM)
half3 foamLighting = rawFoamSample.rgb * (lightColorAndAttenuation * NdotL + VertexAndGILighting);
#endif
// Specular Lighting
half3 specularLighting = 0;
#if !defined(_SPECULARHIGHLIGHTS_OFF)
float3 halfDir = SafeNormalize(float3(mainLight.direction) + float3(inputData.viewDirectionWS));
float NoH = saturate(dot(inputData.normalWS, halfDir));
half LoH = saturate(dot(mainLight.direction, halfDir));
float d = NoH * NoH * (roughness2 - 1.h) + 1.0001f;
half LoH2 = LoH * LoH;
half specularTerm = roughness2 / ((d * d) * max(0.1h, LoH2) * normalizationTerm );
#if defined (SHADER_API_MOBILE)
specularTerm = specularTerm - HALF_MIN;
specularTerm = clamp(specularTerm, 0.0, 100.0); // Prevent FP16 overflow on mobiles
#endif
specularLighting = specularTerm * specular * lightColorAndAttenuation;
specularLighting *= NdotL;
#endif
#ifdef _ADDITIONAL_LIGHTS
for (int i = 0; i < pixelLightCount; ++i) {
Light light = GetAdditionalLight(i, inputData.positionWS);
NdotL = saturate(dot(inputData.normalWS, light.direction));
diffuse_nl = saturate(dot(half3(0,1,0), light.direction));
half3 addLightColorAndAttenuation = light.color * light.distanceAttenuation * light.shadowAttenuation;
diffuseUnderwaterLighting += _Color.rgb * addLightColorAndAttenuation * diffuse_nl;
#if defined(_FOAM)
foamLighting += rawFoamSample.rgb * addLightColorAndAttenuation * NdotL;
#endif
#if !defined(_SPECULARHIGHLIGHTS_OFF)
halfDir = SafeNormalize(float3(light.direction) + float3(inputData.viewDirectionWS));
NoH = saturate(dot(inputData.normalWS, halfDir));
LoH = saturate(dot(light.direction, halfDir));
d = NoH * NoH * (roughness2 - 1.h) + 1.0001f;
LoH2 = LoH * LoH;
specularTerm = roughness2 / ((d * d) * max(0.1h, LoH2) * normalizationTerm );
#if defined (SHADER_API_MOBILE)
specularTerm = specularTerm - HALF_MIN;
specularTerm = clamp(specularTerm, 0.0, 100.0); // Prevent FP16 overflow on mobiles
#endif
specularLighting += specularTerm * specular * addLightColorAndAttenuation;
#endif
}
#endif
// Fog - diffuseUnderwaterLighting
#if defined(FOG_LINEAR) || defined(FOG_EXP) || defined(FOG_EXP2)
#if defined(_REFRACTION)
diffuseUnderwaterLighting = lerp(unity_FogColor.rgb, diffuseUnderwaterLighting, fogFactor);
#endif
#endif
// Add underwater fog
#if defined(_REFRACTION)
refraction.rgb = lerp(refraction.rgb, diffuseUnderwaterLighting, underwaterFogDensity);
#else
// Handle transparent mode
refraction.rgb = diffuseUnderwaterLighting * underwaterFogDensity; // premul
#endif
// Fog foam
#if defined(_FOAM) && defined(_REFRACTION)
#if defined(FOG_LINEAR) || defined(FOG_EXP) || defined(FOG_EXP2)
foamLighting = lerp(unity_FogColor.rgb, foamLighting, fogFactor);
#endif
#endif
// Reflections
#if !defined(_ENVIRONMENTREFLECTIONS_OFF)
// Calculate smoothedReflectionNormal
half3 reflectionNormal = lerp( input.normalWS.xyz, inputData.normalWS, _ReflectionBumpScale);
half3 reflectionVector = reflect(-inputData.viewDirectionWS, reflectionNormal);
half fresnelTerm = Pow4(1.0 - saturate(dot(inputData.normalWS, inputData.viewDirectionWS)));
half3 reflections = GlossyEnvironmentReflection(reflectionVector, perceptualRoughness, occlusion);
float surfaceReduction = 1.0 / (roughness2 + 1.0);
half grazingTerm = saturate(smoothness + reflectivity);
reflections = reflections * surfaceReduction * lerp(specular, grazingTerm, fresnelTerm);
// Combine specular lighting and reflections
specularLighting += reflections;
#endif
#if !defined(_SPECULARHIGHLIGHTS_OFF) || !defined(_ENVIRONMENTREFLECTIONS_OFF)
#if defined(FOG_LINEAR) || defined(FOG_EXP) || defined(FOG_EXP2)
// "Apply" fog
#if defined(_REFRACTION)
specularLighting *= fogFactor;
#endif
#endif
#endif
// Combine all
color.rgb = refraction.rgb;
#if defined(_FOAM)
color.rgb = lerp(color.rgb, foamLighting, rawFoamSample.a );
#endif
#if !defined(_SPECULARHIGHLIGHTS_OFF) || !defined(_ENVIRONMENTREFLECTIONS_OFF)
color.rgb += specularLighting;
#endif
// Soft edge blending
#if defined(_REFRACTION)
color.rgb = lerp(origRefraction, color.rgb, alpha.xxx );
#else
// Transparent mode
#if defined(_FOAM)
float visibility = saturate(underwaterFogDensity + rawFoamSample.a) * oneMinusReflectivity + reflectivity;
#else
float visibility = underwaterFogDensity * oneMinusReflectivity + reflectivity;
#endif
#if defined(FOG_LINEAR) || defined(FOG_EXP) || defined(FOG_EXP2)
color.rgb = lerp(unity_FogColor.rgb * visibility, color.rgb, fogFactor );
#endif
color.rgb *= alpha;
color.a = alpha * visibility;
#endif
//color.rgb = shad;
//color.rgb = refractedSceneDepth;
//color.rgb = surfaceEyeDepth;
//color.rgb = viewDepth;
return color;
}
ENDHLSL
}
}
}