verus/Verus/src/Shaders/Sky.hlsl

198 lines
6.0 KiB
HLSL

// Copyright (C) 2021-2022, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
#include "Lib.hlsl"
#include "LibColor.hlsl"
#include "LibSurface.hlsl"
#include "LibVertex.hlsl"
#include "Sky.inc.hlsl"
CBUFFER(0, UB_PerFrame, g_ubPerFrame)
CBUFFER(1, UB_PerMaterialFS, g_ubPerMaterialFS)
CBUFFER(2, UB_PerMeshVS, g_ubPerMeshVS)
CBUFFER(3, UB_PerObject, g_ubPerObject)
Texture2D g_texSky : REG(t1, space1, t0);
SamplerState g_samSky : REG(s1, space1, s0);
Texture2D g_texStars : REG(t2, space1, t1);
SamplerState g_samStars : REG(s2, space1, s1);
Texture2D g_texClouds : REG(t3, space1, t2);
SamplerState g_samClouds : REG(s3, space1, s2);
Texture2D g_texCloudsNM : REG(t4, space1, t3);
SamplerState g_samCloudsNM : REG(s4, space1, s3);
struct VSI
{
VK_LOCATION_POSITION int4 pos : POSITION;
VK_LOCATION_NORMAL float3 nrm : NORMAL;
VK_LOCATION(8) int2 tc0 : TEXCOORD0;
};
struct VSI_SKY_BODY
{
VK_LOCATION_POSITION float4 pos : POSITION;
VK_LOCATION(8) int2 tc0 : TEXCOORD0;
};
struct VSO
{
float4 pos : SV_Position;
float3 color0 : COLOR0;
float2 tc0 : TEXCOORD0;
float2 tcStars : TEXCOORD1;
#ifdef DEF_CLOUDS
float2 tcPhaseA : TEXCOORD2;
float2 tcPhaseB : TEXCOORD3;
#endif
};
struct VSO_SKY_BODY
{
float4 pos : SV_Position;
float2 tc0 : TEXCOORD0;
float height : TEXCOORD1;
};
struct FSO
{
float4 color : SV_Target0;
};
#ifdef _VS
VSO mainVS(VSI si)
{
VSO so;
const float3 inPos = DequantizeUsingDeq3D(si.pos.xyz, g_ubPerMeshVS._posDeqScale.xyz, g_ubPerMeshVS._posDeqBias.xyz);
so.pos = mul(float4(inPos, 1), g_ubPerObject._matWVP).xyww; // Peg the depth. (c) ATI
so.color0 = pow(saturate(dot(normalize(inPos * float3(1, 0.25, 1)), g_ubPerFrame._dirToSun.xyz)), 4.0);
so.tc0 = float2(g_ubPerFrame._time_cloudiness.x, 0.5 - inPos.y);
so.tcStars = inPos.xz * 16.0; // Stars.
#ifdef DEF_CLOUDS
so.tcPhaseA = inPos.xz * (4.0 - 4.0 * inPos.y) + g_ubPerFrame._phaseAB.xy;
so.tcPhaseB = inPos.xz * (2.0 - 2.0 * inPos.y) + g_ubPerFrame._phaseAB.zw;
#endif
return so;
}
VSO_SKY_BODY mainSkyBodyVS(VSI_SKY_BODY si)
{
VSO_SKY_BODY so;
so.pos = mul(si.pos, g_ubPerObject._matWVP).xyww;
so.tc0 = si.tc0;
so.height = mul(si.pos.xyz, (float3x3)g_ubPerObject._matW).y;
return so;
}
#endif
#ifdef _FS
FSO mainFS(VSO si)
{
FSO so;
const float3 rand = Rand(si.pos.xy);
const float time = g_ubPerFrame._time_cloudiness.x;
const float cloudiness = g_ubPerFrame._time_cloudiness.y;
const float sunAlpha = g_ubPerFrame._sunColor.a;
#ifdef DEF_CLOUDS
const float3 sunSam = g_texSky.Sample(g_samSky, float2(time, 248.0 / 256.0)).rgb;
const float3 skySam = g_texSky.Sample(g_samSky, float2(time, 0.3)).rgb;
const float3 rimSam = g_texSky.Sample(g_samSky, float2(time, 0.4)).rgb;
const float colorA = g_texClouds.Sample(g_samClouds, si.tcPhaseA).r;
const float colorB = g_texClouds.Sample(g_samClouds, si.tcPhaseB).r;
const float4 normalA = g_texCloudsNM.Sample(g_samCloudsNM, si.tcPhaseA);
const float4 normalB = g_texCloudsNM.Sample(g_samCloudsNM, si.tcPhaseB);
const float noon = saturate(g_ubPerFrame._dirToSun.y);
const float noonHalf = noon * 0.5;
const float avgColor = (colorA + colorB) * 0.5;
const float negative = 1.0 - avgColor;
const float3 cloudColor = saturate(Desaturate(skySam, 0.4 + noonHalf) + 0.4 * noon); // White, bright clouds at noon.
const float3 rimColor = saturate(rimSam * 2.0);
// <Normal>
float3 normal = 1.0 - (normalA.agb + normalB.agb);
normal.b = ComputeNormalZ(normal.rg);
normal.xyz = normal.xzy; // From normal-map space to world.
// </Normal>
// <Alpha>
const float clearSky = 1.0 - cloudiness;
const float clearSkySoft = 0.6 + 0.4 * clearSky;
const float alpha = saturate((avgColor - clearSky) * 3.0);
// </Alpha>
const float dayRatio = (1.0 - abs(0.5 - time) * 1.99);
const float3 sunBoost = si.color0.r * sunAlpha * sunSam;
const float nDosL = saturate(dot(normal, g_ubPerFrame._dirToSun.xyz)) * sunAlpha;
const float edgeMask = saturate((0.9 - alpha) * 2.0);
const float3 glowAmbient = edgeMask * 0.1 + noonHalf * 0.2 + sunBoost * dayRatio;
const float3 glow = saturate(lerp(nDosL * nDosL, edgeMask, noonHalf) + glowAmbient);
const float3 diff = saturate((0.7 + 0.3 * (max(nDosL, negative) + sunBoost)) * dayRatio * clearSkySoft);
const float3 finalColor = saturate(diff * cloudColor + glow * rimColor * clearSkySoft * 0.25);
const float3 hdrScale = g_ubPerFrame._ambientColor.w * (1.5 + 1.5 * sunBoost);
so.color.rgb = finalColor * hdrScale;
so.color.a = alpha;
// <Fog>
{
const float strengthA = saturate(cloudiness + 40.0 * g_ubPerFrame._fogColor.a);
const float strengthB = strengthA * strengthA * strengthA;
const float fogBias = 0.05 + 0.45 * strengthB;
const float fogContrast = 1.0 + 2.0 * strengthB;
const float fog = saturate((si.tc0.y - 0.5 + fogBias) * (fogContrast / fogBias));
so.color.rgb = lerp(so.color.rgb, g_ubPerFrame._fogColor.rgb, fog);
so.color.a = max(so.color.a, fog);
}
// </Fog>
#else
const float4 skySam = g_texSky.Sample(g_samSky, si.tc0);
const float3 skyColor = skySam.rgb + rand * lerp(0.001, 0.01, skySam.rgb); // Dithering.
const float4 starsSam = g_texStars.Sample(g_samStars, si.tcStars);
const float sunBoost = si.color0.r * sunAlpha;
const float hdrScale = g_ubPerFrame._ambientColor.w * (1.0 + sunBoost);
so.color = float4(skyColor.rgb * hdrScale + starsSam.rgb * 25.0, 1);
#endif
so.color.rgb = SaturateHDR(so.color.rgb);
return so;
}
FSO mainSkyBodyFS(VSO_SKY_BODY si)
{
FSO so;
so.color = g_texClouds.Sample(g_samClouds, si.tc0);
const float mask = abs(si.height);
#ifdef DEF_SUN
so.color.rgb *= lerp(float3(1.0, 0.2, 0.001), 1.0, mask);
so.color.rgb *= (60.0 * 1000.0) + (100.0 * 1000.0) * mask;
so.color.rgb = SaturateHDR(so.color.rgb);
#endif
#ifdef DEF_MOON
const float hdrScale = Grayscale(g_ubPerFrame._ambientColor.xyz) * 50.0;
so.color.rgb *= lerp(float3(1.0, 0.9, 0.8), 1.0, mask);
so.color.rgb *= max(100.0, hdrScale);
so.color.a *= mask;
#endif
return so;
}
#endif
//@main:#Sky SKY
//@main:#Clouds CLOUDS
//@mainSkyBody:#Sun SUN
//@mainSkyBody:#Moon MOON