1
0
Fork 0

HDR pipeline: a lot of improvements to atmospheric scattering

This commit is contained in:
Fernando García Liñán 2021-07-26 12:10:58 +02:00
parent 0a9a0527aa
commit 9eaef501c7
13 changed files with 330 additions and 205 deletions

View file

@ -6,4 +6,8 @@
<!-- Only render the skydome and terrain -->
<!-- TODO: Explicitly select the LOD level -->
<cull-mask>0x801</cull-mask>
<binding>
<unit>11</unit>
<buffer>sky-view</buffer>
</binding>
</PropertyList>

View file

@ -55,15 +55,6 @@
<format>rgb16f</format>
</buffer>
<!-- HDR with rendered atmosphere -->
<buffer>
<name>hdr-with-atmosphere</name>
<type>2d</type>
<width>screen</width>
<height>screen</height>
<format>rgb16f</format>
</buffer>
<!-- Final LDR buffer -->
<buffer>
<name>final</name>
@ -73,6 +64,41 @@
<format>rgb8</format>
</buffer>
<!-- Atmosphere LUTs -->
<buffer>
<name>sky-view</name>
<type>2d</type>
<width>256</width>
<height>128</height>
<format>rgb16f</format>
<min-filter>linear</min-filter>
<mag-filter>linear</mag-filter>
<wrap-s>repeat</wrap-s>
<wrap-t>clamp-to-edge</wrap-t>
</buffer>
<buffer>
<name>aerial-inscatter</name>
<type>2d</type>
<width>512</width>
<height>32</height>
<format>rgba16f</format>
<min-filter>linear</min-filter>
<mag-filter>linear</mag-filter>
<wrap-s>clamp-to-edge</wrap-s>
<wrap-t>clamp-to-edge</wrap-t>
</buffer>
<buffer>
<name>aerial-transmittance</name>
<type>2d</type>
<width>512</width>
<height>32</height>
<format>rgba16f</format>
<min-filter>linear</min-filter>
<mag-filter>linear</mag-filter>
<wrap-s>clamp-to-edge</wrap-s>
<wrap-t>clamp-to-edge</wrap-t>
</buffer>
<!-- Environment cubemap -->
<buffer>
<name>envmap</name>
@ -187,6 +213,31 @@
<!--=======================================================================-->
<!-- Sky-View -->
<pass>
<name>atmos-sky-view</name>
<type>quad</type>
<effect>Effects/HDR/atmos-sky-view</effect>
<attachment>
<component>color</component>
<buffer>sky-view</buffer>
</attachment>
</pass>
<!-- Aerial Perspective -->
<pass>
<name>atmos-aerial-perspective</name>
<type>quad</type>
<effect>Effects/HDR/atmos-aerial-perspective</effect>
<attachment>
<component>color0</component>
<buffer>aerial-inscatter</buffer>
</attachment>
<attachment>
<component>color1</component>
<buffer>aerial-transmittance</buffer>
</attachment>
</pass>
<!--
Environment capture passes
Render to a cubemap using forward rendering. Only render the skydome and
@ -643,6 +694,14 @@
<unit>10</unit>
<buffer>sun-shadowmap-atlas</buffer>
</binding>
<binding>
<unit>11</unit>
<buffer>aerial-inscatter</buffer>
</binding>
<binding>
<unit>12</unit>
<buffer>aerial-transmittance</buffer>
</binding>
<attachment>
<component>color0</component>
<buffer>hdr-result</buffer>
@ -665,6 +724,10 @@
<unit>9</unit>
<buffer>envmap</buffer>
</binding>
<binding>
<unit>11</unit>
<buffer>sky-view</buffer>
</binding>
<attachment>
<component>color</component>
<buffer>hdr-result</buffer>
@ -675,24 +738,6 @@
</attachment>
</pass>
<pass>
<name>atmosphere</name>
<type>quad</type>
<effect>Effects/HDR/atmosphere</effect>
<binding>
<unit>0</unit>
<buffer>hdr-result</buffer>
</binding>
<binding>
<unit>1</unit>
<buffer>depth</buffer>
</binding>
<attachment>
<component>color0</component>
<buffer>hdr-with-atmosphere</buffer>
</attachment>
</pass>
<!--
Average luminance calculation
1. Convert the RGB values to luminance values and store them on a fixed
@ -710,7 +755,7 @@
<effect>Effects/HDR/luminance</effect>
<binding>
<unit>0</unit>
<buffer>hdr-with-atmosphere</buffer>
<buffer>hdr-result</buffer>
</binding>
<attachment>
<component>color</component>
@ -762,7 +807,7 @@
<effect>Effects/HDR/bloom-threshold</effect>
<binding>
<unit>0</unit>
<buffer>hdr-with-atmosphere</buffer>
<buffer>hdr-result</buffer>
</binding>
<binding>
<unit>1</unit>
@ -924,7 +969,7 @@
<effect>Effects/HDR/postprocess</effect>
<binding>
<unit>0</unit>
<buffer>hdr-with-atmosphere</buffer>
<buffer>hdr-result</buffer>
</binding>
<binding>
<unit>1</unit>

