From 7b0211031ac7044dba26baaed3a62445d4f62c4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Garc=C3=ADa=20Li=C3=B1=C3=A1n?= <fernandogarcialinan@gmail.com> Date: Sun, 7 Jan 2024 16:18:55 +0100 Subject: [PATCH] HDR: Improve stars rendering Previously we did not take into account the atmospheric transmittance to render the stars, leading to stars being incorrectly rendered in low visibility conditions. Also place the stars in the correct render bin. --- Effects/stars.eff | 30 +++++++++++++++++++++++++++--- Shaders/HDR/stars.frag | 40 +++++++++++++++++++++++++++++++++++++++- Shaders/HDR/stars.vert | 3 +++ 3 files changed, 69 insertions(+), 4 deletions(-) diff --git a/Effects/stars.eff b/Effects/stars.eff index 648f3dbd9..e6e950016 100644 --- a/Effects/stars.eff +++ b/Effects/stars.eff @@ -4,7 +4,7 @@ <name>Effects/stars</name> <parameters> - <max-radiance type="float">2.0</max-radiance> + <max-radiance type="float">50.0</max-radiance> </parameters> <!-- Fixed-pipeline fallback --> @@ -20,6 +20,7 @@ <technique n="129"> <scheme>hdr-forward</scheme> <pass> + <!-- Disable depth testing --> <depth> <enabled>false</enabled> </depth> @@ -28,21 +29,44 @@ <function>equal</function> <value>0</value> </stencil> + <!-- Make sure we render after the skydome --> + <render-bin> + <bin-number>-9</bin-number> + <bin-name>RenderBin</bin-name> + </render-bin> <cull-face>off</cull-face> + <!-- Additive blending to add the sky in-scattering from the skydome --> <blend> <active>true</active> - <source>src-alpha</source> - <destination>one-minus-src-alpha</destination> + <source>one</source> + <destination>one</destination> </blend> <program> <vertex-shader>Shaders/HDR/stars.vert</vertex-shader> <fragment-shader>Shaders/HDR/stars.frag</fragment-shader> + <fragment-shader>Shaders/HDR/exposure.glsl</fragment-shader> </program> <uniform> <name>max_radiance</name> <type>float</type> <value><use>max-radiance</use></value> </uniform> + <uniform> + <name>transmittance_tex</name> + <type>sampler-2d</type> + <value type="int">12</value> + </uniform> + <!-- exposure.glsl --> + <uniform> + <name>lum_tex</name> + <type>sampler-2d</type> + <value type="int">14</value> + </uniform> + <uniform> + <name>exposure_compensation</name> + <type>float</type> + <value><use>exposure-compensation</use></value> + </uniform> </pass> </technique> </PropertyList> diff --git a/Shaders/HDR/stars.frag b/Shaders/HDR/stars.frag index ff56fb78b..ed0130ccc 100644 --- a/Shaders/HDR/stars.frag +++ b/Shaders/HDR/stars.frag @@ -4,11 +4,49 @@ layout(location = 0) out vec4 fragColor; in VS_OUT { vec4 color; + vec3 view_vector; } fs_in; +uniform sampler2D transmittance_tex; + uniform float max_radiance; +uniform float fg_CameraDistanceToEarthCenter; +uniform float fg_EarthRadius; +uniform vec3 fg_CameraViewUp; + +const float ATMOSPHERE_RADIUS = 6471e3; + +// exposure.glsl +vec3 apply_exposure(vec3 color); + void main() { - fragColor = vec4(fs_in.color.rgb * max_radiance, fs_in.color.a); + vec3 color = fs_in.color.rgb * fs_in.color.a * max_radiance; + + vec3 V = normalize(fs_in.view_vector); + + // Apply aerial perspective + float normalized_altitude = + (fg_CameraDistanceToEarthCenter - fg_EarthRadius) + / (ATMOSPHERE_RADIUS - fg_EarthRadius); + float cos_theta = dot(-V, fg_CameraViewUp); + + vec2 uv = vec2(cos_theta * 0.5 + 0.5, clamp(normalized_altitude, 0.0, 1.0)); + vec4 transmittance = texture(transmittance_tex, uv); + + // The proper thing would be to have spectral data for the stars' radiance. + // This could be approximated by taking the star's temperature and using + // Plank's law to obtain the spectral radiance for our 4 wavelengths. + // That's too complicated for now, so instead we just average the four + // spectral samples from the atmospheric transmittance. + color *= dot(transmittance, vec4(0.25)); + + // Pre-expose + color = apply_exposure(color); + + // Final color = transmittance * star radiance + sky inscattering + // In this frag shader we output the multiplication part, and the sky + // in-scattering is added by doing additive blending on top of the skydome. + fragColor = vec4(color, 1.0); } diff --git a/Shaders/HDR/stars.vert b/Shaders/HDR/stars.vert index cca905cd2..fa3f02758 100644 --- a/Shaders/HDR/stars.vert +++ b/Shaders/HDR/stars.vert @@ -5,12 +5,15 @@ layout(location = 2) in vec4 vertex_color; out VS_OUT { vec4 color; + vec3 view_vector; } vs_out; +uniform mat4 osg_ModelViewMatrix; uniform mat4 osg_ModelViewProjectionMatrix; void main() { gl_Position = osg_ModelViewProjectionMatrix * pos; vs_out.color = vertex_color; + vs_out.view_vector = (osg_ModelViewMatrix * pos).xyz; }