123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413 |
- import defined from "../Core/defined.js";
- import destroyObject from "../Core/destroyObject.js";
- import TerrainQuantization from "../Core/TerrainQuantization.js";
- import ShaderProgram from "../Renderer/ShaderProgram.js";
- import getClippingFunction from "./getClippingFunction.js";
- import SceneMode from "./SceneMode.js";
- function GlobeSurfaceShader(
- numberOfDayTextures,
- flags,
- material,
- shaderProgram,
- clippingShaderState
- ) {
- this.numberOfDayTextures = numberOfDayTextures;
- this.flags = flags;
- this.material = material;
- this.shaderProgram = shaderProgram;
- this.clippingShaderState = clippingShaderState;
- }
- /**
- * Manages the shaders used to shade the surface of a {@link Globe}.
- *
- * @alias GlobeSurfaceShaderSet
- * @private
- */
- function GlobeSurfaceShaderSet() {
- this.baseVertexShaderSource = undefined;
- this.baseFragmentShaderSource = undefined;
- this._shadersByTexturesFlags = [];
- this.material = undefined;
- }
- function getPositionMode(sceneMode) {
- const getPosition3DMode =
- "vec4 getPosition(vec3 position, float height, vec2 textureCoordinates) { return getPosition3DMode(position, height, textureCoordinates); }";
- const getPositionColumbusViewAnd2DMode =
- "vec4 getPosition(vec3 position, float height, vec2 textureCoordinates) { return getPositionColumbusViewMode(position, height, textureCoordinates); }";
- const getPositionMorphingMode =
- "vec4 getPosition(vec3 position, float height, vec2 textureCoordinates) { return getPositionMorphingMode(position, height, textureCoordinates); }";
- let positionMode;
- switch (sceneMode) {
- case SceneMode.SCENE3D:
- positionMode = getPosition3DMode;
- break;
- case SceneMode.SCENE2D:
- case SceneMode.COLUMBUS_VIEW:
- positionMode = getPositionColumbusViewAnd2DMode;
- break;
- case SceneMode.MORPHING:
- positionMode = getPositionMorphingMode;
- break;
- }
- return positionMode;
- }
- function get2DYPositionFraction(useWebMercatorProjection) {
- const get2DYPositionFractionGeographicProjection =
- "float get2DYPositionFraction(vec2 textureCoordinates) { return get2DGeographicYPositionFraction(textureCoordinates); }";
- const get2DYPositionFractionMercatorProjection =
- "float get2DYPositionFraction(vec2 textureCoordinates) { return get2DMercatorYPositionFraction(textureCoordinates); }";
- return useWebMercatorProjection
- ? get2DYPositionFractionMercatorProjection
- : get2DYPositionFractionGeographicProjection;
- }
- GlobeSurfaceShaderSet.prototype.getShaderProgram = function (options) {
- const frameState = options.frameState;
- const surfaceTile = options.surfaceTile;
- const numberOfDayTextures = options.numberOfDayTextures;
- const applyBrightness = options.applyBrightness;
- const applyContrast = options.applyContrast;
- const applyHue = options.applyHue;
- const applySaturation = options.applySaturation;
- const applyGamma = options.applyGamma;
- const applyAlpha = options.applyAlpha;
- const applyDayNightAlpha = options.applyDayNightAlpha;
- const applySplit = options.applySplit;
- const showReflectiveOcean = options.showReflectiveOcean;
- const showOceanWaves = options.showOceanWaves;
- const enableLighting = options.enableLighting;
- const dynamicAtmosphereLighting = options.dynamicAtmosphereLighting;
- const dynamicAtmosphereLightingFromSun =
- options.dynamicAtmosphereLightingFromSun;
- const showGroundAtmosphere = options.showGroundAtmosphere;
- const perFragmentGroundAtmosphere = options.perFragmentGroundAtmosphere;
- const hasVertexNormals = options.hasVertexNormals;
- const useWebMercatorProjection = options.useWebMercatorProjection;
- const enableFog = options.enableFog;
- const enableClippingPlanes = options.enableClippingPlanes;
- const clippingPlanes = options.clippingPlanes;
- const clippedByBoundaries = options.clippedByBoundaries;
- const hasImageryLayerCutout = options.hasImageryLayerCutout;
- const colorCorrect = options.colorCorrect;
- const highlightFillTile = options.highlightFillTile;
- const colorToAlpha = options.colorToAlpha;
- const hasGeodeticSurfaceNormals = options.hasGeodeticSurfaceNormals;
- const hasExaggeration = options.hasExaggeration;
- const showUndergroundColor = options.showUndergroundColor;
- const translucent = options.translucent;
- let quantization = 0;
- let quantizationDefine = "";
- const mesh = surfaceTile.renderedMesh;
- const terrainEncoding = mesh.encoding;
- const quantizationMode = terrainEncoding.quantization;
- if (quantizationMode === TerrainQuantization.BITS12) {
- quantization = 1;
- quantizationDefine = "QUANTIZATION_BITS12";
- }
- let cartographicLimitRectangleFlag = 0;
- let cartographicLimitRectangleDefine = "";
- if (clippedByBoundaries) {
- cartographicLimitRectangleFlag = 1;
- cartographicLimitRectangleDefine = "TILE_LIMIT_RECTANGLE";
- }
- let imageryCutoutFlag = 0;
- let imageryCutoutDefine = "";
- if (hasImageryLayerCutout) {
- imageryCutoutFlag = 1;
- imageryCutoutDefine = "APPLY_IMAGERY_CUTOUT";
- }
- const sceneMode = frameState.mode;
- const flags =
- sceneMode |
- (applyBrightness << 2) |
- (applyContrast << 3) |
- (applyHue << 4) |
- (applySaturation << 5) |
- (applyGamma << 6) |
- (applyAlpha << 7) |
- (showReflectiveOcean << 8) |
- (showOceanWaves << 9) |
- (enableLighting << 10) |
- (dynamicAtmosphereLighting << 11) |
- (dynamicAtmosphereLightingFromSun << 12) |
- (showGroundAtmosphere << 13) |
- (perFragmentGroundAtmosphere << 14) |
- (hasVertexNormals << 15) |
- (useWebMercatorProjection << 16) |
- (enableFog << 17) |
- (quantization << 18) |
- (applySplit << 19) |
- (enableClippingPlanes << 20) |
- (cartographicLimitRectangleFlag << 21) |
- (imageryCutoutFlag << 22) |
- (colorCorrect << 23) |
- (highlightFillTile << 24) |
- (colorToAlpha << 25) |
- (hasGeodeticSurfaceNormals << 26) |
- (hasExaggeration << 27) |
- (showUndergroundColor << 28) |
- (translucent << 29) |
- (applyDayNightAlpha << 30);
- let currentClippingShaderState = 0;
- if (defined(clippingPlanes) && clippingPlanes.length > 0) {
- currentClippingShaderState = enableClippingPlanes
- ? clippingPlanes.clippingPlanesState
- : 0;
- }
- let surfaceShader = surfaceTile.surfaceShader;
- if (
- defined(surfaceShader) &&
- surfaceShader.numberOfDayTextures === numberOfDayTextures &&
- surfaceShader.flags === flags &&
- surfaceShader.material === this.material &&
- surfaceShader.clippingShaderState === currentClippingShaderState
- ) {
- return surfaceShader.shaderProgram;
- }
- // New tile, or tile changed number of textures, flags, or clipping planes
- let shadersByFlags = this._shadersByTexturesFlags[numberOfDayTextures];
- if (!defined(shadersByFlags)) {
- shadersByFlags = this._shadersByTexturesFlags[numberOfDayTextures] = [];
- }
- surfaceShader = shadersByFlags[flags];
- if (
- !defined(surfaceShader) ||
- surfaceShader.material !== this.material ||
- surfaceShader.clippingShaderState !== currentClippingShaderState
- ) {
- // Cache miss - we've never seen this combination of numberOfDayTextures and flags before.
- const vs = this.baseVertexShaderSource.clone();
- const fs = this.baseFragmentShaderSource.clone();
- if (currentClippingShaderState !== 0) {
- fs.sources.unshift(
- getClippingFunction(clippingPlanes, frameState.context)
- ); // Need to go before GlobeFS
- }
- vs.defines.push(quantizationDefine);
- fs.defines.push(
- `TEXTURE_UNITS ${numberOfDayTextures}`,
- cartographicLimitRectangleDefine,
- imageryCutoutDefine
- );
- if (applyBrightness) {
- fs.defines.push("APPLY_BRIGHTNESS");
- }
- if (applyContrast) {
- fs.defines.push("APPLY_CONTRAST");
- }
- if (applyHue) {
- fs.defines.push("APPLY_HUE");
- }
- if (applySaturation) {
- fs.defines.push("APPLY_SATURATION");
- }
- if (applyGamma) {
- fs.defines.push("APPLY_GAMMA");
- }
- if (applyAlpha) {
- fs.defines.push("APPLY_ALPHA");
- }
- if (applyDayNightAlpha) {
- fs.defines.push("APPLY_DAY_NIGHT_ALPHA");
- }
- if (showReflectiveOcean) {
- fs.defines.push("SHOW_REFLECTIVE_OCEAN");
- vs.defines.push("SHOW_REFLECTIVE_OCEAN");
- }
- if (showOceanWaves) {
- fs.defines.push("SHOW_OCEAN_WAVES");
- }
- if (colorToAlpha) {
- fs.defines.push("APPLY_COLOR_TO_ALPHA");
- }
- if (showUndergroundColor) {
- vs.defines.push("UNDERGROUND_COLOR");
- fs.defines.push("UNDERGROUND_COLOR");
- }
- if (translucent) {
- vs.defines.push("TRANSLUCENT");
- fs.defines.push("TRANSLUCENT");
- }
- if (enableLighting) {
- if (hasVertexNormals) {
- vs.defines.push("ENABLE_VERTEX_LIGHTING");
- fs.defines.push("ENABLE_VERTEX_LIGHTING");
- } else {
- vs.defines.push("ENABLE_DAYNIGHT_SHADING");
- fs.defines.push("ENABLE_DAYNIGHT_SHADING");
- }
- }
- if (dynamicAtmosphereLighting) {
- vs.defines.push("DYNAMIC_ATMOSPHERE_LIGHTING");
- fs.defines.push("DYNAMIC_ATMOSPHERE_LIGHTING");
- if (dynamicAtmosphereLightingFromSun) {
- vs.defines.push("DYNAMIC_ATMOSPHERE_LIGHTING_FROM_SUN");
- fs.defines.push("DYNAMIC_ATMOSPHERE_LIGHTING_FROM_SUN");
- }
- }
- if (showGroundAtmosphere) {
- vs.defines.push("GROUND_ATMOSPHERE");
- fs.defines.push("GROUND_ATMOSPHERE");
- if (perFragmentGroundAtmosphere) {
- vs.defines.push("PER_FRAGMENT_GROUND_ATMOSPHERE");
- fs.defines.push("PER_FRAGMENT_GROUND_ATMOSPHERE");
- }
- }
- vs.defines.push("INCLUDE_WEB_MERCATOR_Y");
- fs.defines.push("INCLUDE_WEB_MERCATOR_Y");
- if (enableFog) {
- vs.defines.push("FOG");
- fs.defines.push("FOG");
- }
- if (applySplit) {
- fs.defines.push("APPLY_SPLIT");
- }
- if (enableClippingPlanes) {
- fs.defines.push("ENABLE_CLIPPING_PLANES");
- }
- if (colorCorrect) {
- fs.defines.push("COLOR_CORRECT");
- }
- if (highlightFillTile) {
- fs.defines.push("HIGHLIGHT_FILL_TILE");
- }
- if (hasGeodeticSurfaceNormals) {
- vs.defines.push("GEODETIC_SURFACE_NORMALS");
- }
- if (hasExaggeration) {
- vs.defines.push("EXAGGERATION");
- }
- let computeDayColor =
- "\
- vec4 computeDayColor(vec4 initialColor, vec3 textureCoordinates, float nightBlend)\n\
- {\n\
- vec4 color = initialColor;\n";
- if (hasImageryLayerCutout) {
- computeDayColor +=
- "\
- vec4 cutoutAndColorResult;\n\
- bool texelUnclipped;\n";
- }
- for (let i = 0; i < numberOfDayTextures; ++i) {
- if (hasImageryLayerCutout) {
- computeDayColor += `\
- cutoutAndColorResult = u_dayTextureCutoutRectangles[${i}];\n\
- texelUnclipped = v_textureCoordinates.x < cutoutAndColorResult.x || cutoutAndColorResult.z < v_textureCoordinates.x || v_textureCoordinates.y < cutoutAndColorResult.y || cutoutAndColorResult.w < v_textureCoordinates.y;\n\
- cutoutAndColorResult = sampleAndBlend(\n`;
- } else {
- computeDayColor += "\
- color = sampleAndBlend(\n";
- }
- computeDayColor += `\
- color,\n\
- u_dayTextures[${i}],\n\
- u_dayTextureUseWebMercatorT[${i}] ? textureCoordinates.xz : textureCoordinates.xy,\n\
- u_dayTextureTexCoordsRectangle[${i}],\n\
- u_dayTextureTranslationAndScale[${i}],\n\
- ${applyAlpha ? `u_dayTextureAlpha[${i}]` : "1.0"},\n\
- ${applyDayNightAlpha ? `u_dayTextureNightAlpha[${i}]` : "1.0"},\n${
- applyDayNightAlpha ? `u_dayTextureDayAlpha[${i}]` : "1.0"
- },\n${applyBrightness ? `u_dayTextureBrightness[${i}]` : "0.0"},\n\
- ${applyContrast ? `u_dayTextureContrast[${i}]` : "0.0"},\n\
- ${applyHue ? `u_dayTextureHue[${i}]` : "0.0"},\n\
- ${applySaturation ? `u_dayTextureSaturation[${i}]` : "0.0"},\n\
- ${applyGamma ? `u_dayTextureOneOverGamma[${i}]` : "0.0"},\n\
- ${applySplit ? `u_dayTextureSplit[${i}]` : "0.0"},\n\
- ${colorToAlpha ? `u_colorsToAlpha[${i}]` : "vec4(0.0)"},\n\
- nightBlend\
- );\n`;
- if (hasImageryLayerCutout) {
- computeDayColor +=
- "\
- color = czm_branchFreeTernary(texelUnclipped, cutoutAndColorResult, color);\n";
- }
- }
- computeDayColor += "\
- return color;\n\
- }";
- fs.sources.push(computeDayColor);
- vs.sources.push(getPositionMode(sceneMode));
- vs.sources.push(get2DYPositionFraction(useWebMercatorProjection));
- const shader = ShaderProgram.fromCache({
- context: frameState.context,
- vertexShaderSource: vs,
- fragmentShaderSource: fs,
- attributeLocations: terrainEncoding.getAttributeLocations(),
- });
- surfaceShader = shadersByFlags[flags] = new GlobeSurfaceShader(
- numberOfDayTextures,
- flags,
- this.material,
- shader,
- currentClippingShaderState
- );
- }
- surfaceTile.surfaceShader = surfaceShader;
- return surfaceShader.shaderProgram;
- };
- GlobeSurfaceShaderSet.prototype.destroy = function () {
- let flags;
- let shader;
- const shadersByTexturesFlags = this._shadersByTexturesFlags;
- for (const textureCount in shadersByTexturesFlags) {
- if (shadersByTexturesFlags.hasOwnProperty(textureCount)) {
- const shadersByFlags = shadersByTexturesFlags[textureCount];
- if (!defined(shadersByFlags)) {
- continue;
- }
- for (flags in shadersByFlags) {
- if (shadersByFlags.hasOwnProperty(flags)) {
- shader = shadersByFlags[flags];
- if (defined(shader)) {
- shader.shaderProgram.destroy();
- }
- }
- }
- }
- }
- return destroyObject(this);
- };
- export default GlobeSurfaceShaderSet;
|