View file

@ -1,24 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<PropertyList>
<name>Effects/HDR/atmosphere</name>
<name>Effects/HDR/atmos-aerial-perspective</name>
<technique n="1">
<pass>
<program>
<vertex-shader>Shaders/HDR/trivial.vert</vertex-shader>
<fragment-shader>Shaders/HDR/atmosphere.frag</fragment-shader>
<fragment-shader>Shaders/HDR/atmos-aerial-perspective.frag</fragment-shader>
<fragment-shader>Shaders/HDR/atmosphere-include.frag</fragment-shader>
<fragment-shader>Shaders/HDR/gbuffer-include.frag</fragment-shader>
</program>
<uniform>
<name>hdr_tex</name>
<type>sampler-2d</type>
<value type="int">0</value>
</uniform>
<uniform>
<name>depth_tex</name>
<type>sampler-2d</type>
<value type="int">1</value>
</uniform>
</pass>
</technique>
</PropertyList>

View file

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<PropertyList>
<name>Effects/HDR/atmos-sky-view</name>
<technique n="1">
<pass>
<program>
<vertex-shader>Shaders/HDR/trivial.vert</vertex-shader>
<fragment-shader>Shaders/HDR/atmos-sky-view.frag</fragment-shader>
<fragment-shader>Shaders/HDR/atmosphere-include.frag</fragment-shader>
</program>
</pass>
</technique>
</PropertyList>

View file

@ -67,6 +67,16 @@
<type>sampler-2d-shadow</type>
<value type="int">10</value>
</uniform>
<uniform>
<name>aerial_inscatter_lut</name>
<type>sampler-2d</type>
<value type="int">11</value>
</uniform>
<uniform>
<name>aerial_transmittance_lut</name>
<type>sampler-2d</type>
<value type="int">12</value>
</uniform>
</pass>
</technique>
</PropertyList>

View file

@ -300,6 +300,27 @@
<technique n="109">
<scheme>hdr-geometry</scheme>
</technique>
<technique n="129">
<scheme>hdr-forward</scheme>
<pass>
<cull-face>back</cull-face>
<depth>
<function>lequal</function>
<near>0.0</near>
<far>1.0</far>
<write-mask>true</write-mask>
</depth>
<program>
<vertex-shader>Shaders/HDR/skydome.vert</vertex-shader>
<fragment-shader>Shaders/HDR/skydome.frag</fragment-shader>
</program>
<uniform>
<name>sky_view_lut</name>
<type>sampler-2d</type>
<value type="int">11</value>
</uniform>
</pass>
</technique>
<technique n="139">
<scheme>hdr-envmap</scheme>
<pass>
@ -313,17 +334,11 @@
<program>
<vertex-shader>Shaders/HDR/skydome.vert</vertex-shader>
<fragment-shader>Shaders/HDR/skydome.frag</fragment-shader>
<fragment-shader>Shaders/HDR/atmosphere-include.frag</fragment-shader>
</program>
<uniform>
<name>sun_disk</name>
<type>bool</type>
<value type="bool">false</value>
</uniform>
<uniform>
<name>num_samples</name>
<type>int</type>
<value type="int">16</value>
<name>sky_view_lut</name>
<type>sampler-2d</type>
<value type="int">11</value>
</uniform>
</pass>
</technique>

