-
Notifications
You must be signed in to change notification settings - Fork 60
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: impl multi scattering cache
- Loading branch information
Showing
5 changed files
with
290 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
132 changes: 130 additions & 2 deletions
132
features/PhysicalSky/Shaders/PhysicalSky/MultiScatteringLutCS.hlsl
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,139 @@ | ||
#include "./Common.hlsli" | ||
|
||
#define MULTI_SCATTERING_LUT_WIDTH 32 | ||
#define MULTI_SCATTERING_LUT_HEIGHT 32 | ||
#define SAMPLE_COUNT 64 | ||
|
||
groupshared float3 gsRadianceMS[SAMPLE_COUNT]; | ||
groupshared float3 gsRadiance[SAMPLE_COUNT]; | ||
|
||
RWTexture2D<float3> MultiScatteringLUT : register(u0); | ||
Texture2D<float3> Transmittance : register(t0); | ||
|
||
SamplerState TransmittanceSampler; | ||
|
||
void ComputeIntegrateResult(float3 ro, float3 rd, float end, float3 lightDir, | ||
out float3 skyMultiScattering, out float3 skyColor, out float3 skyTransmittance) | ||
{ | ||
skyColor = 0.0f; | ||
skyTransmittance = 1.0f; | ||
skyMultiScattering = 0.0f; | ||
|
||
const uint sampleCount = 16; | ||
|
||
for (uint s = 0; s < sampleCount; s++) | ||
{ | ||
float t0 = (s) / (float) sampleCount, t1 = (s + 1.0f) / (float) sampleCount; | ||
t0 = t0 * t0 * end; | ||
t1 = t1 * t1 * end; | ||
float t = lerp(t0, t1, 0.5f); | ||
float dt = t1 - t0; | ||
|
||
const float3 p = ro + t * rd; | ||
const float r = max(length(p), PlanetRadius); | ||
const float3 n = p * rcp(r); | ||
const float h = r - PlanetRadius; | ||
|
||
const float3 sigmaE = ComputeExtinction(h); | ||
const float3 sigmaS = RayleighScattering.rgb * exp(-h / RayleighHeight) + MieScattering.rgb * exp(-h / MieHeight); | ||
const float3 transmittance = exp(-sigmaE * dt); | ||
|
||
skyMultiScattering += skyTransmittance * ((sigmaS - sigmaS * transmittance) / sigmaE); | ||
|
||
float cosTheta = dot(n, lightDir); | ||
float sinThetaH = PlanetRadius * rcp(r); | ||
float cosThetaH = -sqrt(saturate(1 - sinThetaH * sinThetaH)); | ||
if (cosTheta >= cosThetaH) // Above horizon | ||
{ | ||
const float3 phaseScatter = sigmaS * rcp(4.0 * Math::PI); // Isotropic | ||
float3 ms = SampleTransmittance(Transmittance, TransmittanceSampler, cosTheta, r) * phaseScatter; | ||
skyColor += skyTransmittance * ((ms - ms * transmittance) / sigmaE); | ||
} | ||
|
||
skyTransmittance *= transmittance; | ||
} | ||
} | ||
|
||
float3 DrawPlanet(float3 pos, float3 lightDir) | ||
{ | ||
float3 n = normalize(pos); | ||
|
||
float3 albedo = GroundAlbedo.xyz; | ||
float3 gBrdf = albedo * rcp(Math::PI); | ||
|
||
float cosTheta = dot(n, lightDir); | ||
|
||
float3 intensity = 0.0f; | ||
if (cosTheta >= 0) | ||
{ | ||
intensity = SampleTransmittance(Transmittance, TransmittanceSampler, cosTheta, PlanetRadius); | ||
} | ||
|
||
return gBrdf * (saturate(cosTheta) * intensity); | ||
} | ||
|
||
void ParallelSum(uint threadIdx, inout float3 radiance, inout float3 radianceMS) | ||
{ | ||
gsRadiance[threadIdx] = radiance; | ||
gsRadianceMS[threadIdx] = radianceMS; | ||
GroupMemoryBarrierWithGroupSync(); | ||
|
||
[unroll] | ||
for (uint s = SAMPLE_COUNT / 2u; s > 0u; s >>= 1u) | ||
{ | ||
if (threadIdx < s) | ||
{ | ||
gsRadiance[threadIdx] += gsRadiance[threadIdx + s]; | ||
gsRadianceMS[threadIdx] += gsRadianceMS[threadIdx + s]; | ||
} | ||
|
||
GroupMemoryBarrierWithGroupSync(); | ||
} | ||
|
||
radiance = gsRadiance[0]; | ||
radianceMS = gsRadianceMS[0]; | ||
} | ||
|
||
[numthreads(1, 1, SAMPLE_COUNT)] void main(uint3 coord | ||
: SV_DispatchThreadID) { | ||
const float2 data = UnmapMultipleScattering(coord.xy); | ||
const float2 uv = coord.xy / (float2(MULTI_SCATTERING_LUT_WIDTH, MULTI_SCATTERING_LUT_HEIGHT) - 1); | ||
const uint threadIdx = coord.z; | ||
|
||
float3 ld = float3(0.0, data.x, sqrt(saturate(1 - data.x * data.x))); | ||
float3 ro = float3(0.0f, data.y, 0.0f); | ||
|
||
float2 sample = Hammersley2d(threadIdx, SAMPLE_COUNT); | ||
float3 rd = SampleSphereUniform(sample.x, sample.y); | ||
|
||
float3 n; float r; | ||
float2 t = IntersectAtmosphere(ro, -rd, n, r); | ||
float entry = t.x, exit = t.y; | ||
|
||
float cosChi = dot(n, rd); | ||
float sinThetaH = PlanetRadius * rcp(r); | ||
float cosThetaH = -sqrt(saturate(1 - sinThetaH * sinThetaH)); | ||
|
||
bool targetGround = entry >= 0 && cosChi < cosThetaH; | ||
|
||
if (targetGround) | ||
exit = entry + IntersectSphere(PlanetRadius, cosChi, r).x; | ||
|
||
float3 skyMultiScattering = 0.0f, skyColor = 0.0f, skyTransmittance = 1.0f; | ||
if (exit > 0.0f) | ||
ComputeIntegrateResult(ro, rd, exit, ld, skyMultiScattering, skyColor, skyTransmittance); | ||
|
||
if (targetGround) | ||
skyColor += DrawPlanet(ro + exit * rd, ld) * skyTransmittance; | ||
|
||
const float dS = 1 / SAMPLE_COUNT; | ||
float3 radiance = skyColor * dS; | ||
float3 radianceMS = skyMultiScattering * dS; | ||
|
||
ParallelSum(threadIdx, radiance, radianceMS); | ||
if (threadIdx > 0) | ||
return; | ||
|
||
const float3 fms = 1.0f * rcp(1.0 - radianceMS); // Equation 9 | ||
const float3 ms = radiance * fms; // Equation 10 | ||
|
||
MultiScatteringLUT[coord.xy] = ms; | ||
} |
38 changes: 38 additions & 0 deletions
38
features/PhysicalSky/Shaders/PhysicalSky/TransmittanceLutCS.hlsl
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
#include "./Common.hlsli" | ||
|
||
#define SAMPLE_COUNT 500 | ||
|
||
RWTexture2D<float3> TransmittanceLUT : register(u0); | ||
|
||
[numthreads(8, 8, 1)] void main(uint2 coord | ||
: SV_DispatchThreadID) { | ||
const float2 data = UnmapTransmittance(float2(coord)); | ||
float cosTheta = data.x, r = data.y; | ||
|
||
float3 ro = float3(0, r, 0); | ||
float3 rd = float3(sqrt(1 - cosTheta * cosTheta), cosTheta, 0); | ||
|
||
float2 t = IntersectSphere(AtmosphericRadius, cosTheta, r); | ||
|
||
float3 transmittance = 1.0f; | ||
if (t.y > 0.0) | ||
{ | ||
t.x = max(t.x, 0.0); | ||
float3 start = ro + rd * t.x; | ||
float3 end = ro + rd * t.y; | ||
float len = t.y - t.x; | ||
|
||
float3 h = 0.0f; | ||
for(int i = 0; i < SAMPLE_COUNT; ++i) | ||
{ | ||
float3 p = lerp(start, end, float(i) / SAMPLE_COUNT); | ||
float e = ComputeExtinction(length(p) - PlanetRadius); | ||
|
||
h += e * (i == 0 || i == SAMPLE_COUNT) ? 0.5f : 1.0f; | ||
} | ||
|
||
transmittance = exp(-h * (len / SAMPLE_COUNT)); | ||
} | ||
|
||
TransmittanceLUT[coord.xy] = transmittance; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters