@arcgis/core
Version:
ArcGIS Maps SDK for JavaScript: A complete 2D and 3D mapping and data visualization API
34 lines (33 loc) • 3.04 kB
JavaScript
/* COPYRIGHT Esri - https://js.arcgis.com/5.0.8/LICENSE.txt */
import{clamp as e}from"../../../core/mathUtils.js";import{create as t}from"../../../core/libs/gl-matrix-2/factories/vec2f64.js";import{squaredLength as r}from"../../../core/libs/gl-matrix-2/math/vec3.js";import{earth as s}from"../../../geometry/support/Ellipsoid.js";import{Float2PassUniform as a}from"../webgl-engine/core/shaderModules/Float2PassUniform.js";import{Float3BindUniform as i}from"../webgl-engine/core/shaderModules/Float3BindUniform.js";import{FloatsPassUniform as o}from"../webgl-engine/core/shaderModules/FloatsPassUniform.js";import{glsl as n}from"../webgl-engine/core/shaderModules/glsl.js";import{SphereIntersect as c}from"../webgl-engine/shaders/SphereIntersect.glsl.js";import{NoParameters as h}from"../../webgl/NoParameters.js";class l extends h{constructor(){super(...arguments),this.radii=t()}}function m(e){e.code.add(n`float chapmanApproximation(float thickness, float height, float cosZenith) {
float c = sqrt(thickness + height);
float cExpH = c * exp(-height);
if (cosZenith >= 0.0) {
return cExpH / (c * cosZenith + 1.0);
} else {
float x0 = sqrt(1.0 - cosZenith * cosZenith) * (thickness + height);
float c0 = sqrt(x0);
return 2.0 * c0 * exp(thickness - x0) - cExpH / (1.0 - c * cosZenith);
}
}`),e.constants.add("scaleHeight","float",s.scaleHeight*s.atmosphereHeight).uniforms.add(new a("radii",e=>e.radii)).code.add(n`float getOpticalDepth(vec3 position, vec3 dir, float h) {
return scaleHeight * chapmanApproximation(radii[0] / scaleHeight, h, dot(normalize(position), dir));
}`),e.include(c),e.constants.add("planetRadiusReduction","float",p).uniforms.add(new o("heightParameters",5,(e,t)=>d(t,e)),new i("cameraPosition",e=>e.camera.eye)).code.add(n`vec4 planetIntersect(vec3 rayDir) {
float rayPlanetDistanceReduced = heightParameters[4];
vec2 rayPlanetIntersect = sphereIntersect(cameraPosition, rayDir, rayPlanetDistanceReduced);
vec2 rayAtmosphereIntersect = sphereIntersect(cameraPosition, rayDir, heightParameters[1]);
bool hitsAtmosphere = (rayAtmosphereIntersect.x <= rayAtmosphereIntersect.y) && rayAtmosphereIntersect.x > 0.0;
bool insideAtmosphere = heightParameters[0] < radii[1];
if (!hitsAtmosphere && !insideAtmosphere) {
return vec4(1.0, 0.0, 0.0, 0.0);
}
bool hitsPlanet = (rayPlanetIntersect.x <= rayPlanetIntersect.y) && rayPlanetIntersect.x > 0.0;
float start = insideAtmosphere ? 0.0 : rayAtmosphereIntersect.x;
if (heightParameters[0] < radii[0] - planetRadiusReduction) {
if (dot(rayDir, normalize(cameraPosition)) < -0.01) {
return vec4(1.0, 0.0, 0.0, 0.0);
}
start = rayPlanetIntersect.y;
}
float end = hitsPlanet ? rayPlanetIntersect.x : rayAtmosphereIntersect.y;
return vec4(0.0, hitsPlanet ? 1.0 : 0.0, start, end);
}`)}function d({camera:t},{radii:a}){const i=r(t.eye),o=Math.sqrt(i);return f[0]=o,f[1]=i-a[1]**2,f[2]=e((o-a[0])/s.atmosphereHeight,0,1),f[3]=i-a[0]**2,f[4]=i-(a[0]-p)**2,f}const p=2e4,f=new Array;export{m as ChapmanApproximation,l as ChapmanApproximationPassParameters,d as getHeightParameters};