Skip to content

Commit

Permalink
Cleanup, fix race condition
Browse files Browse the repository at this point in the history
  • Loading branch information
ggetz committed Aug 19, 2024
1 parent 84bbd77 commit 53d45a0
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 68 deletions.
107 changes: 48 additions & 59 deletions packages/engine/Source/Scene/DynamicEnvironmentMapManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import Sampler from "../Renderer/Sampler.js";
import ShaderProgram from "../Renderer/ShaderProgram.js";
import ShaderSource from "../Renderer/ShaderSource.js";
import TextureMinificationFilter from "../Renderer/TextureMinificationFilter.js";
import SkyAtmosphereCommon from "../Shaders/SkyAtmosphereCommon.js";
import AtmosphereCommon from "../Shaders/AtmosphereCommon.js";
import ComputeIrradianceMapFS from "../Shaders/ComputeIrradianceMapFS.js";
import ComputeRadianceMapFS from "../Shaders/ComputeRadianceMapFS.js";
Expand Down Expand Up @@ -55,8 +54,8 @@ import DynamicAtmosphereLightingType from "./DynamicAtmosphereLightingType.js";
function DynamicEnvironmentMapManager(options) {
this._position = undefined;

this._radianceCommandsDirty = true;
this._radianceMapDirty = true;
this._radianceMapDirty = false;
this._radianceCommandsDirty = false;
this._convolutionsCommandsDirty = false;
this._irradianceCommandDirty = false;
this._irradianceTextureDirty = false;
Expand Down Expand Up @@ -290,25 +289,16 @@ DynamicEnvironmentMapManager.setOwner = function (
DynamicEnvironmentMapManager.prototype._reset = function () {
let length = this._radianceMapComputeCommands.length;
for (let i = 0; i < length; ++i) {
const command = this._radianceMapComputeCommands[i];
if (defined(command)) {
command.canceled = true;
}
this._radianceMapComputeCommands[i] = undefined;
}

length = this._convolutionComputeCommands.length;
for (let i = 0; i < length; ++i) {
const command = this._convolutionComputeCommands[i];
if (defined(command)) {
command.canceled = true;
}
this._convolutionComputeCommands[i] = undefined;
}

if (defined(this._irradianceMapComputeCommand)) {
this._irradianceMapComputeCommand.canceled = true;
this._irradianceMapComputeCommand = undefined;
if (defined(this._irradianceComputeCommand)) {
this._irradianceComputeCommand = undefined;
}

this._radianceMapDirty = true;
Expand Down Expand Up @@ -380,42 +370,43 @@ function updateRadianceMap(manager, frameState) {
let fs = manager._radianceMapFS;
if (!defined(fs)) {
fs = new ShaderSource({
sources: [AtmosphereCommon, SkyAtmosphereCommon, ComputeRadianceMapFS],
sources: [AtmosphereCommon, ComputeRadianceMapFS],
});
manager._radianceMapFS = fs;
}

const position = manager._position;
const radiiAndDynamicAtmosphereColor =
manager._radiiAndDynamicAtmosphereColor;

const ellipsoid = frameState.mapProjection.ellipsoid;
const enuToFixedFrame = Transforms.eastNorthUpToFixedFrame(
manager._position,
ellipsoid,
scratchMatrix
);

const adjustments = scratchAdjustments;
adjustments.x = manager.brightness;
adjustments.y = manager.saturation;
adjustments.z = manager.gamma;
adjustments.w = manager.intensity;

let i = 0;
for (const face of CubeMap.faces()) {
let texture = manager._radianceMapTextures[i];
if (!defined(texture)) {
texture = new Texture({
context: context,
width: textureDimensions.x,
height: textureDimensions.y,
pixelDatatype: PixelDatatype.UNSIGNED_BYTE,
pixelFormat: PixelFormat.RGBA,
});
manager._radianceMapTextures[i] = texture;
if (defined(texture)) {
texture.destroy();
}

const atmosphere = frameState.atmosphere;
const position = manager._position;
const radiiAndDynamicAtmosphereColor =
manager._radiiAndDynamicAtmosphereColor;

const ellipsoid = frameState.mapProjection.ellipsoid;
const enuToFixedFrame = Transforms.eastNorthUpToFixedFrame(
manager._position,
ellipsoid,
scratchMatrix
);

const adjustments = scratchAdjustments;
adjustments.x = manager.brightness;
adjustments.y = manager.saturation;
adjustments.z = manager.gamma;
adjustments.w = manager.intensity;
texture = new Texture({
context: context,
width: textureDimensions.x,
height: textureDimensions.y,
pixelDatatype: PixelDatatype.UNSIGNED_BYTE,
pixelFormat: PixelFormat.RGBA,
});
manager._radianceMapTextures[i] = texture;

const index = i;
const command = new ComputeCommand({
Expand All @@ -424,22 +415,20 @@ function updateRadianceMap(manager, frameState) {
uniformMap: {
u_radiiAndDynamicAtmosphereColor: () =>
radiiAndDynamicAtmosphereColor,
u_atmosphereLightIntensity: () => atmosphere.lightIntensity,
u_atmosphereRayleighCoefficient: () => atmosphere.rayleighCoefficient,
u_atmosphereMieCoefficient: () => atmosphere.mieCoefficient,
u_atmosphereRayleighScaleHeight: () => atmosphere.rayleighScaleHeight,
u_atmosphereMieScaleHeight: () => atmosphere.mieScaleHeight,
u_atmosphereMieAnisotropy: () => atmosphere.mieAnisotropy,
u_enuToFixedFrame: () => enuToFixedFrame,
u_faceDirection: () => CubeMap.getDirection(face, scratchCartesian),
u_positionWC: () => position,
u_brightnessSaturationGammaIntensity: () => adjustments,
u_groundColor: () => manager.groundColor,
},
persists: false,
persists: true,
owner: manager,
postExecute: () => {
const commands = manager._radianceMapComputeCommands;
if (!defined(commands[index])) {
// This command was cancelled
return;
}
commands[index] = undefined;

const framebuffer = new Framebuffer({
Expand Down Expand Up @@ -487,6 +476,10 @@ function updateSpecularMaps(manager, frameState) {
const getPostExecute = (index, texture, face, level) => () => {
// Copy output texture to corresponding face and mipmap level
const commands = manager._convolutionComputeCommands;
if (!defined(commands[index])) {
// This command was cancelled
return;
}
commands[index] = undefined;

radianceCubeMap.copyFace(frameState, texture, face, level);
Expand Down Expand Up @@ -592,6 +585,10 @@ function updateIrradianceResources(manager, frameState) {
u_radianceMap: () => manager._radianceCubeMap,
},
postExecute: () => {
if (!defined(manager._irradianceComputeCommand)) {
// This command was cancelled
return;
}
manager._irradianceTextureDirty = false;
manager._irradianceComputeCommand = undefined;
manager._sphericalHarmonicCoefficientsDirty = true;
Expand Down Expand Up @@ -722,23 +719,15 @@ DynamicEnvironmentMapManager.prototype.destroy = function () {
// Cancel in-progress commands
let length = this._radianceMapComputeCommands.length;
for (let i = 0; i < length; ++i) {
const command = this._radianceMapComputeCommands[i];
if (defined(command)) {
command.canceled = true;
}
this._radianceMapComputeCommands[i] = undefined;
}

length = this._convolutionComputeCommands.length;
for (let i = 0; i < length; ++i) {
const command = this._convolutionComputeCommands[i];
if (defined(command)) {
command.canceled = true;
}
this._convolutionComputeCommands[i] = undefined;
}

if (defined(this._irradianceMapComputeCommand)) {
this._irradianceMapComputeCommand.canceled = true;
}
this._irradianceMapComputeCommand = undefined;

// Destroy all textures
length = this._radianceMapTextures.length;
Expand Down
4 changes: 3 additions & 1 deletion packages/engine/Source/Scene/SunLight.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ function SunLight(options) {
* @type {Color}
* @default Color.WHITE
*/
this.color = Color.clone(defaultValue(options.color, Color.fromBytes(255, 245, 240)));
this.color = Color.clone(
defaultValue(options.color, Color.fromBytes(255, 255, 251))
); // From https://planetpixelemporium.com/tutorialpages/light.html

/**
* The intensity of the light.
Expand Down
31 changes: 31 additions & 0 deletions packages/engine/Source/Shaders/AtmosphereCommon.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -185,3 +185,34 @@ vec4 computeAtmosphereColor(

return vec4(color, opacity);
}


vec4 computeAtmosphereColor(
czm_ray primaryRay,
vec3 lightDirection,
vec3 rayleighColor,
vec3 mieColor,
float opacity
) {
vec3 cameraToPositionWCDirection = normalize(primaryRay.direction);

float cosAngle = dot(cameraToPositionWCDirection, lightDirection);
float cosAngleSq = cosAngle * cosAngle;

float G = u_atmosphereMieAnisotropy;
float GSq = G * G;

// The Rayleigh phase function.
float rayleighPhase = 3.0 / (50.2654824574) * (1.0 + cosAngleSq);
// The Mie phase function.
float miePhase = 3.0 / (25.1327412287) * ((1.0 - GSq) * (cosAngleSq + 1.0)) / (pow(1.0 + GSq - 2.0 * cosAngle * G, 1.5) * (2.0 + GSq));

// The final color is generated by combining the effects of the Rayleigh and Mie scattering.
vec3 rayleigh = rayleighPhase * rayleighColor;
vec3 mie = miePhase * mieColor;

vec3 color = (rayleigh + mie) * u_atmosphereLightIntensity;

return vec4(color, opacity);
}

Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,47 @@ vec4 czm_computeAtmosphereColor(

return vec4(color, opacity);
}

/**
* Compute the atmosphere color, applying Rayleigh and Mie scattering. This
* builtin uses automatic uniforms so the atmophere settings are synced with the
* state of the Scene, even in other contexts like Model.
*
* @name czm_computeAtmosphereColor
* @glslFunction
*
* @param {czm_rat} primaryRay Ray from the origin to sky fragment to in world coords (low precision)
* @param {vec3} lightDirection Light direction from the sun or other light source.
* @param {vec3} rayleighColor The Rayleigh scattering color computed by a scattering function
* @param {vec3} mieColor The Mie scattering color computed by a scattering function
* @param {float} opacity The opacity computed by a scattering function.
*/
vec4 czm_computeAtmosphereColor(
czm_ray primaryRay,
vec3 lightDirection,
vec3 rayleighColor,
vec3 mieColor,
float opacity
) {
vec3 direction = normalize(primaryRay.direction);

float cosAngle = dot(direction, lightDirection);
float cosAngleSq = cosAngle * cosAngle;

float G = czm_atmosphereMieAnisotropy;
float GSq = G * G;

// The Rayleigh phase function.
float rayleighPhase = 3.0 / (50.2654824574) * (1.0 + cosAngleSq);
// The Mie phase function.
float miePhase = 3.0 / (25.1327412287) * ((1.0 - GSq) * (cosAngleSq + 1.0)) / (pow(1.0 + GSq - 2.0 * cosAngle * G, 1.5) * (2.0 + GSq));

// The final color is generated by combining the effects of the Rayleigh and Mie scattering.
vec3 rayleigh = rayleighPhase * rayleighColor;
vec3 mie = miePhase * mieColor;

vec3 color = (rayleigh + mie) * czm_atmosphereLightIntensity;

return vec4(color, opacity);
}

22 changes: 14 additions & 8 deletions packages/engine/Source/Shaders/ComputeRadianceMapFS.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,17 @@ vec4 getCubeMapDirection(vec2 uv, vec3 faceDir) {

void main() {
float height = length(u_positionWC);
float ellipsoidHeight = height - u_radiiAndDynamicAtmosphereColor.y;
float atmosphereHeight = u_radiiAndDynamicAtmosphereColor.x - u_radiiAndDynamicAtmosphereColor.y;
float radius = max(u_radiiAndDynamicAtmosphereColor.x - height, 2.0 * ellipsoidHeight);
float atmosphereInnerRadius = u_radiiAndDynamicAtmosphereColor.y;
float ellipsoidHeight = height - atmosphereInnerRadius;
float atmosphereOuterRadius = u_radiiAndDynamicAtmosphereColor.x;
float atmosphereHeight = atmosphereOuterRadius - atmosphereInnerRadius;
float radius = max(atmosphereOuterRadius - height, 2.0 * ellipsoidHeight);

vec3 direction = (u_enuToFixedFrame * getCubeMapDirection(v_textureCoordinates, u_faceDirection)).xyz * vec3(1.0, 1.0, -1.0); // TODO: Where does this come from?
vec3 normalizedDirection = normalize(direction);

czm_ray ray = czm_ray(u_positionWC, normalizedDirection);
czm_raySegment intersection = czm_rayEllipsoidIntersectionInterval(ray, vec3(0.0), czm_ellipsoidInverseRadii);
czm_raySegment intersection = czm_raySphereIntersectionInterval(ray, vec3(0.0), atmosphereInnerRadius);
float d = czm_branchFreeTernary(czm_isEmpty(intersection), radius, clamp(intersection.start, ellipsoidHeight, radius));

// Compute sky color for each position on a sphere at radius centered around the model's origin
Expand All @@ -45,17 +47,21 @@ void main() {
vec3 mieColor;
vec3 rayleighColor;
float opacity;
float translucent;
computeScattering(
czm_computeScattering(
ray,
d,
lightDirectionWC,
u_radiiAndDynamicAtmosphereColor.y,
atmosphereInnerRadius,
rayleighColor,
mieColor,
opacity
);
vec4 skyColor = computeAtmosphereColor(skyPositionWC, lightDirectionWC, rayleighColor, mieColor, opacity);

vec4 skyColor = czm_computeAtmosphereColor(ray, lightDirectionWC, rayleighColor, mieColor, opacity);

// Alter the opacity based on how close the object is to the ground.
// (0.0 = At edge of atmosphere, 1.0 = On ground)
opacity = clamp((atmosphereOuterRadius - height) / (atmosphereOuterRadius - atmosphereInnerRadius), 0.0, 1.0);

vec3 sceneSkyBoxColor = czm_textureCube(czm_environmentMap, normalizedDirection).rgb; // TODO: I'm not sure if this is oriented correctly
vec3 groundColor = mix(vec3(0.0), u_groundColor.xyz, u_groundColor.a * (1.0 - ellipsoidHeight / atmosphereHeight));
Expand Down

0 comments on commit 53d45a0

Please sign in to comment.