HDR: Use precomputed uniforms for atmospheric scattering
This commit is contained in:
parent
d4dfafaac7
commit
94f4007793
4 changed files with 41 additions and 47 deletions
|
@ -16,14 +16,16 @@ out vec4 fragColor;
|
||||||
|
|
||||||
in vec2 texCoord;
|
in vec2 texCoord;
|
||||||
|
|
||||||
uniform mat4 fg_ViewMatrixInverse;
|
|
||||||
uniform vec3 fg_CameraPositionCart;
|
|
||||||
uniform vec3 fg_CameraPositionGeod;
|
|
||||||
uniform vec3 fg_SunDirectionWorld;
|
|
||||||
|
|
||||||
uniform sampler2D transmittance_lut;
|
uniform sampler2D transmittance_lut;
|
||||||
uniform sampler2D multiscattering_lut;
|
uniform sampler2D multiscattering_lut;
|
||||||
|
|
||||||
|
uniform mat4 fg_ViewMatrixInverse;
|
||||||
|
uniform vec3 fg_CameraPositionCart;
|
||||||
|
uniform vec3 fg_SunDirectionWorld;
|
||||||
|
uniform float fg_SunZenithCosTheta;
|
||||||
|
uniform float fg_CameraDistanceToEarthCenter;
|
||||||
|
uniform float fg_EarthRadius;
|
||||||
|
|
||||||
const float PI = 3.141592653;
|
const float PI = 3.141592653;
|
||||||
const float ATMOSPHERE_RADIUS = 6471e3;
|
const float ATMOSPHERE_RADIUS = 6471e3;
|
||||||
const float TOTAL_SLICES = 32.0;
|
const float TOTAL_SLICES = 32.0;
|
||||||
|
@ -43,11 +45,7 @@ vec3 getValueFromLUT(sampler2D lut, float sunCosTheta, float normalizedHeight);
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec3 up = normalize(fg_CameraPositionCart);
|
|
||||||
float sunCosTheta = dot(fg_SunDirectionWorld, up);
|
|
||||||
|
|
||||||
// Account for the depth layer we are currently in
|
// Account for the depth layer we are currently in
|
||||||
// FIXME: We should probably be writing the pixel center
|
|
||||||
float x = texCoord.x * TOTAL_SLICES;
|
float x = texCoord.x * TOTAL_SLICES;
|
||||||
vec2 coord = vec2(fract(x), texCoord.y);
|
vec2 coord = vec2(fract(x), texCoord.y);
|
||||||
// Depth goes from the 0 to DEPTH_RANGE in a squared distribution.
|
// Depth goes from the 0 to DEPTH_RANGE in a squared distribution.
|
||||||
|
@ -59,16 +57,16 @@ void main()
|
||||||
vec3 fragPos = positionFromDepth(coord, 1.0);
|
vec3 fragPos = positionFromDepth(coord, 1.0);
|
||||||
vec3 rayDir = vec4(fg_ViewMatrixInverse * vec4(normalize(fragPos), 0.0)).xyz;
|
vec3 rayDir = vec4(fg_ViewMatrixInverse * vec4(normalize(fragPos), 0.0)).xyz;
|
||||||
|
|
||||||
float cameraHeight = length(fg_CameraPositionCart);
|
|
||||||
float earthRadius = cameraHeight - max(fg_CameraPositionGeod.z, 0.0);
|
|
||||||
|
|
||||||
vec3 rayOrigin = fg_CameraPositionCart;
|
vec3 rayOrigin = fg_CameraPositionCart;
|
||||||
|
|
||||||
|
// Handle the camera being underground
|
||||||
|
float earthRadius = min(fg_EarthRadius, fg_CameraDistanceToEarthCenter);
|
||||||
|
|
||||||
float atmosDist = raySphereIntersection(rayOrigin, rayDir, ATMOSPHERE_RADIUS);
|
float atmosDist = raySphereIntersection(rayOrigin, rayDir, ATMOSPHERE_RADIUS);
|
||||||
float groundDist = raySphereIntersection(rayOrigin, rayDir, earthRadius);
|
float groundDist = raySphereIntersection(rayOrigin, rayDir, earthRadius);
|
||||||
|
|
||||||
float tmax;
|
float tmax;
|
||||||
if (cameraHeight < ATMOSPHERE_RADIUS) {
|
if (fg_CameraDistanceToEarthCenter < ATMOSPHERE_RADIUS) {
|
||||||
// We are inside the atmosphere
|
// We are inside the atmosphere
|
||||||
if (groundDist < 0.0) {
|
if (groundDist < 0.0) {
|
||||||
// No ground collision, use the distance to the outer atmosphere
|
// No ground collision, use the distance to the outer atmosphere
|
||||||
|
@ -99,8 +97,8 @@ void main()
|
||||||
t = newT;
|
t = newT;
|
||||||
|
|
||||||
vec3 samplePos = rayOrigin + rayDir * t;
|
vec3 samplePos = rayOrigin + rayDir * t;
|
||||||
float height = length(samplePos) - earthRadius;
|
float height = length(samplePos) - fg_EarthRadius;
|
||||||
float normalizedHeight = height / (ATMOSPHERE_RADIUS - earthRadius);
|
float normalizedHeight = height / (ATMOSPHERE_RADIUS - fg_EarthRadius);
|
||||||
|
|
||||||
float mieScattering, mieAbsorption;
|
float mieScattering, mieAbsorption;
|
||||||
vec3 rayleighScattering, ozoneAbsorption;
|
vec3 rayleighScattering, ozoneAbsorption;
|
||||||
|
@ -110,9 +108,9 @@ void main()
|
||||||
vec3 sampleTransmittance = exp(-dt*extinction);
|
vec3 sampleTransmittance = exp(-dt*extinction);
|
||||||
|
|
||||||
vec3 sunTransmittance = getValueFromLUT(
|
vec3 sunTransmittance = getValueFromLUT(
|
||||||
transmittance_lut, sunCosTheta, normalizedHeight);
|
transmittance_lut, fg_SunZenithCosTheta, normalizedHeight);
|
||||||
vec3 multiscattering = getValueFromLUT(
|
vec3 multiscattering = getValueFromLUT(
|
||||||
multiscattering_lut, sunCosTheta, normalizedHeight);
|
multiscattering_lut, fg_SunZenithCosTheta, normalizedHeight);
|
||||||
|
|
||||||
vec3 S =
|
vec3 S =
|
||||||
rayleighScattering * (rayleighPhase * sunTransmittance + multiscattering) +
|
rayleighScattering * (rayleighPhase * sunTransmittance + multiscattering) +
|
||||||
|
|
|
@ -9,11 +9,10 @@ out vec3 fragColor;
|
||||||
|
|
||||||
in vec2 texCoord;
|
in vec2 texCoord;
|
||||||
|
|
||||||
uniform vec3 fg_CameraPositionCart;
|
|
||||||
uniform vec3 fg_CameraPositionGeod;
|
|
||||||
|
|
||||||
uniform sampler2D transmittance_lut;
|
uniform sampler2D transmittance_lut;
|
||||||
|
|
||||||
|
uniform float fg_EarthRadius;
|
||||||
|
|
||||||
const float PI = 3.141592653;
|
const float PI = 3.141592653;
|
||||||
const float ATMOSPHERE_RADIUS = 6471e3;
|
const float ATMOSPHERE_RADIUS = 6471e3;
|
||||||
const int SQRT_SAMPLES = 4;
|
const int SQRT_SAMPLES = 4;
|
||||||
|
@ -44,8 +43,7 @@ void main()
|
||||||
float sunCosTheta = texCoord.x * 2.0 - 1.0;
|
float sunCosTheta = texCoord.x * 2.0 - 1.0;
|
||||||
vec3 sunDir = vec3(-sqrt(1.0 - sunCosTheta*sunCosTheta), 0.0, sunCosTheta);
|
vec3 sunDir = vec3(-sqrt(1.0 - sunCosTheta*sunCosTheta), 0.0, sunCosTheta);
|
||||||
|
|
||||||
float earthRadius = length(fg_CameraPositionCart) - fg_CameraPositionGeod.z;
|
float altitude = mix(fg_EarthRadius, ATMOSPHERE_RADIUS, texCoord.y);
|
||||||
float altitude = mix(earthRadius, ATMOSPHERE_RADIUS, texCoord.y);
|
|
||||||
vec3 rayOrigin = vec3(0.0, 0.0, altitude);
|
vec3 rayOrigin = vec3(0.0, 0.0, altitude);
|
||||||
|
|
||||||
vec3 Ltotal = vec3(0.0);
|
vec3 Ltotal = vec3(0.0);
|
||||||
|
@ -58,7 +56,7 @@ void main()
|
||||||
vec3 rayDir = generateRayDir(theta, phi);
|
vec3 rayDir = generateRayDir(theta, phi);
|
||||||
|
|
||||||
float atmosDist = raySphereIntersection(rayOrigin, rayDir, ATMOSPHERE_RADIUS);
|
float atmosDist = raySphereIntersection(rayOrigin, rayDir, ATMOSPHERE_RADIUS);
|
||||||
float groundDist = raySphereIntersection(rayOrigin, rayDir, earthRadius);
|
float groundDist = raySphereIntersection(rayOrigin, rayDir, fg_EarthRadius);
|
||||||
|
|
||||||
float tmax;
|
float tmax;
|
||||||
if (groundDist < 0.0) {
|
if (groundDist < 0.0) {
|
||||||
|
@ -84,8 +82,8 @@ void main()
|
||||||
t = newT;
|
t = newT;
|
||||||
|
|
||||||
vec3 samplePos = rayOrigin + rayDir * t;
|
vec3 samplePos = rayOrigin + rayDir * t;
|
||||||
float height = length(samplePos) - earthRadius;
|
float height = length(samplePos) - fg_EarthRadius;
|
||||||
float normalizedHeight = height / (ATMOSPHERE_RADIUS - earthRadius);
|
float normalizedHeight = height / (ATMOSPHERE_RADIUS - fg_EarthRadius);
|
||||||
|
|
||||||
float mieScattering, mieAbsorption;
|
float mieScattering, mieAbsorption;
|
||||||
vec3 rayleighScattering, ozoneAbsorption;
|
vec3 rayleighScattering, ozoneAbsorption;
|
||||||
|
@ -116,8 +114,8 @@ void main()
|
||||||
float pHeight = length(p);
|
float pHeight = length(p);
|
||||||
vec3 up = p / pHeight;
|
vec3 up = p / pHeight;
|
||||||
|
|
||||||
float normHeight = (pHeight - earthRadius)
|
float normHeight = (pHeight - fg_EarthRadius)
|
||||||
/ (ATMOSPHERE_RADIUS - earthRadius);
|
/ (ATMOSPHERE_RADIUS - fg_EarthRadius);
|
||||||
float sunZenithCosTheta = dot(sunDir, up);
|
float sunZenithCosTheta = dot(sunDir, up);
|
||||||
|
|
||||||
vec3 transmittanceFromGround = getValueFromLUT(
|
vec3 transmittanceFromGround = getValueFromLUT(
|
||||||
|
|
|
@ -13,13 +13,13 @@ out vec3 fragColor;
|
||||||
|
|
||||||
in vec2 texCoord;
|
in vec2 texCoord;
|
||||||
|
|
||||||
uniform vec3 fg_CameraPositionCart;
|
|
||||||
uniform vec3 fg_CameraPositionGeod;
|
|
||||||
uniform vec3 fg_SunDirectionWorld;
|
|
||||||
|
|
||||||
uniform sampler2D transmittance_lut;
|
uniform sampler2D transmittance_lut;
|
||||||
uniform sampler2D multiscattering_lut;
|
uniform sampler2D multiscattering_lut;
|
||||||
|
|
||||||
|
uniform float fg_SunZenithCosTheta;
|
||||||
|
uniform float fg_CameraDistanceToEarthCenter;
|
||||||
|
uniform float fg_EarthRadius;
|
||||||
|
|
||||||
const float PI = 3.141592653;
|
const float PI = 3.141592653;
|
||||||
|
|
||||||
const float ATMOSPHERE_RADIUS = 6471e3;
|
const float ATMOSPHERE_RADIUS = 6471e3;
|
||||||
|
@ -37,9 +37,9 @@ void main()
|
||||||
{
|
{
|
||||||
// Always leave the sun right in the middle of the texture as the skydome
|
// Always leave the sun right in the middle of the texture as the skydome
|
||||||
// model is already being rotated.
|
// model is already being rotated.
|
||||||
vec3 up = normalize(fg_CameraPositionCart);
|
vec3 sunDir = vec3(-sqrt(1.0 - fg_SunZenithCosTheta*fg_SunZenithCosTheta),
|
||||||
float sunCosTheta = dot(fg_SunDirectionWorld, up);
|
0.0,
|
||||||
vec3 sunDir = vec3(-sqrt(1.0 - sunCosTheta*sunCosTheta), 0.0, sunCosTheta);
|
fg_SunZenithCosTheta);
|
||||||
|
|
||||||
float azimuth = 2.0 * PI * texCoord.x; // [0, 2pi]
|
float azimuth = 2.0 * PI * texCoord.x; // [0, 2pi]
|
||||||
// Apply a non-linear transformation to the elevation to dedicate more
|
// Apply a non-linear transformation to the elevation to dedicate more
|
||||||
|
@ -48,16 +48,16 @@ void main()
|
||||||
float elev = l*l * sign(l) * PI * 0.5; // [-pi/2, pi/2]
|
float elev = l*l * sign(l) * PI * 0.5; // [-pi/2, pi/2]
|
||||||
vec3 rayDir = vec3(cos(elev) * cos(azimuth), cos(elev) * sin(azimuth), sin(elev));
|
vec3 rayDir = vec3(cos(elev) * cos(azimuth), cos(elev) * sin(azimuth), sin(elev));
|
||||||
|
|
||||||
float cameraHeight = length(fg_CameraPositionCart);
|
vec3 rayOrigin = vec3(0.0, 0.0, fg_CameraDistanceToEarthCenter);
|
||||||
float earthRadius = cameraHeight - max(fg_CameraPositionGeod.z, 0.0);
|
|
||||||
|
|
||||||
vec3 rayOrigin = vec3(0.0, 0.0, cameraHeight);
|
// Handle the camera being underground
|
||||||
|
float earthRadius = min(fg_EarthRadius, fg_CameraDistanceToEarthCenter);
|
||||||
|
|
||||||
float atmosDist = raySphereIntersection(rayOrigin, rayDir, ATMOSPHERE_RADIUS);
|
float atmosDist = raySphereIntersection(rayOrigin, rayDir, ATMOSPHERE_RADIUS);
|
||||||
float groundDist = raySphereIntersection(rayOrigin, rayDir, earthRadius);
|
float groundDist = raySphereIntersection(rayOrigin, rayDir, earthRadius);
|
||||||
|
|
||||||
float tmax;
|
float tmax;
|
||||||
if (cameraHeight < ATMOSPHERE_RADIUS) {
|
if (fg_CameraDistanceToEarthCenter < ATMOSPHERE_RADIUS) {
|
||||||
// We are inside the atmosphere
|
// We are inside the atmosphere
|
||||||
if (groundDist < 0.0) {
|
if (groundDist < 0.0) {
|
||||||
// No ground collision, use the distance to the outer atmosphere
|
// No ground collision, use the distance to the outer atmosphere
|
||||||
|
@ -86,8 +86,8 @@ void main()
|
||||||
t = newT;
|
t = newT;
|
||||||
|
|
||||||
vec3 samplePos = rayOrigin + rayDir * t;
|
vec3 samplePos = rayOrigin + rayDir * t;
|
||||||
float height = length(samplePos) - earthRadius;
|
float height = length(samplePos) - fg_EarthRadius;
|
||||||
float normalizedHeight = height / (ATMOSPHERE_RADIUS - earthRadius);
|
float normalizedHeight = height / (ATMOSPHERE_RADIUS - fg_EarthRadius);
|
||||||
|
|
||||||
float mieScattering, mieAbsorption;
|
float mieScattering, mieAbsorption;
|
||||||
vec3 rayleighScattering, ozoneAbsorption;
|
vec3 rayleighScattering, ozoneAbsorption;
|
||||||
|
@ -97,9 +97,9 @@ void main()
|
||||||
vec3 sampleTransmittance = exp(-dt*extinction);
|
vec3 sampleTransmittance = exp(-dt*extinction);
|
||||||
|
|
||||||
vec3 sunTransmittance = getValueFromLUT(
|
vec3 sunTransmittance = getValueFromLUT(
|
||||||
transmittance_lut, sunCosTheta, normalizedHeight);
|
transmittance_lut, fg_SunZenithCosTheta, normalizedHeight);
|
||||||
vec3 multiscattering = getValueFromLUT(
|
vec3 multiscattering = getValueFromLUT(
|
||||||
multiscattering_lut, sunCosTheta, normalizedHeight);
|
multiscattering_lut, fg_SunZenithCosTheta, normalizedHeight);
|
||||||
|
|
||||||
vec3 S =
|
vec3 S =
|
||||||
rayleighScattering * (rayleighPhase * sunTransmittance + multiscattering) +
|
rayleighScattering * (rayleighPhase * sunTransmittance + multiscattering) +
|
||||||
|
|
|
@ -11,8 +11,7 @@ out vec3 fragColor;
|
||||||
|
|
||||||
in vec2 texCoord;
|
in vec2 texCoord;
|
||||||
|
|
||||||
uniform vec3 fg_CameraPositionCart;
|
uniform float fg_EarthRadius;
|
||||||
uniform vec3 fg_CameraPositionGeod;
|
|
||||||
|
|
||||||
const float ATMOSPHERE_RADIUS = 6471e3;
|
const float ATMOSPHERE_RADIUS = 6471e3;
|
||||||
const int TRANSMITTANCE_STEPS = 40;
|
const int TRANSMITTANCE_STEPS = 40;
|
||||||
|
@ -27,8 +26,7 @@ void main()
|
||||||
float sunCosTheta = texCoord.x * 2.0 - 1.0;
|
float sunCosTheta = texCoord.x * 2.0 - 1.0;
|
||||||
vec3 sunDir = vec3(-sqrt(1.0 - sunCosTheta*sunCosTheta), 0.0, sunCosTheta);
|
vec3 sunDir = vec3(-sqrt(1.0 - sunCosTheta*sunCosTheta), 0.0, sunCosTheta);
|
||||||
|
|
||||||
float earthRadius = length(fg_CameraPositionCart) - fg_CameraPositionGeod.z;
|
float altitude = mix(fg_EarthRadius, ATMOSPHERE_RADIUS, texCoord.y);
|
||||||
float altitude = mix(earthRadius, ATMOSPHERE_RADIUS, texCoord.y);
|
|
||||||
vec3 rayOrigin = vec3(0.0, 0.0, altitude);
|
vec3 rayOrigin = vec3(0.0, 0.0, altitude);
|
||||||
|
|
||||||
float dist = raySphereIntersection(rayOrigin, sunDir, ATMOSPHERE_RADIUS);
|
float dist = raySphereIntersection(rayOrigin, sunDir, ATMOSPHERE_RADIUS);
|
||||||
|
@ -41,7 +39,7 @@ void main()
|
||||||
t = newT;
|
t = newT;
|
||||||
|
|
||||||
vec3 samplePos = rayOrigin + sunDir * t;
|
vec3 samplePos = rayOrigin + sunDir * t;
|
||||||
float height = length(samplePos) - earthRadius;
|
float height = length(samplePos) - fg_EarthRadius;
|
||||||
|
|
||||||
float mieScattering, mieAbsorption;
|
float mieScattering, mieAbsorption;
|
||||||
vec3 rayleighScattering, ozoneAbsorption;
|
vec3 rayleighScattering, ozoneAbsorption;
|
||||||
|
|
Loading…
Reference in a new issue