@arcgis/core
Version:
ArcGIS Maps SDK for JavaScript: A complete 2D and 3D mapping and data visualization API
50 lines (49 loc) • 5.17 kB
JavaScript
/* COPYRIGHT Esri - https://js.arcgis.com/5.0.19/LICENSE.txt */
import{fromValues as o}from"../../../../../../core/libs/gl-matrix-2/factories/vec3f64.js";import{earth as t}from"../../../../../../geometry/support/Ellipsoid.js";import{cloudsHeight as a}from"../../../../environment/weather.js";import{addMainLightDirection as r,addMainLightIntensity as e}from"../shading/MainLighting.glsl.js";import{LookupCloudsFromTextureArray as i}from"./LookupCloudsFromTextureArray.glsl.js";import{BooleanBindUniform as c}from"../../shaderModules/BooleanBindUniform.js";import{Float3BindUniform as n}from"../../shaderModules/Float3BindUniform.js";import{FloatBindUniform as d}from"../../shaderModules/FloatBindUniform.js";import{glsl as l}from"../../shaderModules/glsl.js";import{Matrix4BindUniform as s}from"../../shaderModules/Matrix4BindUniform.js";import{Texture2DArrayBindUniform as u}from"../../shaderModules/Texture2DArrayBindUniform.js";function m(t){const a=t.fragment;a.constants.add("radiusCloudsSquared","float",C).code.add(l`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;
}`),a.uniforms.add(new d("radiusCurvatureCorrection",({clouds:o})=>o.parallax.radiusCurvatureCorrection)).code.add(l`vec3 correctForPlanetCurvature(vec3 dir) {
dir.z = dir.z * (1.0 - radiusCurvatureCorrection) + radiusCurvatureCorrection;
return dir;
}`),a.code.add(l`vec3 rotateDirectionToAnchorPoint(mat4 rotMat, vec3 inVec) {
return (rotMat * vec4(inVec, 0.0)).xyz;
}`),r(a),e(a),a.constants.add("RIM_COLOR","vec3",o(.28,.175,.035)),a.constants.add("sunsetTransitionFactor","float",.3),a.constants.add("rimScattering","float",140),a.constants.add("backlightFactor","float",.2),a.constants.add("backlightScattering","float",10),a.constants.add("backlightTransition","float",.3),a.code.add(l`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), sunsetTransitionFactor), 0.0, 1.0);
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));
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, rimScattering)) * scatteringMod;
float additionalLight = backlightFactor * pow(dirDotLight, backlightScattering) * (1. - pow(sunsetTransition, backlightTransition)) ;
return vec3(baseCloudColor * (1.0 + additionalLight) + directSunScattering);
}`),t.include(i),a.uniforms.add(new c("readChannelsRG",o=>0===o.clouds.readChannels),new u("cubeMap",o=>o.clouds.data?.cubeMap?.colorTexture)).code.add(l`vec4 sampleCloud(vec3 rayDir, bool readOtherChannel) {
vec4 s = lookupCloudsFromTextureArray(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;
}`),a.uniforms.add(new n("anchorPoint",o=>o.clouds.parallax.anchorPoint),new n("anchorPointNew",o=>o.clouds.parallaxNew.anchorPoint),new s("rotationClouds",o=>o.clouds.parallax.transform),new s("rotationCloudsNew",o=>o.clouds.parallaxNew.transform),new d("cloudsOpacity",o=>o.clouds.opacity),new d("fadeFactor",o=>o.clouds.fadeFactor),new c("crossFade",o=>3===o.clouds.fadeState)).code.add(l`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+a)**2;export{m as CloudsParallaxShading};