UNPKG

@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
/* 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};