@arcgis/core
Version:
ArcGIS Maps SDK for JavaScript: A complete 2D and 3D mapping and data visualization API
62 lines (57 loc) • 5.4 kB
JavaScript
/*
All material copyright ESRI, All Rights Reserved, unless otherwise specified.
See https://js.arcgis.com/4.32/esri/copyright.txt for details.
*/
import{fromValues as o}from"../../../../../../core/libs/gl-matrix-2/factories/vec3f64.js";import{earth as t}from"../../../../../../geometry/support/Ellipsoid.js";import{CloudsTextureChannels as e}from"../../../../environment/Clouds.js";import{FadeState as a}from"../../../../environment/CloudsParameters.js";import{cloudsHeight as r}from"../../../../environment/weather.js";import{addMainLightDirection as i,addMainLightIntensity as c}from"../shading/MainLighting.glsl.js";import{BooleanBindUniform as d}from"../../shaderModules/BooleanBindUniform.js";import{Float3BindUniform as n}from"../../shaderModules/Float3BindUniform.js";import{FloatBindUniform as l}from"../../shaderModules/FloatBindUniform.js";import{glsl as s}from"../../shaderModules/glsl.js";import{Matrix4BindUniform as u}from"../../shaderModules/Matrix4BindUniform.js";import{TextureCubeBindUniform as m}from"../../shaderModules/TextureCubeBindUniform.js";function h(t){const r=t.fragment;r.constants.add("radiusCloudsSquared","float",C).code.add(s`vec3 intersectWithCloudLayer(vec3 dir, vec3 cameraPosition, vec3 spherePos) {
float B = 2.0 * dot(cameraPosition, dir);
float C = dot(cameraPosition, cameraPosition) - radiusCloudsSquared;
float det = B * B - 4.0 * C;
float pointIntDist = max(0.0, 0.5 *(-B + sqrt(det)));
return (cameraPosition + dir * pointIntDist) - spherePos;
}`),r.uniforms.add(new l("radiusCurvatureCorrection",(({clouds:o})=>o.parallax.radiusCurvatureCorrection))).code.add(s`vec3 correctForPlanetCurvature(vec3 dir) {
dir.z = dir.z * (1.0 - radiusCurvatureCorrection) + radiusCurvatureCorrection;
return dir;
}`),r.code.add(s`vec3 rotateDirectionToAnchorPoint(mat4 rotMat, vec3 inVec) {
return (rotMat * vec4(inVec, 0.0)).xyz;
}`),i(r),c(r);const h=o(.28,.175,.035);r.constants.add("RIM_COLOR","vec3",h);const v=.3,f=140,p=.2,g=10,w=.3;r.code.add(s`
vec3 calculateCloudColor(vec3 cameraPosition, vec3 worldSpaceRay, vec4 clouds) {
float upDotLight = dot(cameraPosition, mainLightDirection);
float dirDotLight = max(dot(worldSpaceRay, mainLightDirection), 0.0);
float sunsetTransition = clamp(pow(max(upDotLight, 0.0), ${s.float(v)}), 0.0, 1.0);
// Base color of the clouds that depends on lighting of the sun and sky
vec3 ambientLight = calculateAmbientIrradiance(cameraPosition, 0.0);
vec3 combinedLight = clamp((mainLightIntensity + ambientLight )/PI, vec3(0.0), vec3(1.0));
vec3 baseCloudColor = pow(combinedLight * pow(clouds.xyz, vec3(GAMMA)), vec3(INV_GAMMA));
// Rim light around the edge of the clouds simulating scattering of the direct lun light
float scatteringMod = max(clouds.a < 0.5 ? clouds.a / 0.5 : - clouds.a / 0.5 + 2.0, 0.0);
float rimLightIntensity = 0.5 + 0.5 * pow(max(upDotLight, 0.0), 0.35);
vec3 directSunScattering = RIM_COLOR * rimLightIntensity * (pow(dirDotLight, ${s.float(f)})) * scatteringMod;
// Brighten the clouds around the sun at the sunsets
float additionalLight = ${s.float(p)} * pow(dirDotLight, ${s.float(g)}) * (1. - pow(sunsetTransition, ${s.float(w)})) ;
return vec3(baseCloudColor * (1.0 + additionalLight) + directSunScattering);
}
`),r.uniforms.add(new d("readChannelsRG",(o=>o.clouds.readChannels===e.RG)),new m("cubeMap",(o=>o.clouds.data?.cubeMap?.colorTexture??null))).code.add(s`vec4 sampleCloud(vec3 rayDir, bool readOtherChannel) {
vec4 s = texture(cubeMap, rayDir);
bool readRG = readChannelsRG ^^ readOtherChannel;
s = readRG ? vec4(vec3(s.r), s.g) : vec4(vec3(s.b), s.a);
return length(s) == 0.0 ? vec4(s.rgb, 1.0) : s;
}`),r.uniforms.add(new n("anchorPoint",(o=>o.clouds.parallax.anchorPoint)),new n("anchorPointNew",(o=>o.clouds.parallaxNew.anchorPoint)),new u("rotationClouds",(o=>o.clouds.parallax.transform)),new u("rotationCloudsNew",(o=>o.clouds.parallaxNew.transform)),new l("cloudsOpacity",(o=>o.clouds.opacity)),new l("fadeFactor",(o=>o.clouds.fadeFactor)),new d("crossFade",(o=>o.clouds.fadeState===a.CROSS_FADE))).code.add(s`vec4 renderClouds(vec3 worldRay, vec3 cameraPosition) {
vec3 intersectionPoint = intersectWithCloudLayer(worldRay, cameraPosition, anchorPoint);
vec3 worldRayRotated = rotateDirectionToAnchorPoint(rotationClouds, normalize(intersectionPoint));
vec3 worldRayRotatedCorrected = correctForPlanetCurvature(worldRayRotated);
vec4 cloudData = sampleCloud(worldRayRotatedCorrected, crossFade);
vec3 cameraPositionN = normalize(cameraPosition);
vec4 cloudColor = vec4(calculateCloudColor(cameraPositionN, worldRay, cloudData), cloudData.a);
if(crossFade) {
intersectionPoint = intersectWithCloudLayer(worldRay, cameraPosition, anchorPointNew);
worldRayRotated = rotateDirectionToAnchorPoint(rotationCloudsNew, normalize(intersectionPoint));
worldRayRotatedCorrected = correctForPlanetCurvature(worldRayRotated);
cloudData = sampleCloud(worldRayRotatedCorrected, false);
vec4 cloudColorNew = vec4(calculateCloudColor(cameraPositionN, worldRay, cloudData), cloudData.a);
cloudColor = mix(cloudColor, cloudColorNew, fadeFactor);
}
float totalTransmittance = length(cloudColor.rgb) == 0.0 ?
1.0 :
clamp(cloudColor.a * cloudsOpacity + (1.0 - cloudsOpacity), 0.0 , 1.0);
return vec4(cloudColor.rgb, totalTransmittance);
}`)}const C=(t.radius+r)**2;export{h as CloudsParallaxShading};