From 691337a00e669ca5e05cc363d98c2977dc4fe922 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Garc=C3=ADa=20Li=C3=B1=C3=A1n?= Date: Fri, 21 Apr 2023 02:15:42 +0200 Subject: [PATCH] HDR: Add separate fog layer to atmosphere Also use Nasal to feed the shaders' uniforms. Much better than running the computations on the GPU. --- Effects/HDR/atmos-aerial-perspective.eff | 93 ++++++++--- Effects/HDR/atmos-sky-view.eff | 93 ++++++++--- Effects/HDR/atmos-transmittance.eff | 93 ++++++++--- Nasal/hdr.nas | 33 ++++ Shaders/HDR/atmos.glsl | 194 +++++++---------------- defaults.xml | 5 - 6 files changed, 305 insertions(+), 206 deletions(-) create mode 100644 Nasal/hdr.nas diff --git a/Effects/HDR/atmos-aerial-perspective.eff b/Effects/HDR/atmos-aerial-perspective.eff index bfdfd044a..62664a5f5 100644 --- a/Effects/HDR/atmos-aerial-perspective.eff +++ b/Effects/HDR/atmos-aerial-perspective.eff @@ -3,18 +3,42 @@ Effects/HDR/atmos-aerial-perspective - - /sim/rendering/hdr/atmos/aerosol-type - - - /sim/rendering/hdr/atmos/aerosol-turbidity - - - /sim/rendering/hdr/atmos/ground-albedo + + /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] - - /sim/time/utc/month - @@ -33,25 +57,50 @@ - aerosol_type - int - aerosol-type + aerosol_absorption_cross_section + float-vec4 + aerosol-absorption-cross-section - aerosol_turbidity + aerosol_scattering_cross_section + float-vec4 + aerosol-scattering-cross-section + + + aerosol_base_density float - aerosol-turbidity + 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 + float-vec4 ground-albedo - - month_of_the_year - int - month-of-the-year - diff --git a/Effects/HDR/atmos-sky-view.eff b/Effects/HDR/atmos-sky-view.eff index 837eb5f97..5c6338ea8 100644 --- a/Effects/HDR/atmos-sky-view.eff +++ b/Effects/HDR/atmos-sky-view.eff @@ -3,18 +3,42 @@ Effects/HDR/atmos-sky-view - - /sim/rendering/hdr/atmos/aerosol-type - - - /sim/rendering/hdr/atmos/aerosol-turbidity - - - /sim/rendering/hdr/atmos/ground-albedo + + /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] - - /sim/time/utc/month - @@ -31,25 +55,50 @@ - aerosol_type - int - aerosol-type + aerosol_absorption_cross_section + float-vec4 + aerosol-absorption-cross-section - aerosol_turbidity + aerosol_scattering_cross_section + float-vec4 + aerosol-scattering-cross-section + + + aerosol_base_density float - aerosol-turbidity + 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 + float-vec4 ground-albedo - - month_of_the_year - int - month-of-the-year - diff --git a/Effects/HDR/atmos-transmittance.eff b/Effects/HDR/atmos-transmittance.eff index 48682a52b..a755decc2 100644 --- a/Effects/HDR/atmos-transmittance.eff +++ b/Effects/HDR/atmos-transmittance.eff @@ -3,18 +3,42 @@ Effects/HDR/atmos-transmittance - - /sim/rendering/hdr/atmos/aerosol-type - - - /sim/rendering/hdr/atmos/aerosol-turbidity - - - /sim/rendering/hdr/atmos/ground-albedo + + /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] - - /sim/time/utc/month - @@ -26,25 +50,50 @@ - aerosol_type - int - aerosol-type + aerosol_absorption_cross_section + float-vec4 + aerosol-absorption-cross-section - aerosol_turbidity + aerosol_scattering_cross_section + float-vec4 + aerosol-scattering-cross-section + + + aerosol_base_density float - aerosol-turbidity + 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 + float-vec4 ground-albedo - - month_of_the_year - int - month-of-the-year - diff --git a/Nasal/hdr.nas b/Nasal/hdr.nas new file mode 100644 index 000000000..5343e00ca --- /dev/null +++ b/Nasal/hdr.nas @@ -0,0 +1,33 @@ +# Copyright (C) 2023 Fernando García Liñán +# SPDX-License-Identifier: GPL-2.0-or-later + +#------------------------------------------------------------------------------- +# Utilities for the HDR Pipeline +# +# Shaders usually need to be fed uniforms that are either too expensive to +# compute on the GPU or can be precomputed once per frame. In this file we +# transform values from already existing properties into data that can be used +# by the shaders directly. +#------------------------------------------------------------------------------- + +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); +setprop("/sim/rendering/hdr/atmos/aerosol-absorption-cross-section[3]", 1.3578e-23); + +setprop("/sim/rendering/hdr/atmos/aerosol-scattering-cross-section[0]", 1.5908e-22); +setprop("/sim/rendering/hdr/atmos/aerosol-scattering-cross-section[1]", 1.7711e-22); +setprop("/sim/rendering/hdr/atmos/aerosol-scattering-cross-section[2]", 2.0942e-22); +setprop("/sim/rendering/hdr/atmos/aerosol-scattering-cross-section[3]", 2.4033e-22); + +setprop("/sim/rendering/hdr/atmos/aerosol-base-density", 1.3681e17); +setprop("/sim/rendering/hdr/atmos/aerosol-relative-background-density", 1.4619e-17); +setprop("/sim/rendering/hdr/atmos/aerosol-scale-height", 0.73); +setprop("/sim/rendering/hdr/atmos/fog-density", 0.0); +setprop("/sim/rendering/hdr/atmos/fog-scale-height", 1.0); +setprop("/sim/rendering/hdr/atmos/ozone-mean-dobson", 347.0); + +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); diff --git a/Shaders/HDR/atmos.glsl b/Shaders/HDR/atmos.glsl index 5c73bc668..c1edb0ecf 100644 --- a/Shaders/HDR/atmos.glsl +++ b/Shaders/HDR/atmos.glsl @@ -1,9 +1,24 @@ +/* + * Common atmosphere rendering functions + * + * See https://www.shadertoy.com/view/msXXDS for a more complete description + * of what the shader does and more references. + * + * All 4-component vectors in this file represent values sampled for the + * following wavelengths: 630, 560, 490, 430 nm + */ + #version 330 core -uniform int aerosol_type; -uniform float aerosol_turbidity; -uniform float ground_albedo; -uniform int month_of_the_year; +uniform vec4 aerosol_absorption_cross_section; +uniform vec4 aerosol_scattering_cross_section; +uniform float aerosol_base_density; +uniform float aerosol_relative_background_density; +uniform float aerosol_scale_height; +uniform float fog_density; +uniform float fog_scale_height; +uniform float ozone_mean_dobson; +uniform vec4 ground_albedo; uniform float fg_EarthRadius; @@ -19,37 +34,21 @@ const float HENYEY_ASYMMETRY2 = HENYEY_ASYMMETRY*HENYEY_ASYMMETRY; const vec4 molecular_scattering_coefficient_base = vec4(6.605e-6, 1.067e-5, 1.842e-5, 3.156e-5); +/* + * Fog scattering/extinction cross section, units m^2 / molecules + * Mie theory results for IOR of 1.333. Particle size is a log normal + * distribution of mean diameter=15 and std deviation=0.4 + */ +const vec4 fog_scattering_cross_section = + vec4(5.015e-10, 4.987e-10, 4.966e-10, 4.949e-10); + /* * Ozone absorption cross section, units m^2 / molecules * "High spectral resolution ozone absorption cross-sections" * by V. Gorshelev et al. (2014). */ -const vec4 ozone_cross_section = - vec4(3.472e-21, 3.914e-21, 1.349e-21, 11.03e-23) * 1e-4f; - -const float ozone_mean_monthly_dobson[] = float[]( - 347.0, // January - 370.0, // February - 381.0, // March - 384.0, // April - 372.0, // May - 352.0, // June - 333.0, // July - 317.0, // August - 298.0, // September - 285.0, // October - 290.0, // November - 315.0 // December - ); -const float ozone_height_distribution[] = float[]( - 9.0 / 210.0, - 14.0 / 210.0, - 111.0 / 210.0, - 64.0 / 210.0, - 6.0 / 210.0, - 6.0 / 210.0, - 0.0 - ); +const vec4 ozone_absorption_cross_section = + vec4(3.472e-25, 3.914e-25, 1.349e-25, 11.03e-27); // math.glsl float M_PI(); @@ -156,131 +155,46 @@ vec4 get_molecular_scattering_coefficient(float h) } /* - * Return the molecular volume absorption coefficient (km^-1) for a given altitude + * Return the molecular volume absorption coefficient (m^-1) for a given altitude * in kilometers. */ vec4 get_molecular_absorption_coefficient(float h) { - int i = int(clamp(h / 9.0, 0.0, 6.0)); - float density = ozone_height_distribution[i] * - ozone_mean_monthly_dobson[month_of_the_year-1] * 2.6867e20f; // molecules / m^2 - density /= 9e3; // m^-3 - return ozone_cross_section * density; // m^-1 + h += 1e-4; // Avoid division by 0 + float t = log(h) - 3.22261; + float density = 3.78547397e17 * (1.0 / h) * exp(-t * t * 5.55555555); + return ozone_absorption_cross_section * ozone_mean_dobson * density; } /* * Return the aerosol density for a given altitude in kilometers. */ -float get_aerosol_density(float h, float base_density, float height_scale, - float relative_background_density) +float get_aerosol_density(float h) { - if (aerosol_type == 0) { - // Only for the Background aerosol type, no dependency on height - return base_density * (1.0 + relative_background_density); - } else { - return base_density * (exp(-h / height_scale) + relative_background_density); - } + return aerosol_base_density * (exp(-h / aerosol_scale_height) + + aerosol_relative_background_density); } /* - * Get the aerosol collision coefficients for a given altitude h in km. - * The two main parameters are the aerosol type (0 to 8), and the turbidity. - * Every aerosol type expects 5 parameters: - * - Scattering cross section - * - Absorption cross section - * - Base density (km^-3) - * - Background density (km^-3) - * - Height scaling parameter + * Return the fog volume scattering coefficient (m^-1) for a given altitude in + * kilometers. * - * This model for aerosols and their corresponding parameters come from - * "A Physically-Based Spatio-Temporal Sky Model" - * by Guimera et al. (2018). + * Fog (or mist, depending on density) is a special kind of aerosol consisting + * of water droplets or ice crystals. Visibility is mostly dependent on fog. */ -void get_aerosol_collision_coefficients(in float h, - out vec4 absorption, - out vec4 scattering) +vec4 get_fog_scattering_coefficient(float h) { - vec4 aerosol_absorption_cross_section, aerosol_scattering_cross_section; - float aerosol_base_density, aerosol_background_density, aerosol_height_scale; - if (aerosol_type == 0) { - // Background - aerosol_absorption_cross_section = vec4(4.5517e-19, 5.9269e-19, 6.9143e-19, 8.5228e-19); - aerosol_scattering_cross_section = vec4(1.8921e-26, 1.6951e-26, 1.7436e-26, 2.1158e-26); - aerosol_base_density = 2.584e17; - aerosol_background_density = 2e6; - } else if (aerosol_type == 1) { - // Desert-Dust - aerosol_absorption_cross_section = vec4(4.6758e-16, 4.4654e-16, 4.1989e-16, 4.1493e-16); - aerosol_scattering_cross_section = vec4(2.9144e-16, 3.1463e-16, 3.3902e-16, 3.4298e-16); - aerosol_base_density = 1.8662e18; - aerosol_background_density = 2e6; - aerosol_height_scale = 2.0; - } else if (aerosol_type == 2) { - // Maritime Clean - aerosol_absorption_cross_section = vec4(6.3312e-19, 7.5567e-19, 9.2627e-19, 1.0391e-18); - aerosol_scattering_cross_section = vec4(4.6539e-26, 2.721e-26, 4.1104e-26, 5.6249e-26); - aerosol_base_density = 2.0266e17; - aerosol_background_density = 2e6; - aerosol_height_scale = 0.9; - } else if (aerosol_type == 3) { - // Maritime Mineral - aerosol_absorption_cross_section = vec4(6.9365e-19, 7.5951e-19, 8.2423e-19, 8.9101e-19); - aerosol_scattering_cross_section = vec4(2.3699e-19, 2.2439e-19, 2.2126e-19, 2.021e-19); - aerosol_base_density = 2.0266e17; - aerosol_background_density = 2e6; - aerosol_height_scale = 2.0; - } else if (aerosol_type == 4) { - // Polar Antarctic - aerosol_absorption_cross_section = vec4(1.3399e-16, 1.3178e-16, 1.2909e-16, 1.3006e-16); - aerosol_scattering_cross_section = vec4(1.5506e-19, 1.809e-19, 2.3069e-19, 2.5804e-19); - aerosol_base_density = 2.3864e16; - aerosol_background_density = 2e6; - aerosol_height_scale = 30.0; - } else if (aerosol_type == 5) { - // Polar Arctic - aerosol_absorption_cross_section = vec4(1.0364e-16, 1.0609e-16, 1.0193e-16, 1.0092e-16); - aerosol_scattering_cross_section = vec4(2.1609e-17, 2.2759e-17, 2.5089e-17, 2.6323e-17); - aerosol_base_density = 2.3864e16; - aerosol_background_density = 2e6; - aerosol_height_scale = 30.0; - } else if (aerosol_type == 6) { - // Remote Continental - aerosol_absorption_cross_section = vec4(4.5307e-18, 5.0662e-18, 4.4877e-18, 3.7917e-18); - aerosol_scattering_cross_section = vec4(1.8764e-18, 1.746e-18, 1.6902e-18, 1.479e-18); - aerosol_base_density = 6.103e18; - aerosol_background_density = 2e6; - aerosol_height_scale = 0.73; - } else if (aerosol_type == 7) { - // Rural - aerosol_absorption_cross_section = vec4(5.0393e-23, 8.0765e-23, 1.3823e-22, 2.3383e-22); - aerosol_scattering_cross_section = vec4(2.6004e-22, 2.4844e-22, 2.8362e-22, 2.7494e-22); - aerosol_base_density = 8.544e18; - aerosol_background_density = 2e6; - aerosol_height_scale = 0.73; - } else if (aerosol_type == 8) { - // Urban - aerosol_absorption_cross_section = vec4(2.8722e-24, 4.6168e-24, 7.9706e-24, 1.3578e-23); - aerosol_scattering_cross_section = vec4(1.5908e-22, 1.7711e-22, 2.0942e-22, 2.4033e-22); - aerosol_base_density = 1.3681e20; - aerosol_background_density = 2e6; - aerosol_height_scale = 0.73; + if (fog_density > 0.0) { + return fog_scattering_cross_section * fog_density + * exp(-h / fog_scale_height); + } else { + return vec4(0.0); } - - float aerosol_relative_background_density = - aerosol_background_density / aerosol_base_density; - - float aerosol_density = get_aerosol_density( - h, aerosol_base_density, aerosol_height_scale, - aerosol_relative_background_density); - aerosol_density *= aerosol_turbidity * 1e-3; - - absorption = aerosol_absorption_cross_section * aerosol_density; - scattering = aerosol_scattering_cross_section * aerosol_density; } /* * Get the collision coefficients (scattering and absorption) of the - * atmospheric medium for a given point at an altitude h. + * atmospheric medium for a given point at an altitude h in meters. */ void get_atmosphere_collision_coefficients(in float h, out vec4 aerosol_absorption, @@ -291,9 +205,19 @@ void get_atmosphere_collision_coefficients(in float h, { h *= 1e-3; // To km h = max(h, 0.0); // In case height is negative - get_aerosol_collision_coefficients(h, aerosol_absorption, aerosol_scattering); + + // Molecules molecular_absorption = get_molecular_absorption_coefficient(h); molecular_scattering = get_molecular_scattering_coefficient(h); + + // Aerosols + float aerosol_density = get_aerosol_density(h); + aerosol_absorption = aerosol_absorption_cross_section * aerosol_density; + aerosol_scattering = aerosol_scattering_cross_section * aerosol_density; + + // Add contribution from fog + aerosol_scattering += get_fog_scattering_coefficient(h); + extinction = aerosol_absorption + aerosol_scattering + molecular_absorption + molecular_scattering; diff --git a/defaults.xml b/defaults.xml index 577fb38ad..bb1371f12 100644 --- a/defaults.xml +++ b/defaults.xml @@ -535,11 +535,6 @@ Started September 2000 by David Megginson, david@megginson.com 2 0.0 - - 8 - 1.0 - 0.4 - 0.01 0.005