123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291 |
- 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 PixelFormat from '../Core/PixelFormat.js';
- import PrimitiveType from '../Core/PrimitiveType.js';
- import ClearCommand from '../Renderer/ClearCommand.js';
- import DrawCommand from '../Renderer/DrawCommand.js';
- import Framebuffer from '../Renderer/Framebuffer.js';
- import Pass from '../Renderer/Pass.js';
- import PixelDatatype from '../Renderer/PixelDatatype.js';
- import RenderState from '../Renderer/RenderState.js';
- import Sampler from '../Renderer/Sampler.js';
- import ShaderSource from '../Renderer/ShaderSource.js';
- import Texture from '../Renderer/Texture.js';
- import TextureMagnificationFilter from '../Renderer/TextureMagnificationFilter.js';
- import TextureMinificationFilter from '../Renderer/TextureMinificationFilter.js';
- import TextureWrap from '../Renderer/TextureWrap.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 = undefined;
- this._colorGBuffer = undefined; // color gbuffer
- this._depthGBuffer = undefined; // depth gbuffer
- this._depthTexture = undefined; // needed to write depth so camera based on depth works
- this._drawCommand = undefined;
- this._clearCommand = undefined;
- this._strength = 1.0;
- this._radius = 1.0;
- }
- function createSampler() {
- return new Sampler({
- wrapS : TextureWrap.CLAMP_TO_EDGE,
- wrapT : TextureWrap.CLAMP_TO_EDGE,
- minificationFilter : TextureMinificationFilter.NEAREST,
- magnificationFilter : TextureMagnificationFilter.NEAREST
- });
- }
- function destroyFramebuffer(processor) {
- var framebuffer = processor._framebuffer;
- if (!defined(framebuffer)) {
- return;
- }
- processor._colorGBuffer.destroy();
- processor._depthGBuffer.destroy();
- processor._depthTexture.destroy();
- framebuffer.destroy();
- processor._framebuffer = undefined;
- processor._colorGBuffer = undefined;
- processor._depthGBuffer = undefined;
- processor._depthTexture = undefined;
- processor._drawCommand = undefined;
- processor._clearCommand = undefined;
- }
- function createFramebuffer(processor, context) {
- var screenWidth = context.drawingBufferWidth;
- var screenHeight = context.drawingBufferHeight;
- var colorGBuffer = new Texture({
- context : context,
- width : screenWidth,
- height : screenHeight,
- pixelFormat : PixelFormat.RGBA,
- pixelDatatype : PixelDatatype.UNSIGNED_BYTE,
- sampler : createSampler()
- });
- var depthGBuffer = new Texture({
- context : context,
- width : screenWidth,
- height : screenHeight,
- pixelFormat : PixelFormat.RGBA,
- pixelDatatype : PixelDatatype.UNSIGNED_BYTE,
- sampler : createSampler()
- });
- var depthTexture = new Texture({
- context : context,
- width : screenWidth,
- height : screenHeight,
- pixelFormat : PixelFormat.DEPTH_COMPONENT,
- pixelDatatype : PixelDatatype.UNSIGNED_INT,
- sampler : createSampler()
- });
- processor._framebuffer = new Framebuffer({
- context : context,
- colorTextures : [
- colorGBuffer,
- depthGBuffer
- ],
- depthTexture : depthTexture,
- destroyAttachments : false
- });
- processor._colorGBuffer = colorGBuffer;
- processor._depthGBuffer = depthGBuffer;
- processor._depthTexture = depthTexture;
- }
- var distanceAndEdlStrengthScratch = new Cartesian2();
- function createCommands(processor, context) {
- var blendFS = PointCloudEyeDomeLightingShader;
- var 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;
- }
- };
- var 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) {
- var screenWidth = context.drawingBufferWidth;
- var screenHeight = context.drawingBufferHeight;
- var colorGBuffer = processor._colorGBuffer;
- var nowDirty = false;
- var resized = defined(colorGBuffer) &&
- ((colorGBuffer.width !== screenWidth) ||
- (colorGBuffer.height !== screenHeight));
- if (!defined(colorGBuffer) || resized) {
- destroyFramebuffer(processor);
- createFramebuffer(processor, context);
- createCommands(processor, context);
- nowDirty = true;
- }
- return nowDirty;
- }
- function isSupported(context) {
- return context.drawBuffers && context.fragmentDepth;
- }
- PointCloudEyeDomeLighting.isSupported = isSupported;
- function getECShaderProgram(context, shaderProgram) {
- var shader = context.shaderCache.getDerivedShaderProgram(shaderProgram, 'EC');
- if (!defined(shader)) {
- var attributeLocations = shaderProgram._attributeLocations;
- var 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' +
- ' gl_FragData[1] = czm_packDepth(gl_FragCoord.z); \n' +
- '}');
- shader = context.shaderCache.createDerivedShaderProgram(shaderProgram, 'EC', {
- vertexShaderSource : shaderProgram.vertexShaderSource,
- fragmentShaderSource : fs,
- attributeLocations : attributeLocations
- });
- }
- return shader;
- }
- PointCloudEyeDomeLighting.prototype.update = function(frameState, commandStart, pointCloudShading) {
- if (!isSupported(frameState.context)) {
- return;
- }
- this._strength = pointCloudShading.eyeDomeLightingStrength;
- this._radius = pointCloudShading.eyeDomeLightingRadius * frameState.pixelRatio;
- var dirty = createResources(this, frameState.context);
- // Hijack existing point commands to render into an offscreen FBO.
- var i;
- var commandList = frameState.commandList;
- var commandEnd = commandList.length;
- for (i = commandStart; i < commandEnd; ++i) {
- var command = commandList[i];
- if (command.primitiveType !== PrimitiveType.POINTS || command.pass === Pass.TRANSLUCENT) {
- continue;
- }
- var derivedCommand = command.derivedCommands.pointCloudProcessor;
- if (!defined(derivedCommand) || command.dirty || dirty ||
- (derivedCommand.framebuffer !== this._framebuffer)) { // Prevent crash when tiles out-of-view come in-view during context size change
- derivedCommand = DrawCommand.shallowClone(command);
- command.derivedCommands.pointCloudProcessor = derivedCommand;
- derivedCommand.framebuffer = this._framebuffer;
- derivedCommand.shaderProgram = getECShaderProgram(frameState.context, command.shaderProgram);
- derivedCommand.castShadows = false;
- derivedCommand.receiveShadows = false;
- }
- commandList[i] = derivedCommand;
- }
- var clearCommand = this._clearCommand;
- var blendCommand = this._drawCommand;
- // 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;
|