diff --git a/Compositor/HDR/env-capture-pass.xml b/Compositor/HDR/env-capture-pass.xml index a661e8317..b8fa9ac3c 100644 --- a/Compositor/HDR/env-capture-pass.xml +++ b/Compositor/HDR/env-capture-pass.xml @@ -5,9 +5,17 @@ depth hdr-envmap depth - - - 0x800 + + 0x1801 + + 12 + transmittance + 13 sky-view diff --git a/Compositor/HDR/env-prefilter-pass.xml b/Compositor/HDR/env-prefilter-pass.xml index f32ea3a35..ddecddf18 100644 --- a/Compositor/HDR/env-prefilter-pass.xml +++ b/Compositor/HDR/env-prefilter-pass.xml @@ -6,4 +6,7 @@ 0 envmap + + /sim/rendering/hdr/envmap/should-prefilter + diff --git a/Compositor/HDR/hdr.xml b/Compositor/HDR/hdr.xml index 1be08eb40..64558e1ca 100644 --- a/Compositor/HDR/hdr.xml +++ b/Compositor/HDR/hdr.xml @@ -343,6 +343,9 @@ envmap 0 + + /sim/rendering/hdr/envmap/should-render-face-0 + env-capture1 @@ -352,6 +355,9 @@ envmap 1 + + /sim/rendering/hdr/envmap/should-render-face-1 + env-capture2 @@ -361,6 +367,9 @@ envmap 2 + + /sim/rendering/hdr/envmap/should-render-face-2 + env-capture3 @@ -370,6 +379,9 @@ envmap 3 + + /sim/rendering/hdr/envmap/should-render-face-3 + env-capture4 @@ -379,6 +391,9 @@ envmap 4 + + /sim/rendering/hdr/envmap/should-render-face-4 + env-capture5 @@ -390,6 +405,9 @@ true + + /sim/rendering/hdr/envmap/should-render-face-5 + transmittance_tex sampler-2d diff --git a/Effects/HDR/water-shading.eff b/Effects/HDR/water-shading.eff index 94659d378..e7dc3bf90 100644 --- a/Effects/HDR/water-shading.eff +++ b/Effects/HDR/water-shading.eff @@ -19,6 +19,7 @@ Shaders/HDR/math.glsl Shaders/HDR/normal_encoding.glsl Shaders/HDR/pos_from_depth.glsl + Shaders/HDR/sun.glsl Shaders/HDR/aerial_perspective.glsl Shaders/HDR/atmos_spectral.glsl Shaders/HDR/exposure.glsl @@ -50,6 +51,7 @@ sampler-2d 11 + transmittance_tex sampler-2d diff --git a/Effects/cloud-impostor.eff b/Effects/cloud-impostor.eff index 4b4ac6879..7859014b5 100644 --- a/Effects/cloud-impostor.eff +++ b/Effects/cloud-impostor.eff @@ -25,6 +25,43 @@ /sim/rendering/hdr/exposure-compensation + + + /sim/rendering/hdr/atmos/aerosol-absorption-cross-section[0] + /sim/rendering/hdr/atmos/aerosol-absorption-cross-section[1] + /sim/rendering/hdr/atmos/aerosol-absorption-cross-section[2] + /sim/rendering/hdr/atmos/aerosol-absorption-cross-section[3] + + + /sim/rendering/hdr/atmos/aerosol-scattering-cross-section[0] + /sim/rendering/hdr/atmos/aerosol-scattering-cross-section[1] + /sim/rendering/hdr/atmos/aerosol-scattering-cross-section[2] + /sim/rendering/hdr/atmos/aerosol-scattering-cross-section[3] + + + /sim/rendering/hdr/atmos/aerosol-base-density + + + /sim/rendering/hdr/atmos/aerosol-relative-background-density + + + /sim/rendering/hdr/atmos/aerosol-scale-height + + + /sim/rendering/hdr/atmos/fog-density + + + /sim/rendering/hdr/atmos/fog-scale-height + + + /sim/rendering/hdr/atmos/ozone-mean-dobson + + + /sim/rendering/hdr/atmos/ground-albedo[0] + /sim/rendering/hdr/atmos/ground-albedo[1] + /sim/rendering/hdr/atmos/ground-albedo[2] + /sim/rendering/hdr/atmos/ground-albedo[3] + @@ -263,9 +300,12 @@ transparent Shaders/HDR/cloud_static.vert + Shaders/HDR/cloud_static_common.vert + Shaders/HDR/sun.glsl Shaders/HDR/aerial_perspective.glsl Shaders/HDR/atmos_spectral.glsl Shaders/HDR/3dcloud.frag + Shaders/HDR/3dcloud_common.frag Shaders/HDR/aerial_perspective.glsl Shaders/HDR/exposure.glsl @@ -280,6 +320,7 @@ sampler-2d 11 + transmittance_tex sampler-2d @@ -298,4 +339,92 @@ + + + hdr-envmap + + + false + + + 0 + 2d + texture[0]/image + clamp-to-border + clamp-to-border + + 1 + transparent + + Shaders/HDR/cloud_static_envmap.vert + Shaders/HDR/cloud_static_common.vert + Shaders/HDR/math.glsl + Shaders/HDR/sun.glsl + Shaders/HDR/aerial_perspective_envmap.glsl + Shaders/HDR/atmos.glsl + Shaders/HDR/atmos_spectral.glsl + Shaders/HDR/3dcloud_envmap.frag + Shaders/HDR/3dcloud_common.frag + Shaders/HDR/aerial_perspective_envmap.glsl + + + base_tex + sampler-2d + 0 + + + + + transmittance_tex + sampler-2d + 12 + + + + aerosol_absorption_cross_section + float-vec4 + aerosol-absorption-cross-section + + + aerosol_scattering_cross_section + float-vec4 + aerosol-scattering-cross-section + + + aerosol_base_density + float + aerosol-base-density + + + aerosol_relative_background_density + float + aerosol-relative-background-density + + + aerosol_scale_height + float + aerosol-scale-height + + + fog_density + float + fog-density + + + fog_scale_height + float + fog-scale-height + + + ozone_mean_dobson + float + ozone-mean-dobson + + + ground_albedo + float-vec4 + ground-albedo + + + diff --git a/Effects/cloud-noctilucent.eff b/Effects/cloud-noctilucent.eff index 6ffc58b28..d25bdbdb7 100644 --- a/Effects/cloud-noctilucent.eff +++ b/Effects/cloud-noctilucent.eff @@ -12,6 +12,43 @@ /sim/rendering/hdr/exposure-compensation + + + /sim/rendering/hdr/atmos/aerosol-absorption-cross-section[0] + /sim/rendering/hdr/atmos/aerosol-absorption-cross-section[1] + /sim/rendering/hdr/atmos/aerosol-absorption-cross-section[2] + /sim/rendering/hdr/atmos/aerosol-absorption-cross-section[3] + + + /sim/rendering/hdr/atmos/aerosol-scattering-cross-section[0] + /sim/rendering/hdr/atmos/aerosol-scattering-cross-section[1] + /sim/rendering/hdr/atmos/aerosol-scattering-cross-section[2] + /sim/rendering/hdr/atmos/aerosol-scattering-cross-section[3] + + + /sim/rendering/hdr/atmos/aerosol-base-density + + + /sim/rendering/hdr/atmos/aerosol-relative-background-density + + + /sim/rendering/hdr/atmos/aerosol-scale-height + + + /sim/rendering/hdr/atmos/fog-density + + + /sim/rendering/hdr/atmos/fog-scale-height + + + /sim/rendering/hdr/atmos/ozone-mean-dobson + + + /sim/rendering/hdr/atmos/ground-albedo[0] + /sim/rendering/hdr/atmos/ground-albedo[1] + /sim/rendering/hdr/atmos/ground-albedo[2] + /sim/rendering/hdr/atmos/ground-albedo[3] + @@ -183,9 +220,12 @@ transparent Shaders/HDR/cloud_static.vert + Shaders/HDR/cloud_static_common.vert + Shaders/HDR/sun.glsl Shaders/HDR/aerial_perspective.glsl Shaders/HDR/atmos_spectral.glsl Shaders/HDR/3dcloud.frag + Shaders/HDR/3dcloud_common.frag Shaders/HDR/aerial_perspective.glsl Shaders/HDR/exposure.glsl @@ -200,6 +240,7 @@ sampler-2d 11 + transmittance_tex sampler-2d @@ -218,4 +259,92 @@ + + + hdr-envmap + + + false + + + 0 + 2d + texture[0]/image + clamp-to-border + clamp-to-border + + 1 + transparent + + Shaders/HDR/cloud_static_envmap.vert + Shaders/HDR/cloud_static_common.vert + Shaders/HDR/math.glsl + Shaders/HDR/sun.glsl + Shaders/HDR/aerial_perspective_envmap.glsl + Shaders/HDR/atmos.glsl + Shaders/HDR/atmos_spectral.glsl + Shaders/HDR/3dcloud_envmap.frag + Shaders/HDR/3dcloud_common.frag + Shaders/HDR/aerial_perspective_envmap.glsl + + + base_tex + sampler-2d + 0 + + + + + transmittance_tex + sampler-2d + 12 + + + + aerosol_absorption_cross_section + float-vec4 + aerosol-absorption-cross-section + + + aerosol_scattering_cross_section + float-vec4 + aerosol-scattering-cross-section + + + aerosol_base_density + float + aerosol-base-density + + + aerosol_relative_background_density + float + aerosol-relative-background-density + + + aerosol_scale_height + float + aerosol-scale-height + + + fog_density + float + fog-density + + + fog_scale_height + float + fog-scale-height + + + ozone_mean_dobson + float + ozone-mean-dobson + + + ground_albedo + float-vec4 + ground-albedo + + + diff --git a/Effects/cloud-static.eff b/Effects/cloud-static.eff index b34feceda..1daf465e2 100644 --- a/Effects/cloud-static.eff +++ b/Effects/cloud-static.eff @@ -24,6 +24,43 @@ /sim/rendering/hdr/exposure-compensation + + + /sim/rendering/hdr/atmos/aerosol-absorption-cross-section[0] + /sim/rendering/hdr/atmos/aerosol-absorption-cross-section[1] + /sim/rendering/hdr/atmos/aerosol-absorption-cross-section[2] + /sim/rendering/hdr/atmos/aerosol-absorption-cross-section[3] + + + /sim/rendering/hdr/atmos/aerosol-scattering-cross-section[0] + /sim/rendering/hdr/atmos/aerosol-scattering-cross-section[1] + /sim/rendering/hdr/atmos/aerosol-scattering-cross-section[2] + /sim/rendering/hdr/atmos/aerosol-scattering-cross-section[3] + + + /sim/rendering/hdr/atmos/aerosol-base-density + + + /sim/rendering/hdr/atmos/aerosol-relative-background-density + + + /sim/rendering/hdr/atmos/aerosol-scale-height + + + /sim/rendering/hdr/atmos/fog-density + + + /sim/rendering/hdr/atmos/fog-scale-height + + + /sim/rendering/hdr/atmos/ozone-mean-dobson + + + /sim/rendering/hdr/atmos/ground-albedo[0] + /sim/rendering/hdr/atmos/ground-albedo[1] + /sim/rendering/hdr/atmos/ground-albedo[2] + /sim/rendering/hdr/atmos/ground-albedo[3] + @@ -391,9 +428,12 @@ transparent Shaders/HDR/cloud_static.vert + Shaders/HDR/cloud_static_common.vert + Shaders/HDR/sun.glsl Shaders/HDR/aerial_perspective.glsl Shaders/HDR/atmos_spectral.glsl Shaders/HDR/3dcloud.frag + Shaders/HDR/3dcloud_common.frag Shaders/HDR/aerial_perspective.glsl Shaders/HDR/exposure.glsl @@ -408,6 +448,7 @@ sampler-2d 11 + transmittance_tex sampler-2d @@ -426,4 +467,92 @@ + + + hdr-envmap + + + false + + + 0 + 2d + texture[0]/image + clamp-to-border + clamp-to-border + + 1 + transparent + + Shaders/HDR/cloud_static_envmap.vert + Shaders/HDR/cloud_static_common.vert + Shaders/HDR/math.glsl + Shaders/HDR/sun.glsl + Shaders/HDR/aerial_perspective_envmap.glsl + Shaders/HDR/atmos.glsl + Shaders/HDR/atmos_spectral.glsl + Shaders/HDR/3dcloud_envmap.frag + Shaders/HDR/3dcloud_common.frag + Shaders/HDR/aerial_perspective_envmap.glsl + + + base_tex + sampler-2d + 0 + + + + + transmittance_tex + sampler-2d + 12 + + + + aerosol_absorption_cross_section + float-vec4 + aerosol-absorption-cross-section + + + aerosol_scattering_cross_section + float-vec4 + aerosol-scattering-cross-section + + + aerosol_base_density + float + aerosol-base-density + + + aerosol_relative_background_density + float + aerosol-relative-background-density + + + aerosol_scale_height + float + aerosol-scale-height + + + fog_density + float + fog-density + + + fog_scale_height + float + fog-scale-height + + + ozone_mean_dobson + float + ozone-mean-dobson + + + ground_albedo + float-vec4 + ground-albedo + + + diff --git a/Effects/cloud.eff b/Effects/cloud.eff index 0a0b8ae92..e91183bde 100644 --- a/Effects/cloud.eff +++ b/Effects/cloud.eff @@ -31,6 +31,43 @@ /sim/rendering/hdr/exposure-compensation + + + /sim/rendering/hdr/atmos/aerosol-absorption-cross-section[0] + /sim/rendering/hdr/atmos/aerosol-absorption-cross-section[1] + /sim/rendering/hdr/atmos/aerosol-absorption-cross-section[2] + /sim/rendering/hdr/atmos/aerosol-absorption-cross-section[3] + + + /sim/rendering/hdr/atmos/aerosol-scattering-cross-section[0] + /sim/rendering/hdr/atmos/aerosol-scattering-cross-section[1] + /sim/rendering/hdr/atmos/aerosol-scattering-cross-section[2] + /sim/rendering/hdr/atmos/aerosol-scattering-cross-section[3] + + + /sim/rendering/hdr/atmos/aerosol-base-density + + + /sim/rendering/hdr/atmos/aerosol-relative-background-density + + + /sim/rendering/hdr/atmos/aerosol-scale-height + + + /sim/rendering/hdr/atmos/fog-density + + + /sim/rendering/hdr/atmos/fog-scale-height + + + /sim/rendering/hdr/atmos/ozone-mean-dobson + + + /sim/rendering/hdr/atmos/ground-albedo[0] + /sim/rendering/hdr/atmos/ground-albedo[1] + /sim/rendering/hdr/atmos/ground-albedo[2] + /sim/rendering/hdr/atmos/ground-albedo[3] + @@ -504,9 +541,12 @@ transparent Shaders/HDR/3dcloud.vert + Shaders/HDR/3dcloud_common.vert + Shaders/HDR/sun.glsl Shaders/HDR/aerial_perspective.glsl Shaders/HDR/atmos_spectral.glsl Shaders/HDR/3dcloud.frag + Shaders/HDR/3dcloud_common.frag Shaders/HDR/aerial_perspective.glsl Shaders/HDR/exposure.glsl @@ -539,6 +579,7 @@ sampler-2d 11 + transmittance_tex sampler-2d @@ -557,4 +598,110 @@ + + + hdr-envmap + + + false + + + 0 + 2d + texture[0]/image + clamp-to-border + clamp-to-border + + 1 + transparent + + Shaders/HDR/3dcloud_envmap.vert + Shaders/HDR/3dcloud_common.vert + Shaders/HDR/math.glsl + Shaders/HDR/sun.glsl + Shaders/HDR/aerial_perspective_envmap.glsl + Shaders/HDR/atmos.glsl + Shaders/HDR/atmos_spectral.glsl + Shaders/HDR/3dcloud_envmap.frag + Shaders/HDR/3dcloud_common.frag + Shaders/HDR/aerial_perspective_envmap.glsl + + usrAttr1 + 10 + + + usrAttr2 + 11 + + + + base_tex + sampler-2d + 0 + + + range + float + range + + + detail_range + float + detail + + + + + transmittance_tex + sampler-2d + 12 + + + + aerosol_absorption_cross_section + float-vec4 + aerosol-absorption-cross-section + + + aerosol_scattering_cross_section + float-vec4 + aerosol-scattering-cross-section + + + aerosol_base_density + float + aerosol-base-density + + + aerosol_relative_background_density + float + aerosol-relative-background-density + + + aerosol_scale_height + float + aerosol-scale-height + + + fog_density + float + fog-density + + + fog_scale_height + float + fog-scale-height + + + ozone_mean_dobson + float + ozone-mean-dobson + + + ground_albedo + float-vec4 + ground-albedo + + + diff --git a/Effects/model-pbr-transparent.eff b/Effects/model-pbr-transparent.eff index 3c4261ace..a07386c5a 100644 --- a/Effects/model-pbr-transparent.eff +++ b/Effects/model-pbr-transparent.eff @@ -102,6 +102,7 @@ Shaders/HDR/surface.glsl Shaders/HDR/ibl.glsl Shaders/HDR/shadows.glsl + Shaders/HDR/sun.glsl Shaders/HDR/aerial_perspective.glsl Shaders/HDR/atmos_spectral.glsl Shaders/HDR/clustered.glsl @@ -185,6 +186,7 @@ sampler-2d 11 + transmittance_tex sampler-2d diff --git a/Effects/model-transparent.eff b/Effects/model-transparent.eff index 6f716bed1..f1d0dafd4 100644 --- a/Effects/model-transparent.eff +++ b/Effects/model-transparent.eff @@ -106,6 +106,7 @@ Shaders/HDR/surface.glsl Shaders/HDR/ibl.glsl Shaders/HDR/shadows.glsl + Shaders/HDR/sun.glsl Shaders/HDR/aerial_perspective.glsl Shaders/HDR/atmos_spectral.glsl Shaders/HDR/clustered.glsl @@ -154,6 +155,7 @@ sampler-2d 11 + transmittance_tex sampler-2d diff --git a/Effects/terrain-default.eff b/Effects/terrain-default.eff index 2e341320a..d6874b926 100644 --- a/Effects/terrain-default.eff +++ b/Effects/terrain-default.eff @@ -189,6 +189,43 @@ /sim/rendering/shadows/sun-atlas-size + + + /sim/rendering/hdr/atmos/aerosol-absorption-cross-section[0] + /sim/rendering/hdr/atmos/aerosol-absorption-cross-section[1] + /sim/rendering/hdr/atmos/aerosol-absorption-cross-section[2] + /sim/rendering/hdr/atmos/aerosol-absorption-cross-section[3] + + + /sim/rendering/hdr/atmos/aerosol-scattering-cross-section[0] + /sim/rendering/hdr/atmos/aerosol-scattering-cross-section[1] + /sim/rendering/hdr/atmos/aerosol-scattering-cross-section[2] + /sim/rendering/hdr/atmos/aerosol-scattering-cross-section[3] + + + /sim/rendering/hdr/atmos/aerosol-base-density + + + /sim/rendering/hdr/atmos/aerosol-relative-background-density + + + /sim/rendering/hdr/atmos/aerosol-scale-height + + + /sim/rendering/hdr/atmos/fog-density + + + /sim/rendering/hdr/atmos/fog-scale-height + + + /sim/rendering/hdr/atmos/ozone-mean-dobson + + + /sim/rendering/hdr/atmos/ground-albedo[0] + /sim/rendering/hdr/atmos/ground-albedo[1] + /sim/rendering/hdr/atmos/ground-albedo[2] + /sim/rendering/hdr/atmos/ground-albedo[3] + @@ -1714,4 +1751,95 @@ + + + hdr-envmap + + + 0 + texture[0]/type + texture[0]/image + texture[0]/filter + texture[0]/wrap-s + texture[0]/wrap-t + + 0 + opaque + back + + Shaders/HDR/terrain_envmap.vert + Shaders/HDR/terrain_envmap.frag + Shaders/HDR/math.glsl + Shaders/HDR/color.glsl + Shaders/HDR/sun.glsl + Shaders/HDR/aerial_perspective_envmap.glsl + Shaders/HDR/atmos.glsl + Shaders/HDR/atmos_spectral.glsl + + + color_tex + sampler-2d + 0 + + + + orthophoto_tex + sampler-2d + 15 + + + + + transmittance_tex + sampler-2d + 12 + + + + aerosol_absorption_cross_section + float-vec4 + aerosol-absorption-cross-section + + + aerosol_scattering_cross_section + float-vec4 + aerosol-scattering-cross-section + + + aerosol_base_density + float + aerosol-base-density + + + aerosol_relative_background_density + float + aerosol-relative-background-density + + + aerosol_scale_height + float + aerosol-scale-height + + + fog_density + float + fog-density + + + fog_scale_height + float + fog-scale-height + + + ozone_mean_dobson + float + ozone-mean-dobson + + + ground_albedo + float-vec4 + ground-albedo + + + diff --git a/Nasal/hdr.nas b/Nasal/hdr.nas index 5343e00ca..240f3f5f0 100644 --- a/Nasal/hdr.nas +++ b/Nasal/hdr.nas @@ -10,6 +10,9 @@ # by the shaders directly. #------------------------------------------------------------------------------- +################################################################################ +# Atmosphere +################################################################################ setprop("/sim/rendering/hdr/atmos/aerosol-absorption-cross-section[0]", 2.8722e-24); setprop("/sim/rendering/hdr/atmos/aerosol-absorption-cross-section[1]", 4.6168e-24); setprop("/sim/rendering/hdr/atmos/aerosol-absorption-cross-section[2]", 7.9706e-24); @@ -31,3 +34,63 @@ setprop("/sim/rendering/hdr/atmos/ground-albedo[0]", 0.4); setprop("/sim/rendering/hdr/atmos/ground-albedo[1]", 0.4); setprop("/sim/rendering/hdr/atmos/ground-albedo[2]", 0.4); setprop("/sim/rendering/hdr/atmos/ground-albedo[3]", 0.4); + +################################################################################ +# Environment map +################################################################################ +var is_envmap_updating = false; +var current_envmap_face = 0; + +var update_envmap_face = func { + if (current_envmap_face < 6) { + # Render the current face + setprop("/sim/rendering/hdr/envmap/should-render-face-" + ~ current_envmap_face, true); + } + if (current_envmap_face > 0) { + # Stop rendering the previous face + setprop("/sim/rendering/hdr/envmap/should-render-face-" + ~ (current_envmap_face - 1), false); + } + if (current_envmap_face < 6) { + # Go to next face and update it next frame + current_envmap_face += 1; + settimer(update_envmap_face, 0); + } else { + # We have finished updating all faces, reset the face counter, end the + # update loop and prefilter the envmap. + current_envmap_face = 0; + setprop("/sim/rendering/hdr/envmap/should-prefilter", true); + settimer(func { + setprop("/sim/rendering/hdr/envmap/should-prefilter", false); + is_envmap_updating = false; + }, 0); + } +} + +var update_envmap = func { + if (!is_envmap_updating) { + is_envmap_updating = true; + settimer(update_envmap_face, 0); + } +} + +var update_envmap_periodically = func { + update_envmap(); + var update_rate = getprop("/sim/rendering/hdr/envmap/update-rate-s"); + settimer(update_envmap_periodically, update_rate); +} + +# Start updating the envmap on FDM initialization +setlistener("/sim/signals/fdm-initialized", func { + update_envmap_periodically(); + # Do a single update after 5 seconds when most of the scenery is loaded + settimer(update_envmap, 5) +}); + +setlistener("/sim/rendering/hdr/envmap/force-update", func(p) { + if (p.getValue()) { + update_envmap(); + p.setValue(false); + } +}, 0, 0); diff --git a/Shaders/HDR/3dcloud.frag b/Shaders/HDR/3dcloud.frag index a25e76aa4..4c15ee3a1 100644 --- a/Shaders/HDR/3dcloud.frag +++ b/Shaders/HDR/3dcloud.frag @@ -2,70 +2,17 @@ layout(location = 0) out vec4 fragColor; -in vec2 texcoord; -in vec4 cloud_color; -in vec4 ap_color; - -uniform sampler2D base_tex; - -uniform mat4 osg_ProjectionMatrix; -uniform vec4 fg_Viewport; -uniform vec3 fg_SunDirection; - -uniform float density = 30.0; -uniform float max_sample_dist = 0.05; - -const int STEPS = 8; - -// aerial_perspective.glsl -vec3 mix_aerial_perspective(vec3 color, vec4 ap); +// 3dcloud_common.frag +vec4 cloud_common_frag(); // exposure.glsl vec3 apply_exposure(vec3 color); void main() { - vec4 base = texture(base_tex, texcoord); + vec4 color = cloud_common_frag(); - // Directly discard fragments below a threshold - if (base.a < 0.02) - discard; - - // Pixel position in screen space [-1, 1] - vec2 screen_uv = ((gl_FragCoord.xy - fg_Viewport.xy) / fg_Viewport.zw) * 2.0 - 1.0; - - // XXX: Sun's screen-space position. This should be passed as an uniform - vec4 sun_dir_screen = osg_ProjectionMatrix * vec4(fg_SunDirection, 0.0); - sun_dir_screen.xyz /= sun_dir_screen.w; - sun_dir_screen.xyz = normalize(sun_dir_screen.xyz); - - // Direction from pixel to Sun in screen space - vec2 sun_dir = screen_uv - sun_dir_screen.xy; - // Flip the x axis - sun_dir.x = -sun_dir.x; - - float dt = max_sample_dist / STEPS; - - // 2D ray march along the Sun's direction to estimate the transmittance - float T = 1.0; - for (int i = 0; i < STEPS; ++i) { - float t = (float(i) + 0.5) * dt; - vec2 uv_t = texcoord - sun_dir * t; - vec4 texel = texture(base_tex, uv_t); - // Beer-Lambert's law - T *= exp(-texel.a * dt * density); - } - - // When the camera is facing perpendicularly to the Sun, the Sun's - // screen-space location can tend toward infinity. Fade the effect toward - // the perpendicular. - float fade = smoothstep(0.1, 0.5, dot(vec3(0.0, 0.0, -1.0), fg_SunDirection)); - - vec4 color = base * cloud_color; - color.rgb *= base.a * mix(0.5, T, fade); - - color.rgb = mix_aerial_perspective(color.rgb, ap_color); - - // Pre-expose + // Only pre-expose when not rendering to the environment map. + // We want the non-exposed radiance values for IBL. color.rgb = apply_exposure(color.rgb); fragColor = color; diff --git a/Shaders/HDR/3dcloud.vert b/Shaders/HDR/3dcloud.vert index 74a9bf22e..3921ddb53 100644 --- a/Shaders/HDR/3dcloud.vert +++ b/Shaders/HDR/3dcloud.vert @@ -1,116 +1,19 @@ #version 330 core -layout(location = 0) in vec4 pos; -layout(location = 2) in vec4 vertex_color; -layout(location = 3) in vec4 multitexcoord0; -layout(location = 10) in vec4 usrAttr1; -layout(location = 11) in vec4 usrAttr2; - -out vec2 texcoord; -out vec4 cloud_color; out vec4 ap_color; -uniform float range; -uniform float detail_range; - -uniform mat4 osg_ModelViewMatrix; -uniform mat4 osg_ModelViewProjectionMatrix; -uniform mat4 osg_ViewMatrixInverse; -uniform vec3 fg_SunDirectionWorld; - +// 3dcloud_common.vert +void cloud_common_vert(out vec4 vs_pos, out vec4 ws_pos); // aerial_perspective.glsl vec4 get_aerial_perspective(vec2 coord, float depth); -vec3 get_sun_radiance(vec3 p); void main() { - float alpha_factor = usrAttr1.r; - float shade_factor = usrAttr1.g; - float cloud_height = usrAttr1.b; - float bottom_factor = usrAttr2.r; - float middle_factor = usrAttr2.g; - float top_factor = usrAttr2.b; + vec4 vs_pos, ws_pos; + cloud_common_vert(vs_pos, ws_pos); - texcoord = multitexcoord0.st; - - // XXX: Should be sent as an uniform - mat4 inverseModelViewMatrix = inverse(osg_ModelViewMatrix); - - vec4 ep = inverseModelViewMatrix * vec4(0.0, 0.0, 0.0, 1.0); - vec4 l = inverseModelViewMatrix * vec4(0.0, 0.0, 1.0, 1.0); - vec3 u = normalize(ep.xyz - l.xyz); - - // Find a rotation matrix that rotates 1,0,0 into u. u, r and w are - // the columns of that matrix. - vec3 absu = abs(u); - vec3 r = normalize(vec3(-u.y, u.x, 0.0)); - vec3 w = cross(u, r); - - // Do the matrix multiplication by [ u r w pos]. Assume no - // scaling in the homogeneous component of pos. - vec4 final_pos = vec4(0.0, 0.0, 0.0, 1.0); - final_pos.xyz = pos.x * u; - final_pos.xyz += pos.y * r; - final_pos.xyz += pos.z * w; - // Apply Z scaling to allow sprites to be squashed in the z-axis - final_pos.z = final_pos.z * vertex_color.w; - - // Now shift the sprite to the correct position in the cloud. - final_pos.xyz += vertex_color.xyz; - - // Determine the position - used for fog and shading calculations - float fogCoord = length(vec3(osg_ModelViewMatrix * vec4(vertex_color.xyz, 1.0))); - float center_dist = length(vec3(osg_ModelViewMatrix * vec4(0.0, 0.0, 0.0, 1.0))); - - if ((fogCoord > detail_range) && (fogCoord > center_dist) && (shade_factor < 0.7)) { - // More than detail_range away, so discard all sprites on opposite side of - // cloud center by shifting them beyond the view fustrum - gl_Position = vec4(0.0, 0.0, 10.0, 1.0); - cloud_color = vec4(0.0); - } else { - gl_Position = osg_ModelViewProjectionMatrix * final_pos; - - vec4 final_view_pos = osg_ModelViewMatrix * final_pos; - vec4 final_world_pos = osg_ViewMatrixInverse * final_view_pos; - - // Determine a lighting normal based on the vertex position from the - // center of the cloud, so that sprite on the opposite side of the cloud - // to the sun are darker. - vec3 n = normalize(vec3(osg_ViewMatrixInverse * - osg_ModelViewMatrix * vec4(-final_pos.xyz, 0.0))); - float NdotL = dot(-fg_SunDirectionWorld, n); - - // Determine the shading of the vertex. We shade it based on it's position - // in the cloud relative to the sun, and it's vertical position in the cloud. - float shade = mix(shade_factor, top_factor, smoothstep(-0.3, 0.3, NdotL)); - - if (final_pos.z < 0.5 * cloud_height) { - shade = min(shade, mix(bottom_factor, middle_factor, - final_pos.z * 2.0 / cloud_height)); - } else { - shade = min(shade, mix(middle_factor, top_factor, - final_pos.z * 2.0 / cloud_height - 1.0)); - } - - cloud_color.rgb = shade * get_sun_radiance(final_world_pos.xyz); - - // Perspective division and scale to [0, 1] to get the screen position - // of the vertex. - vec2 coord = (gl_Position.xy / gl_Position.w) * 0.5 + 0.5; - ap_color = get_aerial_perspective(coord, length(final_view_pos)); - - if ((fogCoord > (0.9 * detail_range)) - && (fogCoord > center_dist) - && (shade_factor < 0.7)) { - // cloudlet is almost at the detail range, so fade it out. - cloud_color.a = 1.0 - smoothstep(0.9 * detail_range, detail_range, fogCoord); - } else { - // As we get within 100m of the sprite, it is faded out. - // Equally at large distances it also fades out. - cloud_color.a = min(smoothstep(10.0, 100.0, fogCoord), - 1.0 - smoothstep(0.9 * range, range, fogCoord)); - } - - cloud_color.a *= alpha_factor; - } + // Perspective division and scale to [0, 1] to get the screen position + // of the vertex. + vec2 coord = (gl_Position.xy / gl_Position.w) * 0.5 + 0.5; + ap_color = get_aerial_perspective(coord, length(vs_pos.xyz)); } diff --git a/Shaders/HDR/3dcloud_common.frag b/Shaders/HDR/3dcloud_common.frag new file mode 100644 index 000000000..9399c6ce5 --- /dev/null +++ b/Shaders/HDR/3dcloud_common.frag @@ -0,0 +1,65 @@ +#version 330 core + +in vec2 texcoord; +in vec4 cloud_color; +in vec4 ap_color; + +uniform sampler2D base_tex; + +uniform mat4 osg_ProjectionMatrix; +uniform vec4 fg_Viewport; +uniform vec3 fg_SunDirection; + +uniform float density = 30.0; +uniform float max_sample_dist = 0.05; + +const int STEPS = 8; + +// aerial_perspective.glsl +vec3 mix_aerial_perspective(vec3 color, vec4 ap); + +vec4 cloud_common_frag() +{ + vec4 base = texture(base_tex, texcoord); + + // Directly discard fragments below a threshold + if (base.a < 0.02) + discard; + + // Pixel position in screen space [-1, 1] + vec2 screen_uv = ((gl_FragCoord.xy - fg_Viewport.xy) / fg_Viewport.zw) * 2.0 - 1.0; + + // XXX: Sun's screen-space position. This should be passed as an uniform + vec4 sun_dir_screen = osg_ProjectionMatrix * vec4(fg_SunDirection, 0.0); + sun_dir_screen.xyz /= sun_dir_screen.w; + sun_dir_screen.xyz = normalize(sun_dir_screen.xyz); + + // Direction from pixel to Sun in screen space + vec2 sun_dir = screen_uv - sun_dir_screen.xy; + // Flip the x axis + sun_dir.x = -sun_dir.x; + + float dt = max_sample_dist / STEPS; + + // 2D ray march along the Sun's direction to estimate the transmittance + float T = 1.0; + for (int i = 0; i < STEPS; ++i) { + float t = (float(i) + 0.5) * dt; + vec2 uv_t = texcoord - sun_dir * t; + vec4 texel = texture(base_tex, uv_t); + // Beer-Lambert's law + T *= exp(-texel.a * dt * density); + } + + // When the camera is facing perpendicularly to the Sun, the Sun's + // screen-space location can tend toward infinity. Fade the effect toward + // the perpendicular. + float fade = smoothstep(0.1, 0.5, dot(vec3(0.0, 0.0, -1.0), fg_SunDirection)); + + vec4 color = base * cloud_color; + color.rgb *= base.a * mix(0.5, T, fade); + + color.rgb = mix_aerial_perspective(color.rgb, ap_color); + + return color; +} diff --git a/Shaders/HDR/3dcloud_common.vert b/Shaders/HDR/3dcloud_common.vert new file mode 100644 index 000000000..5c0539ff6 --- /dev/null +++ b/Shaders/HDR/3dcloud_common.vert @@ -0,0 +1,109 @@ +#version 330 core + +layout(location = 0) in vec4 pos; +layout(location = 2) in vec4 vertex_color; +layout(location = 3) in vec4 multitexcoord0; +layout(location = 10) in vec4 usrAttr1; +layout(location = 11) in vec4 usrAttr2; + +out vec2 texcoord; +out vec4 cloud_color; + +uniform float range; +uniform float detail_range; + +uniform mat4 osg_ModelViewMatrix; +uniform mat4 osg_ModelViewProjectionMatrix; +uniform mat4 osg_ViewMatrixInverse; +uniform vec3 fg_SunDirectionWorld; + +// sun.glsl +vec3 get_sun_radiance(vec3 p); + +void cloud_common_vert(out vec4 vs_pos, out vec4 ws_pos) +{ + float alpha_factor = usrAttr1.r; + float shade_factor = usrAttr1.g; + float cloud_height = usrAttr1.b; + float bottom_factor = usrAttr2.r; + float middle_factor = usrAttr2.g; + float top_factor = usrAttr2.b; + + texcoord = multitexcoord0.st; + + // XXX: Should be sent as an uniform + mat4 inverseModelViewMatrix = inverse(osg_ModelViewMatrix); + + vec4 ep = inverseModelViewMatrix * vec4(0.0, 0.0, 0.0, 1.0); + vec4 l = inverseModelViewMatrix * vec4(0.0, 0.0, 1.0, 1.0); + vec3 u = normalize(ep.xyz - l.xyz); + + // Find a rotation matrix that rotates 1,0,0 into u. u, r and w are + // the columns of that matrix. + vec3 absu = abs(u); + vec3 r = normalize(vec3(-u.y, u.x, 0.0)); + vec3 w = cross(u, r); + + // Do the matrix multiplication by [ u r w pos]. Assume no + // scaling in the homogeneous component of pos. + vec4 final_pos = vec4(0.0, 0.0, 0.0, 1.0); + final_pos.xyz = pos.x * u; + final_pos.xyz += pos.y * r; + final_pos.xyz += pos.z * w; + // Apply Z scaling to allow sprites to be squashed in the z-axis + final_pos.z = final_pos.z * vertex_color.w; + + // Now shift the sprite to the correct position in the cloud. + final_pos.xyz += vertex_color.xyz; + + // Determine the position - used for fog and shading calculations + float fogCoord = length(vec3(osg_ModelViewMatrix * vec4(vertex_color.xyz, 1.0))); + float center_dist = length(vec3(osg_ModelViewMatrix * vec4(0.0, 0.0, 0.0, 1.0))); + + if ((fogCoord > detail_range) && (fogCoord > center_dist) && (shade_factor < 0.7)) { + // More than detail_range away, so discard all sprites on opposite side of + // cloud center by shifting them beyond the view fustrum + gl_Position = vec4(0.0, 0.0, 10.0, 1.0); + cloud_color = vec4(0.0); + } else { + gl_Position = osg_ModelViewProjectionMatrix * final_pos; + + vs_pos = osg_ModelViewMatrix * final_pos; + ws_pos = osg_ViewMatrixInverse * vs_pos; + + // Determine a lighting normal based on the vertex position from the + // center of the cloud, so that sprite on the opposite side of the cloud + // to the sun are darker. + vec3 n = normalize(vec3(osg_ViewMatrixInverse * + osg_ModelViewMatrix * vec4(-final_pos.xyz, 0.0))); + float NdotL = dot(-fg_SunDirectionWorld, n); + + // Determine the shading of the vertex. We shade it based on it's position + // in the cloud relative to the sun, and it's vertical position in the cloud. + float shade = mix(shade_factor, top_factor, smoothstep(-0.3, 0.3, NdotL)); + + if (final_pos.z < 0.5 * cloud_height) { + shade = min(shade, mix(bottom_factor, middle_factor, + final_pos.z * 2.0 / cloud_height)); + } else { + shade = min(shade, mix(middle_factor, top_factor, + final_pos.z * 2.0 / cloud_height - 1.0)); + } + + cloud_color.rgb = shade * get_sun_radiance(ws_pos.xyz); + + if ((fogCoord > (0.9 * detail_range)) + && (fogCoord > center_dist) + && (shade_factor < 0.7)) { + // cloudlet is almost at the detail range, so fade it out. + cloud_color.a = 1.0 - smoothstep(0.9 * detail_range, detail_range, fogCoord); + } else { + // As we get within 100m of the sprite, it is faded out. + // Equally at large distances it also fades out. + cloud_color.a = min(smoothstep(10.0, 100.0, fogCoord), + 1.0 - smoothstep(0.9 * range, range, fogCoord)); + } + + cloud_color.a *= alpha_factor; + } +} diff --git a/Shaders/HDR/3dcloud_envmap.frag b/Shaders/HDR/3dcloud_envmap.frag new file mode 100644 index 000000000..61ab4ff78 --- /dev/null +++ b/Shaders/HDR/3dcloud_envmap.frag @@ -0,0 +1,12 @@ +#version 330 core + +layout(location = 0) out vec4 fragColor; + +// 3dcloud_common.frag +vec4 cloud_common_frag(); + +void main() +{ + vec4 color = cloud_common_frag(); + fragColor = color; +} diff --git a/Shaders/HDR/3dcloud_envmap.vert b/Shaders/HDR/3dcloud_envmap.vert new file mode 100644 index 000000000..40e687afa --- /dev/null +++ b/Shaders/HDR/3dcloud_envmap.vert @@ -0,0 +1,16 @@ +#version 330 core + +out vec4 ap_color; + +// 3dcloud_common.vert +void cloud_common_vert(out vec4 vs_pos, out vec4 ws_pos); +// aerial_perspective_envmap.glsl +vec4 get_aerial_perspective(vec3 pos); + +void main() +{ + vec4 vs_pos, ws_pos; + cloud_common_vert(vs_pos, ws_pos); + + ap_color = get_aerial_perspective(ws_pos.xyz); +} diff --git a/Shaders/HDR/aerial_perspective.glsl b/Shaders/HDR/aerial_perspective.glsl index f9200f56f..bba108650 100644 --- a/Shaders/HDR/aerial_perspective.glsl +++ b/Shaders/HDR/aerial_perspective.glsl @@ -1,12 +1,6 @@ #version 330 core uniform sampler2D aerial_perspective_tex; -uniform sampler2D transmittance_tex; - -uniform vec3 fg_SunDirectionWorld; -uniform float fg_CameraDistanceToEarthCenter; -uniform float fg_SunZenithCosTheta; -uniform float fg_EarthRadius; const float AP_SLICE_COUNT = 32.0; const float AP_MAX_DEPTH = 128000.0; @@ -14,12 +8,6 @@ const float AP_SLICE_WIDTH_PIXELS = 32.0; const float AP_SLICE_SIZE = 1.0 / AP_SLICE_COUNT; const float AP_TEXEL_WIDTH = 1.0 / (AP_SLICE_COUNT * AP_SLICE_WIDTH_PIXELS); -const float ATMOSPHERE_RADIUS = 6471e3; - -// atmos_spectral.glsl -vec4 get_sun_spectral_irradiance(); -vec3 linear_srgb_from_spectral_samples(vec4 L); - vec4 sample_aerial_perspective_slice(sampler2D lut, vec2 coord, float slice) { // Sample at the pixel center @@ -62,33 +50,3 @@ vec3 add_aerial_perspective(vec3 color, vec2 coord, float depth) { return mix_aerial_perspective(color, get_aerial_perspective(coord, depth)); } - -/* - * Get the Sun radiance at a point 'p' in world space. - * We cannot use the Sun extraterrestial irradiance directly because it will be - * attenuated by the transmittance of the atmospheric medium. - */ -vec3 get_sun_radiance(vec3 p) -{ - float distance_to_earth_center = length(p); - float normalized_altitude = (distance_to_earth_center - fg_EarthRadius) - / (ATMOSPHERE_RADIUS - fg_EarthRadius); - - vec3 zenith_dir = p / distance_to_earth_center; - float sun_cos_theta = dot(zenith_dir, fg_SunDirectionWorld); - - float u = sun_cos_theta * 0.5 + 0.5; - float v = clamp(normalized_altitude, 0.0, 1.0); - vec4 transmittance = texture(transmittance_tex, vec2(u, v)); - - vec4 L = get_sun_spectral_irradiance() * transmittance; - return linear_srgb_from_spectral_samples(L); -} - -vec3 get_sun_radiance_sea_level() -{ - vec2 uv = vec2(fg_SunZenithCosTheta * 0.5 + 0.5, 0.0); - vec4 transmittance = texture(transmittance_tex, uv); - vec4 L = get_sun_spectral_irradiance() * transmittance; - return linear_srgb_from_spectral_samples(L); -} diff --git a/Shaders/HDR/aerial_perspective_envmap.glsl b/Shaders/HDR/aerial_perspective_envmap.glsl new file mode 100644 index 000000000..be6e63f57 --- /dev/null +++ b/Shaders/HDR/aerial_perspective_envmap.glsl @@ -0,0 +1,60 @@ +#version 330 core + +uniform sampler2D transmittance_tex; + +uniform vec3 fg_CameraPositionCart; +uniform vec3 fg_SunDirectionWorld; + +const int AERIAL_PERSPECTIVE_ENVMAP_STEPS = 4; + +// atmos.glsl +float get_earth_radius(); +float get_ray_end(vec3 ray_origin, vec3 ray_dir, float t_max); +vec4 compute_inscattering(in vec3 ray_origin, + in vec3 ray_dir, + in float t_max, + in vec3 sun_dir, + in int steps, + in sampler2D transmittance_lut, + out vec4 transmittance); +// atmos_spectral.glsl +vec4 get_sun_spectral_irradiance(); +vec3 linear_srgb_from_spectral_samples(vec4 L); + +vec4 get_aerial_perspective(vec3 pos) +{ + vec3 ray_origin = fg_CameraPositionCart; + vec3 ray_end = pos; + + // Make sure both ray ends are above the ground. + // We also apply a small bias to the ray end to prevent both points from + // being at the exact same place due to floating point precision. + float radius = get_earth_radius(); + ray_origin += max(0.0, radius - length(ray_origin)); + ray_end += max(0.0, radius - length(ray_end)) + 1.0; + + vec3 ray_dir = ray_end - ray_origin; + float t_d = length(ray_dir); + ray_dir /= t_d; + + float t_max = get_ray_end(ray_origin, ray_dir, t_d); + + vec4 transmittance; + vec4 L = compute_inscattering(ray_origin, + ray_dir, + t_max, + fg_SunDirectionWorld, + AERIAL_PERSPECTIVE_ENVMAP_STEPS, + transmittance_tex, + transmittance); + + vec4 ap; + ap.rgb = linear_srgb_from_spectral_samples(L * get_sun_spectral_irradiance()); + ap.a = dot(transmittance, vec4(0.25)); + return ap; +} + +vec3 mix_aerial_perspective(vec3 color, vec4 ap) +{ + return color * ap.a + ap.rgb; +} diff --git a/Shaders/HDR/atmos.glsl b/Shaders/HDR/atmos.glsl index c1edb0ecf..a32f7064c 100644 --- a/Shaders/HDR/atmos.glsl +++ b/Shaders/HDR/atmos.glsl @@ -203,8 +203,8 @@ void get_atmosphere_collision_coefficients(in float h, out vec4 molecular_scattering, out vec4 extinction) { + h = max(h, 1e-3); // In case height is negative h *= 1e-3; // To km - h = max(h, 0.0); // In case height is negative // Molecules molecular_absorption = get_molecular_absorption_coefficient(h); diff --git a/Shaders/HDR/cloud_static.vert b/Shaders/HDR/cloud_static.vert index c774995dd..dd7af6a8d 100644 --- a/Shaders/HDR/cloud_static.vert +++ b/Shaders/HDR/cloud_static.vert @@ -1,74 +1,19 @@ #version 330 core -layout(location = 0) in vec4 pos; -layout(location = 2) in vec4 vertex_color; -layout(location = 3) in vec4 multitexcoord0; - -out vec2 texcoord; -out vec4 cloud_color; out vec4 ap_color; -uniform mat4 osg_ModelViewMatrix; -uniform mat4 osg_ModelViewProjectionMatrix; -uniform mat4 osg_ViewMatrixInverse; -uniform vec3 fg_SunDirectionWorld; - -const float shade = 0.8; -const float cloud_height = 1000.0; - +// cloud_static_common.vert +void cloud_static_common_vert(out vec4 vs_pos, out vec4 ws_pos); // aerial_perspective.glsl vec4 get_aerial_perspective(vec2 coord, float depth); -vec3 get_sun_radiance(vec3 p); void main() { - texcoord = multitexcoord0.st; - - // XXX: Should be sent as an uniform - mat4 inverseModelViewMatrix = inverse(osg_ModelViewMatrix); - - vec4 ep = inverseModelViewMatrix * vec4(0.0, 0.0, 0.0, 1.0); - vec4 l = inverseModelViewMatrix * vec4(0.0, 0.0, 1.0, 1.0); - vec3 u = normalize(ep.xyz - l.xyz); - - vec4 final_pos = vec4(0.0, 0.0, 0.0, 1.0); - final_pos.x = pos.x; - final_pos.y = pos.y; - final_pos.z = pos.z; - final_pos.xyz += vertex_color.xyz; - - gl_Position = osg_ModelViewProjectionMatrix * final_pos; - - // Determine a lighting normal based on the vertex position from the - // center of the cloud, so that sprite on the opposite side of the cloud - // to the sun are darker. - vec3 n = normalize(vec3(osg_ViewMatrixInverse * - osg_ModelViewMatrix * vec4(-final_pos.xyz, 0.0))); - float NdotL = dot(-fg_SunDirectionWorld, n); - - vec4 final_view_pos = osg_ModelViewMatrix * final_pos; - vec4 final_world_pos = osg_ViewMatrixInverse * final_view_pos; - - float fogCoord = abs(final_view_pos.z); - float fract = smoothstep(0.0, cloud_height, final_pos.z + cloud_height); - - vec3 sun_radiance = get_sun_radiance(final_world_pos.xyz); - - // Determine the shading of the sprite based on its vertical position and - // position relative to the sun. - NdotL = min(smoothstep(-0.5, 0.0, NdotL), fract); - // Determine the shading based on a mixture from the backlight to the front - vec3 backlight = shade * sun_radiance; - - cloud_color.rgb = mix(backlight, sun_radiance, NdotL); + vec4 vs_pos, ws_pos; + cloud_static_common_vert(vs_pos, ws_pos); // Perspective division and scale to [0, 1] to get the screen position // of the vertex. vec2 coord = (gl_Position.xy / gl_Position.w) * 0.5 + 0.5; - ap_color = get_aerial_perspective(coord, length(final_view_pos)); - - // As we get within 100m of the sprite, it is faded out. Equally at large - // distances it also fades out. - cloud_color.a = min(smoothstep(100.0, 250.0, fogCoord), - 1.0 - smoothstep(70000.0, 75000.0, fogCoord)); + ap_color = get_aerial_perspective(coord, length(vs_pos)); } diff --git a/Shaders/HDR/cloud_static_common.vert b/Shaders/HDR/cloud_static_common.vert new file mode 100644 index 000000000..b57bbd115 --- /dev/null +++ b/Shaders/HDR/cloud_static_common.vert @@ -0,0 +1,67 @@ +#version 330 core + +layout(location = 0) in vec4 pos; +layout(location = 2) in vec4 vertex_color; +layout(location = 3) in vec4 multitexcoord0; + +out vec2 texcoord; +out vec4 cloud_color; + +uniform mat4 osg_ModelViewMatrix; +uniform mat4 osg_ModelViewProjectionMatrix; +uniform mat4 osg_ViewMatrixInverse; +uniform vec3 fg_SunDirectionWorld; + +const float shade = 0.8; +const float cloud_height = 1000.0; + +// sun.glsl +vec3 get_sun_radiance(vec3 p); + +void cloud_static_common_vert(out vec4 vs_pos, out vec4 ws_pos) +{ + texcoord = multitexcoord0.st; + + // XXX: Should be sent as an uniform + mat4 inverseModelViewMatrix = inverse(osg_ModelViewMatrix); + + vec4 ep = inverseModelViewMatrix * vec4(0.0, 0.0, 0.0, 1.0); + vec4 l = inverseModelViewMatrix * vec4(0.0, 0.0, 1.0, 1.0); + vec3 u = normalize(ep.xyz - l.xyz); + + vec4 final_pos = vec4(0.0, 0.0, 0.0, 1.0); + final_pos.x = pos.x; + final_pos.y = pos.y; + final_pos.z = pos.z; + final_pos.xyz += vertex_color.xyz; + + gl_Position = osg_ModelViewProjectionMatrix * final_pos; + + // Determine a lighting normal based on the vertex position from the + // center of the cloud, so that sprite on the opposite side of the cloud + // to the sun are darker. + vec3 n = normalize(vec3(osg_ViewMatrixInverse * + osg_ModelViewMatrix * vec4(-final_pos.xyz, 0.0))); + float NdotL = dot(-fg_SunDirectionWorld, n); + + vs_pos = osg_ModelViewMatrix * final_pos; + ws_pos = osg_ViewMatrixInverse * vs_pos; + + float fogCoord = abs(vs_pos.z); + float fract = smoothstep(0.0, cloud_height, final_pos.z + cloud_height); + + vec3 sun_radiance = get_sun_radiance(ws_pos.xyz); + + // Determine the shading of the sprite based on its vertical position and + // position relative to the sun. + NdotL = min(smoothstep(-0.5, 0.0, NdotL), fract); + // Determine the shading based on a mixture from the backlight to the front + vec3 backlight = shade * sun_radiance; + + cloud_color.rgb = mix(backlight, sun_radiance, NdotL); + + // As we get within 100m of the sprite, it is faded out. Equally at large + // distances it also fades out. + cloud_color.a = min(smoothstep(100.0, 250.0, fogCoord), + 1.0 - smoothstep(70000.0, 75000.0, fogCoord)); +} diff --git a/Shaders/HDR/cloud_static_envmap.vert b/Shaders/HDR/cloud_static_envmap.vert new file mode 100644 index 000000000..d42357412 --- /dev/null +++ b/Shaders/HDR/cloud_static_envmap.vert @@ -0,0 +1,16 @@ +#version 330 core + +out vec4 ap_color; + +// cloud_static_common.vert +void cloud_static_common_vert(out vec4 vs_pos, out vec4 ws_pos); +// aerial_perspective_envmap.glsl +vec4 get_aerial_perspective(vec3 pos); + +void main() +{ + vec4 vs_pos, ws_pos; + cloud_static_common_vert(vs_pos, ws_pos); + + ap_color = get_aerial_perspective(ws_pos.xyz); +} diff --git a/Shaders/HDR/sun.glsl b/Shaders/HDR/sun.glsl new file mode 100644 index 000000000..8ce653ab2 --- /dev/null +++ b/Shaders/HDR/sun.glsl @@ -0,0 +1,44 @@ +#version 330 core + +uniform sampler2D transmittance_tex; + +uniform float fg_EarthRadius; +uniform vec3 fg_SunDirectionWorld; +uniform float fg_CameraDistanceToEarthCenter; +uniform float fg_SunZenithCosTheta; + +const float ATMOSPHERE_RADIUS = 6471e3; + +// atmos_spectral.glsl +vec4 get_sun_spectral_irradiance(); +vec3 linear_srgb_from_spectral_samples(vec4 L); + +/* + * Get the Sun radiance at a point 'p' in world space. + * We cannot use the Sun extraterrestial irradiance directly because it will be + * attenuated by the transmittance of the atmospheric medium. + */ +vec3 get_sun_radiance(vec3 p) +{ + float distance_to_earth_center = length(p); + float normalized_altitude = (distance_to_earth_center - fg_EarthRadius) + / (ATMOSPHERE_RADIUS - fg_EarthRadius); + + vec3 zenith_dir = p / distance_to_earth_center; + float sun_cos_theta = dot(zenith_dir, fg_SunDirectionWorld); + + float u = sun_cos_theta * 0.5 + 0.5; + float v = clamp(normalized_altitude, 0.0, 1.0); + vec4 transmittance = texture(transmittance_tex, vec2(u, v)); + + vec4 L = get_sun_spectral_irradiance() * transmittance; + return linear_srgb_from_spectral_samples(L); +} + +vec3 get_sun_radiance_sea_level() +{ + vec2 uv = vec2(fg_SunZenithCosTheta * 0.5 + 0.5, 0.0); + vec4 transmittance = texture(transmittance_tex, uv); + vec4 L = get_sun_spectral_irradiance() * transmittance; + return linear_srgb_from_spectral_samples(L); +} diff --git a/Shaders/HDR/terrain_envmap.frag b/Shaders/HDR/terrain_envmap.frag new file mode 100644 index 000000000..94e4fec42 --- /dev/null +++ b/Shaders/HDR/terrain_envmap.frag @@ -0,0 +1,52 @@ +#version 330 core + +layout(location = 0) out vec4 fragColor; + +in VS_OUT { + vec2 texcoord; + vec2 orthophoto_texcoord; + vec3 vertex_normal; + vec3 world_vector; +} fs_in; + +uniform sampler2D color_tex; +uniform sampler2D orthophoto_tex; + +uniform bool orthophotoAvailable; +uniform vec3 fg_SunDirectionWorld; +uniform vec4 fg_Viewport; + +// math.glsl +float M_1_PI(); +// color.glsl +vec3 eotf_inverse_sRGB(vec3 srgb); +// sun.glsl +vec3 get_sun_radiance_sea_level(); +// aerial_perspective_envmap.glsl +vec4 get_aerial_perspective(vec3 pos); +vec3 mix_aerial_perspective(vec3 color, vec4 ap); + +void main() +{ + vec3 texel = texture(color_tex, fs_in.texcoord).rgb; + if (orthophotoAvailable) { + vec4 sat_texel = texture(orthophoto_tex, fs_in.orthophoto_texcoord); + if (sat_texel.a > 0.0) { + texel.rgb = sat_texel.rgb; + } + } + + vec3 color = eotf_inverse_sRGB(texel); + vec3 sun_radiance = get_sun_radiance_sea_level(); + + vec3 N = normalize(fs_in.vertex_normal); + float NdotL = max(dot(N, fg_SunDirectionWorld), 1e-4); + + // Assume a perfectly diffuse Lambertian surface + color = M_1_PI() * color * sun_radiance * NdotL; + + vec4 ap = get_aerial_perspective(fs_in.world_vector); + color = mix_aerial_perspective(color, ap); + + fragColor = vec4(color, 1.0); +} diff --git a/Shaders/HDR/terrain_envmap.vert b/Shaders/HDR/terrain_envmap.vert new file mode 100644 index 000000000..47e7a764b --- /dev/null +++ b/Shaders/HDR/terrain_envmap.vert @@ -0,0 +1,28 @@ +#version 330 core + +layout(location = 0) in vec4 pos; +layout(location = 1) in vec3 normal; +layout(location = 3) in vec4 multitexcoord0; +layout(location = 5) in vec4 multitexcoord2; + +out VS_OUT { + vec2 texcoord; + vec2 orthophoto_texcoord; + vec3 vertex_normal; + vec3 world_vector; +} vs_out; + +uniform mat4 osg_ModelViewMatrix; +uniform mat4 osg_ModelViewProjectionMatrix; +uniform mat3 osg_NormalMatrix; +uniform mat4 osg_ViewMatrixInverse; + +void main() +{ + gl_Position = osg_ModelViewProjectionMatrix * pos; + vs_out.texcoord = multitexcoord0.st; + vs_out.orthophoto_texcoord = multitexcoord2.st; + vs_out.vertex_normal = (osg_ViewMatrixInverse + * vec4(osg_NormalMatrix * normal, 0.0)).xyz; + vs_out.world_vector = (osg_ViewMatrixInverse * osg_ModelViewMatrix * pos).xyz; +} diff --git a/defaults.xml b/defaults.xml index bb1371f12..cc1b7352b 100644 --- a/defaults.xml +++ b/defaults.xml @@ -535,6 +535,17 @@ Started September 2000 by David Megginson, david@megginson.com 2 0.0 + + false + 90.0 + false + false + false + false + false + false + false + 0.01 0.005