@itwin/core-frontend
Version:
iTwin.js frontend components
156 lines • 8.43 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AtmosphereUniforms = exports.MAX_SAMPLE_POINTS = void 0;
const core_geometry_1 = require("@itwin/core-geometry");
const Matrix_1 = require("./Matrix");
const Sync_1 = require("./Sync");
exports.MAX_SAMPLE_POINTS = 40; // Maximum number of sample points to be used for the in-scattering and out-scattering computations.
class AtmosphereUniforms {
_atmosphere;
_ellipsoid;
// Main shader uniforms
_earthScaleMatrix = new core_geometry_1.Matrix3d(new Float64Array([1, 0, 0, 0, 1, 0, 0, 0, 1]));
_inverseEllipsoidRotationMatrix = new core_geometry_1.Matrix3d(new Float64Array([1, 0, 0, 0, 1, 0, 0, 0, 1]));
_atmosphereScaleMatrix = new core_geometry_1.Matrix3d(new Float64Array([1, 0, 0, 0, 1, 0, 0, 0, 1]));
_atmosphereData = new Matrix_1.Matrix4();
/**
* uniform mat3 u_atmosphereData;
* { { atmosphereRadiusScaleFactor, atmosphereMaxDensityThresholdScaleFactor, densityFalloff, 0 },
* { numViewRaySamples, numSunRaySamples, 0, 0 },
* { earthCenter.x, earthCenter.y, earthCenter.z, 0 },
* { scatteringCoefficients.x, scatteringCoefficients.y, scatteringCoefficients.z, 0 } }
*/
get atmosphereData() { return this._atmosphereData; }
// Fragment shader uniforms
_exposure = 0.0;
// utility
syncKey = 0;
_scratchMatrix3d = new core_geometry_1.Matrix3d();
_scratchPoint3d = new core_geometry_1.Point3d();
update(target) {
const atmosphereHasNotChanged = this._atmosphere && target.plan.atmosphere && this._atmosphere.equals(target.plan.atmosphere);
const ellipsoidHasNotChanged = this._ellipsoid && target.plan.ellipsoid && this._ellipsoid.equals(target.plan.ellipsoid);
if (atmosphereHasNotChanged && ellipsoidHasNotChanged) {
return;
}
this._atmosphere = target.plan.atmosphere;
this._ellipsoid = target.plan.ellipsoid;
(0, Sync_1.desync)(this);
if (!this._atmosphere || !this._ellipsoid) {
return;
}
this._updateAtmosphereScaleMatrix(this._atmosphere.atmosphereHeightAboveEarth);
this._updateExposure(this._atmosphere.exposure);
this._updateDensityFalloff(this._atmosphere.densityFalloff);
this._updateEarthCenter(this._ellipsoid.ellipsoidCenter, target.uniforms.frustum.viewMatrix);
this._updateEarthScaleMatrix(this._ellipsoid.ellipsoidRadii);
this._updateInverseEllipsoidRotationMatrix(this._ellipsoid.ellipsoidRotation, target.uniforms.frustum.viewMatrix.matrix);
this._updateAtmosphereRadiusScaleFactor(this._atmosphere.atmosphereHeightAboveEarth);
this._updateAtmosphereMaxDensityThresholdScaleFactor(this._atmosphere.depthBelowEarthForMaxDensity);
this._updateNumViewRaySamples(this._atmosphere.numViewRaySamples);
this._updateNumSunRaySamples(this._atmosphere.numSunRaySamples);
this._updateScatteringCoefficients(this._atmosphere.scatteringStrength, this._atmosphere.wavelengths);
}
_updateEarthCenter(earthCenter, viewMatrix) {
viewMatrix.multiplyPoint3d(earthCenter, this._scratchPoint3d);
this._atmosphereData.data[8] = this._scratchPoint3d.x;
this._atmosphereData.data[9] = this._scratchPoint3d.y;
this._atmosphereData.data[10] = this._scratchPoint3d.z;
}
_updateInverseEllipsoidRotationMatrix(ellipsoidRotation, viewRotation) {
viewRotation.inverse(this._scratchMatrix3d);
ellipsoidRotation.multiplyMatrixInverseMatrix(this._scratchMatrix3d, this._inverseEllipsoidRotationMatrix);
}
_updateEarthScaleMatrix(earthRadii) {
this._earthScaleMatrix.setAt(0, 0, earthRadii.x);
this._earthScaleMatrix.setAt(1, 1, earthRadii.y);
this._earthScaleMatrix.setAt(2, 2, earthRadii.z);
}
_updateAtmosphereScaleMatrix(heightAboveSurface) {
const earthPolarRadius = this._earthScaleMatrix.at(2, 2);
const scaleFactor = earthPolarRadius === 0 ? 1.0 : (earthPolarRadius + heightAboveSurface) / earthPolarRadius;
this._earthScaleMatrix.scale(scaleFactor, this._atmosphereScaleMatrix);
}
_updateAtmosphereRadiusScaleFactor(atmosphereHeightAboveEarth) {
const earthPolarRadius = this._earthScaleMatrix.at(2, 2);
const minDensityThresholdRadius = earthPolarRadius + atmosphereHeightAboveEarth;
const atmosphereRadiusScaleFactor = (earthPolarRadius === 0)
? 1
: (minDensityThresholdRadius / earthPolarRadius);
this.atmosphereData.data[0] = atmosphereRadiusScaleFactor;
}
_updateAtmosphereMaxDensityThresholdScaleFactor(maxDensityDepthBelowEarth) {
const earthPolarRadius = this._earthScaleMatrix.at(2, 2);
const maxDensityThresholdRadius = earthPolarRadius - maxDensityDepthBelowEarth;
const atmosphereMaxDensityThresholdScaleFactor = (earthPolarRadius === 0)
? 1
: (maxDensityThresholdRadius / earthPolarRadius);
this.atmosphereData.data[1] = atmosphereMaxDensityThresholdScaleFactor;
}
_updateDensityFalloff(densityFalloff) {
this.atmosphereData.data[2] = densityFalloff;
}
_updateScatteringCoefficients(scatteringStrength, wavelengths) {
// Rayleigh scattering strength is inversely related to the 4th power of the wavelength -> 1/pow(wavelength, 4)
// Because this produces very small values when the wavelengths are taken in nanometers,
// we attempt to normalize them around 1 by taking the smallest wavelength of visible light as a baseline (violet light - 400nm)
const violetLightWavelength = 400.0;
this.atmosphereData.data[12] = ((violetLightWavelength / wavelengths.r) ** 4.0) * scatteringStrength;
this.atmosphereData.data[13] = ((violetLightWavelength / wavelengths.g) ** 4.0) * scatteringStrength;
this.atmosphereData.data[14] = ((violetLightWavelength / wavelengths.b) ** 4.0) * scatteringStrength;
}
_updateExposure(exposure) {
this._exposure = exposure;
}
bindExposure(uniform) {
if (!(0, Sync_1.sync)(this, uniform)) {
uniform.setUniform1f(this._exposure);
}
}
_updateNumViewRaySamples(_numViewRaySamples) {
const numViewRaySamples = Math.max(0, Math.min(exports.MAX_SAMPLE_POINTS, _numViewRaySamples));
this.atmosphereData.data[4] = numViewRaySamples;
}
_updateNumSunRaySamples(_numSunRaySamples) {
const numSunRaySamples = Math.max(0, Math.min(exports.MAX_SAMPLE_POINTS, _numSunRaySamples));
this.atmosphereData.data[5] = numSunRaySamples;
}
bindInverseRotationInverseEarthScaleMatrix(uniform) {
if (!(0, Sync_1.sync)(this, uniform)) {
this._earthScaleMatrix.multiplyMatrixInverseMatrix(this._inverseEllipsoidRotationMatrix, this._scratchMatrix3d);
uniform.setMatrix3(Matrix_1.Matrix3.fromMatrix3d(this._scratchMatrix3d));
}
}
bindInverseRotationInverseAtmosphereScaleMatrix(uniform) {
if (!(0, Sync_1.sync)(this, uniform)) {
this._atmosphereScaleMatrix.multiplyMatrixInverseMatrix(this._inverseEllipsoidRotationMatrix, this._scratchMatrix3d);
uniform.setMatrix3(Matrix_1.Matrix3.fromMatrix3d(this._scratchMatrix3d));
}
}
bindEarthScaleMatrix(uniform) {
if (!(0, Sync_1.sync)(this, uniform))
uniform.setMatrix3(Matrix_1.Matrix3.fromMatrix3d(this._earthScaleMatrix));
}
bindAtmosphereScaleMatrix(uniform) {
if (!(0, Sync_1.sync)(this, uniform))
uniform.setMatrix3(Matrix_1.Matrix3.fromMatrix3d(this._atmosphereScaleMatrix));
}
bindInverseEarthScaleMatrix(uniform) {
if (!(0, Sync_1.sync)(this, uniform))
uniform.setMatrix3(Matrix_1.Matrix3.fromMatrix3d(this._earthScaleMatrix.inverse()));
}
bindInverseAtmosphereScaleMatrix(uniform) {
if (!(0, Sync_1.sync)(this, uniform))
uniform.setMatrix3(Matrix_1.Matrix3.fromMatrix3d(this._atmosphereScaleMatrix.inverse()));
}
get isDisposed() {
return true;
}
[Symbol.dispose]() { }
/** @deprecated in 5.0 - will not be removed until after 2026-06-13. Use [Symbol.dispose] instead. */
dispose() {
this[Symbol.dispose]();
}
}
exports.AtmosphereUniforms = AtmosphereUniforms;
//# sourceMappingURL=AtmosphereUniforms.js.map