1
0
Fork 0

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.
This commit is contained in:
Fernando García Liñán 2024-01-07 16:18:55 +01:00
parent 00b4275ee8
commit 7b0211031a
3 changed files with 69 additions and 4 deletions

View file

@ -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>

View file

@ -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);
}

View file

@ -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;
}