View file

@ -0,0 +1,47 @@
#version 330 core
layout(location = 0) out vec3 out_inscatter;
layout(location = 1) out vec3 out_transmittance;
in vec2 texCoord;
uniform mat4 fg_ViewMatrixInverse;
uniform vec3 fg_CameraPositionCart;
uniform vec3 fg_CameraPositionGeod;
uniform vec3 fg_SunDirectionWorld;
uniform vec2 fg_NearFar;
const float TOTAL_SLICES = 16.0;
const float DEPTH_RANGE = 32000.0;
vec3 positionFromDepth(vec2 pos, float depth);
void calculateScattering(in vec3 rayOrigin,
in vec3 rayDir,
in float tmax,
in vec3 lightDir,
in float earthRadius,
out vec3 inscatter,
out vec3 transmittance);
void main()
{
float x = texCoord.x * TOTAL_SLICES;
vec2 coord = vec2(fract(x), texCoord.y);
float depth = mix(fg_NearFar.x, DEPTH_RANGE, ceil(x) / TOTAL_SLICES);
vec3 fragPos = positionFromDepth(coord * 2.0 - 1.0, 0.0);
vec3 rayDir = vec4(fg_ViewMatrixInverse * vec4(normalize(fragPos), 0.0)).xyz;
float earthRadius = length(fg_CameraPositionCart) - fg_CameraPositionGeod.z;
vec3 inscatter, transmittance;
calculateScattering(fg_CameraPositionCart,
rayDir,
depth,
fg_SunDirectionWorld,
earthRadius,
inscatter, transmittance);
out_inscatter = inscatter;
out_transmittance = transmittance;
}

View file

@ -0,0 +1,51 @@
#version 330 core
out vec3 fragColor;
in vec2 texCoord;
uniform vec3 fg_CameraPositionCart;
uniform vec3 fg_CameraPositionGeod;
uniform vec3 fg_SunDirectionWorld;
const float PI = 3.141592653;
void calculateScattering(in vec3 rayOrigin,
in vec3 rayDir,
in float tmax,
in vec3 lightDir,
in float earthRadius,
out vec3 inscatter,
out vec3 transmittance);
void main()
{
// Always leave the sun right in the middle of the texture as the skydome
// model is already being rotated.
float sunCosTheta = dot(fg_SunDirectionWorld, normalize(fg_CameraPositionCart));
vec3 lightDir = vec3(-sqrt(1.0 - sunCosTheta*sunCosTheta), 0.0, sunCosTheta);
float azimuth = 2.0 * PI * texCoord.x; // [0, 2pi]
// Apply a non-linear transformation to the elevation to dedicate more
// texels to the horizon, which is where having more detail matters.
float l = texCoord.y * 2.0 - 1.0;
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));
float cameraPosLength = length(fg_CameraPositionCart);
// Since FG internally uses WG84 coordinates, we use the current Earth
// radius under the camera, which varies with the latitude. For practical
// purposes we model the Earth as a perfect sphere with this radius.
float earthRadius = cameraPosLength - fg_CameraPositionGeod.z;
vec3 rayOrigin = vec3(0.0, 0.0, cameraPosLength);
vec3 inscatter, transmittance;
calculateScattering(rayOrigin,
rayDir,
9.0e8,
lightDir,
earthRadius,
inscatter, transmittance);
fragColor = inscatter;
}

View file

