54 lines
1.7 KiB
HLSL
54 lines
1.7 KiB
HLSL
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
// Atmosphere function that are independent of any shader parameters
|
|
|
|
float Gain(float x, float k)
|
|
{
|
|
float a = 1 - 2 * x;
|
|
return 0.5 - 0.5 * sign(a) * pow(abs(a), k);
|
|
}
|
|
|
|
float ComputeHorizonCosine(float ViewHeight, float BotRadius)
|
|
{
|
|
const float R = BotRadius / ViewHeight;
|
|
return -sqrt(saturate(1.0 - R * R));
|
|
}
|
|
|
|
float2 ToAtmosphereOpticalDepthLUTUV(float Height, float Cosine, float BotRadius, float TopRadius)
|
|
{
|
|
const float HorizonCosine = ComputeHorizonCosine(Height, BotRadius);
|
|
|
|
const float Q = 0.5; // line up horizon line to u=Q
|
|
const float2 ab = Cosine >= HorizonCosine
|
|
? float2((HorizonCosine - 1) / (Q - 1), (Q - HorizonCosine) / (Q - 1)) // above horizon
|
|
: float2((1 + HorizonCosine) / Q, -1); // below horizon
|
|
|
|
float2 UV = float2((Cosine - ab.y) / ab.x, sqrt(saturate((Height - BotRadius) / (TopRadius - BotRadius))));
|
|
// un-squish
|
|
const float Sq = 2.0;
|
|
UV.x = Gain(UV.x, 1.0 / Sq);
|
|
return UV;
|
|
}
|
|
|
|
float2 FromAtmosphereOpticalDepthLUTUV(float2 UV, float BotRadius, float TopRadius)
|
|
{
|
|
const float Height = lerp(BotRadius, TopRadius, Pow2(UV.y)); // more resolution toward the ground
|
|
|
|
// from this height, at what cosine is the horizon line?
|
|
const float HorizonCosine = ComputeHorizonCosine(Height, BotRadius);
|
|
|
|
// squish around 0.5 to increase resolution near the horizon
|
|
const float Sq = 2.0;
|
|
const float U = Gain(UV.x, Sq);
|
|
|
|
const float Q = 0.5; // line up horizon line to u=Q
|
|
const float2 ab = U > Q
|
|
? float2((HorizonCosine - 1) / (Q - 1), (Q - HorizonCosine) / (Q - 1)) // above horizon
|
|
: float2((1 + HorizonCosine) / Q, -1); // below horizon
|
|
const float Cosine = ab.x * U + ab.y;
|
|
|
|
return float2(Height, Cosine);
|
|
}
|