| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279 | import Cartesian2 from "../Core/Cartesian2.js";import Color from "../Core/Color.js";import defined from "../Core/defined.js";import destroyObject from "../Core/destroyObject.js";import PrimitiveType from "../Core/PrimitiveType.js";import ClearCommand from "../Renderer/ClearCommand.js";import DrawCommand from "../Renderer/DrawCommand.js";import FramebufferManager from "../Renderer/FramebufferManager.js";import Pass from "../Renderer/Pass.js";import RenderState from "../Renderer/RenderState.js";import ShaderSource from "../Renderer/ShaderSource.js";import BlendingState from "../Scene/BlendingState.js";import StencilConstants from "../Scene/StencilConstants.js";import PointCloudEyeDomeLightingShader from "../Shaders/PostProcessStages/PointCloudEyeDomeLighting.js";/** * Eye dome lighting. Does not support points with per-point translucency, but does allow translucent styling against the globe. * Requires support for EXT_frag_depth and WEBGL_draw_buffers extensions in WebGL 1.0. * * @private */function PointCloudEyeDomeLighting() {  this._framebuffer = new FramebufferManager({    colorAttachmentsLength: 2,    depth: true,    supportsDepthTexture: true,  });  this._drawCommand = undefined;  this._clearCommand = undefined;  this._strength = 1.0;  this._radius = 1.0;}Object.defineProperties(PointCloudEyeDomeLighting.prototype, {  framebuffer: {    get: function () {      return this._framebuffer.framebuffer;    },  },  colorGBuffer: {    get: function () {      return this._framebuffer.getColorTexture(0);    },  },  depthGBuffer: {    get: function () {      return this._framebuffer.getColorTexture(1);    },  },});function destroyFramebuffer(processor) {  processor._framebuffer.destroy();  processor._drawCommand = undefined;  processor._clearCommand = undefined;}const distanceAndEdlStrengthScratch = new Cartesian2();function createCommands(processor, context) {  const blendFS = new ShaderSource({    defines: ["LOG_DEPTH_WRITE"],    sources: [PointCloudEyeDomeLightingShader],  });  const blendUniformMap = {    u_pointCloud_colorGBuffer: function () {      return processor.colorGBuffer;    },    u_pointCloud_depthGBuffer: function () {      return processor.depthGBuffer;    },    u_distanceAndEdlStrength: function () {      distanceAndEdlStrengthScratch.x = processor._radius;      distanceAndEdlStrengthScratch.y = processor._strength;      return distanceAndEdlStrengthScratch;    },  };  const blendRenderState = RenderState.fromCache({    blending: BlendingState.ALPHA_BLEND,    depthMask: true,    depthTest: {      enabled: true,    },    stencilTest: StencilConstants.setCesium3DTileBit(),    stencilMask: StencilConstants.CESIUM_3D_TILE_MASK,  });  processor._drawCommand = context.createViewportQuadCommand(blendFS, {    uniformMap: blendUniformMap,    renderState: blendRenderState,    pass: Pass.CESIUM_3D_TILE,    owner: processor,  });  processor._clearCommand = new ClearCommand({    framebuffer: processor.framebuffer,    color: new Color(0.0, 0.0, 0.0, 0.0),    depth: 1.0,    renderState: RenderState.fromCache(),    pass: Pass.CESIUM_3D_TILE,    owner: processor,  });}function createResources(processor, context) {  const width = context.drawingBufferWidth;  const height = context.drawingBufferHeight;  processor._framebuffer.update(context, width, height);  createCommands(processor, context);}function isSupported(context) {  return context.drawBuffers && context.fragmentDepth;}PointCloudEyeDomeLighting.isSupported = isSupported;function getECShaderProgram(context, shaderProgram) {  let shader = context.shaderCache.getDerivedShaderProgram(shaderProgram, "EC");  if (!defined(shader)) {    const attributeLocations = shaderProgram._attributeLocations;    const fs = shaderProgram.fragmentShaderSource.clone();    fs.sources = fs.sources.map(function (source) {      source = ShaderSource.replaceMain(        source,        "czm_point_cloud_post_process_main"      );      source = source.replace(/gl_FragColor/g, "gl_FragData[0]");      return source;    });    fs.sources.unshift("#extension GL_EXT_draw_buffers : enable \n");    fs.sources.push(      "void main() \n" +        "{ \n" +        "    czm_point_cloud_post_process_main(); \n" +        "#ifdef LOG_DEPTH\n" +        "    czm_writeLogDepth();\n" +        "    gl_FragData[1] = czm_packDepth(gl_FragDepthEXT); \n" +        "#else\n" +        "    gl_FragData[1] = czm_packDepth(gl_FragCoord.z);\n" +        "#endif\n" +        "}"    );    shader = context.shaderCache.createDerivedShaderProgram(      shaderProgram,      "EC",      {        vertexShaderSource: shaderProgram.vertexShaderSource,        fragmentShaderSource: fs,        attributeLocations: attributeLocations,      }    );  }  return shader;}PointCloudEyeDomeLighting.prototype.update = function (  frameState,  commandStart,  pointCloudShading,  boundingVolume) {  if (!isSupported(frameState.context)) {    return;  }  this._strength = pointCloudShading.eyeDomeLightingStrength;  this._radius =    pointCloudShading.eyeDomeLightingRadius * frameState.pixelRatio;  createResources(this, frameState.context);  // Hijack existing point commands to render into an offscreen FBO.  let i;  const commandList = frameState.commandList;  const commandEnd = commandList.length;  for (i = commandStart; i < commandEnd; ++i) {    const command = commandList[i];    if (      command.primitiveType !== PrimitiveType.POINTS ||      command.pass === Pass.TRANSLUCENT    ) {      continue;    }    let derivedCommand;    let originalShaderProgram;    let derivedCommandObject = command.derivedCommands.pointCloudProcessor;    if (defined(derivedCommandObject)) {      derivedCommand = derivedCommandObject.command;      originalShaderProgram = derivedCommandObject.originalShaderProgram;    }    if (      !defined(derivedCommand) ||      command.dirty ||      originalShaderProgram !== command.shaderProgram ||      derivedCommand.framebuffer !== this.framebuffer    ) {      // Prevent crash when tiles out-of-view come in-view during context size change or      // when the underlying shader changes while EDL is disabled      derivedCommand = DrawCommand.shallowClone(command, derivedCommand);      derivedCommand.framebuffer = this.framebuffer;      derivedCommand.shaderProgram = getECShaderProgram(        frameState.context,        command.shaderProgram      );      derivedCommand.castShadows = false;      derivedCommand.receiveShadows = false;      if (!defined(derivedCommandObject)) {        derivedCommandObject = {          command: derivedCommand,          originalShaderProgram: command.shaderProgram,        };        command.derivedCommands.pointCloudProcessor = derivedCommandObject;      }      derivedCommandObject.originalShaderProgram = command.shaderProgram;    }    commandList[i] = derivedCommand;  }  const clearCommand = this._clearCommand;  const blendCommand = this._drawCommand;  blendCommand.boundingVolume = boundingVolume;  // Blend EDL into the main FBO  commandList.push(blendCommand);  commandList.push(clearCommand);};/** * Returns true if this object was destroyed; otherwise, false. * <br /><br /> * If this object was destroyed, it should not be used; calling any function other than * <code>isDestroyed</code> will result in a {@link DeveloperError} exception. * * @returns {Boolean} <code>true</code> if this object was destroyed; otherwise, <code>false</code>. * * @see PointCloudEyeDomeLighting#destroy */PointCloudEyeDomeLighting.prototype.isDestroyed = function () {  return false;};/** * Destroys the WebGL resources held by this object.  Destroying an object allows for deterministic * release of WebGL resources, instead of relying on the garbage collector to destroy this object. * <br /><br /> * Once an object is destroyed, it should not be used; calling any function other than * <code>isDestroyed</code> will result in a {@link DeveloperError} exception.  Therefore, * assign the return value (<code>undefined</code>) to the object as done in the example. * * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called. * * @example * processor = processor && processor.destroy(); * * @see PointCloudEyeDomeLighting#isDestroyed */PointCloudEyeDomeLighting.prototype.destroy = function () {  destroyFramebuffer(this);  return destroyObject(this);};export default PointCloudEyeDomeLighting;
 |