@ -1,6 +1,5 @@
#version 330 core
uniform bool sun_disk = true;
uniform vec3 beta_rayleigh = vec3(5.5e-6, 13.0e-6, 22.4e-6);
uniform float beta_mie = 21e-6;
uniform vec3 beta_absortion = vec3(2.04e-5, 4.97e-5, 1.95e-6);
@ -9,54 +8,42 @@ uniform float rayleigh_scale_height = 8e3;
uniform float mie_scale_height = 1.2e3;
uniform float absortion_scale_height = 30e3;
uniform float absortion_falloff = 3e3;
uniform int num_samples = 64;
uniform int num_samples = 32;
uniform int num_light_samples = 4;
const float PI = 3.141592653;
const float ATMOSPHERE_RADIUS = 6471e3;
const vec3 SUN_INTENSITY = vec3(20.0);
const float COS_SUN_ANGULAR_DIAMETER = 0.999956676946448443553574619906976478926848692873900859324;
vec2 raySphereIntersection(vec3 r0, vec3 rd, float radius)
vec2 raySphereIntersection(vec3 ro, vec3 rd, float radius)
{
float a = dot(rd, rd);
float b = 2.0 * dot(rd, r0);
float c = dot(r0, r0) - (radius * radius);
float d = (b*b) - 4.0*a*c;
if (d < 0.0) return vec2(1e5, -1e5);
return vec2((-b - sqrt(d))/(2.0*a), (-b + sqrt(d))/(2.0*a));
vec3 tc = -ro;
float b = dot(tc, rd);
float d = b*b - dot(tc, tc) + radius*radius;
if (d < 0.0) return vec2(-1.0);
float s = sqrt(d);
return vec2(b-s, b+s);
}
vec3 calculateScattering(vec3 rayOrigin,
vec3 rayDir,
vec3 sceneColor,
float depth,
float maxDist,
float earthRadius,
vec3 lightDir)
void calculateScattering(in vec3 rayOrigin,
in vec3 rayDir,
in float tmax,
in vec3 lightDir,
in float earthRadius,
out vec3 inscatter,
out vec3 transmittance)
{
vec2 hit = raySphereIntersection(rayOrigin, rayDir, ATMOSPHERE_RADIUS);
if (hit.x > hit.y) {
// The ray did not hit the atmosphere, we are in outer space
return sceneColor;
}
hit.x = max(hit.x, 0.0); // Do not sample behind the camera
// Avoid clamping the ray to the far plane when there is no geometry in
// front of the sky
if (depth < 1.0) {
// Stop the ray at the geometry
hit.y = min(hit.y, maxDist);
} else {
// If there is no geometry, simulate a collision with the Earth at sea
// level. This only happens when FG hasn't loaded any terrain
vec2 hitEarth = raySphereIntersection(
rayOrigin, rayDir, earthRadius - 1.0);
if (hitEarth.x < hitEarth.y && hitEarth.x > 0.0) {
hit.y = min(hit.y, hitEarth.x);
}
}
vec2 hitEarth = raySphereIntersection(rayOrigin, rayDir, earthRadius - 1.0);
if (hitEarth.y > 0.0)
tmax = max(0.0, hitEarth.x);
float stepSize = (hit.y - hit.x) / float(num_samples);
float tmin = max(hit.x, 0.0);
tmax = min(hit.y, tmax);
if (tmax < 0.0)
discard;
float stepSize = (tmax - tmin) / float(num_samples);
const float g = 0.758; // Mie scattering direction
const float gg = g*g;
@ -70,7 +57,7 @@ vec3 calculateScattering(vec3 rayOrigin,
float opticalDepthMie = 0.0;
float opticalDepthAbsortion = 0.0;
float primaryTime = hit.x;
float primaryTime = tmin;
vec3 extinctionFactor = vec3(0.0);
vec3 totalRayleigh = vec3(0.0);
@ -100,11 +87,14 @@ vec3 calculateScattering(vec3 rayOrigin,
float secondaryTime = 0.0;
for (int j = 0; j < num_light_samples; ++j) {
int j;
for (j = 0; j < num_light_samples; ++j) {
vec3 samplePointLight = samplePoint + lightDir *
(secondaryTime + stepSizeLight * 0.5);
float altitudeLight = length(samplePointLight) - earthRadius;
if (altitudeLight < 0.0)
break;
float densityLightRayleigh = exp(-altitudeLight / rayleigh_scale_height);
float densityLightMie = exp(-altitudeLight / mie_scale_height);
@ -116,37 +106,28 @@ vec3 calculateScattering(vec3 rayOrigin,
secondaryTime += stepSizeLight;
}
vec3 tau =
beta_rayleigh * (opticalDepthRayleigh + opticalDepthLightRayleigh) +
beta_mie * (opticalDepthMie + opticalDepthLightMie) +
beta_absortion * (opticalDepthAbsortion + opticalDepthLightAbsortion);
vec3 attenuation = exp(-tau);
if (j == num_light_samples) {
vec3 tau =
beta_rayleigh * (opticalDepthRayleigh + opticalDepthLightRayleigh) +
beta_mie * (opticalDepthMie + opticalDepthLightMie) +
beta_absortion * (opticalDepthAbsortion + opticalDepthLightAbsortion);
vec3 attenuation = exp(-tau);
extinctionFactor += attenuation;
extinctionFactor += attenuation;
totalRayleigh += stepOpticalDepthRayleigh * attenuation;
totalMie += stepOpticalDepthMie * attenuation;
totalRayleigh += stepOpticalDepthRayleigh * attenuation;
totalMie += stepOpticalDepthMie * attenuation;
}
primaryTime += stepSize;
}
vec3 opacity = exp(-(beta_rayleigh * opticalDepthRayleigh +
beta_mie * opticalDepthMie +
beta_absortion * opticalDepthAbsortion));
transmittance = exp(-(beta_rayleigh * opticalDepthRayleigh +
beta_mie * opticalDepthMie +
beta_absortion * opticalDepthAbsortion));
vec3 color = SUN_INTENSITY *
inscatter = SUN_INTENSITY *
(totalRayleigh * beta_rayleigh * phaseRayleigh +
totalMie * beta_mie * phaseMie +
opticalDepthRayleigh * beta_ambient)
+ sceneColor * opacity;
if (sun_disk && (depth >= 1.0)) {
float costheta = dot(rayDir, lightDir);
float sundisk = smoothstep(COS_SUN_ANGULAR_DIAMETER,
COS_SUN_ANGULAR_DIAMETER + 0.00002,
costheta);
color += SUN_INTENSITY * extinctionFactor * sundisk;
}
return color;
opticalDepthRayleigh * beta_ambient);
}

View file

@ -1,48 +0,0 @@
#version 330 core
out vec3 fragColor;
in vec2 texCoord;
uniform mat4 fg_ViewMatrixInverse;
uniform mat4 fg_ProjectionMatrixInverse;
uniform vec3 fg_CameraPositionCart;
uniform vec3 fg_CameraPositionGeod;
uniform vec3 fg_SunDirection;
uniform vec2 fg_BufferSize;
uniform sampler2D hdr_tex;
uniform sampler2D depth_tex;
vec3 calculateScattering(vec3 rayOrigin,
vec3 rayDir,
vec3 sceneColor,
float depth,
float maxDist,
float earthRadius,
vec3 lightDir);
vec3 positionFromDepth(vec2 pos, float depth);
void main()
{
float depth = texture(depth_tex, texCoord).r;
vec3 fragPos = positionFromDepth(texCoord * 2.0 - 1.0,
depth * 2.0 - 1.0);
vec3 rayDir = vec4(fg_ViewMatrixInverse * vec4(normalize(fragPos), 0.0)).xyz;
// Since FG internally uses WG84 coordinates, we use the current Earth
// radius under the camera, which varies with the latitude. For practical
// purposes we model the Earth as a perfect sphere with this radius.
float earthRadius = length(fg_CameraPositionCart) - fg_CameraPositionGeod.z;
vec3 sceneColor = texture(hdr_tex, texCoord).rgb;
vec3 color = calculateScattering(fg_CameraPositionCart,
rayDir,
sceneColor,
depth,
length(fragPos),
earthRadius,
fg_SunDirection);
fragColor = color;
}

View file

@ -12,11 +12,14 @@ uniform sampler2D ao_tex;
uniform samplerCube prefiltered_envmap;
uniform sampler2DShadow shadow_tex;
uniform sampler2D dfg_lut;
uniform sampler2D aerial_inscatter_lut;
uniform sampler2D aerial_transmittance_lut;
uniform mat4 fg_ViewMatrix;
uniform mat4 fg_ViewMatrixInverse;
uniform vec3 fg_SunDirection;
uniform vec3 fg_CameraPositionCart;
uniform vec2 fg_NearFar;
uniform mat4 fg_LightMatrix_csm0;
uniform mat4 fg_LightMatrix_csm1;
@ -40,6 +43,11 @@ const vec2 uv_shifts[4] = vec2[4](
vec2(0.0, 0.5), vec2(0.5, 0.5));
const vec2 uv_factor = vec2(0.5, 0.5);
const float AERIAL_SLICES = 16.0;
const float AERIAL_LUT_TILE_SIZE = 1.0 / AERIAL_SLICES;
const float AERIAL_LUT_TEXEL_SIZE = 1.0 / 512.0;
const float AERIAL_MAX_DEPTH = 32000.0;
const float MAX_PREFILTERED_LOD = 4.0;
const vec3 SUN_INTENSITY = vec3(20.0);
@ -163,10 +171,10 @@ float getShadowing(vec3 p, vec3 n, float NdotL)
float shadow = 1.0;
vec4 lightSpacePos[4];
lightSpacePos[0] = getLightSpacePosition(p, n, NdotL, 0.01, fg_LightMatrix_csm0);
lightSpacePos[1] = getLightSpacePosition(p, n, NdotL, 0.01, fg_LightMatrix_csm1);
lightSpacePos[2] = getLightSpacePosition(p, n, NdotL, 0.01, fg_LightMatrix_csm2);
lightSpacePos[3] = getLightSpacePosition(p, n, NdotL, 0.01, fg_LightMatrix_csm3);
lightSpacePos[0] = getLightSpacePosition(p, n, NdotL, 0.05, fg_LightMatrix_csm0);
lightSpacePos[1] = getLightSpacePosition(p, n, NdotL, 0.2, fg_LightMatrix_csm1);
lightSpacePos[2] = getLightSpacePosition(p, n, NdotL, 1.0, fg_LightMatrix_csm2);
lightSpacePos[3] = getLightSpacePosition(p, n, NdotL, 5.0, fg_LightMatrix_csm3);
for (int i = 0; i < 4; ++i) {
// Map-based cascade selection
@ -322,15 +330,44 @@ vec3 BRDF(in vec3 albedo, in float metalness, in float roughness,
//------------------------------------------------------------------------------
float map(float value, float min1, float max1, float min2, float max2) {
return min2 + (value - min1) * (max2 - min2) / (max1 - min1);
}
vec3 sampleAerialPerspectiveSlice(sampler2D tex, int slice)
{
float offset = slice * AERIAL_LUT_TILE_SIZE + AERIAL_LUT_TEXEL_SIZE * 0.5;
float x = texCoord.x * (AERIAL_LUT_TILE_SIZE - AERIAL_LUT_TEXEL_SIZE) + offset;
return texture(tex, vec2(x, texCoord.y)).rgb;
}
vec3 sampleAerialPerspective(sampler2D tex, vec3 zero, float depth)
{
vec3 color;
depth = min(abs(depth), AERIAL_MAX_DEPTH);
float d = map(depth, fg_NearFar.x, AERIAL_MAX_DEPTH, 0.0, AERIAL_SLICES);
if (d <= 1.0) {
color = mix(zero, sampleAerialPerspectiveSlice(tex, 0), d);
} else {
d -= 1.0;
color = mix(sampleAerialPerspectiveSlice(tex, int(floor(d))),
sampleAerialPerspectiveSlice(tex, int(ceil(d))),
fract(d));
}
return color;
}
//------------------------------------------------------------------------------
void main()
{
float depth = texture(depth_tex, texCoord).r;
vec4 gbuffer0 = texture(gbuffer0_tex, texCoord);
vec2 gbuffer1 = texture(gbuffer1_tex, texCoord).rg;
vec4 gbuffer2 = texture(gbuffer2_tex, texCoord);
float depth = texture(depth_tex, texCoord).r * 2.0 - 1.0; // Clip space
float ao = texture(ao_tex, texCoord).r;
vec3 pos = positionFromDepth(texCoord * 2.0 - 1.0, depth);
vec3 pos = positionFromDepth(texCoord * 2.0 - 1.0, depth * 2.0 - 1.0);
vec3 v = normalize(-pos);
vec3 n = decodeNormal(gbuffer1);
@ -341,7 +378,7 @@ void main()
float clearcoat = gbuffer2.b;
float clearcoatRoughness = gbuffer2.a;
vec3 l = normalize(vec4(fg_ViewMatrix * vec4(fg_SunDirection, 0.0)).xyz);
vec3 l = fg_SunDirection;
vec3 h = normalize(v + l);
float NdotL = clamp(dot(n, l), 0.001, 1.0);
@ -366,5 +403,10 @@ void main()
float shadowFactor = getShadowing(pos, n, NdotL);
vec3 color = ambient + brdf * sunIlluminance * shadowFactor;
fragHdrColor = color;
vec3 inscatter = sampleAerialPerspective(
aerial_inscatter_lut, vec3(0.0), length(pos));
vec3 transmittance = sampleAerialPerspective(
aerial_transmittance_lut, vec3(1.0), length(pos));
fragHdrColor = color * transmittance + inscatter;
}

View file

@ -2,39 +2,19 @@
out vec4 fragColor;
in vec3 rayDirVertex;
in vec3 rayDir;
uniform mat4 osg_ModelViewMatrix;
uniform mat4 osg_ViewMatrix;
uniform vec3 fg_SunDirection;
uniform sampler2D sky_view_lut;
vec3 calculateScattering(vec3 rayOrigin,
vec3 rayDir,
vec3 sceneColor,
float depth,
float maxDist,
float earthRadius,
vec3 lightDir);
const float PI = 3.141592653;
void main()
{
// Ground point (skydome center) in eye coordinates
vec4 groundPoint = inverse(osg_ViewMatrix) * osg_ModelViewMatrix
* vec4(0.0, 0.0, 0.0, 1.0);
float azimuth = atan(rayDir.y, rayDir.x) / PI * 0.5 + 0.5;
// Undo the non-linear transformation from the sky-view LUT
float l = asin(rayDir.z);
float elev = sqrt(abs(l) / (PI * 0.5)) * sign(l) * 0.5 + 0.5;
// HACK: WGS84 models the Earth as an oblate spheroid, so we can't use
// a constant Earth radius. This should be precomputed!
float earthRadius = length(groundPoint);
vec3 cameraPos = vec4(inverse(osg_ViewMatrix) * vec4(0.0, 0.0, 0.0, 1.0)).xyz;
vec3 rayDir = normalize(rayDirVertex);
vec3 color = calculateScattering(cameraPos,
rayDir,
vec3(0.0),
1.0,
3.0 * earthRadius,
earthRadius,
fg_SunDirection);
vec3 color = texture(sky_view_lut, vec2(azimuth, elev)).rgb;
fragColor = vec4(color, 1.0);
}

View file

@ -2,17 +2,12 @@
layout(location = 0) in vec4 pos;
out vec3 rayDirVertex;
out vec3 rayDir;
uniform mat4 osg_ModelViewMatrix;
uniform mat4 osg_ModelViewProjectionMatrix;
uniform mat4 osg_ViewMatrix;
void main()
{
gl_Position = osg_ModelViewProjectionMatrix * pos;
vec4 rayDirView = normalize(osg_ModelViewMatrix * pos);
rayDirView.w = 0.0;
rayDirVertex = vec4(inverse(osg_ViewMatrix) * rayDirView).xyz;
rayDirVertex = normalize(rayDirVertex);
rayDir = normalize(pos.xyz);
}