Files
AIC-Project/Client/Assets/Game/shader/SGame/Base/DynamicSkyTOD_Base.hlsl
T

403 lines
17 KiB
HLSL

#ifndef TOD_BASE_INCLUDED
#define TOD_BASE_INCLUDED
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/SurfaceInput.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
TEXTURE2D(_MainTex); SAMPLER(sampler_MainTex);
TEXTURE2D(_CloudMainTex); SAMPLER(sampler_CloudMainTex);
TEXTURE2D(TOD_BayerTexture); SAMPLER(samplerTOD_BayerTexture);
TEXTURE2D(TOD_CloudTexture); SAMPLER(samplerTOD_CloudTexture);
TEXTURE2D(TOD_CloudAlphaTexture); SAMPLER(samplerTOD_CloudAlphaTexture);
TEXTURECUBE(_CubeTex); SAMPLER(sampler_CubeTex);
CBUFFER_START(UnityPerMaterial_TOD)
float _CubeBrightness;
half4 _MainTex_ST; half4 _TintColor;
half4 _CloudMainTex_ST; half4 _CloudTintColor; half _CloudBrightness;
half4x4 TOD_World2Sky, TOD_Sky2World, TOD_World2CloudCameraProjMatrix;
half3 TOD_SunLightColor, TOD_MoonLightColor, TOD_SunSkyColor, TOD_MoonSkyColor;
half3 TOD_SunMeshColor, TOD_MoonMeshColor, TOD_SunCloudColor, TOD_MoonCloudColor;
half3 TOD_FogColor, TOD_GroundColor, TOD_AmbientColor;
half3 TOD_SunDirection, TOD_MoonDirection, TOD_LightDirection;
half3 TOD_LocalSunDirection, TOD_LocalMoonDirection, TOD_LocalLightDirection;
half TOD_Contrast, TOD_Brightness, TOD_Fogginess;
half TOD_MoonHaloPower; half3 TOD_MoonHaloColor;
half TOD_CloudOpacity, TOD_CloudCoverage, TOD_CloudSharpness, TOD_CloudDensity, TOD_CloudColoring,
TOD_CloudAttenuation, TOD_CloudSaturation, TOD_CloudScattering, TOD_CloudBrightness;
half3 TOD_CloudOffset, TOD_CloudWind, TOD_CloudSize;
half TOD_CloudShadowCutoff, TOD_CloudShadowFade, TOD_CloudShadowIntensity;
half TOD_StarSize, TOD_StarBrightness, TOD_StarVisibility;
half TOD_SunMeshContrast, TOD_SunMeshBrightness;
half TOD_MoonMeshContrast, TOD_MoonMeshBrightness;
half3 TOD_ScatterDensity, TOD_kBetaMie;
half4 TOD_kSun, TOD_k4PI, TOD_kRadius, TOD_kScale;
half3 TOD_SunWorldPos, TOD_HeroWorldPos;
half TOD_IsDay;
half4 _SG_VirtualScatterLightColor; half _SG_AtmosphereFogDensityFactor;
CBUFFER_END
// Vertex transform used by the entire sky dome
#if UNITY_VERSION >= 540
#define TOD_TRANSFORM_VERT(vert) UnityObjectToClipPos(vert)
#else
#define TOD_TRANSFORM_VERT(vert) UnityObjectToClipPos(vert)
#endif
#define TOD_ROTATION_UV(angle) half2x2(cos(angle), -sin(angle), sin(angle), cos(angle)) // UV rotation matrix constructor
#define TOD_HDR2LDR(color) (1.0 - exp2(-TOD_Brightness * color)) // Fast and simple tonemapping
#define TOD_GAMMA2LINEAR(color) (color * color) // Approximates gamma by 2.0 instead of 2.2
#define TOD_LINEAR2GAMMA(color) sqrt(color)
#if UNITY_VERSION >= 540 // Matrices
#define TOD_Object2World unity_ObjectToWorld
#define TOD_World2Object unity_WorldToObject
#else
#define TOD_Object2World unity_ObjectToWorld
#define TOD_World2Object unity_WorldToObject
#endif
#if UNITY_VERSION >= 540 // Screen space adjust
#define TOD_UV(x, y) UnityStereoScreenSpaceUVAdjust(x, y)
#else
#define TOD_UV(x, y) x
#endif
#if UNITY_VERSION >= 540 // Stereo output
#define TOD_VERTEX_OUTPUT_STEREO UNITY_VERTEX_OUTPUT_STEREO
#define TOD_INITIALIZE_VERTEX_OUTPUT_STEREO(o) UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o)
#else
#define TOD_VERTEX_OUTPUT_STEREO
#define TOD_INITIALIZE_VERTEX_OUTPUT_STEREO(o)
#endif
#if UNITY_VERSION >= 540 // Instancing
#define TOD_INSTANCE_ID UNITY_VERTEX_INPUT_INSTANCE_ID
#define TOD_SETUP_INSTANCE_ID(o) UNITY_SETUP_INSTANCE_ID(o)
#else
#define TOD_INSTANCE_ID
#define TOD_SETUP_INSTANCE_ID(o)
#endif
#ifndef TOD_SCATTERING_MIE
#define TOD_SCATTERING_MIE 1
#endif
#ifndef TOD_SCATTERING_RAYLEIGH
#define TOD_SCATTERING_RAYLEIGH 1
#endif
#ifndef TOD_BAYER_DIM
#define TOD_BAYER_DIM 8.0
#endif
half4 Adjust(half4 color)
{
#if !TOD_OUTPUT_HDR
color = TOD_HDR2LDR(color);
#endif
#if !TOD_OUTPUT_LINEAR
color = TOD_LINEAR2GAMMA(color);
#endif
return color;
}
//////////////////////////////////////////CLOUD CALCULATION//////////////////////////////////////////////////
inline half3 CloudPosition(half3 viewDir, half3 offset)
{
half mult = 1.0 / lerp(0.1, 1.0, viewDir.y);
return (half3(viewDir.x * mult + offset.x, 0, viewDir.z * mult + offset.z)) / TOD_CloudSize;
}
inline half4 CloudUV(half3 viewDir, half3 offset)
{
half3 cloudPos = CloudPosition(viewDir, offset);
half2 uv1 = cloudPos.xz + TOD_CloudOffset.xz + TOD_CloudWind.xz;
half2 uv2 = mul(TOD_ROTATION_UV(radians(10.0)), cloudPos.xz) + TOD_CloudOffset.xz + TOD_CloudWind.xz;
return half4(uv1.x, uv1.y, uv2.x, uv2.y);
}
inline half4 CloudUV(half3 viewDir)
{
return CloudUV(viewDir, 0);
}
inline half3 CloudColor(half3 viewDir, half3 lightDir)
{
half lerpValue = saturate(1 + 4 * lightDir.y) * saturate(dot(viewDir, lightDir) + 1.25);
half3 cloudColor = lerp(TOD_MoonCloudColor, TOD_SunCloudColor, lerpValue);
half3 fogColor = TOD_FogColor;
return TOD_Brightness * lerp(cloudColor, fogColor, TOD_Fogginess);
}
inline half3 CloudLayerDensity(half4 uv, half3 viewDir)
{
half3 density = 0;
#if TOD_CLOUDS_DENSITY
const half thickness = 0.1;
const half4 stepoffset = half4(0.0, 1.0, 2.0, 3.0) * thickness;
const half4 sumy = half4(0.5000, 0.2500, 0.1250, 0.0625) / half4(1, 2, 3, 4);
const half4 sumz = half4(0.5000, 0.2500, 0.1250, 0.0625);
half2 uv1 = uv.xy + viewDir.xz * stepoffset.x;
half2 uv2 = uv.zw + viewDir.xz * stepoffset.y;
half2 uv3 = uv.xy + viewDir.xz * stepoffset.z;
half2 uv4 = uv.zw + viewDir.xz * stepoffset.w;
half4 n1 = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv1);
half4 n2 = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv2);
half4 n3 = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv3);
half4 n4 = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv4);
half4 ny = half4(n1.r, n1.g + n2.g, n1.b + n2.b + n3.b, n1.a + n2.a + n3.a + n4.a); // Noise when marching in up direction
half4 nz = half4(n1.r, n2.g, n3.b, n4.a); // Noise when marching in view direction
density.y += dot(ny, sumy); // Density when marching in up direction
density.z += dot(nz, sumz); // Density when marching in view direction
half2 stepA = TOD_CloudCoverage; // Coverage
half2 stepB = TOD_CloudCoverage + TOD_CloudSharpness;
half2 stepC = TOD_CloudDensity;
density.yz = smoothstep(stepA, stepB, density.yz) + saturate(density.yz - stepB) * stepC;
density.x = saturate(density.z); // Opacity
density.yz *= half2(TOD_CloudAttenuation, TOD_CloudSaturation); // Shading
density.yz = 1.0 - exp2(-density.yz); // Remap
#else
half4 n = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv.xy);
density.y += n.r; // Density when marching in up direction
density.z += n.r; // Density when marching in view direction
density.yz = (density.yz - TOD_CloudCoverage) * half2(TOD_CloudAttenuation, TOD_CloudDensity); // Coverage
density.x = saturate(density.z); // Opacity
#endif
return density;
}
inline half4 CloudLayerColor(half4 uv, half4 color, half3 viewDir, half3 lightDir, half3 lightCol)
{
half3 density = CloudLayerDensity(uv, viewDir);
half4 res = 0;
res.a = density.x;
res.rgb = 1.0 - density.y;
res *= color;
#if TOD_CLOUDS_BUMPED
res.rgb += saturate((1.0 - density.z) * (1.0 - TOD_Fogginess)) * lightCol;
#endif
return res;
}
inline half CloudShadow(half4 uv)
{
return CloudLayerDensity(uv, half3(0, 1, 0)).x;
}
inline half CloudShadow(half3 cameraToWorldPos)
{
half3 worldPos = _WorldSpaceCameraPos + cameraToWorldPos;
half3 skyPos = mul((half3x3)TOD_World2Sky, worldPos);
half4 cloudUV = CloudUV(TOD_LocalLightDirection, skyPos);
return TOD_CloudOpacity * CloudShadow(cloudUV);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////SCATTERING CALCULATION////////////////////////////////////////////
inline half3 ApplayVirtualScatterLight(half3 curColor, float3 worldPos)
{
float3 worldViewDir = _WorldSpaceCameraPos.xyz - worldPos.xyz;
half3 worldLightDir = normalize(GetMainLight().direction);
half angleFactor = 1.0 - saturate(dot(normalize(worldViewDir), worldLightDir) * 0.5 + 0.8);
half3 scatterLightColor = _SG_VirtualScatterLightColor.rgb * angleFactor;
half3 finalColor = curColor + scatterLightColor;
return finalColor;
}
inline half Scale(half inCos)
{
half x = 1.0 - inCos;
return 0.25 * exp(-0.00287 + x*(0.459 + x*(3.83 + x*(-6.80 + x*5.25))));
}
inline half MiePhase(half eyeCos, half eyeCos2)
{
return TOD_kBetaMie.x * (1.0 + eyeCos2) / pow(TOD_kBetaMie.y + TOD_kBetaMie.z * eyeCos, 1.5);
}
inline half RayleighPhase(half eyeCos2)
{
return 0.75 + 0.75 * eyeCos2;
}
inline half RayleighPhase(half eyeCos2, half3 dir)
{
half groundPercent = 1-saturate(dir.y);
half base = lerp(1.5, 0.2, groundPercent);
half phase = base + 0.75 * eyeCos2;
half isBottom = dir.y < -0.5;
phase *= lerp(1, 0.2, isBottom);
return phase;
}
inline half CloudPhase(half eyeCos, half eyeCos2)
{
const half g = 0.3;
const half g2 = g * g;
return TOD_CloudScattering * (1.5 * (1.0 - g2) / (2.0 + g2) * (1.0 + eyeCos2) / (1.0 + g2 - 2.0 * g * eyeCos) + g * eyeCos);
}
inline half3 NightPhase(half3 dir)
{
dir.y = abs(dir.y);
return TOD_MoonSkyColor * (1.0 - 0.75 * dir.y);
}
inline half3 MoonPhase(half3 dir)
{
return TOD_MoonHaloColor * pow(max(0, dot(dir, TOD_LocalMoonDirection)), TOD_MoonHaloPower);
}
inline half3 PostProcess(half3 col, half3 dir)
{
col = pow(col * TOD_Brightness, TOD_Contrast);
return col;
}
#if TOD_SCATTERING_RAYLEIGH && TOD_SCATTERING_MIE
inline void ScatteringCoefficients(half3 dir, out half3 inscatter, out half3 outscatter)
#elif TOD_SCATTERING_RAYLEIGH
inline void ScatteringCoefficients(half3 dir, out half3 inscatter)
#else
inline void ScatteringCoefficients(half3 dir, out half3 outscatter)
#endif
{
dir = normalize(half3(dir.x, max(0, dir.y), dir.z));
half kInnerRadius = TOD_kRadius.x;
half kInnerRadius2 = TOD_kRadius.y;
half kOuterRadius2 = TOD_kRadius.w;
half kScale = TOD_kScale.x;
half kScaleOverScaleDepth = TOD_kScale.z;
half kCameraHeight = TOD_kScale.w;
half3 kKr4PI = TOD_k4PI.xyz;
half kKm4PI = TOD_k4PI.w;
half3 kKrESun = TOD_kSun.xyz;
half kKmESun = TOD_kSun.w;
half3 cameraPos = half3(0, kInnerRadius + kCameraHeight, 0); // Current camera position
half far = sqrt(kOuterRadius2 + kInnerRadius2 * dir.y * dir.y - kInnerRadius2) - kInnerRadius * dir.y; // Length of the atmosphere
half startDepth = exp(kScaleOverScaleDepth * (-kCameraHeight)); // Ray starting position and its scattering offset
half startAngle = dot(dir, cameraPos) / (kInnerRadius + kCameraHeight);
half startOffset = startDepth * Scale(startAngle);
half sampleLength = far / 2; // Scattering loop variables
half scaledLength = sampleLength * kScale;
half3 sampleRay = dir * sampleLength;
half3 samplePoint = cameraPos + sampleRay * 0.5;
half3 sunColor = half3(0.0, 0.0, 0.0);
half height = max(1, length(samplePoint));
half invHeight = 1.0 / height;
half depth = exp(kScaleOverScaleDepth * (kInnerRadius - height));
half atten = depth * scaledLength;
half cameraAngle = dot(dir, samplePoint) * invHeight;
half sunAngle = dot(TOD_LocalSunDirection, samplePoint) * invHeight;
half sunScatter = startOffset + depth * (Scale(sunAngle) - Scale(cameraAngle));
half3 sunAtten = exp(-sunScatter * (kKr4PI + kKm4PI));
sunColor += sunAtten * atten;
samplePoint += sampleRay;
height = max(1, length(samplePoint));
invHeight = 1.0 / height;
depth = exp(kScaleOverScaleDepth * (kInnerRadius - height));
atten = depth * scaledLength;
cameraAngle = dot(dir, samplePoint) * invHeight;
sunAngle = dot(TOD_LocalSunDirection, samplePoint) * invHeight;
sunScatter = startOffset + depth * (Scale(sunAngle) - Scale(cameraAngle));
sunAtten = exp(-sunScatter * (kKr4PI + kKm4PI));
sunColor += sunAtten * atten;
samplePoint += sampleRay;
#if TOD_SCATTERING_RAYLEIGH // Sun scattering
inscatter = TOD_SunSkyColor * sunColor * kKrESun;
#endif
#if TOD_SCATTERING_MIE
outscatter = TOD_SunSkyColor * sunColor * kKmESun;
#endif
}
#if TOD_SCATTERING_RAYLEIGH && TOD_SCATTERING_MIE
inline half4 ScatteringColor(half3 dir, half3 inscatter, half3 outscatter)
#elif TOD_SCATTERING_RAYLEIGH
inline half4 ScatteringColor(half3 dir, half3 inscatter)
#else
inline half4 ScatteringColor(half3 dir, half3 outscatter)
#endif
{
half3 resultColor = half3(0.05, 0.05, 0.1);
half sunCos = dot(TOD_LocalSunDirection, dir);
half sunCos2 = sunCos * sunCos;
#if TOD_SCATTERING_RAYLEIGH
resultColor += NightPhase(dir);
#endif
#if TOD_SCATTERING_MIE
resultColor += MoonPhase(dir);
#endif
#if TOD_SCATTERING_RAYLEIGH
resultColor += RayleighPhase(sunCos2, dir) * inscatter;
#endif
#if TOD_SCATTERING_MIE
resultColor += MiePhase(sunCos, sunCos2) * outscatter;
#endif
return half4(PostProcess(resultColor, dir), 1.0);
}
inline half4 ScatteringColor(half3 dir)
{
#if TOD_SCATTERING_RAYLEIGH && TOD_SCATTERING_MIE
half3 inscatter, outscatter;
ScatteringCoefficients(dir, inscatter, outscatter);
return ScatteringColor(dir, inscatter, outscatter);
#elif TOD_SCATTERING_RAYLEIGH
half3 inscatter;
ScatteringCoefficients(dir, inscatter);
return ScatteringColor(dir, inscatter);
#else
half3 outscatter;
ScatteringCoefficients(dir, outscatter);
return ScatteringColor(dir, outscatter);
#endif
}
inline half FogDensity(half3 worldPos)
{
half camDist = length(worldPos - _WorldSpaceCameraPos);
half globalDensity = TOD_ScatterDensity.z;
half heightDensity = TOD_ScatterDensity.x * (worldPos.y - TOD_ScatterDensity.y);
half heightDensityExpInv = exp(-heightDensity);
half fogIntensity = camDist * heightDensityExpInv; // Get base fog intensity at pixel
half clampRes = step(abs(heightDensity), 0.01); // Apply height falloff
fogIntensity *= ((1.0 - heightDensityExpInv) / heightDensity) * step(abs(heightDensity), 0.01) + step(0.01, abs(heightDensity));
fogIntensity = min(10, globalDensity * fogIntensity); // Clamp intensity
return 1.0 - exp(-fogIntensity);
}
inline half4 AtmosphericScattering(half3 cameraRay, half3 worldPos, half depth, half mask)
{
half3 dir = normalize(mul((half3x3)TOD_World2Sky, cameraRay));
#if TOD_SCATTERING_RAYLEIGH && TOD_SCATTERING_MIE
half3 inscatter, outscatter;
ScatteringCoefficients(dir, inscatter, outscatter);
#elif TOD_SCATTERING_RAYLEIGH
half3 inscatter;
ScatteringCoefficients(dir, inscatter);
#else
half3 outscatter;
ScatteringCoefficients(dir, outscatter);
#endif
depth = FogDensity(worldPos);
#if TOD_SCATTERING_MIE
outscatter = outscatter * depth * mask;
#endif
#if TOD_SCATTERING_RAYLEIGH
inscatter = inscatter * depth;
#endif
#if TOD_SCATTERING_RAYLEIGH && TOD_SCATTERING_MIE
half3 color = ScatteringColor(dir, inscatter, outscatter).rgb;
#elif TOD_SCATTERING_RAYLEIGH
half3 color = ScatteringColor(dir, inscatter).rgb;
#else
half3 color = ScatteringColor(dir, outscatter).rgb;
#endif
return half4(color, depth);
}
inline half4 AtmosphericScattering(half3 cameraRay, half3 worldPos, half depth)
{
const half mask = 1; // This should be sampled from the scattering occlusion mask
return AtmosphericScattering(cameraRay, worldPos, depth, mask);
}
inline half4 AtmosphericScattering(half3 cameraRay, half3 worldPos)
{
half3 dir = normalize(mul((half3x3)TOD_World2Sky, cameraRay));
half depth = FogDensity(worldPos);
half3 color = ScatteringColor(dir).rgb;
return half4(color, depth);
}
inline half2 DitheringCoords(half2 screenPos)
{
return screenPos * _ScreenParams.xy * (1.0 / TOD_BAYER_DIM);
}
inline half DitheringColor(half2 uv)
{
return SAMPLE_TEXTURE2D(TOD_BayerTexture, samplerTOD_BayerTexture, uv).a * (1.0 / (TOD_BAYER_DIM * TOD_BAYER_DIM + 1.0));
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
#endif