Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Advanced eclipses #395

Draft
wants to merge 142 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
142 commits
Select commit Hold shift + click to select a range
d229174
:wrench: Add refraction parameter
Schneegans Jun 13, 2024
ce31ca0
:tada: Add IoR computation to the preprocessor
Schneegans Jun 13, 2024
a51d32d
:wrench: Add IoR data
Schneegans Jun 13, 2024
778e8cb
:wrench: Write n-1 in IoR mode
Schneegans Jun 13, 2024
5ec1566
:wrench: Tweak CSV header
Schneegans Jun 13, 2024
ae01688
:wrench: Load IoR data for preprocessing
Schneegans Jun 13, 2024
4d964cf
:wrench: Temporarily increase the transmittance texture size
Schneegans Jun 17, 2024
a32b087
:wrench: Do ray-marching in 2D and not in mu-r parameter space
Schneegans Jun 17, 2024
964e63f
:wrench: Compute mu deviation while tracing rays
Schneegans Jun 18, 2024
1d1979b
:wrench: Write refraction metadata
Schneegans Jun 18, 2024
7c28876
:wrench: Read refraction data
Schneegans Jun 18, 2024
9744f9e
:beetle: Fix angle output
Schneegans Jun 19, 2024
5cc5086
:wrench: Unregister all callbacks in atmosphere plugin
Schneegans Jun 19, 2024
cb7845a
:wrench: Use more stable angle computation
Schneegans Jun 19, 2024
4d36a72
:beetle: Fix sun direction in atmosphere shader
Schneegans Jun 19, 2024
b2eef52
:wrench: Work on refraction
Schneegans Jun 19, 2024
8c65ec0
:wrench: Add some simple sun antialiasing
Schneegans Jun 19, 2024
2a098c6
:arrow_up: Upgrade output submodule
Schneegans Jun 21, 2024
db311f3
:truck: Rename mu-deviation to theta-deviation
Schneegans Jun 24, 2024
48b50e8
Merge branch 'feature/separate-atmosphere-preprocessor' into feature/…
Schneegans Jun 26, 2024
3882be3
Merge branch 'main' into feature/refraction
Schneegans Jul 15, 2024
913b6be
:arrow_up: Upgrade submodules
Schneegans Jul 16, 2024
b863c3d
:recycle: Put simple shadow computation in their own files
Schneegans Jul 16, 2024
c8a0de8
:wrench: Load pre-processed textures
Schneegans Jul 16, 2024
6bb9252
:wrench: Upload textures to Cuda device
Schneegans Jul 17, 2024
3174223
:wrench: Add some atmosphere code
Schneegans Jul 17, 2024
22d2285
:wrench: Draw atmosphere with Cuda
Schneegans Jul 18, 2024
a173700
:wrench: Optimize code for the outer space case
Schneegans Jul 18, 2024
5425c29
:wrench: Add Sun
Schneegans Jul 18, 2024
6274662
:tada: Add refraction
Schneegans Jul 18, 2024
94d42f6
:wrench: Tweak example scenes
Schneegans Jul 18, 2024
8a379e8
:wrench: Add tonemapping
Schneegans Jul 18, 2024
6a79d10
:wrench: Tweak example scenes
Schneegans Jul 18, 2024
7332df1
:tada: Add atmo-pano-mode
Schneegans Jul 19, 2024
4771dc1
:recycle: Refactor code to be a little bit more modular
Schneegans Jul 22, 2024
d2df416
:wrench: Expose some parameters as command line flags
Schneegans Jul 22, 2024
65e02f1
:memo: Add loop example
Schneegans Jul 22, 2024
289608d
:wrench: Add initial bruneton mode code
Schneegans Jul 22, 2024
71c05ef
:wrench: Work on eclipse shadow
Schneegans Jul 23, 2024
d7bd7a7
:recycle: Improve code structure
Schneegans Jul 25, 2024
6fef8c5
:truck: Shorten some struct names
Schneegans Jul 25, 2024
a922bde
:wrench: Remove some hard-coded values
Schneegans Jul 25, 2024
dc43e06
:memo: Add some comments
Schneegans Jul 25, 2024
f33e9aa
:copyright: Add correct SPDX tags
Schneegans Jul 25, 2024
75f28c3
:wrench: Streamline eclipse intensity computation
Schneegans Jul 25, 2024
6f30574
:wrench: Print retrieved observer position
Schneegans Jul 29, 2024
baae8bc
:wrench: Add mars IoR data
Schneegans Aug 2, 2024
92f6aa2
:wrench: Add approximate progress print
Schneegans Aug 2, 2024
795b8a1
:memo: Use size flags
Schneegans Aug 2, 2024
478a622
:wrench: Optimize getting IoR
Schneegans Aug 2, 2024
f807cd1
:wrench: Encode hits-ground property in sign
Schneegans Aug 2, 2024
ff2d3ba
:wrench: Make refraction wavelength-independent
Schneegans Aug 5, 2024
dbb1149
:wrench: Improve sampling
Schneegans Aug 5, 2024
67e317a
:start Working on refraction for single scattering
Schneegans Aug 6, 2024
2e46478
:rench: Increase sample count
Schneegans Aug 6, 2024
d383c59
:wrench: Fix single-scattering refraction
Schneegans Aug 7, 2024
8606b5a
:wrench: Do not refract rays in the underground
Schneegans Aug 7, 2024
1eb25db
:recycle: Use method for ray refraction
Schneegans Aug 7, 2024
7605069
:beetle: Fix getting refracted framebuffer color
Schneegans Aug 8, 2024
378531a
:wrench: Compute single-scattering transmittance on-the-fly
Schneegans Aug 8, 2024
589c763
:wrench: Tweak sampling settings
Schneegans Aug 8, 2024
d39795e
:wrench: Improve precision by using sine instead of cosine
Schneegans Aug 9, 2024
408c58d
:wrench: Simplify projection of refracted view ray
Schneegans Aug 9, 2024
3de5852
:wrench: Add expermiental ray jittering
Schneegans Aug 9, 2024
c4c8d71
:fire: Remove jittering again
Schneegans Aug 12, 2024
7958f09
:wrench: Add initial code for atmosphere pano mode
Schneegans Aug 12, 2024
9c0a4dd
:wrench: Store output as tiff files
Schneegans Aug 13, 2024
01a204a
:wrench: Load eclipse shadows from tif files
Schneegans Aug 13, 2024
438d142
:wrench: Add limb-luminance mode
Schneegans Aug 13, 2024
ecca07b
:tada: Add limb luminance lookups
Schneegans Aug 13, 2024
0ed8a2f
:wrench: Prevent some nans
Schneegans Aug 14, 2024
e5ccf57
:lipstick: Improve layout of plugin settings pane
Schneegans Aug 14, 2024
9de1080
:memo: Update example commands
Schneegans Aug 14, 2024
147d926
:truck: Move frustum class to cs::utils
Schneegans Aug 14, 2024
f5c4383
:wrench: Switch to limb luminance approximation based on atmosphere w…
Schneegans Aug 14, 2024
6cf7b7c
:wrench: Update ozone absoprtion data
Schneegans Aug 14, 2024
cd979c1
:wrench: Update ozone constants
Schneegans Aug 15, 2024
876a8bc
:wrench: Print maximum ray deviation
Schneegans Aug 15, 2024
80f7193
:memo: Use different base directory for example commands
Schneegans Aug 15, 2024
539c26b
:memo: Use different base directory for example commands
Schneegans Aug 15, 2024
f893374
:bug: Fix limb luminance texture lookup
Schneegans Aug 15, 2024
37228eb
:wrench: Add Runge Kutta
Schneegans Aug 15, 2024
1b57d5d
:wrench: Store contact radius in texture
Schneegans Aug 16, 2024
1b68c71
:wrench: Use linear interpolation for average land height
Schneegans Aug 16, 2024
f06ec78
:recycle: Refactor computeSingleScattering
Schneegans Aug 16, 2024
44b7aec
:beetle: Fix space view
Schneegans Aug 16, 2024
5c40bef
:wrench: Implement refraction for multiple scattering
Schneegans Aug 19, 2024
95fef57
:fire: Remove useless cast to vec3
Schneegans Aug 19, 2024
af99aff
:beetle: Fix sun direction
Schneegans Aug 20, 2024
06326a1
:beetle: Fix sun being visible through the planet
Schneegans Aug 20, 2024
4f0111e
:beetle: Fix multi scattering refraction
Schneegans Aug 20, 2024
17fcb16
:wrench: Update atmosphere settings
Schneegans Aug 20, 2024
fd072b9
:wrench: Update atmosphere data
Schneegans Aug 20, 2024
463c479
:arrow_up: Update submodule
Schneegans Aug 20, 2024
db40880
:wrench: Update atmosphere settings
Schneegans Aug 20, 2024
93c2640
:beetle: Fix compilation on MSVC
Schneegans Aug 28, 2024
277e7e8
:wrench: Add alternative integration scheme comments
Schneegans Aug 29, 2024
eee330f
:wrench: reset molecule scale height
Schneegans Aug 29, 2024
2c412fc
:wrench: Increase sampling rate
Schneegans Aug 29, 2024
fcaf624
:wrench: Improve transition to limb luminance approximation
Schneegans Aug 29, 2024
75c3d29
:wrench: Update scattering data
Schneegans Aug 29, 2024
6a326bc
:beetle: Fix file paths
Schneegans Aug 29, 2024
aa72c49
:wrench: Add eclipse shadow maps to default config
Schneegans Aug 29, 2024
1f3f9cb
:wrench: Increase resolution of transmittance texture
Schneegans Sep 5, 2024
633efa2
:wrench: Make terrain height configurable
Schneegans Sep 8, 2024
117bc11
:wrench: Add cloud-altitude parameter
Schneegans Sep 13, 2024
e478024
:wrench: Add support for eclipses without refraction
Schneegans Sep 15, 2024
ae667ad
:wrench: Check for refraction support when using limb luminance
Schneegans Sep 17, 2024
63ece3e
:wrench: Increase sampling rate
Schneegans Sep 17, 2024
4dcbf47
Merge branch 'main' into feature/advanced-eclipses
Schneegans Sep 20, 2024
0b7faf1
:wrench: Shrink last segment of multiple scattered rays hitting the g…
Schneegans Sep 20, 2024
0da98ba
:wrench: Enable precomputed limb luminance foll all atmospheres together
Schneegans Sep 24, 2024
9b0eb92
Merge branch 'feature/advanced-eclipses' of https://gitlab.dlr.de/sci…
Schneegans Sep 24, 2024
f60ae1d
:wrench: Reduce limit for precomputed limb luminance atmosphere width
Schneegans Sep 24, 2024
e040d25
:arrow_up: Update submodule
Schneegans Oct 30, 2024
4dbff1f
Merge branch 'main' into feature/advanced-eclipses
Schneegans Oct 30, 2024
212c2b3
:wrench: Handle impossible shadow map positions
Schneegans Oct 30, 2024
97bfb64
:memo: Add some eclipse shadow documentation
Schneegans Oct 30, 2024
38f9914
:memo: Start adding some comments
Schneegans Nov 4, 2024
5deda4d
:wrench: Add alternative integration schemes
Schneegans Nov 5, 2024
d3764f8
:memo: Add lots of comments
Schneegans Nov 5, 2024
33f5944
:memo: add more documentation
Schneegans Nov 5, 2024
a748476
:memo: Add several comments
Schneegans Nov 6, 2024
cf0b924
:memo: Add several comments
Schneegans Nov 6, 2024
e3c0e91
:wrench: Update precomputed textures
Schneegans Nov 6, 2024
60c30e5
:memo: Add documentation for how to re-create the eclipse shadow maps
Schneegans Nov 6, 2024
b58bd06
:wrench: Reduce bottom altitude of atmospheres
Schneegans Nov 6, 2024
9da7229
:wrench: Do not hard-code sun angular radius and luminance
Schneegans Nov 6, 2024
62071ae
:wrench: Boost sun disc brightness in non-HDR mode
Schneegans Nov 6, 2024
f921b11
:truck: Rename parameters
Schneegans Jan 3, 2025
6249166
:memo: Fix commands
Schneegans Jan 3, 2025
63fa7bb
:wrench: Use variable names more in line with the paper
Schneegans Jan 3, 2025
17021a5
:truck: Move limb luminance to atmosphere plugin
Schneegans Jan 5, 2025
ee4414f
:copyright: Add license information
Schneegans Jan 5, 2025
83276fb
:tada: Add support for multiple layers in limb luminance
Schneegans Jan 5, 2025
dc19972
:memo: Use two luminance layers per default
Schneegans Jan 5, 2025
839ff61
Merge branch 'main' into feature/advanced-eclipses
Schneegans Jan 5, 2025
b391b4b
:fire: Revert some unnecessary changes
Schneegans Jan 6, 2025
4bd3456
:memo: Add some comments
Schneegans Jan 6, 2025
6596b16
:memo: Add note regarding IoR usage
Schneegans Jan 6, 2025
42fcf20
:fire: Revert some unnecessary changes
Schneegans Jan 6, 2025
f70dc02
:memo: Add plenty of comments
Schneegans Jan 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions config/base/scene/simple_desktop.json
Original file line number Diff line number Diff line change
Expand Up @@ -282,9 +282,13 @@
"graphics": {
"enableHDR": true,
"eclipseShadowMaps": {
"Earth": {},
"Earth": {
"texture":"../share/resources/textures/earthShadow.tif"
},
"Moon": {},
"Mars": {},
"Mars": {
"texture":"../share/resources/textures/marsShadow.tif"
},
"Phobos": {},
"Deimos": {},
"Jupiter": {},
Expand Down Expand Up @@ -739,6 +743,7 @@
"atmospheres": {
"Earth": {
"cloudTexture": "../share/resources/textures/earth-clouds.jpg",
"limbLuminanceTexture": "../share/resources/textures/earthLimbLuminance.tif",
"topAltitude": 80000,
"bottomAltitude": -100,
"model": "Bruneton",
Expand Down
14 changes: 10 additions & 4 deletions plugins/csp-atmospheres/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,15 +145,21 @@ They are not physically based but provide some plausible results.
The Bruneton model is significantly more advanced.
It precomputes multiple scattering and is based on [this open-source implementation](https://github.com/ebruneton/precomputed_atmospheric_scattering) (see also the corresponding [Paper](https://inria.hal.science/inria-00288758/en)).

Similar to the `CosmoScoutVR` model, the original implementation by Eric Bruneton uses Rayleigh scattering for molecules and the Cornette-Shanks phase function for aerosols.
We generalized this implementation by loading phase functions, extinction coefficients, and particle density distributions from CSV files.
We have significantly extended the original implementation to allow for more flexibility.
See our paper [Physically Based Real-Time Rendering of Atmospheres using Mie Theory](https://onlinelibrary.wiley.com/doi/full/10.1111/cgf.15010) for more details.

As a first change, we now load phase functions, extinction coefficients, and particle density distributions from CSV files.
This allows us to simulate arbitrary particle types.
In particular, we can now use Mie Theory to precompute the scattering behaviour of a wide variety of particle types, including for instance Martian dust.

Next, our implementation can compute refraction.
This allows for displaced horizons and the simulation of astronomical refraction.
This is also used for computing light entering the eclipse shadows of celestial bodies.

Another change to the original implementation is that we put the precomputation of the atmospheric scattering into a separate executable.
This allows us to perform the preprocessing offline with a much higher fidelity than what would be possible during application startup.

As a consequence to the changes mentioned above, **two preprocessing steps are required to use this model**.
There are **two preprocessing steps are required to use this model**.

#### Preprocessing Step 1: Precompute the Particle-Scattering CSV Tables

Expand Down Expand Up @@ -197,7 +203,7 @@ Once the multiple scattering textures are precomputed, the configuration for the
</details>

<details>
<summary>Example Configuration for Mars (Realistic)</summary>
<summary>Example Configuration for Mars</summary>

```javascript
"Mars": {
Expand Down
6 changes: 6 additions & 0 deletions plugins/csp-atmospheres/REUSE.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ precedence = "aggregate"
SPDX-FileCopyrightText = "German Aerospace Center (DLR) <[email protected]>"
SPDX-License-Identifier = "CC0-1.0"

[[annotations]]
path = "scattering-table-generator/ior-settings/**"
precedence = "aggregate"
SPDX-FileCopyrightText = "German Aerospace Center (DLR) <[email protected]>"
SPDX-License-Identifier = "CC0-1.0"

[[annotations]]
path = "scattering-table-generator/output/**"
precedence = "aggregate"
Expand Down
1 change: 1 addition & 0 deletions plugins/csp-atmospheres/bruneton-preprocessor/Metadata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ void to_json(nlohmann::json& j, Metadata const& o) {
cs::core::Settings::serialize(j, "sunIlluminance", o.mSunIlluminance);
cs::core::Settings::serialize(j, "scatteringTextureNuSize", o.mScatteringTextureNuSize);
cs::core::Settings::serialize(j, "maxSunZenithAngle", o.mMaxSunZenithAngle);
cs::core::Settings::serialize(j, "refraction", o.mRefraction);
}

////////////////////////////////////////////////////////////////////////////////////////////////////
3 changes: 3 additions & 0 deletions plugins/csp-atmospheres/bruneton-preprocessor/Metadata.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ struct Metadata {

/// The maximum Sun zenith angle for which atmospheric scattering was be precomputed.
float mMaxSunZenithAngle{};

/// Whether refraction was used during preprocessing.
bool mRefraction{};
};

void to_json(nlohmann::json& j, Metadata const& o);
Expand Down
5 changes: 5 additions & 0 deletions plugins/csp-atmospheres/bruneton-preprocessor/Params.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,18 @@ void from_json(nlohmann::json const& j, Params& o) {
cs::core::Settings::deserialize(j, "molecules", o.mMolecules);
cs::core::Settings::deserialize(j, "aerosols", o.mAerosols);
cs::core::Settings::deserialize(j, "ozone", o.mOzone);
cs::core::Settings::deserialize(j, "ior", o.mRefractiveIndex);
cs::core::Settings::deserialize(j, "minAltitude", o.mMinAltitude);
cs::core::Settings::deserialize(j, "maxAltitude", o.mMaxAltitude);
cs::core::Settings::deserialize(j, "refraction", o.mRefraction);
cs::core::Settings::deserialize(j, "groundAlbedo", o.mGroundAlbedo);
cs::core::Settings::deserialize(j, "multiScatteringOrder", o.mMultiScatteringOrder);
cs::core::Settings::deserialize(j, "sampleCountOpticalDepth", o.mSampleCountOpticalDepth);
cs::core::Settings::deserialize(j, "stepSizeOpticalDepth", o.mStepSizeOpticalDepth);
cs::core::Settings::deserialize(j, "sampleCountSingleScattering", o.mSampleCountSingleScattering);
cs::core::Settings::deserialize(j, "stepSizeSingleScattering", o.mStepSizeSingleScattering);
cs::core::Settings::deserialize(j, "sampleCountMultiScattering", o.mSampleCountMultiScattering);
cs::core::Settings::deserialize(j, "stepSizeMultiScattering", o.mStepSizeMultiScattering);
cs::core::Settings::deserialize(
j, "sampleCountScatteringDensity", o.mSampleCountScatteringDensity);
cs::core::Settings::deserialize(
Expand Down
24 changes: 21 additions & 3 deletions plugins/csp-atmospheres/bruneton-preprocessor/Params.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ struct Params {
ScatteringComponent mAerosols;
std::optional<AbsorbingComponent> mOzone;

/// To compute the refraction of light in the atmosphere, the refractive index of the atmosphere
/// is needed. For increased precision, the refractive index is stored as n-1.
float mRefractiveIndex = 0.0002777F;

/// The wavelength values, in nanometers, and sorted in increasing order, for which the
/// phase functions and extinction coefficients in the atmosphere components are given.
std::vector<float> mWavelengths;
Expand All @@ -69,22 +73,36 @@ struct Params {
float mMinAltitude = 6371000.F;
float mMaxAltitude = 6471000.F;

/// Refract the light when it travels through the atmosphere. This will produce an additional
/// look-up texture in the same parameter space as the transmittance texture. For each sample,
/// it contains the wavelength-dependent angular deviation of the light ray due to refraction.
cs::utils::DefaultProperty<bool> mRefraction{true};

/// The average reflectance of the ground used during multiple scattering.
cs::utils::DefaultProperty<float> mGroundAlbedo{0.1F};

/// The number of multiple scattering events to precompute. Use zero for single-scattering only.
cs::utils::DefaultProperty<int32_t> mMultiScatteringOrder{4};

/// The number of samples to evaluate when precomputing the optical depth.
/// The number of samples to evaluate when precomputing the optical depth. If refraction is used,
/// the algorithm uses a fixed step size instead of a fixed number of samples. So if mRefraction
/// is true, mStepSizeOpticalDepth (in meters) will be used instead of mSampleCountOpticalDepth.
cs::utils::DefaultProperty<int32_t> mSampleCountOpticalDepth{500};
cs::utils::DefaultProperty<int32_t> mStepSizeOpticalDepth{10000};

/// The number of samples to evaluate when precomputing the single scattering. Larger values
/// improve the sampling of thin atmospheric layers.
/// improve the sampling of thin atmospheric layers. If refraction is used, the algorithm uses a
/// fixed step size instead of a fixed number of samples. So if mRefraction is true,
/// mStepSizeSingleScattering (in meters) will be used instead of mSampleCountSingleScattering.
cs::utils::DefaultProperty<int32_t> mSampleCountSingleScattering{50};
cs::utils::DefaultProperty<int32_t> mStepSizeSingleScattering{10000};

/// The number of samples to evaluate when precomputing the multiple scattering. Larger values
/// tend to darken the horizon for thick atmospheres.
/// tend to darken the horizon for thick atmospheres. If refraction is used, the algorithm uses a
/// fixed step size instead of a fixed number of samples. So if mRefraction is true,
/// mStepSizeMultiScattering (in meters) will be used instead of mSampleCountMultiScattering.
cs::utils::DefaultProperty<int32_t> mSampleCountMultiScattering{50};
cs::utils::DefaultProperty<int32_t> mStepSizeMultiScattering{10000};

/// The number of samples to evaluate when precomputing the scattering density. Larger values
/// spread out colors in the sky.
Expand Down
97 changes: 86 additions & 11 deletions plugins/csp-atmospheres/bruneton-preprocessor/Preprocessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@
// density distributions are now loaded from CSV files and then later sampled from textures. We also
// store photometric values instead of radiometric values in the final textures.

// Also, we added the possibility to compute the refraction of light rays through the atmosphere.
// If enabled, an additional texture is generated which contains the angular deviation of the light
// rays as well as their closest approach to the planet's surface (this can be negative if the light
// ray intersects the planet's surface).
// The texture uses the same parametrization as the transmittance texture. The values are computed
// by the kComputeTransmittanceShader.

// Below, we will indicate for each group of function whether something has been changed and a link
// to the original explanations of the methods by Eric Bruneton.

Expand Down Expand Up @@ -185,9 +192,11 @@ constexpr float XYZ_TO_SRGB[9] = {
// An explanation of the following shaders is available online:
// https://ebruneton.github.io/precomputed_atmospheric_scattering/atmosphere/model.cc.html#shaders

// The only functional difference is that the kAtmosphereShader does not provide the radiance API
// The only functional differences are that the kAtmosphereShader does not provide the radiance API
// anymore as it is not required by CosmoScout VR. Also, the shadow_length parameters have been
// removed and the GetSunAndSkyIlluminance() does not require the surface normal anymore.
// Lastly, the kComputeTransmittanceShader has been extended to compute the refraction of light rays
// through the atmosphere.

const char kVertexShader[] = R"(
#version 330
Expand Down Expand Up @@ -227,8 +236,20 @@ const char kGeometryShader[] = R"(
const char kComputeTransmittanceShader[] = R"(
layout(location = 0) out vec3 oTransmittance;

#if COMPUTE_REFRACTION
layout(location = 1) out vec3 oThetaDeviationContactRadius;
#endif

void main() {
oTransmittance = computeTransmittanceToTopAtmosphereBoundaryTexture(ATMOSPHERE, gl_FragCoord.xy);
#if COMPUTE_REFRACTION
float contactRadius;
float thetaDeviation;
oTransmittance = computeTransmittanceToTopAtmosphereBoundaryTexture(ATMOSPHERE, gl_FragCoord.xy, thetaDeviation, contactRadius);
oThetaDeviationContactRadius = vec3(thetaDeviation, contactRadius, 0.0);

#else
oTransmittance = computeTransmittanceToTopAtmosphereBoundaryTexture(ATMOSPHERE, gl_FragCoord.xy);
#endif
}
)";

Expand Down Expand Up @@ -313,7 +334,7 @@ const char kComputeMultipleScatteringShader[] = R"(

void main() {
float nu;
oDeltaMultipleScattering = computeMultipleScatteringTexture(uTransmittanceTexture,
oDeltaMultipleScattering = computeMultipleScatteringTexture(ATMOSPHERE, uTransmittanceTexture,
uScatteringDensityTexture,
vec3(gl_FragCoord.xy, uLayer + 0.5),
nu);
Expand Down Expand Up @@ -674,6 +695,7 @@ Preprocessor::Preprocessor(Params params)
mMetadata.mSunIlluminance = glm::vec3(sunKR, sunKG, sunKB);
mMetadata.mScatteringTextureNuSize = mParams.mScatteringTextureNuSize.get();
mMetadata.mMaxSunZenithAngle = mParams.mMaxSunZenithAngle.get();
mMetadata.mRefraction = mParams.mRefraction.get();

// A lambda that creates a GLSL header containing our atmosphere computation functions,
// specialized for the given atmosphere parameters and for the 3 wavelengths in 'lambdas'.
Expand All @@ -689,8 +711,9 @@ Preprocessor::Preprocessor(Params params)
// clang-format off
mGlslHeaderFactory = [=](glm::vec3 const& lambdas) {
return
"#version 330\n" +
"#version 400\n" +
definitions +
"#define COMPUTE_REFRACTION " + cs::utils::toString(mParams.mRefraction) + "\n" +
"const int TRANSMITTANCE_TEXTURE_WIDTH = " + cs::utils::toString(mParams.mTransmittanceTextureWidth) + ";\n" +
"const int TRANSMITTANCE_TEXTURE_HEIGHT = " + cs::utils::toString(mParams.mTransmittanceTextureHeight) + ";\n" +
"const int SCATTERING_TEXTURE_R_SIZE = " + cs::utils::toString(mParams.mScatteringTextureRSize) + ";\n" +
Expand All @@ -700,12 +723,16 @@ Preprocessor::Preprocessor(Params params)
"const int IRRADIANCE_TEXTURE_WIDTH = " + cs::utils::toString(mParams.mIrradianceTextureWidth) + ";\n" +
"const int IRRADIANCE_TEXTURE_HEIGHT = " + cs::utils::toString(mParams.mIrradianceTextureHeight) + ";\n" +
"const int SAMPLE_COUNT_OPTICAL_DEPTH = " + cs::utils::toString(mParams.mSampleCountOpticalDepth) + ";\n" +
"const int STEP_SIZE_OPTICAL_DEPTH = " + cs::utils::toString(mParams.mStepSizeOpticalDepth) + ";\n" +
"const int SAMPLE_COUNT_SINGLE_SCATTERING = " + cs::utils::toString(mParams.mSampleCountSingleScattering) + ";\n" +
"const int STEP_SIZE_SINGLE_SCATTERING = " + cs::utils::toString(mParams.mStepSizeSingleScattering) + ";\n" +
"const int SAMPLE_COUNT_SCATTERING_DENSITY = " + cs::utils::toString(mParams.mSampleCountScatteringDensity) + ";\n" +
"const int SAMPLE_COUNT_MULTI_SCATTERING = " + cs::utils::toString(mParams.mSampleCountMultiScattering) + ";\n" +
"const int STEP_SIZE_MULTI_SCATTERING = " + cs::utils::toString(mParams.mStepSizeMultiScattering) + ";\n" +
"const int SAMPLE_COUNT_INDIRECT_IRRADIANCE = " + cs::utils::toString(mParams.mSampleCountIndirectIrradiance) + ";\n" +
"const vec3 SOLAR_IRRADIANCE = " + extractVec3(WAVELENGTHS, SOLAR_IRRADIANCE, lambdas) + ";\n" +
"const vec3 GROUND_ALBEDO = vec3(" + cs::utils::toString(mParams.mGroundAlbedo) + ");\n" +
"const float INDEX_OF_REFRACTION = " + cs::utils::toString(mParams.mRefractiveIndex) + ";\n" +
"const float SUN_ANGULAR_RADIUS = " + cs::utils::toString(mMetadata.mSunAngularRadius) + ";\n" +
"const float BOTTOM_RADIUS = " + cs::utils::toString(mParams.mMinAltitude) + ";\n" +
"const float TOP_RADIUS = " + cs::utils::toString(mParams.mMaxAltitude) + ";\n" +
Expand All @@ -723,6 +750,9 @@ Preprocessor::Preprocessor(Params params)
mTransmittanceTexture = NewTexture2d(mParams.mTransmittanceTextureWidth.get(),
mParams.mTransmittanceTextureHeight.get(), GL_RGB32F, GL_RGB, GL_FLOAT);

mThetaDeviationTexture = NewTexture2d(mParams.mTransmittanceTextureWidth.get(),
mParams.mTransmittanceTextureHeight.get(), GL_RGB32F, GL_RGB, GL_FLOAT);

mMultipleScatteringTexture = NewTexture3d(mScatteringTextureWidth, mScatteringTextureHeight,
mScatteringTextureDepth, GL_RGB32F, GL_RGB, GL_FLOAT);

Expand Down Expand Up @@ -782,6 +812,7 @@ Preprocessor::~Preprocessor() {
glDeleteVertexArrays(1, &mFullScreenQuadVAO);
glDeleteTextures(1, &mPhaseTexture);
glDeleteTextures(1, &mTransmittanceTexture);
glDeleteTextures(1, &mThetaDeviationTexture);
glDeleteTextures(1, &mMultipleScatteringTexture);
glDeleteTextures(1, &mSingleAerosolsScatteringTexture);
glDeleteTextures(1, &mIrradianceTexture);
Expand Down Expand Up @@ -872,13 +903,22 @@ void Preprocessor::run(unsigned int numScatteringOrders) {
numScatteringOrders);
}

// After the above iterations, the transmittance texture contains the transmittance for the 3
// wavelengths used at the last iteration. But we want the transmittance at kLambdaR, kLambdaG,
// kLambdaB instead, so we must recompute it here for these 3 wavelengths:
// After the above iterations, the transmittance texture and the theta-deviation texture contain
// data for the 3 wavelengths used at the last iteration. But we want data at kLambdaR,
// kLambdaG, kLambdaB instead, so we must recompute it here for these 3 wavelengths:
std::string header = mGlslHeaderFactory({kLambdaR, kLambdaG, kLambdaB});
Program computeTransmittance(kVertexShader, header + kComputeTransmittanceShader);
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTransmittanceTexture, 0);
glDrawBuffer(GL_COLOR_ATTACHMENT0);

if (mParams.mRefraction.get()) {
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, mThetaDeviationTexture, 0);

const GLuint kDrawBuffers[4] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
glDrawBuffers(2, kDrawBuffers);
} else {
glDrawBuffer(GL_COLOR_ATTACHMENT0);
}

glViewport(
0, 0, mParams.mTransmittanceTextureWidth.get(), mParams.mTransmittanceTextureHeight.get());
glScissor(
Expand Down Expand Up @@ -915,8 +955,29 @@ void Preprocessor::run(unsigned int numScatteringOrders) {
void Preprocessor::save(std::string const& directory) {
std::cout << "Saving precomputed atmosphere to disk..." << std::endl;

// Save the precomputed textures to disk. We need to store mMultipleScatteringTexture,
// mSingleAerosolsScatteringTexture, mPhaseTexture, mTransmittanceTexture, and mIrradianceTexture.
// For debugging purposes, we print the maximum ray deviation in degrees.
std::vector<float> pixels(
mParams.mTransmittanceTextureWidth.get() * mParams.mTransmittanceTextureHeight.get() * 3);
glBindTexture(GL_TEXTURE_2D, mThetaDeviationTexture);
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_FLOAT, pixels.data());
glBindTexture(GL_TEXTURE_2D, 0);

float maxThetaDeviation = 0.F;
for (int x = 0; x < mParams.mTransmittanceTextureWidth.get(); ++x) {
for (int y = 0; y < mParams.mTransmittanceTextureHeight.get(); ++y) {
int i = 3 * (y * mParams.mTransmittanceTextureWidth.get() + x);

float thetaDeviation = pixels[i];
float contactRadius = pixels[i + 1];

if (contactRadius > 0.F) {
maxThetaDeviation = std::max(maxThetaDeviation, thetaDeviation);
}
}
}

std::cout << "Maximum ray deviation: " << maxThetaDeviation * 180.F / glm::pi<float>()
<< " degrees." << std::endl;

auto write2D = [](std::string const& path, GLuint texture, int width, int height) {
std::vector<float> data(width * height * 3);
Expand Down Expand Up @@ -977,6 +1038,11 @@ void Preprocessor::save(std::string const& directory) {
write3D(directory + "/single_aerosols_scattering.tif", mSingleAerosolsScatteringTexture,
mScatteringTextureWidth, mScatteringTextureHeight, mScatteringTextureDepth);

if (mParams.mRefraction.get()) {
write2D(directory + "/theta_deviation.tif", mThetaDeviationTexture,
mParams.mTransmittanceTextureWidth.get(), mParams.mTransmittanceTextureHeight.get());
}

std::ofstream out(directory + "/metadata.json");
nlohmann::json data = mMetadata;
out << std::setw(2) << data;
Expand Down Expand Up @@ -1069,7 +1135,16 @@ void Preprocessor::precompute(GLuint fbo, GLuint deltaIrradianceTexture,

// 1. Compute the transmittance, and store it in mTransmittanceTexture.
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTransmittanceTexture, 0);
glDrawBuffer(GL_COLOR_ATTACHMENT0);

if (mParams.mRefraction.get()) {
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, mThetaDeviationTexture, 0);

const GLuint kDrawBuffers[4] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
glDrawBuffers(2, kDrawBuffers);
} else {
glDrawBuffer(GL_COLOR_ATTACHMENT0);
}

glViewport(
0, 0, mParams.mTransmittanceTextureWidth.get(), mParams.mTransmittanceTextureHeight.get());
glScissor(
Expand Down
Loading
Loading