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

450 lines
17 KiB
HLSL

#ifndef TOD_BASE
#define TOD_BASE
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
TEXTURE2D(TOD_BayerTexture); SAMPLER(samplerTOD_BayerTexture);
TEXTURE2D(TOD_CloudTexture); SAMPLER(samplerTOD_CloudTexture);
TEXTURE2D(TOD_CloudAlphaTexture); SAMPLER(samplerTOD_CloudAlphaTexture);
CBUFFER_START(UnityPerMaterial_TOD)
half4x4 TOD_World2Sky, TOD_Sky2World, TOD_World2CloudCameraProjMatrix;
half3 TOD_FogColor;
half3 TOD_SunLightColor; half3 TOD_GroundColor;
half3 TOD_MoonLightColor; half3 TOD_AmbientColor;
half3 TOD_SunSkyColor; half3 TOD_SunDirection;
half3 TOD_MoonSkyColor; half3 TOD_MoonDirection;
half3 TOD_SunMeshColor; half3 TOD_LightDirection;
half3 TOD_MoonMeshColor; half3 TOD_LocalSunDirection;
half3 TOD_SunCloudColor; half3 TOD_LocalMoonDirection;
half3 TOD_MoonCloudColor; half3 TOD_LocalLightDirection;
half TOD_Contrast; half TOD_CloudDensity;
half TOD_Brightness; half TOD_CloudColoring;
half TOD_Fogginess; half TOD_CloudAttenuation;
half TOD_MoonHaloPower; half TOD_CloudSaturation;
half3 TOD_MoonHaloColor; half TOD_CloudScattering;
half TOD_CloudOpacity; half TOD_CloudBrightness;
half TOD_CloudCoverage; half3 TOD_CloudOffset;
half TOD_CloudSharpness; half3 TOD_CloudWind;
half3 TOD_CloudSize; half TOD_SunMeshContrast;
half TOD_CloudShadowCutoff; half TOD_SunMeshBrightness;
half TOD_CloudShadowFade; half TOD_MoonMeshContrast;
half TOD_CloudShadowIntensity; half TOD_MoonMeshBrightness;
half TOD_StarSize; half3 TOD_ScatterDensity;
half TOD_StarBrightness; half3 TOD_kBetaMie;
half TOD_StarVisibility; half4 TOD_kSun;
half4 TOD_k4PI; half3 TOD_SunWorldPos;
half4 TOD_kRadius; half3 TOD_HeroWorldPos;
half4 TOD_kScale; half TOD_IsDay;
CBUFFER_END
#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)
#define TOD_Object2World unity_ObjectToWorld
#define TOD_World2Object unity_WorldToObject
#define TOD_UV(x, y) x // Screen space adjust
#define TOD_VERTEX_OUTPUT_STEREO // Stereo output
#define TOD_INITIALIZE_VERTEX_OUTPUT_STEREO(o)
#define TOD_INSTANCE_ID // Instancing
#define TOD_SETUP_INSTANCE_ID(o)
//////////////////////////////////////////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(TOD_CloudTexture, samplerTOD_CloudTexture, uv1);
half4 n2 = SAMPLE_TEXTURE2D(TOD_CloudTexture, samplerTOD_CloudTexture, uv2);
half4 n3 = SAMPLE_TEXTURE2D(TOD_CloudTexture, samplerTOD_CloudTexture, uv3);
half4 n4 = SAMPLE_TEXTURE2D(TOD_CloudTexture, samplerTOD_CloudTexture, uv4);
// Noise when marching in up direction
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 view direction
half4 nz = half4(n1.r, n2.g, n3.b, n4.a);
// Density when marching in up direction
density.y += dot(ny, sumy);
// Density when marching in view direction
density.z += dot(nz, sumz);
// Coverage
half2 stepA = TOD_CloudCoverage;
half2 stepB = TOD_CloudCoverage + TOD_CloudSharpness;
half2 stepC = TOD_CloudDensity;
density.yz = smoothstep(stepA, stepB, density.yz) + saturate(density.yz - stepB) * stepC;
// Opacity
density.x = saturate(density.z);
// Shading
density.yz *= half2(TOD_CloudAttenuation, TOD_CloudSaturation);
// Remap
density.yz = 1.0 - exp2(-density.yz);
#else
half4 n = SAMPLE_TEXTURE2D(TOD_CloudTexture, samplerTOD_CloudTexture, uv.xy);
// Density when marching in up direction
density.y += n.r;
// Density when marching in view direction
density.z += n.r;
// Coverage
density.yz = (density.yz - TOD_CloudCoverage) * half2(TOD_CloudAttenuation, TOD_CloudDensity);
// Opacity
density.x = saturate(density.z);
#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 half3 CloudBillboardDensity(half2 uv, half3 viewDir)
{
half3 density = 0;
half4 tex = SAMPLE_TEXTURE2D(TOD_CloudTexture, samplerTOD_CloudTexture, uv.xy);
// Density when marching in up direction
density.y = tex.a;
// Density when marching in view direction
#if TOD_CLOUDS_DENSITY
density.z = lerp(lerp(tex.r, tex.g, saturate(viewDir.x)), tex.b, saturate(-viewDir.x));
#else
density.z = tex.r;
#endif
// Opacity
density.x = saturate(density.z);
// Shading
density.y *= TOD_CloudAttenuation;
return density;
}
// inline half4 CloudBillboardColor(sampler2D normalTex, half4 uv, half4 color, half3 viewDir, half3 lightDir, half3 lightCol)
// {
// half3 density = CloudBillboardDensity(uv.xy, viewDir);
// half4 res = 0;
// res.a = density.x;
// res.rgb = 1.0 - density.y;
// #if TOD_CLOUDS_DENSITY
// half3 normal = UnpackNormal(tex2D(normalTex, uv.zw));
// half NdotS = dot(normal, lightDir);
// res.rgb += 0.25 * (1.0 - TOD_Fogginess) * NdotS;
// #endif
// res *= color;
// #if TOD_CLOUDS_BUMPED
// res.rgb += saturate((1.0 - density.z) * (1.0 - TOD_Fogginess)) * lightCol;
// #endif
// return res;
// }
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////////////////////////////////////////////
#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 _SG_VirtualScatterLightColor;
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;
// Current camera position
half3 cameraPos = half3(0, kInnerRadius + kCameraHeight, 0);
// Length of the atmosphere
half far = sqrt(kOuterRadius2 + kInnerRadius2 * dir.y * dir.y - kInnerRadius2) - kInnerRadius * dir.y;
// Ray starting position and its scattering offset
half startDepth = exp(kScaleOverScaleDepth * (-kCameraHeight));
half startAngle = dot(dir, cameraPos) / (kInnerRadius + kCameraHeight);
half startOffset = startDepth * Scale(startAngle);
// Scattering loop variables
half sampleLength = far / 2;
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;
// Sun scattering
#if TOD_SCATTERING_RAYLEIGH
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) * inscatter;
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);
// Get base fog intensity at pixel
half fogIntensity = camDist * heightDensityExpInv;
// Apply height falloff
half clampRes = step(abs(heightDensity), 0.01);
fogIntensity *= ((1.0 - heightDensityExpInv) / heightDensity) * step(abs(heightDensity), 0.01) + step(0.01, abs(heightDensity));
// Clamp intensity
fogIntensity = min(10, globalDensity * fogIntensity);
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.xy).a * (1.0 / (TOD_BAYER_DIM * TOD_BAYER_DIM + 1.0));
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
#endif