From 521dc574827316b5ad952ddc04bb91f8f40604ce Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Wed, 7 Jun 2017 23:16:35 -0400 Subject: [PATCH 001/240] Initial point cloud processing --- Source/Renderer/Context.js | 3 +- Source/Scene/Cesium3DTileset.js | 13 +- Source/Scene/PointCloudPostProcessor.js | 276 ++++++++++++++++++++++++ 3 files changed, 289 insertions(+), 3 deletions(-) create mode 100644 Source/Scene/PointCloudPostProcessor.js diff --git a/Source/Renderer/Context.js b/Source/Renderer/Context.js index 7966c47e0418..d490e65eeea6 100644 --- a/Source/Renderer/Context.js +++ b/Source/Renderer/Context.js @@ -1077,7 +1077,8 @@ define([ }), uniformMap : overrides.uniformMap, owner : overrides.owner, - framebuffer : overrides.framebuffer + framebuffer : overrides.framebuffer, + pass : overrides.pass }); }; diff --git a/Source/Scene/Cesium3DTileset.js b/Source/Scene/Cesium3DTileset.js index 26d03238ea08..84760e0f9250 100644 --- a/Source/Scene/Cesium3DTileset.js +++ b/Source/Scene/Cesium3DTileset.js @@ -35,6 +35,7 @@ define([ './Cesium3DTilesetTraversal', './Cesium3DTileStyleEngine', './LabelCollection', + './PointCloudPostProcessor', './ShadowMode', './TileBoundingRegion', './TileBoundingSphere', @@ -75,6 +76,7 @@ define([ Cesium3DTilesetTraversal, Cesium3DTileStyleEngine, LabelCollection, + PointCloudPostProcessor, ShadowMode, TileBoundingRegion, TileBoundingSphere, @@ -205,6 +207,7 @@ define([ }); this._backfaceCommands = new ManagedArray(); + this._pointCloudPostProcessor = new PointCloudPostProcessor(); this._maximumScreenSpaceError = defaultValue(options.maximumScreenSpaceError, 16); this._maximumMemoryUsage = defaultValue(options.maximumMemoryUsage, 512); @@ -1541,7 +1544,7 @@ define([ ++statistics.selected; } } - var lengthAfterUpdate = commandList.length; + var addedCommandsLength = commandList.length - lengthBeforeUpdate; tileset._backfaceCommands.trim(); @@ -1571,7 +1574,6 @@ define([ */ var backfaceCommands = tileset._backfaceCommands.internalArray; - var addedCommandsLength = (lengthAfterUpdate - lengthBeforeUpdate); var backfaceCommandsLength = backfaceCommands.length; commandList.length += backfaceCommands.length; @@ -1590,6 +1592,13 @@ define([ // Number of commands added by each update above statistics.numberOfCommands = (commandList.length - numberOfInitialCommands); + if (addedCommandsLength > 0) { + // TODO : only do this if the tileset is purely point clouds. + // TODO : this may not work well if point cloud spans multiple frustums + // TODO : make the processor a static class so it can be used by multiple tilesets? + tileset._pointCloudPostProcessor.update(frameState, numberOfInitialCommands); + } + if (tileset.debugShowGeometricError || tileset.debugShowRenderingStatistics || tileset.debugShowMemoryUsage) { if (!defined(tileset._tileDebugLabels)) { tileset._tileDebugLabels = new LabelCollection(); diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js new file mode 100644 index 000000000000..0ba5fb422c5f --- /dev/null +++ b/Source/Scene/PointCloudPostProcessor.js @@ -0,0 +1,276 @@ +/*global define*/ +define([ + '../Core/Color', + '../Core/defined', + '../Core/destroyObject', + '../Core/PixelFormat', + '../Renderer/ClearCommand', + '../Renderer/Framebuffer', + '../Renderer/Pass', + '../Renderer/PixelDatatype', + '../Renderer/RenderState', + '../Renderer/Sampler', + '../Renderer/Texture', + '../Renderer/TextureMagnificationFilter', + '../Renderer/TextureMinificationFilter', + '../Renderer/TextureWrap', + '../Scene/BlendingState' + ], function( + Color, + defined, + destroyObject, + PixelFormat, + ClearCommand, + Framebuffer, + Pass, + PixelDatatype, + RenderState, + Sampler, + Texture, + TextureMagnificationFilter, + TextureMinificationFilter, + TextureWrap, + BlendingState) { + 'use strict'; + + /** + * @private + */ + function PointCloudPostProcessor() { + this._framebuffers = undefined; + this._colorTextures = undefined; + this._depthTexture = undefined; + this._drawCommands = undefined; + this._blendCommand = undefined; + this._clearCommand = undefined; + } + + function createSampler() { + return new Sampler({ + wrapS : TextureWrap.CLAMP_TO_EDGE, + wrapT : TextureWrap.CLAMP_TO_EDGE, + minificationFilter : TextureMinificationFilter.NEAREST, + magnificationFilter : TextureMagnificationFilter.NEAREST + }); + } + + function destroyFramebuffers(processor) { + processor._depthTexture.destroy(); + processor._colorTextures[0].destroy(); + processor._colorTextures[1].destroy(); + processor._framebuffers[0].destroy(); + processor._framebuffers[1].destroy(); + + processor._depthTexture = undefined; + processor._colorTextures = undefined; + processor._framebuffers = undefined; + } + + function createFramebuffers(processor, context) { + var i; + var screenWidth = context.drawingBufferWidth; + var screenHeight = context.drawingBufferHeight; + + var depthTexture = new Texture({ + context : context, + width : screenWidth, + height : screenHeight, + pixelFormat : PixelFormat.DEPTH_STENCIL, + pixelDatatype : PixelDatatype.UNSIGNED_INT_24_8, + sampler : createSampler() + }); + + var colorTextures = new Array(2); + var framebuffers = new Array(2); + + for (i = 0; i < 2; ++i) { + colorTextures[i] = new Texture({ + context : context, + width : screenWidth, + height : screenHeight, + pixelFormat : PixelFormat.RGBA, + pixelDatatype : PixelDatatype.UNSIGNED_BYTE, + sampler : createSampler() + }); + + // TODO : for now assume than any pass can write depth, possibly through EXT_frag_depth. Definitely needed for the initial render into the FBO, possibly also the ping-pong processing. + framebuffers[i] = new Framebuffer({ + context : context, + depthStencilTexture : depthTexture, + colorTextures : [colorTextures[i]], + destroyAttachments : false + }); + } + + processor._depthTexture = depthTexture; + processor._colorTextures = colorTextures; + processor._framebuffers = framebuffers; + } + + function createUniformMap(processor, index) { + return { + pointCloud_colorTexture : function() { + // Use the other color texture as input + return processor._colorTextures[1 - index]; + }, + pointCloud_depthTexture : function() { + // TODO : depth texture is both shader input and output - don't read and write in the same shader. If needed may need to ping-pong depth too. + return processor._depthTexture; + } + }; + } + + function createCommands(processor, context) { + var i; + var framebuffers = processor._framebuffers; + var uniformMaps = [ + createUniformMap(processor, 0), + createUniformMap(processor, 1) + ]; + + var stageFS = + 'uniform sampler2D pointCloud_colorTexture; \n' + + 'uniform sampler2D pointCloud_depthTexture; \n' + + 'varying vec2 v_textureCoordinates; \n' + + 'void main() \n' + + '{ \n' + + ' vec4 color = texture2D(pointCloud_colorTexture, v_textureCoordinates); \n' + + ' float depth = texture2D(pointCloud_depthTexture, v_textureCoordinates).r; \n' + + ' color.rgb = color.rgb * 0.5 + vec3(depth); \n' + + ' gl_FragColor = color; \n' + + '} \n'; + + // TODO : faking post-processing stages for testing + var stagesLength = 3; + var drawCommands = new Array(stagesLength); + for (i = 0; i < stagesLength; ++i) { + drawCommands[i] = context.createViewportQuadCommand(stageFS, { + uniformMap : uniformMaps[i % 2], + framebuffer : framebuffers[i % 2], + renderState : RenderState.fromCache(), + pass : Pass.CESIUM_3D_TILE, + owner : processor + }); + } + + // TODO : point cloud depth information is lost + var blendFS = + 'uniform sampler2D pointCloud_colorTexture; \n' + + 'varying vec2 v_textureCoordinates; \n' + + 'void main() \n' + + '{ \n' + + ' vec4 color = texture2D(pointCloud_colorTexture, v_textureCoordinates); \n' + + ' gl_FragColor = color; \n' + + '} \n'; + + var blendRenderState = RenderState.fromCache({ + blending : BlendingState.ALPHA_BLEND + }); + + var blendCommand = context.createViewportQuadCommand(blendFS, { + uniformMap : uniformMaps[stagesLength % 2], + renderState : blendRenderState, + pass : Pass.CESIUM_3D_TILE, + owner : processor + }); + + // TODO : may need to clear FBOs between each stage instead of just clearing the main FBO. + var clearCommand = new ClearCommand({ + framebuffer : framebuffers[1], + color : new Color(0.0, 0.0, 0.0, 0.0), + depth : 1.0, + renderState : RenderState.fromCache(), + pass : Pass.CESIUM_3D_TILE, + owner : processor + }); + + processor._drawCommands = drawCommands; + processor._blendCommand = blendCommand; + processor._clearCommand = clearCommand; + } + + function updateCommandFramebuffers(processor) { + var framebuffers = processor._framebuffers; + var drawCommands = processor._drawCommands; + var clearCommand = processor._clearCommand; + var length = drawCommands.length; + for (var i = 0; i < length; ++i) { + drawCommands[i].framebuffer = framebuffers[i % 2]; + } + clearCommand.framebuffer = framebuffers[1]; + } + + function createResources(processor, context) { + var screenWidth = context.drawingBufferWidth; + var screenHeight = context.drawingBufferHeight; + var depthTexture = processor._depthTexture; + var drawCommands = processor._drawCommands; + var resized = defined(depthTexture) && ((depthTexture.width !== screenWidth) || (depthTexture.height !== screenHeight)); + + if (!defined(depthTexture)) { + createFramebuffers(processor, context); + } + + if (!defined(drawCommands)) { + createCommands(processor, context); + } + + if (resized) { + destroyFramebuffers(processor); + createFramebuffers(processor, context); + updateCommandFramebuffers(processor); + } + } + + function processingSupported(context) { + return context.depthTexture; + } + + PointCloudPostProcessor.prototype.update = function(frameState, commandStart) { + if (!processingSupported(frameState.context)) { + return; + } + + createResources(this, frameState.context); + + // Render point cloud commands into an offscreen FBO. + var i; + var commandList = frameState.commandList; + var commandEnd = commandList.length; + for (i = commandStart; i < commandEnd; ++i) { + var command = commandList[i]; + command.framebuffer = this._framebuffers[1]; + command.pass = Pass.CESIUM_3D_TILE; // Overrides translucent commands + } + + // Apply processing commands + var drawCommands = this._drawCommands; + var length = drawCommands.length; + for (i = 0; i < length; ++i) { + commandList.push(drawCommands[i]); + } + + // Blend final result back into the main FBO + commandList.push(this._blendCommand); + + // TODO: technically should apply the clear sooner since the FBO's color texture is undefined on the first frame. Related to TODO above. This may also explain some black flashes during resizing. + commandList.push(this._clearCommand); + }; + + /** + * Part of the {@link Cesium3DTileContent} interface. + */ + PointCloudPostProcessor.prototype.isDestroyed = function() { + return false; + }; + + /** + * Part of the {@link Cesium3DTileContent} interface. + */ + PointCloudPostProcessor.prototype.destroy = function() { + // TODO: actually destroy stuff + return destroyObject(this); + }; + + return PointCloudPostProcessor; +}); From 2e742a25bbcde6bfe8751193eb3a0e88a27f5c87 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Thu, 8 Jun 2017 15:13:54 -0400 Subject: [PATCH 002/240] Fixes the depth rendering issue on OS X --- Source/Scene/PointCloudPostProcessor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 0ba5fb422c5f..2e40d066651d 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -136,7 +136,7 @@ define([ '{ \n' + ' vec4 color = texture2D(pointCloud_colorTexture, v_textureCoordinates); \n' + ' float depth = texture2D(pointCloud_depthTexture, v_textureCoordinates).r; \n' + - ' color.rgb = color.rgb * 0.5 + vec3(depth); \n' + + ' color.rgb = color.rgb * 0.5 + vec3(depth) * 0.5; \n' + ' gl_FragColor = color; \n' + '} \n'; From d3ed73f22133e24578e8f717f590c64718fc353e Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Thu, 8 Jun 2017 15:31:39 -0400 Subject: [PATCH 003/240] Now ping-ponging the depth as well --- Source/Scene/PointCloudPostProcessor.js | 43 ++++++++++++++----------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 2e40d066651d..72ef3b7d56fc 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -39,7 +39,7 @@ define([ function PointCloudPostProcessor() { this._framebuffers = undefined; this._colorTextures = undefined; - this._depthTexture = undefined; + this._depthTextures = undefined; this._drawCommands = undefined; this._blendCommand = undefined; this._clearCommand = undefined; @@ -55,13 +55,14 @@ define([ } function destroyFramebuffers(processor) { - processor._depthTexture.destroy(); + processor._depthTextures[0].destroy(); + processor._depthTextures[1].destroy(); processor._colorTextures[0].destroy(); processor._colorTextures[1].destroy(); processor._framebuffers[0].destroy(); processor._framebuffers[1].destroy(); - processor._depthTexture = undefined; + processor._depthTextures = undefined; processor._colorTextures = undefined; processor._framebuffers = undefined; } @@ -71,16 +72,9 @@ define([ var screenWidth = context.drawingBufferWidth; var screenHeight = context.drawingBufferHeight; - var depthTexture = new Texture({ - context : context, - width : screenWidth, - height : screenHeight, - pixelFormat : PixelFormat.DEPTH_STENCIL, - pixelDatatype : PixelDatatype.UNSIGNED_INT_24_8, - sampler : createSampler() - }); var colorTextures = new Array(2); + var depthTextures = new Array(2); var framebuffers = new Array(2); for (i = 0; i < 2; ++i) { @@ -93,16 +87,26 @@ define([ sampler : createSampler() }); - // TODO : for now assume than any pass can write depth, possibly through EXT_frag_depth. Definitely needed for the initial render into the FBO, possibly also the ping-pong processing. + depthTextures[i] = new Texture({ + context : context, + width : screenWidth, + height : screenHeight, + pixelFormat : PixelFormat.DEPTH_STENCIL, + pixelDatatype : PixelDatatype.UNSIGNED_INT_24_8, + sampler : createSampler() + }); + + // TODO : for now assume than any pass can write depth, possibly through EXT_frag_depth. + // Definitely needed for the initial render into the FBO, possibly also the ping-pong processing. framebuffers[i] = new Framebuffer({ context : context, - depthStencilTexture : depthTexture, + depthStencilTexture : depthTextures[i], colorTextures : [colorTextures[i]], destroyAttachments : false }); } - processor._depthTexture = depthTexture; + processor._depthTextures = depthTextures; processor._colorTextures = colorTextures; processor._framebuffers = framebuffers; } @@ -114,8 +118,7 @@ define([ return processor._colorTextures[1 - index]; }, pointCloud_depthTexture : function() { - // TODO : depth texture is both shader input and output - don't read and write in the same shader. If needed may need to ping-pong depth too. - return processor._depthTexture; + return processor._depthTextures[1 - index]; } }; } @@ -203,11 +206,13 @@ define([ function createResources(processor, context) { var screenWidth = context.drawingBufferWidth; var screenHeight = context.drawingBufferHeight; - var depthTexture = processor._depthTexture; + var depthTextures = processor._depthTextures; var drawCommands = processor._drawCommands; - var resized = defined(depthTexture) && ((depthTexture.width !== screenWidth) || (depthTexture.height !== screenHeight)); + var resized = defined(depthTextures) && + ((depthTextures[0].width !== screenWidth) || + (depthTextures[0].height !== screenHeight)); - if (!defined(depthTexture)) { + if (!defined(depthTextures)) { createFramebuffers(processor, context); } From a6d21997f7ff7a31fe015f4333b2f6ecf804caed Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Fri, 9 Jun 2017 10:47:43 -0400 Subject: [PATCH 004/240] Adds eye-space textures to the framebuffer for PointCloudProcessor --- Source/Scene/PointCloudPostProcessor.js | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 72ef3b7d56fc..17224454b645 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -39,6 +39,7 @@ define([ function PointCloudPostProcessor() { this._framebuffers = undefined; this._colorTextures = undefined; + this._ecTextures = undefined; this._depthTextures = undefined; this._drawCommands = undefined; this._blendCommand = undefined; @@ -59,6 +60,8 @@ define([ processor._depthTextures[1].destroy(); processor._colorTextures[0].destroy(); processor._colorTextures[1].destroy(); + processor._ecTextures[0].destroy(); + processor._ecTextures[1].destroy(); processor._framebuffers[0].destroy(); processor._framebuffers[1].destroy(); @@ -74,9 +77,13 @@ define([ var colorTextures = new Array(2); + var ecTextures = new Array(2); var depthTextures = new Array(2); var framebuffers = new Array(2); + if (!context.floatingPointTexture) + throw new DeveloperError('Context must support floating point textures!'); + for (i = 0; i < 2; ++i) { colorTextures[i] = new Texture({ context : context, @@ -87,6 +94,15 @@ define([ sampler : createSampler() }); + ecTextures[i] = new Texture({ + context : context, + width : screenWidth, + height : screenHeight, + pixelFormat : PixelFormat.RGBA, + pixelDatatype : PixelDatatype.FLOAT, + sampler : createSampler() + }); + depthTextures[i] = new Texture({ context : context, width : screenWidth, @@ -101,13 +117,14 @@ define([ framebuffers[i] = new Framebuffer({ context : context, depthStencilTexture : depthTextures[i], - colorTextures : [colorTextures[i]], + colorTextures : [colorTextures[i], ecTextures[i]], destroyAttachments : false }); } processor._depthTextures = depthTextures; processor._colorTextures = colorTextures; + processor._ecTextures = ecTextures; processor._framebuffers = framebuffers; } @@ -117,6 +134,10 @@ define([ // Use the other color texture as input return processor._colorTextures[1 - index]; }, + pointCloud_ecTexture : function() { + // Use the other color texture as input + return processor._ecTextures[1 - index]; + }, pointCloud_depthTexture : function() { return processor._depthTextures[1 - index]; } From 201a9d1b1578f9b6b6ac6f848e13e84077e998b6 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Mon, 12 Jun 2017 09:50:06 -0400 Subject: [PATCH 005/240] Modifies PointCloudPostProcessor so that it handles eye-space coordinates and uses the minimum number of color and depth textures --- Source/Scene/PointCloudPostProcessor.js | 275 +++++++++++++++--------- 1 file changed, 173 insertions(+), 102 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 17224454b645..0a62596e55dd 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -39,11 +39,11 @@ define([ function PointCloudPostProcessor() { this._framebuffers = undefined; this._colorTextures = undefined; - this._ecTextures = undefined; + this._ecTexture = undefined; this._depthTextures = undefined; this._drawCommands = undefined; this._blendCommand = undefined; - this._clearCommand = undefined; + this._clearCommands = undefined; } function createSampler() { @@ -60,8 +60,7 @@ define([ processor._depthTextures[1].destroy(); processor._colorTextures[0].destroy(); processor._colorTextures[1].destroy(); - processor._ecTextures[0].destroy(); - processor._ecTextures[1].destroy(); + processor._ecTexture.destroy(); processor._framebuffers[0].destroy(); processor._framebuffers[1].destroy(); @@ -75,33 +74,29 @@ define([ var screenWidth = context.drawingBufferWidth; var screenHeight = context.drawingBufferHeight; - var colorTextures = new Array(2); - var ecTextures = new Array(2); - var depthTextures = new Array(2); - var framebuffers = new Array(2); - - if (!context.floatingPointTexture) - throw new DeveloperError('Context must support floating point textures!'); - - for (i = 0; i < 2; ++i) { - colorTextures[i] = new Texture({ - context : context, - width : screenWidth, - height : screenHeight, - pixelFormat : PixelFormat.RGBA, - pixelDatatype : PixelDatatype.UNSIGNED_BYTE, - sampler : createSampler() - }); + var depthTextures = new Array(3); + + var ecTexture = new Texture({ + context : context, + width : screenWidth, + height : screenHeight, + pixelFormat : PixelFormat.RGBA, + pixelDatatype : PixelDatatype.FLOAT, + sampler : createSampler() + }); - ecTextures[i] = new Texture({ - context : context, - width : screenWidth, - height : screenHeight, - pixelFormat : PixelFormat.RGBA, - pixelDatatype : PixelDatatype.FLOAT, - sampler : createSampler() - }); + for (i = 0; i < 3; ++i) { + if (i < 2) { + colorTextures[i] = new Texture({ + context : context, + width : screenWidth, + height : screenHeight, + pixelFormat : PixelFormat.RGBA, + pixelDatatype : PixelDatatype.UNSIGNED_BYTE, + sampler : createSampler() + }); + } depthTextures[i] = new Texture({ context : context, @@ -111,48 +106,94 @@ define([ pixelDatatype : PixelDatatype.UNSIGNED_INT_24_8, sampler : createSampler() }); + } - // TODO : for now assume than any pass can write depth, possibly through EXT_frag_depth. - // Definitely needed for the initial render into the FBO, possibly also the ping-pong processing. - framebuffers[i] = new Framebuffer({ + /* We want to reuse textures as much as possible, so here's the order + * of events: + * + * 1. We render normally to our prior: + * * Color -> 0 + * * Depth -> 2 ("dirty depth") + * * EC -> 0 + * 2. Then we perform the screen-space point occlusion stage with color[0] and EC: + * * No color + * * Depth -> 0 + * * No EC + * 3a. Then we perform the region growing stage with color[0] and depth[0]: + * * Color -> 1 + * * Depth -> 1 + * 3b. We do the region growing stage again with color[1] and depth[1]: + * * Color -> 0 + * * Depth -> 0 + * 3c. Repeat steps 3a and 3b until all holes are filled and/or we run + * out of time. + */ + + processor._framebuffers = { + "prior": new Framebuffer({ context : context, - depthStencilTexture : depthTextures[i], - colorTextures : [colorTextures[i], ecTextures[i]], + colorTextures : [ + colorTextures[0], + ecTexture + ], + depthStencilTexture : depthTextures[2], destroyAttachments : false - }); - } - + }), + "screenSpacePass": new Framebuffer({ + context : context, + depthStencilTexture : depthTextures[0], + destroyAttachments : false + }), + "regionGrowingPassA": new Framebuffer({ + context : context, + depthStencilTexture : depthTextures[1], + colorTextures : [colorTextures[1]], + destroyAttachments : false + }), + "regionGrowingPassB": new Framebuffer({ + context: context, + depthStencilTexture: depthTextures[0], + colorTextures: [colorTextures[0]], + destroyAttachments: false + }) + }; processor._depthTextures = depthTextures; processor._colorTextures = colorTextures; - processor._ecTextures = ecTextures; - processor._framebuffers = framebuffers; + processor._ecTexture = ecTexture; } - function createUniformMap(processor, index) { - return { - pointCloud_colorTexture : function() { - // Use the other color texture as input - return processor._colorTextures[1 - index]; - }, - pointCloud_ecTexture : function() { - // Use the other color texture as input - return processor._ecTextures[1 - index]; + function pointOcclusionStage(processor, context) { + var pointOcclusionFS = + 'uniform sampler2D pointCloud_colorTexture; \n' + + 'uniform sampler2D pointCloud_ECTexture; \n' + + 'varying vec2 v_textureCoordinates; \n' + + 'void main() \n' + + '{ \n' + + ' vec4 color = texture2D(pointCloud_colorTexture, v_textureCoordinates); \n' + + ' vec4 EC = texture2D(pointCloud_ECTexture, v_textureCoordinates); \n' + + ' color.rgb = color.rgb * 0.5 + vec3(normalize(EC.xyz)) * 0.1; \n' + + ' gl_FragColor = color; \n' + + '} \n'; + + var uniformMap = { + pointCloud_colorTexture: function() { + return processor._colorTextures[0]; }, - pointCloud_depthTexture : function() { - return processor._depthTextures[1 - index]; + pointCloud_ECTexture: function() { + return processor._ecTexture; } }; + return context.createViewportQuadCommand(pointOcclusionFS, { + uniformMap : uniformMap, + framebuffer : processor._framebuffers.screenSpacePass, + renderState : RenderState.fromCache(), + pass : Pass.CESIUM_3D_TILE, + owner : processor + }); } - function createCommands(processor, context) { - var i; - var framebuffers = processor._framebuffers; - var uniformMaps = [ - createUniformMap(processor, 0), - createUniformMap(processor, 1) - ]; - - var stageFS = + function regionGrowingStage(processor, context, iteration) { + var regionGrowingFS = 'uniform sampler2D pointCloud_colorTexture; \n' + 'uniform sampler2D pointCloud_depthTexture; \n' + 'varying vec2 v_textureCoordinates; \n' + @@ -160,21 +201,43 @@ define([ '{ \n' + ' vec4 color = texture2D(pointCloud_colorTexture, v_textureCoordinates); \n' + ' float depth = texture2D(pointCloud_depthTexture, v_textureCoordinates).r; \n' + - ' color.rgb = color.rgb * 0.5 + vec3(depth) * 0.5; \n' + + ' color.rgb = color.rgb * 0.5 + vec3(depth) * 0.1; \n' + ' gl_FragColor = color; \n' + '} \n'; - // TODO : faking post-processing stages for testing - var stagesLength = 3; - var drawCommands = new Array(stagesLength); - for (i = 0; i < stagesLength; ++i) { - drawCommands[i] = context.createViewportQuadCommand(stageFS, { - uniformMap : uniformMaps[i % 2], - framebuffer : framebuffers[i % 2], - renderState : RenderState.fromCache(), - pass : Pass.CESIUM_3D_TILE, - owner : processor - }); + var i = iteration % 2; + + var uniformMap = { + pointCloud_colorTexture: function() { + return processor._colorTextures[i]; + }, + pointCloud_depthTexture: function() { + return processor._depthTextures[i]; + } + }; + + var framebuffer = (i === 0) ? + processor._framebuffers.regionGrowingPassA : + processor._framebuffers.regionGrowingPassB; + + return context.createViewportQuadCommand(regionGrowingFS, { + uniformMap : uniformMap, + framebuffer : framebuffer, + renderState : RenderState.fromCache(), + pass : Pass.CESIUM_3D_TILE, + owner : processor + }); + } + + function createCommands(processor, context) { + var numRegionGrowingPasses = 4; + var drawCommands = new Array(numRegionGrowingPasses + 1); + + var i; + drawCommands[0] = pointOcclusionStage(processor, context); + + for (i = 0; i < numRegionGrowingPasses; i++) { + drawCommands[i + 1] = regionGrowingStage(processor, context, i); } // TODO : point cloud depth information is lost @@ -191,49 +254,54 @@ define([ blending : BlendingState.ALPHA_BLEND }); + var blendUniformMap = { + pointCloud_colorTexture: function() { + return processor._colorTextures[1 - drawCommands.length % 2]; + }, + pointCloud_depthTexture: function() { + return processor._depthTextures[1 - drawCommands.length % 2]; + } + }; + var blendCommand = context.createViewportQuadCommand(blendFS, { - uniformMap : uniformMaps[stagesLength % 2], + uniformMap : blendUniformMap, renderState : blendRenderState, pass : Pass.CESIUM_3D_TILE, owner : processor }); - // TODO : may need to clear FBOs between each stage instead of just clearing the main FBO. - var clearCommand = new ClearCommand({ - framebuffer : framebuffers[1], - color : new Color(0.0, 0.0, 0.0, 0.0), - depth : 1.0, - renderState : RenderState.fromCache(), - pass : Pass.CESIUM_3D_TILE, - owner : processor - }); + var framebuffers = processor._framebuffers; + var clearCommands = new Array(4); + i = 0; + for (var name in framebuffers) { + if (framebuffers.hasOwnProperty(name)) { + clearCommands[i] = new ClearCommand({ + framebuffer : framebuffers[name], + color : new Color(0.0, 0.0, 0.0, 0.0), + depth : 1.0, + renderState : RenderState.fromCache(), + pass : Pass.CESIUM_3D_TILE, + owner : processor + }); + i++; + } + } processor._drawCommands = drawCommands; processor._blendCommand = blendCommand; - processor._clearCommand = clearCommand; - } - - function updateCommandFramebuffers(processor) { - var framebuffers = processor._framebuffers; - var drawCommands = processor._drawCommands; - var clearCommand = processor._clearCommand; - var length = drawCommands.length; - for (var i = 0; i < length; ++i) { - drawCommands[i].framebuffer = framebuffers[i % 2]; - } - clearCommand.framebuffer = framebuffers[1]; + processor._clearCommands = clearCommands; } function createResources(processor, context) { var screenWidth = context.drawingBufferWidth; var screenHeight = context.drawingBufferHeight; - var depthTextures = processor._depthTextures; + var colorTextures = processor._colorTextures; var drawCommands = processor._drawCommands; - var resized = defined(depthTextures) && - ((depthTextures[0].width !== screenWidth) || - (depthTextures[0].height !== screenHeight)); + var resized = defined(depthTextures[2]) && + ((depthTextures[2].width !== screenWidth) || + (depthTextures[2].height !== screenHeight)); - if (!defined(depthTextures)) { + if (!defined(colorTextures)) { createFramebuffers(processor, context); } @@ -243,8 +311,9 @@ define([ if (resized) { destroyFramebuffers(processor); - createFramebuffers(processor, context); - updateCommandFramebuffers(processor); + //createFramebuffers(processor, context); + //updateCommandFramebuffers(processor); + createCommands(processor, context); } } @@ -265,7 +334,7 @@ define([ var commandEnd = commandList.length; for (i = commandStart; i < commandEnd; ++i) { var command = commandList[i]; - command.framebuffer = this._framebuffers[1]; + command.framebuffer = this._framebuffers.prior; command.pass = Pass.CESIUM_3D_TILE; // Overrides translucent commands } @@ -280,7 +349,9 @@ define([ commandList.push(this._blendCommand); // TODO: technically should apply the clear sooner since the FBO's color texture is undefined on the first frame. Related to TODO above. This may also explain some black flashes during resizing. - commandList.push(this._clearCommand); + for (i = 0; i < this._clearCommands.length; ++i) { + commandList.push(this._clearCommands[i]); + } }; /** From 34247091f7bb4e80890de5317826b7467a0d528c Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Mon, 12 Jun 2017 09:54:56 -0400 Subject: [PATCH 006/240] Minor fixes --- Source/Scene/PointCloudPostProcessor.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 0a62596e55dd..f8c988cea83d 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -297,9 +297,9 @@ define([ var screenHeight = context.drawingBufferHeight; var colorTextures = processor._colorTextures; var drawCommands = processor._drawCommands; - var resized = defined(depthTextures[2]) && - ((depthTextures[2].width !== screenWidth) || - (depthTextures[2].height !== screenHeight)); + var resized = defined(colorTextures) && + ((colorTextures[0].width !== screenWidth) || + (colorTextures[0].height !== screenHeight)); if (!defined(colorTextures)) { createFramebuffers(processor, context); From 1642e54ed95c045ae5fff81d147ef542ac5f94f0 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Mon, 12 Jun 2017 14:28:35 -0400 Subject: [PATCH 007/240] Now tries to update previous shaders to forward their color output to the according framebuffer --- Source/Scene/PointCloudPostProcessor.js | 48 +++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index f8c988cea83d..7d28ca3d04d4 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -10,6 +10,8 @@ define([ '../Renderer/PixelDatatype', '../Renderer/RenderState', '../Renderer/Sampler', + '../Renderer/ShaderSource', + '../Renderer/ShaderProgram', '../Renderer/Texture', '../Renderer/TextureMagnificationFilter', '../Renderer/TextureMinificationFilter', @@ -26,6 +28,8 @@ define([ PixelDatatype, RenderState, Sampler, + ShaderSource, + ShaderProgram, Texture, TextureMagnificationFilter, TextureMinificationFilter, @@ -321,6 +325,49 @@ define([ return context.depthTexture; } + function forwardECForShaders(context, shaderProgram) { + var vsShader = shaderProgram.vertexShaderSource; + var fsShader = shaderProgram.fragmentShaderSource; + + var vsShaderDefines = vsShader.defines.slice(0); + var fsShaderDefines = fsShader.defines.slice(0); + + var vsShaderSources = vsShader.sources.slice(0); + var fsShaderSources = fsShader.sources.slice(0); + + var oldMainVS = ShaderSource.replaceMain(vsShaderSources[0], 'czm_point_cloud_post_process_main'); + var oldMainFS = ShaderSource.replaceMain(fsShaderSources[0], 'czm_point_cloud_post_process_main'); + + oldMainFS = oldMainFS.replace(new RegExp('gl_FragColor', 'g'), 'gl_FragData[0]'); + console.log(oldMainFS); + + var forwardVS = + 'varying vec3 v_positionECPS; \n' + + 'void main() \n' + + '{ \n' + + ' czm_point_cloud_post_process_main(); \n' + + ' v_positionECPS = (czm_inverseProjection * gl_Position).xyz; \n' + + '}'; + var forwardFS = + 'varying vec3 v_positionECPS; \n' + + 'void main() \n' + + '{ \n' + + ' czm_point_cloud_post_process_main(); \n' + + //' gl_FragData[0] = gl_FragColor;' + + ' gl_FragData[1] = v_positionECPS;' + + '}'; + + forwardVS = oldMainVS + forwardVS; + forwardFS = oldMainFS + forwardFS; + + return ShaderProgram.fromCache({ + vertexShaderSource : forwardVS, + fragmentShaderSource : forwardFS, + attributeLocations : shaderProgram._attributeLocations, + context : context + }); + } + PointCloudPostProcessor.prototype.update = function(frameState, commandStart) { if (!processingSupported(frameState.context)) { return; @@ -335,6 +382,7 @@ define([ for (i = commandStart; i < commandEnd; ++i) { var command = commandList[i]; command.framebuffer = this._framebuffers.prior; + command.shaderProgram = forwardECForShaders(frameState.context, command.shaderProgram); command.pass = Pass.CESIUM_3D_TILE; // Overrides translucent commands } From 3cbbbe0a8f0a78d91b5cf1bd7614145e889f10f6 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Mon, 19 Jun 2017 10:15:37 -0400 Subject: [PATCH 008/240] Now moves extensions to the top of the shader --- Source/Renderer/ShaderSource.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Source/Renderer/ShaderSource.js b/Source/Renderer/ShaderSource.js index 09a35221884a..9d8a9ff6fd0d 100644 --- a/Source/Renderer/ShaderSource.js +++ b/Source/Renderer/ShaderSource.js @@ -187,6 +187,17 @@ define([ return '\n'; }); + // Extract existing shader version from sources + var extensions = []; + combinedSources = combinedSources.replace(/#extension\s+(.*?)\n/gm, function(match, group1) { + // Extract extension to put at the top + extensions.push(match); + + // Replace original #extension directive with a new line so the line numbers + // are not off by one. + return '\n'; + }); + // Remove precision qualifier combinedSources = combinedSources.replace(/precision\s(lowp|mediump|highp)\s(float|int);/, ''); @@ -205,6 +216,10 @@ define([ result = '#version ' + version; } + for (i = 0; i < extensions.length; i++) { + result += extensions[i]; + } + if (isFragmentShader) { result += '\ #ifdef GL_FRAGMENT_PRECISION_HIGH\n\ From 8268a56ccf3429fd530e103d38720d8bf617a7da Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Mon, 19 Jun 2017 10:16:00 -0400 Subject: [PATCH 009/240] Not-so-functional existing (non-derived) post-processing framework --- Source/Scene/PointCloudPostProcessor.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 7d28ca3d04d4..25d2fab0d6e9 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -335,11 +335,12 @@ define([ var vsShaderSources = vsShader.sources.slice(0); var fsShaderSources = fsShader.sources.slice(0); + //fsShaderSources.splice(0, 0, '#extension GL_EXT_draw_buffers : enable \n'); + var oldMainVS = ShaderSource.replaceMain(vsShaderSources[0], 'czm_point_cloud_post_process_main'); var oldMainFS = ShaderSource.replaceMain(fsShaderSources[0], 'czm_point_cloud_post_process_main'); oldMainFS = oldMainFS.replace(new RegExp('gl_FragColor', 'g'), 'gl_FragData[0]'); - console.log(oldMainFS); var forwardVS = 'varying vec3 v_positionECPS; \n' + @@ -354,11 +355,14 @@ define([ '{ \n' + ' czm_point_cloud_post_process_main(); \n' + //' gl_FragData[0] = gl_FragColor;' + - ' gl_FragData[1] = v_positionECPS;' + + ' gl_FragData[1] = vec4(v_positionECPS, 0);' + '}'; forwardVS = oldMainVS + forwardVS; - forwardFS = oldMainFS + forwardFS; + forwardFS = '#extension GL_EXT_draw_buffers : enable \n' + + oldMainFS + forwardFS; + + console.log(forwardFS + "\n\n\n\n\n\n\nBLORG\n\n\n\n\n\n\n"); return ShaderProgram.fromCache({ vertexShaderSource : forwardVS, @@ -383,6 +387,8 @@ define([ var command = commandList[i]; command.framebuffer = this._framebuffers.prior; command.shaderProgram = forwardECForShaders(frameState.context, command.shaderProgram); + command.castShadows = false; + command.receiveShadows = false; command.pass = Pass.CESIUM_3D_TILE; // Overrides translucent commands } From 86fac01cd3f90091b02595bcf26cde1d7975f9ec Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Mon, 19 Jun 2017 10:42:57 -0400 Subject: [PATCH 010/240] Adds new derived command code --- Source/Scene/PointCloudPostProcessor.js | 60 ++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 25d2fab0d6e9..0d829373af38 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -325,6 +325,63 @@ define([ return context.depthTexture; } + function getECShaderProgram(context, shaderProgram) { + var shader = context.shaderCache.getDerivedShaderProgram(shaderProgram, 'EC'); + if (!defined(shader)) { + var attributeLocations = shaderProgram._attributeLocations; + + var vs = shaderProgram.vertexShaderSource.clone(); + var fs = shaderProgram.fragmentShaderSource.clone(); + + vs.sources = vs.sources.map(function(source) { + source = ShaderSource.replaceMain(source, 'czm_point_cloud_post_process_main'); + return source; + }); + + 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; + }); + + vs.sources.push( + 'varying vec3 v_positionECPS; \n' + + 'void main() \n' + + '{ \n' + + ' czm_point_cloud_post_process_main(); \n' + + ' v_positionECPS = (czm_inverseProjection * gl_Position).xyz; \n' + + '}'); + fs.sources.splice(0, 0, + '#extension GL_EXT_draw_buffers : enable \n'); + fs.sources.push( + 'varying vec3 v_positionECPS; \n' + + 'void main() \n' + + '{ \n' + + ' czm_point_cloud_post_process_main(); \n' + + //' gl_FragData[0] = gl_FragColor;' + + ' gl_FragData[1] = vec4(v_positionECPS, 0);' + + '}'); + + for (var i = 0; i < vs.sources.length; i++) { + console.log(vs.sources[i] + "\n\n\nORIGINAL:\n\n\n"); + console.log(shaderProgram.vertexShaderSource.sources[i] + "\n\n\n\n\n\n"); + } + + for (i = 0; i < fs.sources.length; i++) { + console.log(fs.sources[i] + "\n\n\nORIGINAL:\n\n\n"); + console.log(shaderProgram.fragmentShaderSource.sources[i] + "\n\n\n\n\n\n"); + } + + shader = context.shaderCache.createDerivedShaderProgram(shaderProgram, 'EC', { + vertexShaderSource : vs, + fragmentShaderSource : fs, + attributeLocations : attributeLocations + }); + } + + return shader; + } + function forwardECForShaders(context, shaderProgram) { var vsShader = shaderProgram.vertexShaderSource; var fsShader = shaderProgram.fragmentShaderSource; @@ -386,7 +443,8 @@ define([ for (i = commandStart; i < commandEnd; ++i) { var command = commandList[i]; command.framebuffer = this._framebuffers.prior; - command.shaderProgram = forwardECForShaders(frameState.context, command.shaderProgram); + //command.shaderProgram = forwardECForShaders(frameState.context, command.shaderProgram); + command.shaderProgram = getECShaderProgram(frameState.context, command.shaderProgram); command.castShadows = false; command.receiveShadows = false; command.pass = Pass.CESIUM_3D_TILE; // Overrides translucent commands From cef8a2aec0fcb98f5494d0e59072834e22b95581 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Mon, 19 Jun 2017 11:38:40 -0400 Subject: [PATCH 011/240] Clearing the framebuffers now happens in the correct order -- nothing is left dirty before use --- Source/Scene/PointCloudPostProcessor.js | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 0d829373af38..7c68aa01e1ef 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -275,11 +275,11 @@ define([ }); var framebuffers = processor._framebuffers; - var clearCommands = new Array(4); + var clearCommands = {}; i = 0; for (var name in framebuffers) { if (framebuffers.hasOwnProperty(name)) { - clearCommands[i] = new ClearCommand({ + clearCommands[name] = new ClearCommand({ framebuffer : framebuffers[name], color : new Color(0.0, 0.0, 0.0, 0.0), depth : 1.0, @@ -444,7 +444,7 @@ define([ var command = commandList[i]; command.framebuffer = this._framebuffers.prior; //command.shaderProgram = forwardECForShaders(frameState.context, command.shaderProgram); - command.shaderProgram = getECShaderProgram(frameState.context, command.shaderProgram); + //command.shaderProgram = getECShaderProgram(frameState.context, command.shaderProgram); command.castShadows = false; command.receiveShadows = false; command.pass = Pass.CESIUM_3D_TILE; // Overrides translucent commands @@ -452,18 +452,27 @@ define([ // Apply processing commands var drawCommands = this._drawCommands; + var clearCommands = this._clearCommands; var length = drawCommands.length; for (i = 0; i < length; ++i) { + // So before each draw call, we should clean up the dirty + // framebuffers that we left behind on the *previous* pass + if (i == 0) { + commandList.push(clearCommands['screenSpacePass']); + } else { + if (i % 2 == 1) + commandList.push(clearCommands['regionGrowingPassA']); + else + commandList.push(clearCommands['regionGrowingPassB']); + } + commandList.push(drawCommands[i]); } // Blend final result back into the main FBO commandList.push(this._blendCommand); - - // TODO: technically should apply the clear sooner since the FBO's color texture is undefined on the first frame. Related to TODO above. This may also explain some black flashes during resizing. - for (i = 0; i < this._clearCommands.length; ++i) { - commandList.push(this._clearCommands[i]); - } + + commandList.push(clearCommands['prior']); }; /** From 8e2d7caab7fa7dae9006f9bc5d0aca5ddf4e6dfa Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Mon, 19 Jun 2017 15:50:28 -0400 Subject: [PATCH 012/240] Now properly hands off data between stages --- Source/Scene/PointCloudPostProcessor.js | 91 ++++++++----------------- 1 file changed, 27 insertions(+), 64 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 7c68aa01e1ef..635525c79b0d 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -5,6 +5,7 @@ define([ '../Core/destroyObject', '../Core/PixelFormat', '../Renderer/ClearCommand', + '../Renderer/DrawCommand', '../Renderer/Framebuffer', '../Renderer/Pass', '../Renderer/PixelDatatype', @@ -23,6 +24,7 @@ define([ destroyObject, PixelFormat, ClearCommand, + DrawCommand, Framebuffer, Pass, PixelDatatype, @@ -168,6 +170,7 @@ define([ function pointOcclusionStage(processor, context) { var pointOcclusionFS = + '#extension GL_EXT_frag_depth : enable \n' + 'uniform sampler2D pointCloud_colorTexture; \n' + 'uniform sampler2D pointCloud_ECTexture; \n' + 'varying vec2 v_textureCoordinates; \n' + @@ -175,9 +178,8 @@ define([ '{ \n' + ' vec4 color = texture2D(pointCloud_colorTexture, v_textureCoordinates); \n' + ' vec4 EC = texture2D(pointCloud_ECTexture, v_textureCoordinates); \n' + - ' color.rgb = color.rgb * 0.5 + vec3(normalize(EC.xyz)) * 0.1; \n' + - ' gl_FragColor = color; \n' + - '} \n'; + ' gl_FragDepthEXT = 0.5; \n' + + '} \n'; // TODO: Fix gl_FragDepthEXT for WebGL2 var uniformMap = { pointCloud_colorTexture: function() { @@ -198,6 +200,7 @@ define([ function regionGrowingStage(processor, context, iteration) { var regionGrowingFS = + '#extension GL_EXT_frag_depth : enable \n' + 'uniform sampler2D pointCloud_colorTexture; \n' + 'uniform sampler2D pointCloud_depthTexture; \n' + 'varying vec2 v_textureCoordinates; \n' + @@ -205,8 +208,9 @@ define([ '{ \n' + ' vec4 color = texture2D(pointCloud_colorTexture, v_textureCoordinates); \n' + ' float depth = texture2D(pointCloud_depthTexture, v_textureCoordinates).r; \n' + - ' color.rgb = color.rgb * 0.5 + vec3(depth) * 0.1; \n' + - ' gl_FragColor = color; \n' + + ' vec3 newColor = color.rgb * 0.5; \n' + + ' gl_FragColor = vec4(newColor, color.a); \n' + + ' gl_FragDepthEXT = depth; \n' + '} \n'; var i = iteration % 2; @@ -276,7 +280,6 @@ define([ var framebuffers = processor._framebuffers; var clearCommands = {}; - i = 0; for (var name in framebuffers) { if (framebuffers.hasOwnProperty(name)) { clearCommands[name] = new ClearCommand({ @@ -287,7 +290,6 @@ define([ pass : Pass.CESIUM_3D_TILE, owner : processor }); - i++; } } @@ -352,7 +354,7 @@ define([ ' v_positionECPS = (czm_inverseProjection * gl_Position).xyz; \n' + '}'); fs.sources.splice(0, 0, - '#extension GL_EXT_draw_buffers : enable \n'); + '#extension GL_EXT_draw_buffers : enable \n'); fs.sources.push( 'varying vec3 v_positionECPS; \n' + 'void main() \n' + @@ -361,14 +363,15 @@ define([ //' gl_FragData[0] = gl_FragColor;' + ' gl_FragData[1] = vec4(v_positionECPS, 0);' + '}'); - + + console.log(context.fragmentDepth); for (var i = 0; i < vs.sources.length; i++) { - console.log(vs.sources[i] + "\n\n\nORIGINAL:\n\n\n"); + //console.log(vs.sources[i] + "\n\n\nORIGINAL:\n\n\n"); console.log(shaderProgram.vertexShaderSource.sources[i] + "\n\n\n\n\n\n"); } for (i = 0; i < fs.sources.length; i++) { - console.log(fs.sources[i] + "\n\n\nORIGINAL:\n\n\n"); + //console.log(fs.sources[i] + "\n\n\nORIGINAL:\n\n\n"); console.log(shaderProgram.fragmentShaderSource.sources[i] + "\n\n\n\n\n\n"); } @@ -382,53 +385,6 @@ define([ return shader; } - function forwardECForShaders(context, shaderProgram) { - var vsShader = shaderProgram.vertexShaderSource; - var fsShader = shaderProgram.fragmentShaderSource; - - var vsShaderDefines = vsShader.defines.slice(0); - var fsShaderDefines = fsShader.defines.slice(0); - - var vsShaderSources = vsShader.sources.slice(0); - var fsShaderSources = fsShader.sources.slice(0); - - //fsShaderSources.splice(0, 0, '#extension GL_EXT_draw_buffers : enable \n'); - - var oldMainVS = ShaderSource.replaceMain(vsShaderSources[0], 'czm_point_cloud_post_process_main'); - var oldMainFS = ShaderSource.replaceMain(fsShaderSources[0], 'czm_point_cloud_post_process_main'); - - oldMainFS = oldMainFS.replace(new RegExp('gl_FragColor', 'g'), 'gl_FragData[0]'); - - var forwardVS = - 'varying vec3 v_positionECPS; \n' + - 'void main() \n' + - '{ \n' + - ' czm_point_cloud_post_process_main(); \n' + - ' v_positionECPS = (czm_inverseProjection * gl_Position).xyz; \n' + - '}'; - var forwardFS = - 'varying vec3 v_positionECPS; \n' + - 'void main() \n' + - '{ \n' + - ' czm_point_cloud_post_process_main(); \n' + - //' gl_FragData[0] = gl_FragColor;' + - ' gl_FragData[1] = vec4(v_positionECPS, 0);' + - '}'; - - forwardVS = oldMainVS + forwardVS; - forwardFS = '#extension GL_EXT_draw_buffers : enable \n' + - oldMainFS + forwardFS; - - console.log(forwardFS + "\n\n\n\n\n\n\nBLORG\n\n\n\n\n\n\n"); - - return ShaderProgram.fromCache({ - vertexShaderSource : forwardVS, - fragmentShaderSource : forwardFS, - attributeLocations : shaderProgram._attributeLocations, - context : context - }); - } - PointCloudPostProcessor.prototype.update = function(frameState, commandStart) { if (!processingSupported(frameState.context)) { return; @@ -442,12 +398,19 @@ define([ var commandEnd = commandList.length; for (i = commandStart; i < commandEnd; ++i) { var command = commandList[i]; - command.framebuffer = this._framebuffers.prior; - //command.shaderProgram = forwardECForShaders(frameState.context, command.shaderProgram); - //command.shaderProgram = getECShaderProgram(frameState.context, command.shaderProgram); - command.castShadows = false; - command.receiveShadows = false; - command.pass = Pass.CESIUM_3D_TILE; // Overrides translucent commands + + var derivedCommand = command.derivedCommands.pointCloudProcessor; + if (!defined(derivedCommand)) { + derivedCommand = DrawCommand.shallowClone(command); + command.derivedCommands.pointCloudProcessor = derivedCommand; + + derivedCommand.framebuffer = this._framebuffers.prior; + derivedCommand.shaderProgram = getECShaderProgram(frameState.context, command.shaderProgram); + derivedCommand.castShadows = false; + derivedCommand.receiveShadows = false; + derivedCommand.pass = Pass.CESIUM_3D_TILE; // Overrides translucent commands + commandList[i] = derivedCommand; + } } // Apply processing commands From 7f4827b26e26f316d124613743936261e9142381 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Tue, 20 Jun 2017 14:06:30 -0400 Subject: [PATCH 013/240] Now correctly currying depth --- Source/Scene/PointCloudPostProcessor.js | 29 +++++++++++++++++-------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 635525c79b0d..b62e08742925 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -176,9 +176,11 @@ define([ 'varying vec2 v_textureCoordinates; \n' + 'void main() \n' + '{ \n' + + ' float near = czm_currentFrustum.x; \n' + + ' float far = czm_currentFrustum.y; \n' + ' vec4 color = texture2D(pointCloud_colorTexture, v_textureCoordinates); \n' + ' vec4 EC = texture2D(pointCloud_ECTexture, v_textureCoordinates); \n' + - ' gl_FragDepthEXT = 0.5; \n' + + ' gl_FragDepthEXT = (-EC.z - near) / (far - near); \n' + '} \n'; // TODO: Fix gl_FragDepthEXT for WebGL2 var uniformMap = { @@ -192,7 +194,12 @@ define([ return context.createViewportQuadCommand(pointOcclusionFS, { uniformMap : uniformMap, framebuffer : processor._framebuffers.screenSpacePass, - renderState : RenderState.fromCache(), + renderState : RenderState.fromCache({ + depthMask : true, + depthTest : { + enabled : true + } + }), pass : Pass.CESIUM_3D_TILE, owner : processor }); @@ -209,7 +216,7 @@ define([ ' vec4 color = texture2D(pointCloud_colorTexture, v_textureCoordinates); \n' + ' float depth = texture2D(pointCloud_depthTexture, v_textureCoordinates).r; \n' + ' vec3 newColor = color.rgb * 0.5; \n' + - ' gl_FragColor = vec4(newColor, color.a); \n' + + ' gl_FragColor = vec4(vec3(depth), color.a); \n' + ' gl_FragDepthEXT = depth; \n' + '} \n'; @@ -231,7 +238,12 @@ define([ return context.createViewportQuadCommand(regionGrowingFS, { uniformMap : uniformMap, framebuffer : framebuffer, - renderState : RenderState.fromCache(), + renderState : RenderState.fromCache({ + depthMask : true, + depthTest : { + enabled : true + } + }), pass : Pass.CESIUM_3D_TILE, owner : processor }); @@ -331,7 +343,7 @@ define([ var shader = context.shaderCache.getDerivedShaderProgram(shaderProgram, 'EC'); if (!defined(shader)) { var attributeLocations = shaderProgram._attributeLocations; - + var vs = shaderProgram.vertexShaderSource.clone(); var fs = shaderProgram.fragmentShaderSource.clone(); @@ -360,9 +372,8 @@ define([ 'void main() \n' + '{ \n' + ' czm_point_cloud_post_process_main(); \n' + - //' gl_FragData[0] = gl_FragColor;' + - ' gl_FragData[1] = vec4(v_positionECPS, 0);' + - '}'); + ' gl_FragData[1] = vec4(v_positionECPS, 0); \n' + + '}'); console.log(context.fragmentDepth); for (var i = 0; i < vs.sources.length; i++) { @@ -409,8 +420,8 @@ define([ derivedCommand.castShadows = false; derivedCommand.receiveShadows = false; derivedCommand.pass = Pass.CESIUM_3D_TILE; // Overrides translucent commands - commandList[i] = derivedCommand; } + commandList[i] = derivedCommand; } // Apply processing commands From 4adc68c02da197694d6455ffd95b05055eade572 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Tue, 20 Jun 2017 14:06:59 -0400 Subject: [PATCH 014/240] Temporarily reducing the number of frustra so that the depth values don't keep resetting --- Source/Scene/Scene.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Scene/Scene.js b/Source/Scene/Scene.js index ac4532665287..48098c1b70d4 100644 --- a/Source/Scene/Scene.js +++ b/Source/Scene/Scene.js @@ -436,7 +436,7 @@ define([ * @type {Number} * @default 1000.0 */ - this.farToNearRatio = 1000.0; + this.farToNearRatio = 1e8; /** * Determines the uniform depth size in meters of each frustum of the multifrustum in 2D. If a primitive or model close From 32810ec60527ebefb90f38a9583f0032581b728e Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Tue, 20 Jun 2017 15:42:07 -0400 Subject: [PATCH 015/240] Moves shaders into their own files --- Source/Scene/PointCloudPostProcessor.js | 40 ++++--------------- .../PointOcclusionPass.glsl | 21 ++++++++++ .../PostProcessFilters/RegionGrowingPass.glsl | 11 +++++ 3 files changed, 40 insertions(+), 32 deletions(-) create mode 100644 Source/Shaders/PostProcessFilters/PointOcclusionPass.glsl create mode 100644 Source/Shaders/PostProcessFilters/RegionGrowingPass.glsl diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index b62e08742925..cd469d15277e 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -17,7 +17,9 @@ define([ '../Renderer/TextureMagnificationFilter', '../Renderer/TextureMinificationFilter', '../Renderer/TextureWrap', - '../Scene/BlendingState' + '../Scene/BlendingState', + '../Shaders/PostProcessFilters/PointOcclusionPass', + '../Shaders/PostProcessFilters/RegionGrowingPass' ], function( Color, defined, @@ -36,7 +38,9 @@ define([ TextureMagnificationFilter, TextureMinificationFilter, TextureWrap, - BlendingState) { + BlendingState, + PointOcclusionPass, + RegionGrowingPass) { 'use strict'; /** @@ -169,20 +173,6 @@ define([ } function pointOcclusionStage(processor, context) { - var pointOcclusionFS = - '#extension GL_EXT_frag_depth : enable \n' + - 'uniform sampler2D pointCloud_colorTexture; \n' + - 'uniform sampler2D pointCloud_ECTexture; \n' + - 'varying vec2 v_textureCoordinates; \n' + - 'void main() \n' + - '{ \n' + - ' float near = czm_currentFrustum.x; \n' + - ' float far = czm_currentFrustum.y; \n' + - ' vec4 color = texture2D(pointCloud_colorTexture, v_textureCoordinates); \n' + - ' vec4 EC = texture2D(pointCloud_ECTexture, v_textureCoordinates); \n' + - ' gl_FragDepthEXT = (-EC.z - near) / (far - near); \n' + - '} \n'; // TODO: Fix gl_FragDepthEXT for WebGL2 - var uniformMap = { pointCloud_colorTexture: function() { return processor._colorTextures[0]; @@ -191,7 +181,7 @@ define([ return processor._ecTexture; } }; - return context.createViewportQuadCommand(pointOcclusionFS, { + return context.createViewportQuadCommand(PointOcclusionPass, { uniformMap : uniformMap, framebuffer : processor._framebuffers.screenSpacePass, renderState : RenderState.fromCache({ @@ -206,20 +196,6 @@ define([ } function regionGrowingStage(processor, context, iteration) { - var regionGrowingFS = - '#extension GL_EXT_frag_depth : enable \n' + - 'uniform sampler2D pointCloud_colorTexture; \n' + - 'uniform sampler2D pointCloud_depthTexture; \n' + - 'varying vec2 v_textureCoordinates; \n' + - 'void main() \n' + - '{ \n' + - ' vec4 color = texture2D(pointCloud_colorTexture, v_textureCoordinates); \n' + - ' float depth = texture2D(pointCloud_depthTexture, v_textureCoordinates).r; \n' + - ' vec3 newColor = color.rgb * 0.5; \n' + - ' gl_FragColor = vec4(vec3(depth), color.a); \n' + - ' gl_FragDepthEXT = depth; \n' + - '} \n'; - var i = iteration % 2; var uniformMap = { @@ -235,7 +211,7 @@ define([ processor._framebuffers.regionGrowingPassA : processor._framebuffers.regionGrowingPassB; - return context.createViewportQuadCommand(regionGrowingFS, { + return context.createViewportQuadCommand(RegionGrowingPass, { uniformMap : uniformMap, framebuffer : framebuffer, renderState : RenderState.fromCache({ diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPass.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPass.glsl new file mode 100644 index 000000000000..6eb406c66c8f --- /dev/null +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPass.glsl @@ -0,0 +1,21 @@ +#extension GL_EXT_frag_depth : enable +uniform sampler2D pointCloud_colorTexture; +uniform sampler2D pointCloud_ECTexture; +varying vec2 v_textureCoordinates; +void main() { + float near = czm_currentFrustum.x; + float far = czm_currentFrustum.y; + vec4 color = texture2D(pointCloud_colorTexture, v_textureCoordinates); + vec4 EC = texture2D(pointCloud_ECTexture, v_textureCoordinates); + + // If the EC of this pixel is zero, that means that it's not a valid + // pixel. We don't care about reprojecting it. + if (length(EC) == 0.) + discard; + + // We discard pixels here + + // This is the depth of this pixel... assuming that it's valid. + float linearizedDepth = (-EC.z - near) / (far - near); + gl_FragDepthEXT = linearizedDepth; +} diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPass.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPass.glsl new file mode 100644 index 000000000000..049f0ab7e8bc --- /dev/null +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPass.glsl @@ -0,0 +1,11 @@ +#extension GL_EXT_frag_depth : enable +uniform sampler2D pointCloud_colorTexture; +uniform sampler2D pointCloud_depthTexture; +varying vec2 v_textureCoordinates; +void main() { + vec4 color = texture2D(pointCloud_colorTexture, v_textureCoordinates); + float depth = texture2D(pointCloud_depthTexture, v_textureCoordinates).r; + vec3 newColor = color.rgb * 0.5; + gl_FragColor = vec4(vec3(depth), color.a); + gl_FragDepthEXT = depth; +} From 9394ccabb8145e243a9aa62594862231263a31c1 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Tue, 20 Jun 2017 17:08:09 -0400 Subject: [PATCH 016/240] Working point occlusion filter --- Source/Scene/PointCloudPostProcessor.js | 11 +- .../PointOcclusionPass.glsl | 183 +++++++++++++++++- 2 files changed, 186 insertions(+), 8 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index cd469d15277e..a7208d0e831e 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -174,11 +174,14 @@ define([ function pointOcclusionStage(processor, context) { var uniformMap = { - pointCloud_colorTexture: function() { + pointCloud_colorTexture : function() { return processor._colorTextures[0]; }, - pointCloud_ECTexture: function() { + pointCloud_ECTexture : function() { return processor._ecTexture; + }, + occlusionAngle : function() { + return 0.1; } }; return context.createViewportQuadCommand(PointOcclusionPass, { @@ -199,10 +202,10 @@ define([ var i = iteration % 2; var uniformMap = { - pointCloud_colorTexture: function() { + pointCloud_colorTexture : function() { return processor._colorTextures[i]; }, - pointCloud_depthTexture: function() { + pointCloud_depthTexture : function() { return processor._depthTextures[i]; } }; diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPass.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPass.glsl index 6eb406c66c8f..4a4d4e96055b 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPass.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPass.glsl @@ -1,21 +1,196 @@ #extension GL_EXT_frag_depth : enable + +#define TAU 6.28318530718 +#define PI 3.14159265359 +#define EPS 1e-6 +#define neighborhoodHalfWidth 4 // TUNABLE PARAMETER -- half-width of point-occlusion neighborhood +#define numSectors 8 + uniform sampler2D pointCloud_colorTexture; uniform sampler2D pointCloud_ECTexture; +uniform float occlusionAngle; varying vec2 v_textureCoordinates; + +float atan2(in float y, in float x) { + return x == 0.0 ? sign(y) * PI / 2.0 : atan(y, x); +} + +void modifySectorHistogram(in int index, + in float value, + inout vec4 shFirst, + inout vec4 shSecond) { + if (index == 0) + shFirst.x = value; + else if (index == 1) + shFirst.y = value; + else if (index == 2) + shFirst.z = value; + else if (index == 3) + shFirst.w = value; + else if (index == 4) + shSecond.x = value; + else if (index == 5) + shSecond.y = value; + else if (index == 6) + shSecond.z = value; + else if (index == 7) + shSecond.w = value; +} + +float readSectorHistogram(in int index, + in vec4 shFirst, + in vec4 shSecond) { + if (index == 0) + return shFirst.x; + else if (index == 1) + return shFirst.y; + else if (index == 2) + return shFirst.z; + else if (index == 3) + return shFirst.w; + else if (index == 4) + return shSecond.x; + else if (index == 5) + return shSecond.y; + else if (index == 6) + return shSecond.z; + else if (index == 7) + return shSecond.w; +} + +int getSector(in vec2 d) { + float angle = (atan2(float(d.y), float(d.x)) + PI) / TAU; + return int(angle * float(numSectors)); +} + +// Subsamples the neighbor pixel and stores the sector number +// in each component of the output +ivec4 getSectors(in vec2 vi) { + return ivec4(getSector(vi + vec2(-0.5, 0.5)), + getSector(vi + vec2(0.5, -0.5)), + getSector(vi + vec2(0.5, 0.5)), + getSector(vi + vec2(-0.5, -0.5))); +} + +ivec2 collapseSectors(in ivec4 sectors) { + int first = sectors[0]; + ivec2 collapsed = ivec2(first, first); + for (int i = 1; i < 4; i++) + if (sectors[i] != first) + collapsed.y = sectors[i]; + return collapsed; +} + void main() { float near = czm_currentFrustum.x; float far = czm_currentFrustum.y; + ivec2 pos = ivec2(int(gl_FragCoord.x), int(gl_FragCoord.y)); vec4 color = texture2D(pointCloud_colorTexture, v_textureCoordinates); - vec4 EC = texture2D(pointCloud_ECTexture, v_textureCoordinates); + //vec4 color = texture2D(pointCloud_colorTexture, gl_FragCoord.xy / czm_viewport.zw); + //vec4 EC = texture2D(pointCloud_ECTexture, gl_FragCoord.xy / czm_viewport.zw); + + // The position of this pixel in 3D (i.e the position of the point) + vec3 centerPosition = texture2D(pointCloud_ECTexture, v_textureCoordinates).xyz; // If the EC of this pixel is zero, that means that it's not a valid // pixel. We don't care about reprojecting it. - if (length(EC) == 0.) + if (length(centerPosition) == 0.) discard; - // We discard pixels here + + // We split our region of interest (the point of interest and its + // neighbors) + // into sectors. For the purposes of this shader, we have eight + // sectors. + // + // Each entry of sector_histogram contains the current best horizon + // pixel angle + ivec2 halfNeighborhood = ivec2(neighborhoodHalfWidth / 2, + neighborhoodHalfWidth / 2); + // Upper left corner of the neighborhood + ivec2 upperLeftCorner = pos - halfNeighborhood; + // Lower right corner of the neighborhood + ivec2 lowerRightCorner = pos + halfNeighborhood; + + // The widest the cone can be is 90 degrees + float maxAngle = PI / 2.0; + + vec4 shFirst = vec4(maxAngle); + vec4 shSecond = vec4(maxAngle); + + // Right now this is obvious because everything happens in eye space, + // but this kind of statement is nice for a reference implementation + vec3 viewer = vec3(0.0); + + for (int i = -neighborhoodHalfWidth; i <= neighborhoodHalfWidth; i++) { + for (int j = -neighborhoodHalfWidth; j <= neighborhoodHalfWidth; j++) { + // d is the relative offset from the horizon pixel to the center pixel + // in 2D + ivec2 d = ivec2(i, j); + ivec2 pI = pos + d; + + // We now calculate the actual 3D position of the horizon pixel (the horizon point) + vec3 neighborPosition = texture2D(pointCloud_ECTexture, + vec2(pI) / czm_viewport.zw).xyz; + + // If our horizon pixel doesn't exist, ignore it and move on + if (length(neighborPosition) < EPS || pI == pos) { + continue; + } + + // sectors contains both possible sectors that the + // neighbor pixel could be in + ivec2 sectors = collapseSectors(getSectors(vec2(d))); + + // This is the offset of the horizon point from the center in 3D + // (a 3D analog of d) + vec3 c = neighborPosition - centerPosition; + + // Now we calculate the dot product between the vector + // from the viewer to the center and the vector to the horizon pixel. + // We normalize both vectors first because we only care about their relative + // directions + // TODO: Redo the math and figure out whether the result should be negated or not + float dotProduct = dot(normalize(viewer - centerPosition), + normalize(c)); + + // We calculate the angle that this horizon pixel would make + // in the cone. The dot product is be equal to + // |vec_1| * |vec_2| * cos(angle_between), and in this case, + // the magnitude of both vectors is 1 because they are both + // normalized. + float angle = acos(dotProduct); + + // This horizon point is behind the current point. That means that it can't + // occlude the current point. So we ignore it and move on. + if (angle > maxAngle) + continue; + // If we've found a horizon pixel, store it in the histogram + if (readSectorHistogram(sectors.x, shFirst, shSecond) > angle) { + modifySectorHistogram(sectors.x, angle, shFirst, shSecond); + } + if (readSectorHistogram(sectors.y, shFirst, shSecond) > angle) { + modifySectorHistogram(sectors.y, angle, shFirst, shSecond); + } + } + } + + float accumulator = 0.0; + for (int i = 0; i < numSectors; i++) { + float angle = readSectorHistogram(i, shFirst, shSecond); + // If the z component is less than zero, + // that means that there is no valid horizon pixel + if (angle <= 0.0 || angle > maxAngle) + angle = maxAngle; + accumulator += angle; + } + + // The solid angle is too small, so we occlude this point + if (accumulator < (2.0 * PI) * (1.0 - occlusionAngle)) { + discard; + } // This is the depth of this pixel... assuming that it's valid. - float linearizedDepth = (-EC.z - near) / (far - near); + float linearizedDepth = (-centerPosition.z - near) / (far - near); gl_FragDepthEXT = linearizedDepth; } From f77cb8b66cb588d9684288cc111c762b6944b663 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 21 Jun 2017 11:06:32 -0400 Subject: [PATCH 017/240] Fixes resizing/destroy issues and takes options now --- Source/Scene/Cesium3DTileset.js | 19 ++++++++++- Source/Scene/PointCloudPostProcessor.js | 43 +++++++++++++------------ 2 files changed, 40 insertions(+), 22 deletions(-) diff --git a/Source/Scene/Cesium3DTileset.js b/Source/Scene/Cesium3DTileset.js index 84760e0f9250..a7349bcbe743 100644 --- a/Source/Scene/Cesium3DTileset.js +++ b/Source/Scene/Cesium3DTileset.js @@ -720,6 +720,20 @@ define([ */ this.debugShowMemoryUsage = defaultValue(options.debugShowMemoryUsage, false); + /** + * This property handles options for the point cloud post processor + *

+ * TODO: Write documentation for these properties + *

+ * + * @type {Event} + * @default {enabled : true, occlusionAngle : 0.1} + */ + this.pointCloudPostProcessorOptions = { + enabled : defaultValue(options.enabled, true), + occlusionAngle : defaultValue(options.occlusionAngle, 0.1) + }; + var that = this; // We don't know the distance of the tileset until tileset.json is loaded, so use the default distance for now @@ -1596,7 +1610,10 @@ define([ // TODO : only do this if the tileset is purely point clouds. // TODO : this may not work well if point cloud spans multiple frustums // TODO : make the processor a static class so it can be used by multiple tilesets? - tileset._pointCloudPostProcessor.update(frameState, numberOfInitialCommands); + tileset._pointCloudPostProcessor.update(frameState, numberOfInitialCommands, { + enabled : tileset.pointCloudPostProcessorOptions.enabled, + occlusionAngle : tileset.pointCloudPostProcessorOptions.occlusionAngle + }); } if (tileset.debugShowGeometricError || tileset.debugShowRenderingStatistics || tileset.debugShowMemoryUsage) { diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index a7208d0e831e..abef8286a20b 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -54,6 +54,8 @@ define([ this._drawCommands = undefined; this._blendCommand = undefined; this._clearCommands = undefined; + + this.occlusionAngle = 0.1; } function createSampler() { @@ -71,8 +73,12 @@ define([ processor._colorTextures[0].destroy(); processor._colorTextures[1].destroy(); processor._ecTexture.destroy(); - processor._framebuffers[0].destroy(); - processor._framebuffers[1].destroy(); + var framebuffers = processor._framebuffers; + for (var name in framebuffers) { + if (framebuffers.hasOwnProperty(name)) { + framebuffers[name].destroy(); + } + } processor._depthTextures = undefined; processor._colorTextures = undefined; @@ -181,7 +187,7 @@ define([ return processor._ecTexture; }, occlusionAngle : function() { - return 0.1; + return processor.occlusionAngle; } }; return context.createViewportQuadCommand(PointOcclusionPass, { @@ -289,7 +295,7 @@ define([ processor._clearCommands = clearCommands; } - function createResources(processor, context) { + function createResources(processor, context, dirty) { var screenWidth = context.drawingBufferWidth; var screenHeight = context.drawingBufferHeight; var colorTextures = processor._colorTextures; @@ -302,14 +308,13 @@ define([ createFramebuffers(processor, context); } - if (!defined(drawCommands)) { + if (!defined(drawCommands) || dirty) { createCommands(processor, context); } if (resized) { destroyFramebuffers(processor); - //createFramebuffers(processor, context); - //updateCommandFramebuffers(processor); + createFramebuffers(processor, context); createCommands(processor, context); } } @@ -354,17 +359,6 @@ define([ ' gl_FragData[1] = vec4(v_positionECPS, 0); \n' + '}'); - console.log(context.fragmentDepth); - for (var i = 0; i < vs.sources.length; i++) { - //console.log(vs.sources[i] + "\n\n\nORIGINAL:\n\n\n"); - console.log(shaderProgram.vertexShaderSource.sources[i] + "\n\n\n\n\n\n"); - } - - for (i = 0; i < fs.sources.length; i++) { - //console.log(fs.sources[i] + "\n\n\nORIGINAL:\n\n\n"); - console.log(shaderProgram.fragmentShaderSource.sources[i] + "\n\n\n\n\n\n"); - } - shader = context.shaderCache.createDerivedShaderProgram(shaderProgram, 'EC', { vertexShaderSource : vs, fragmentShaderSource : fs, @@ -375,12 +369,19 @@ define([ return shader; } - PointCloudPostProcessor.prototype.update = function(frameState, commandStart) { + PointCloudPostProcessor.prototype.update = function(frameState, commandStart, options) { if (!processingSupported(frameState.context)) { return; } - createResources(this, frameState.context); + var dirty = false; + // Set options here + if (options.occlusionAngle != this.occlusionAngle) { + this.occlusionAngle = options.occlusionAngle; + dirty = true; + } + + createResources(this, frameState.context, dirty); // Render point cloud commands into an offscreen FBO. var i; @@ -390,7 +391,7 @@ define([ var command = commandList[i]; var derivedCommand = command.derivedCommands.pointCloudProcessor; - if (!defined(derivedCommand)) { + if (!defined(derivedCommand) || command.dirty) { derivedCommand = DrawCommand.shallowClone(command); command.derivedCommands.pointCloudProcessor = derivedCommand; From 3c9bf841feca48a27ad7b264ae2a8c56c9fc38b2 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 21 Jun 2017 11:06:45 -0400 Subject: [PATCH 018/240] Now drawing color point cloud --- Source/Shaders/PostProcessFilters/RegionGrowingPass.glsl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPass.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPass.glsl index 049f0ab7e8bc..06ac8ee6ecc5 100644 --- a/Source/Shaders/PostProcessFilters/RegionGrowingPass.glsl +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPass.glsl @@ -5,7 +5,7 @@ varying vec2 v_textureCoordinates; void main() { vec4 color = texture2D(pointCloud_colorTexture, v_textureCoordinates); float depth = texture2D(pointCloud_depthTexture, v_textureCoordinates).r; - vec3 newColor = color.rgb * 0.5; - gl_FragColor = vec4(vec3(depth), color.a); + vec3 newColor = color.rgb; + gl_FragColor = vec4(newColor, color.a); gl_FragDepthEXT = depth; } From d36c8ffc6324fbe4c67f15e7cbb43c9435ceab5e Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 21 Jun 2017 11:16:50 -0400 Subject: [PATCH 019/240] Adds enabled property --- Source/Scene/PointCloudPostProcessor.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index abef8286a20b..7d91e2c69baa 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -380,6 +380,10 @@ define([ this.occlusionAngle = options.occlusionAngle; dirty = true; } + + if (!options.enabled) { + return; + } createResources(this, frameState.context, dirty); @@ -401,6 +405,7 @@ define([ derivedCommand.receiveShadows = false; derivedCommand.pass = Pass.CESIUM_3D_TILE; // Overrides translucent commands } + commandList[i] = derivedCommand; } From b5fd034b6ed7020b5d0678aaab0b33df068f035f Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 21 Jun 2017 11:27:15 -0400 Subject: [PATCH 020/240] Adds new Sandcastle demo for point cloud post processing --- .../3D Tiles Point Cloud Post Processing.html | 104 ++++++++++++++++++ .../3D Tiles Point Cloud Post Processing.jpg | Bin 0 -> 4946 bytes 2 files changed, 104 insertions(+) create mode 100644 Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html create mode 100644 Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.jpg diff --git a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html new file mode 100644 index 000000000000..3749ec9d0d44 --- /dev/null +++ b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html @@ -0,0 +1,104 @@ + + + + + + + + + Cesium Demo + + + + + + +
+

Loading...

+
+ + + + + + +
Occlusion Angle + + +
+
+ + + diff --git a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.jpg b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f4deeb0976a904889e26cebbcdab615fc1aec145 GIT binary patch literal 4946 zcmb7H2{e>%+kc)}>@>rWJ%bp#u_gW(gRw6|Swo2=%Vd|bjARR0B72r>5!sb2V@c?r ztx^femL*$ADc&jn-t(UGedjyxcR%;J&vSnF?|RO4U)O#A?&~>tbMOH`7!dRc00@GB z9`ykZ#sMt=3W5CU)CQw=I2{}ggTWbSX=&(~7?_wC85kLvSy&OwEJzkcMg#`}$%bNQ zXJI+$%D}W_{CUY9#^JRo^lF5 z_3FS$rr&*9N3b4WA~HUnHlwmJeKYF{^rJ7X|MVoS0(F1Op#eJ zqb1(J*fWQxi9Qqe8-(AnjkVOS3ve~R@cyk!&moanWHnXUzVCM9XQz3i*M~%~ctq;C z{t2%VUvs-l4uJx{nNaV?-D#eR{;~aycf>}o)g}Ex?*XXA3&-z?dAta;u64coJp4Bm z@UNZAc79-(@v2Vj!uFu-FAy#OEF~FA)j|x8KVCRw{nsNcHO|5a076YJ6rhInuz?UH zfX1>4%Hg1zcs7BvLe!wsQF8>sA^T3ldj!hmLR>2YQK8U)UR+U**>u#_c1yWDP77vr zD{IboRF1X~E!cV5(ywwX#!$pcO-`X4@i;(-Fyxfx9F(n9mRFcyw=lEt^8lbOTnGt(FbD_-pnu{80th4;r-_BI3J}koz3lya-B1wJ0DnaA zA5Rd9hh=DXB~R#0Vg$-8o0#pqs>F<>gL=lNZg?JPE_U1B<3{JSqI6{M^ZRbgYHd^;Xyw6`kEq)~GFyZ4;l!JD9 z_)&pYpN{857iZ}YSo*`zibcVC)2AMHl|d*i-x&qO`NO%sr<%a*lYF)kHXIek=Y z)rahyDQ&fu1mR8Bf4L=#06-`N4uL`G|7;hk zTUa7Q^PD#sfn$}!4+|z!1kBG~jwq;^UjJw7&}cw@$f{4aJP0K06~?LBdk381eG7)z zfW85r<>nN8hlV+6{iXVAQ9n=F__Xes#!i$G?4fP3qu))EYOn%kwLO+@E*V@8{d1W) z&U+0dSoiP05@}cp)!VB++H=gWMprX*h;ah0>5_svwNN5y8YS(5a)T<nG=SA4p2K-37p#+OC<3y>(;NR}pL!@Y z&<8+AWPU#F|>&NSCEq5a(mrO_np=G;I?SV_ud(Ta+&xRbE$*Iv7cH+Ag)G4w?DVG(Oq^(H$uqmpVu2MR9;(2*V zfQebreZsz_5uSC5m^@Ch>$eurx$!B4f3gIgHhLxCp5?~kt8e9$A-8wR>*v&J=IF1R zafuFTJ1|I^S71o~xfIhnO1K+Y zU{LCqa-WFdEX&sU5o{&l!y}>KcC(~v+?!Gq;vTdk*;h#WO*ubc4}^QmQ@h}t;oqT`Iwy|M2T81hZ7XKfSuM=cknEuaf@?z zPpnej8AT<0&eARXkrEGjP*s#)o4}|YuCS$IG&PP$%G>nKMyD*Kx3%mp+`h+a@l)ON z>3z*tiXrX6oEcT^#ag~ES=RZ&Q;hT%BIsB$dnMV>E-W``_>^ouC!3Ru+SNH@a=T>M z7hhOO@R@)kdV%e!Ne$74v2}D0;sWQUMFj*@J{Yk((L8DOaY6KFc23C2%YSJkbia&Q z+8ipmmnif-CkvF=ahy>BpQTp(a4uyHcw84}j^HzI51CqA^na(GzVxk&vZgyRmS<lEA3N>LuUqQ$4M22rOlE=GU)u?3W(TYld5@&OPYM%9_$b-`~j zN2KTr|KFWeUr1}PVDpfsxkp2EKIG?ENLBY8+S1?~LJz@Ivm4g*hoIn-_rc{==h!T)*`rOJXBk}3-z z6r}y53cqgytmZlqN7dZ|$}}RmX84aP{JOFb2Y^OBYuSf|BW3jlr^<$1E!?MCz7$kM zSYuxV;}gzVpre3)1-pSFj zy+MNgR(W8NBXc<2a!o@dGB_xmmXc>H9(=* z3v#O5B_=-;A`Q~A}re&Y%HxFJ?EI8j#MjHuG3n!a1~FwMvh3auGoq%OX@mY z>yQeJxY;-=v$9|*~NhfH5WFO4ux8hd=f#kdN2Ch9zPqTb#&owlN%im;B z;f&y{Z0E13JXK^$m{9O4(QVOT&WKBNHDJ2=gDo%T@Xjx!Ajx!F)#Hs3Uq;N% zUV_(a+Xo9eh(xLA4>r2^tR=XQvCp`Kb!bpG0ft&QLm&Vg_V1#AT1um_nmFP)@;V~9 zfZ|CH#UV@iYH1{tREFgTv5`${O|0)+%xyLQ#kbHZl{1t%{@ zrndylc~J=QusDNBdEnC zvVZiZRxSAG+tvUpW>*{Q4cDrWr~depjY{?tgC_Ia#1UmYQP9 zKULN5Q~s0_;#sy8Ik>!kE{IP@yJPj!%VlK|LI-UmZDZT9G3dK|RN~C|2htP_p^b_N zoVxO1`Zyno%soD7?iyCbj~0WAw0?~M@270Vl9_E`SzpKOTe)*+aLFUG?^UinRy-*= z?8FG~pgE1dqB`sDplkI0)*Y6q?vQYX`bbuj;nyLzXHz)fkM%=$S&EolVhTmn}NIl!z z9KbTY&u^u-cwOSjxW$v#r&SlRyN=y0dJ2`4A^WoTAw&G2IhkB~S0+?h z(F1;=r&-YZxgj~jl`9=g*bru>tLtwYLO5^Lh^dF^VYGOeg4GsuGuKtD*=xj@Y|3XU z#;&PY0bG9LPWdle0}N5RG#-Qe2LQ7UhG_6N?noLm-P}4canFm?TjjiTZIqPLre?~2 zMS0!j6V$*pWtfP0ks$S6D_PngLv=PM>Qa6Qob3^hU$g$gQ7-UP)ZAi8Y5d}x0Y|bC z;~5=2tTuny^Vc`t9St_M+q|5ue)TQDqfHKJ#^>{x5kwnK49`V+{7`j~ZP=B8DWOa? zA8lAAv14)J+!9J--?lqhrpX_!)_I2AJ<|g7XDqlm8N5Du=H8ZpWSk@HFT1(<^pYgm z^DgXL%TA*&sjDfUeQ4s@?%GZa zJF7EL?p48wySgZ1g`(lEwuW3v5T5bbBWf|sO08zj-`%`t%N^;Ia(89_0Eo?trKfAP zKLDzL=gt*P>}_HTSyDhFMqbOL?Ro1L=TAqtFR~Q_#AsDH0^@1DsgpiC-d1n*kE#TB z3b22E?IUG}LqCLVuBZkp^#rZ9(7!Qd3+&5SPh%A^DW(x0jwy4X?ptfRDlzt~u`~fku=zEw{m1 zqZbK77Y<+~;*#}5iavUKjhC_CA1Mttz7;zFnX-V1>UJ(^$lYW_<`X}KRh1h)(H%QN zE-F0dcqOJg^4>!*e?`>o0Okr_hRq61UPwj?9AM;N6LEfj@Y z(va Date: Thu, 22 Jun 2017 13:58:57 -0400 Subject: [PATCH 021/240] Sandcastle demo now includes even more options --- .../3D Tiles Point Cloud Post Processing.html | 32 +++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html index 3749ec9d0d44..a8ce046043c6 100644 --- a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html +++ b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html @@ -31,7 +31,28 @@ - + + + Point Occlusion Filter Size + + + + + + + Region Growing Iterations + + + + + + + Region Growing Range Parameter + + + + + @@ -45,6 +66,7 @@ }); viewer.extend(Cesium.viewerCesium3DTilesInspectorMixin); var inspectorViewModel = viewer.cesium3DTilesInspector.viewModel; +inspectorViewModel.picking = false; viewer.clock.currentTime = new Cesium.JulianDate(2457522.154792); @@ -67,7 +89,10 @@ tileset.style = new Cesium.Cesium3DTileStyle(style); var viewModel = { - occlusionAngle: 0.1, + occlusionAngle: tileset.pointCloudPostProcessorOptions.occlusionAngle, + rangeParameter: tileset.pointCloudPostProcessorOptions.rangeParameter, + numRegionGrowingPasses: tileset.pointCloudPostProcessorOptions.numRegionGrowingPasses, + neighborhoodHalfWidth: tileset.pointCloudPostProcessorOptions.neighborhoodHalfWidth, }; Cesium.knockout.track(viewModel); @@ -84,6 +109,9 @@ } subscribeParameter('occlusionAngle'); +subscribeParameter('rangeParameter'); +subscribeParameter('neighborhoodHalfWidth'); +subscribeParameter('numRegionGrowingPasses'); Sandcastle.addToggleButton('Enabled', true, function(checked) { tileset.pointCloudPostProcessorOptions['enabled'] = checked; From 197b54c9258fb1bd89dae7ad3d525d1b95d63964 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Thu, 22 Jun 2017 14:03:01 -0400 Subject: [PATCH 022/240] Adds region growing pass --- .../PostProcessFilters/RegionGrowingPass.glsl | 152 +++++++++++++++++- 1 file changed, 149 insertions(+), 3 deletions(-) diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPass.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPass.glsl index 06ac8ee6ecc5..d17f00df6ebd 100644 --- a/Source/Shaders/PostProcessFilters/RegionGrowingPass.glsl +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPass.glsl @@ -1,11 +1,157 @@ #extension GL_EXT_frag_depth : enable + +#define neighborhoodHalfWidth 1 // TUNABLE PARAMETER -- half-width of region-growing kernel +#define neighborhoodFullWidth 3 +#define neighborhoodSize 8 +#define EPS 1e-6 + uniform sampler2D pointCloud_colorTexture; uniform sampler2D pointCloud_depthTexture; +uniform float rangeParameter; + varying vec2 v_textureCoordinates; + +#define otherswap(a, b, aC, bC) if (a > b) { temp = a; a = b; b = temp; tempColor = aC; aC = bC; bC = tempColor; } + +void comparisonNetwork8(inout float[neighborhoodSize] neighbors, + inout vec4[neighborhoodSize] neighborsColor) { + float temp; + vec4 tempColor; + + otherswap(neighbors[0], neighbors[1], neighborsColor[0], neighborsColor[1]); + otherswap(neighbors[2], neighbors[3], neighborsColor[2], neighborsColor[3]); + otherswap(neighbors[0], neighbors[2], neighborsColor[0], neighborsColor[2]); + otherswap(neighbors[1], neighbors[3], neighborsColor[1], neighborsColor[3]); + otherswap(neighbors[1], neighbors[2], neighborsColor[1], neighborsColor[2]); + otherswap(neighbors[4], neighbors[5], neighborsColor[4], neighborsColor[5]); + otherswap(neighbors[6], neighbors[7], neighborsColor[6], neighborsColor[7]); + otherswap(neighbors[4], neighbors[6], neighborsColor[4], neighborsColor[6]); + otherswap(neighbors[5], neighbors[7], neighborsColor[5], neighborsColor[7]); + otherswap(neighbors[5], neighbors[6], neighborsColor[5], neighborsColor[6]); + otherswap(neighbors[0], neighbors[4], neighborsColor[0], neighborsColor[4]); + otherswap(neighbors[1], neighbors[5], neighborsColor[1], neighborsColor[5]); + otherswap(neighbors[1], neighbors[4], neighborsColor[1], neighborsColor[4]); + otherswap(neighbors[2], neighbors[6], neighborsColor[2], neighborsColor[6]); + otherswap(neighbors[3], neighbors[7], neighborsColor[3], neighborsColor[7]); + otherswap(neighbors[3], neighbors[6], neighborsColor[3], neighborsColor[6]); + otherswap(neighbors[2], neighbors[4], neighborsColor[2], neighborsColor[4]); + otherswap(neighbors[3], neighbors[5], neighborsColor[3], neighborsColor[5]); + otherswap(neighbors[3], neighbors[4], neighborsColor[3], neighborsColor[4]); +} + +// NOTE: This can be sped up a lot by replacing the depth +// primitive array with two vec4s and using swizzle operations! +// (assuming that the neighborhood is exactly 3x3) +void fastMedianFinder(in float[neighborhoodSize] neighbors, + in vec4[neighborhoodSize] colorNeighbors, + out float outDepth, + out vec4 outColor) { + /*for (int i = 0; i < neighborhoodSize; i++) { + float key = neighbors[i]; + int modifiedFlag = 0; + + for (int c = neighborhoodSize - 1; c >= 0; c--) { + if (c > i - 1) + continue; + + if (neighbors[c] <= key) { + neighbors[c + 1] = key; + modifiedFlag = 1; + break; + } + neighbors[c + 1] = neighbors[c]; + } + if (modifiedFlag == 0) + neighbors[0] = key; + }*/ + comparisonNetwork8(neighbors, colorNeighbors); + + for (int i = neighborhoodSize - 1; i >= 0; i--) { + if (neighbors[i] <= 1.0 - EPS) { + outDepth = neighbors[i / 2]; + outColor = colorNeighbors[i / 2]; + //outColor = vec4(1, 0, 0, 1); + return; + } + } + + outDepth = 0.0; + outColor = vec4(0, 0, 0, 0); +} + void main() { vec4 color = texture2D(pointCloud_colorTexture, v_textureCoordinates); float depth = texture2D(pointCloud_depthTexture, v_textureCoordinates).r; - vec3 newColor = color.rgb; - gl_FragColor = vec4(newColor, color.a); - gl_FragDepthEXT = depth; + + vec4 finalColor = color; + float finalDepth = depth; + + // If our depth value is invalid + if (depth > 1.0 - EPS) { + float depthNeighbors[neighborhoodSize]; + vec4 colorNeighbors[neighborhoodSize]; + + int pastCenter = 0; + for (int j = -neighborhoodHalfWidth; j <= neighborhoodHalfWidth; j++) { + for (int i = -neighborhoodHalfWidth; i <= neighborhoodHalfWidth; i++) { + ivec2 d = ivec2(i, j); + if (d == ivec2(0, 0)) { + pastCenter = 1; + continue; + } + vec2 neighborCoords = vec2(vec2(d) + gl_FragCoord.xy) / czm_viewport.zw; + float neighbor = texture2D(pointCloud_depthTexture, neighborCoords).r; + vec4 colorNeighbor = texture2D(pointCloud_colorTexture, neighborCoords); + if (pastCenter == 1) { + depthNeighbors[(j + 1) * neighborhoodFullWidth + i] = + neighbor; + colorNeighbors[(j + 1) * neighborhoodFullWidth + i] = + colorNeighbor; + } else { + depthNeighbors[(j + 1) * neighborhoodFullWidth + i + 1] = + neighbor; + colorNeighbors[(j + 1) * neighborhoodFullWidth + i + 1] = + colorNeighbor; + } + } + } + + fastMedianFinder(depthNeighbors, colorNeighbors, finalDepth, finalColor); + } + // Otherwise if our depth value is valid + else { + float depthAccum = 0.0; + vec4 colorAccum = vec4(0); + float normalization = 0.0; + + for (int j = -neighborhoodHalfWidth; j <= neighborhoodHalfWidth; j++) { + for (int i = -neighborhoodHalfWidth; i <= neighborhoodHalfWidth; i++) { + ivec2 d = ivec2(i, j); + + // Does this even make sense? + /*if (d == ivec2(0, 0)) { + continue; + }*/ + + float rI = sqrt(float(d.x * d.x + d.y * d.y)); + + vec2 neighborCoords = vec2(vec2(d) + gl_FragCoord.xy) / czm_viewport.zw; + float neighbor = texture2D(pointCloud_depthTexture, neighborCoords).r; + vec4 colorNeighbor = texture2D(pointCloud_colorTexture, neighborCoords); + + float depthDelta = abs(neighbor - depth); + + float weight = (1.0 - rI / 2.0) * (1.0 - min(1.0, depthDelta / max(1e-5, rangeParameter))); + depthAccum += weight * neighbor; + colorAccum += weight * colorNeighbor; + normalization += weight; + } + } + + finalDepth = depthAccum / normalization; + finalColor = colorAccum / normalization; + } + + gl_FragColor = finalColor; + gl_FragDepthEXT = finalDepth; } From 3db09935f75c43c2a1b349eb69a41c975571f17d Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Thu, 22 Jun 2017 14:03:18 -0400 Subject: [PATCH 023/240] Adds more configurable parameters to PointCloudPostProcessor --- Source/Scene/Cesium3DTileset.js | 15 ++++++++--- Source/Scene/PointCloudPostProcessor.js | 36 ++++++++++++++++++++----- 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/Source/Scene/Cesium3DTileset.js b/Source/Scene/Cesium3DTileset.js index a7349bcbe743..ea5fb1ae480a 100644 --- a/Source/Scene/Cesium3DTileset.js +++ b/Source/Scene/Cesium3DTileset.js @@ -207,7 +207,6 @@ define([ }); this._backfaceCommands = new ManagedArray(); - this._pointCloudPostProcessor = new PointCloudPostProcessor(); this._maximumScreenSpaceError = defaultValue(options.maximumScreenSpaceError, 16); this._maximumMemoryUsage = defaultValue(options.maximumMemoryUsage, 512); @@ -727,13 +726,18 @@ define([ *

* * @type {Event} - * @default {enabled : true, occlusionAngle : 0.1} + * @default {enabled : true, occlusionAngle : 0.1, rangeParameter : 1.0} */ this.pointCloudPostProcessorOptions = { enabled : defaultValue(options.enabled, true), - occlusionAngle : defaultValue(options.occlusionAngle, 0.1) + occlusionAngle : defaultValue(options.occlusionAngle, 0.1), + rangeParameter : defaultValue(options.rangeParameter, 0.01), + neighborhoodHalfWidth : defaultValue(options.neighborhoodHalfWidth, 4), + numRegionGrowingPasses : defaultValue(options.numRegionGrowingPasses, 8) }; + this._pointCloudPostProcessor = new PointCloudPostProcessor(this.pointCloudPostProcessorOptions); + var that = this; // We don't know the distance of the tileset until tileset.json is loaded, so use the default distance for now @@ -1612,7 +1616,10 @@ define([ // TODO : make the processor a static class so it can be used by multiple tilesets? tileset._pointCloudPostProcessor.update(frameState, numberOfInitialCommands, { enabled : tileset.pointCloudPostProcessorOptions.enabled, - occlusionAngle : tileset.pointCloudPostProcessorOptions.occlusionAngle + occlusionAngle : tileset.pointCloudPostProcessorOptions.occlusionAngle, + rangeParameter : tileset.pointCloudPostProcessorOptions.rangeParameter, + neighborhoodHalfWidth : tileset.pointCloudPostProcessorOptions.neighborhoodHalfWidth, + numRegionGrowingPasses : tileset.pointCloudPostProcessorOptions.numRegionGrowingPasses }); } diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 7d91e2c69baa..0ed3f1c16167 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -46,7 +46,7 @@ define([ /** * @private */ - function PointCloudPostProcessor() { + function PointCloudPostProcessor(options) { this._framebuffers = undefined; this._colorTextures = undefined; this._ecTexture = undefined; @@ -55,7 +55,10 @@ define([ this._blendCommand = undefined; this._clearCommands = undefined; - this.occlusionAngle = 0.1; + this.occlusionAngle = options.occlusionAngle; + this.rangeParameter = options.rangeParameter; + this.neighborhoodHalfWidth = options.neighborhoodHalfWidth; + this.numRegionGrowingPasses = options.numRegionGrowingPasses; } function createSampler() { @@ -178,6 +181,11 @@ define([ processor._ecTexture = ecTexture; } + function replaceConstants(sourceStr, constantName, replacement) { + var r = "#define\\s" + constantName + "\\s([0-9.]+)"; + return sourceStr.replace(new RegExp(r, "g"), "#define " + constantName + " " + replacement); + }; + function pointOcclusionStage(processor, context) { var uniformMap = { pointCloud_colorTexture : function() { @@ -190,7 +198,14 @@ define([ return processor.occlusionAngle; } }; - return context.createViewportQuadCommand(PointOcclusionPass, { + + var pointOcclusionStr = replaceConstants( + PointOcclusionPass, + "neighborhoodHalfWidth", + processor.neighborhoodHalfWidth + ); + + return context.createViewportQuadCommand(pointOcclusionStr, { uniformMap : uniformMap, framebuffer : processor._framebuffers.screenSpacePass, renderState : RenderState.fromCache({ @@ -213,6 +228,9 @@ define([ }, pointCloud_depthTexture : function() { return processor._depthTextures[i]; + }, + rangeParameter : function() { + return processor.rangeParameter; } }; @@ -235,7 +253,7 @@ define([ } function createCommands(processor, context) { - var numRegionGrowingPasses = 4; + var numRegionGrowingPasses = processor.numRegionGrowingPasses; var drawCommands = new Array(numRegionGrowingPasses + 1); var i; @@ -376,15 +394,21 @@ define([ var dirty = false; // Set options here - if (options.occlusionAngle != this.occlusionAngle) { + if (options.occlusionAngle != this.occlusionAngle || + options.rangeParameter != this.rangeParameter || + options.neighborhoodHalfWidth != this.neighborhoodHalfWidth || + options.numRegionGrowingPasses != this.numRegionGrowingPasses) { this.occlusionAngle = options.occlusionAngle; + this.rangeParameter = options.rangeParameter; + this.neighborhoodHalfWidth = options.neighborhoodHalfWidth; + this.numRegionGrowingPasses = options.numRegionGrowingPasses; dirty = true; } if (!options.enabled) { return; } - + createResources(this, frameState.context, dirty); // Render point cloud commands into an offscreen FBO. From 449f3251c0d101808d5d011ee21be7be8b09b300 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Thu, 22 Jun 2017 15:30:55 -0400 Subject: [PATCH 024/240] Fixes bug where additional region growing passes didn't grow empty areas --- Source/Shaders/PostProcessFilters/RegionGrowingPass.glsl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPass.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPass.glsl index d17f00df6ebd..7198b7004d02 100644 --- a/Source/Shaders/PostProcessFilters/RegionGrowingPass.glsl +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPass.glsl @@ -70,12 +70,11 @@ void fastMedianFinder(in float[neighborhoodSize] neighbors, if (neighbors[i] <= 1.0 - EPS) { outDepth = neighbors[i / 2]; outColor = colorNeighbors[i / 2]; - //outColor = vec4(1, 0, 0, 1); return; } } - outDepth = 0.0; + outDepth = 1.0; outColor = vec4(0, 0, 0, 0); } From ce5bf10583ba436d981a7ff65768e2fed0548ede Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Thu, 22 Jun 2017 15:31:22 -0400 Subject: [PATCH 025/240] More sane parameter for the number of region growing passes --- Source/Scene/Cesium3DTileset.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Scene/Cesium3DTileset.js b/Source/Scene/Cesium3DTileset.js index ea5fb1ae480a..3f575fbdfa63 100644 --- a/Source/Scene/Cesium3DTileset.js +++ b/Source/Scene/Cesium3DTileset.js @@ -733,7 +733,7 @@ define([ occlusionAngle : defaultValue(options.occlusionAngle, 0.1), rangeParameter : defaultValue(options.rangeParameter, 0.01), neighborhoodHalfWidth : defaultValue(options.neighborhoodHalfWidth, 4), - numRegionGrowingPasses : defaultValue(options.numRegionGrowingPasses, 8) + numRegionGrowingPasses : defaultValue(options.numRegionGrowingPasses, 2) }; this._pointCloudPostProcessor = new PointCloudPostProcessor(this.pointCloudPostProcessorOptions); From 2520c89e073905c7e9dc553943b93af7ee23f426 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Thu, 22 Jun 2017 15:40:09 -0400 Subject: [PATCH 026/240] Some code cleanup in the region growing filter --- .../PostProcessFilters/RegionGrowingPass.glsl | 46 +++++++++---------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPass.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPass.glsl index 7198b7004d02..98e31d81564b 100644 --- a/Source/Shaders/PostProcessFilters/RegionGrowingPass.glsl +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPass.glsl @@ -42,28 +42,10 @@ void comparisonNetwork8(inout float[neighborhoodSize] neighbors, // NOTE: This can be sped up a lot by replacing the depth // primitive array with two vec4s and using swizzle operations! // (assuming that the neighborhood is exactly 3x3) -void fastMedianFinder(in float[neighborhoodSize] neighbors, - in vec4[neighborhoodSize] colorNeighbors, - out float outDepth, - out vec4 outColor) { - /*for (int i = 0; i < neighborhoodSize; i++) { - float key = neighbors[i]; - int modifiedFlag = 0; - - for (int c = neighborhoodSize - 1; c >= 0; c--) { - if (c > i - 1) - continue; - - if (neighbors[c] <= key) { - neighbors[c + 1] = key; - modifiedFlag = 1; - break; - } - neighbors[c + 1] = neighbors[c]; - } - if (modifiedFlag == 0) - neighbors[0] = key; - }*/ +void fastMedian3(in float[neighborhoodSize] neighbors, + in vec4[neighborhoodSize] colorNeighbors, + out float outDepth, + out vec4 outColor) { comparisonNetwork8(neighbors, colorNeighbors); for (int i = neighborhoodSize - 1; i >= 0; i--) { @@ -78,6 +60,17 @@ void fastMedianFinder(in float[neighborhoodSize] neighbors, outColor = vec4(0, 0, 0, 0); } +void genericMedianFinder(in float[neighborhoodSize] neighbors, + in vec4[neighborhoodSize] colorNeighbors, + out float outDepth, + out vec4 outColor) { + // Perhaps we should have a valid way of handling the + // difficult-to-optimize cases. + // For now this does nothing. + outDepth = 0.0; + outColor = vec4(1, 0, 0, 1); +} + void main() { vec4 color = texture2D(pointCloud_colorTexture, v_textureCoordinates); float depth = texture2D(pointCloud_depthTexture, v_textureCoordinates).r; @@ -115,7 +108,11 @@ void main() { } } - fastMedianFinder(depthNeighbors, colorNeighbors, finalDepth, finalColor); +#if neighborhoodFullWidth == 3 + fastMedian3(depthNeighbors, colorNeighbors, finalDepth, finalColor); +#else + genericMedianFinder(depthNeighbors, colorNeighbors, finalDepth, finalColor); +#endif } // Otherwise if our depth value is valid else { @@ -140,7 +137,8 @@ void main() { float depthDelta = abs(neighbor - depth); - float weight = (1.0 - rI / 2.0) * (1.0 - min(1.0, depthDelta / max(1e-5, rangeParameter))); + float weight = (1.0 - rI / 2.0) * (1.0 - min(1.0, depthDelta / max(1e-5, + rangeParameter))); depthAccum += weight * neighbor; colorAccum += weight * colorNeighbor; normalization += weight; From 8331358eba71f7ca7bc10a9dc888ff2ffc10fa4e Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Fri, 23 Jun 2017 11:07:06 -0400 Subject: [PATCH 027/240] Sector histogram modification has better branching now --- .../PointOcclusionPass.glsl | 90 ++++++++++++------- 1 file changed, 58 insertions(+), 32 deletions(-) diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPass.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPass.glsl index 4a4d4e96055b..f6f525b41ecc 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPass.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPass.glsl @@ -19,43 +19,69 @@ void modifySectorHistogram(in int index, in float value, inout vec4 shFirst, inout vec4 shSecond) { - if (index == 0) - shFirst.x = value; - else if (index == 1) - shFirst.y = value; - else if (index == 2) - shFirst.z = value; - else if (index == 3) - shFirst.w = value; - else if (index == 4) - shSecond.x = value; - else if (index == 5) - shSecond.y = value; - else if (index == 6) - shSecond.z = value; - else if (index == 7) - shSecond.w = value; + if (index < 4) { + if (index < 2) { + if (index == 0) { + shFirst.x = value; + } else { + shFirst.y = value; + } + } else { + if (index == 2) { + shFirst.z = value; + } else { + shFirst.w = value; + } + } + } else { + if (index < 6) { + if (index == 4) { + shSecond.x = value; + } else { + shSecond.y = value; + } + } else { + if (index == 6) { + shSecond.z = value; + } else { + shSecond.w = value; + } + } + } } float readSectorHistogram(in int index, in vec4 shFirst, in vec4 shSecond) { - if (index == 0) - return shFirst.x; - else if (index == 1) - return shFirst.y; - else if (index == 2) - return shFirst.z; - else if (index == 3) - return shFirst.w; - else if (index == 4) - return shSecond.x; - else if (index == 5) - return shSecond.y; - else if (index == 6) - return shSecond.z; - else if (index == 7) - return shSecond.w; + if (index < 4) { + if (index < 2) { + if (index == 0) { + return shFirst.x; + } else { + return shFirst.y; + } + } else { + if (index == 2) { + return shFirst.z; + } else { + return shFirst.w; + } + } + } else { + if (index < 6) { + if (index == 4) { + return shSecond.x; + } else { + return shSecond.y; + } + } else { + if (index == 6) { + return shSecond.z; + } else { + return shSecond.w; + } + } + } } int getSector(in vec2 d) { From c22a98e2af4b7d89b595c8bf4838edef53559f75 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Fri, 23 Jun 2017 15:30:09 -0400 Subject: [PATCH 028/240] Better inverse trig --- .../PointOcclusionPass.glsl | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPass.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPass.glsl index f6f525b41ecc..724fd19d8ae8 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPass.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPass.glsl @@ -2,6 +2,11 @@ #define TAU 6.28318530718 #define PI 3.14159265359 +#define PI_4 0.785398163 +#define C0 1.57073 +#define C1 -0.212053 +#define C2 0.0740935 +#define C3 -0.0186166 #define EPS 1e-6 #define neighborhoodHalfWidth 4 // TUNABLE PARAMETER -- half-width of point-occlusion neighborhood #define numSectors 8 @@ -11,8 +16,20 @@ uniform sampler2D pointCloud_ECTexture; uniform float occlusionAngle; varying vec2 v_textureCoordinates; +float acosFast(in float inX) { + float x = abs(inX); + float res = ((C3 * x + C2) * x + C1) * x + C0; // p(x) + res *= sqrt(1.0 - x); + + return (inX >= 0.0) ? res : PI - res; +} + +float atanFast(in float x) { + return PI_4 * x - x * (abs(x) - 1.0) * (0.2447 + 0.0663 * abs(x)); +} + float atan2(in float y, in float x) { - return x == 0.0 ? sign(y) * PI / 2.0 : atan(y, x); + return x == 0.0 ? sign(y) * PI / 2.0 : atanFast(y / x); } void modifySectorHistogram(in int index, @@ -111,9 +128,6 @@ void main() { float near = czm_currentFrustum.x; float far = czm_currentFrustum.y; ivec2 pos = ivec2(int(gl_FragCoord.x), int(gl_FragCoord.y)); - vec4 color = texture2D(pointCloud_colorTexture, v_textureCoordinates); - //vec4 color = texture2D(pointCloud_colorTexture, gl_FragCoord.xy / czm_viewport.zw); - //vec4 EC = texture2D(pointCloud_ECTexture, gl_FragCoord.xy / czm_viewport.zw); // The position of this pixel in 3D (i.e the position of the point) vec3 centerPosition = texture2D(pointCloud_ECTexture, v_textureCoordinates).xyz; @@ -123,7 +137,6 @@ void main() { if (length(centerPosition) == 0.) discard; - // We split our region of interest (the point of interest and its // neighbors) // into sectors. For the purposes of this shader, we have eight @@ -185,7 +198,7 @@ void main() { // |vec_1| * |vec_2| * cos(angle_between), and in this case, // the magnitude of both vectors is 1 because they are both // normalized. - float angle = acos(dotProduct); + float angle = acosFast(dotProduct); // This horizon point is behind the current point. That means that it can't // occlude the current point. So we ignore it and move on. From 6930938547ad12f8bb9ef323dcf4d6a3ddab670a Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Fri, 23 Jun 2017 16:37:30 -0400 Subject: [PATCH 029/240] Some code cleanup and branch optimization --- .../PostProcessFilters/RegionGrowingPass.glsl | 106 ++++++++++-------- 1 file changed, 58 insertions(+), 48 deletions(-) diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPass.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPass.glsl index 98e31d81564b..030267e0ab08 100644 --- a/Source/Shaders/PostProcessFilters/RegionGrowingPass.glsl +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPass.glsl @@ -4,6 +4,7 @@ #define neighborhoodFullWidth 3 #define neighborhoodSize 8 #define EPS 1e-6 +#define SQRT2 1.414213562 uniform sampler2D pointCloud_colorTexture; uniform sampler2D pointCloud_depthTexture; @@ -71,6 +72,34 @@ void genericMedianFinder(in float[neighborhoodSize] neighbors, outColor = vec4(1, 0, 0, 1); } +void loadIntoArray(inout float[neighborhoodSize] depthNeighbors, + inout vec4[neighborhoodSize] colorNeighbors) { + bool pastCenter = false; + for (int j = -neighborhoodHalfWidth; j <= neighborhoodHalfWidth; j++) { + for (int i = -neighborhoodHalfWidth; i <= neighborhoodHalfWidth; i++) { + ivec2 d = ivec2(i, j); + if (d == ivec2(0, 0)) { + pastCenter = true; + continue; + } + vec2 neighborCoords = vec2(vec2(d) + gl_FragCoord.xy) / czm_viewport.zw; + float neighbor = texture2D(pointCloud_depthTexture, neighborCoords).r; + vec4 colorNeighbor = texture2D(pointCloud_colorTexture, neighborCoords); + if (pastCenter) { + depthNeighbors[(j + 1) * neighborhoodFullWidth + i] = + neighbor; + colorNeighbors[(j + 1) * neighborhoodFullWidth + i] = + colorNeighbor; + } else { + depthNeighbors[(j + 1) * neighborhoodFullWidth + i + 1] = + neighbor; + colorNeighbors[(j + 1) * neighborhoodFullWidth + i + 1] = + colorNeighbor; + } + } + } +} + void main() { vec4 color = texture2D(pointCloud_colorTexture, v_textureCoordinates); float depth = texture2D(pointCloud_depthTexture, v_textureCoordinates).r; @@ -78,36 +107,22 @@ void main() { vec4 finalColor = color; float finalDepth = depth; + float depthNeighbors[neighborhoodSize]; + vec4 colorNeighbors[neighborhoodSize]; + float rIs[neighborhoodSize]; + rIs[0] = SQRT2; + rIs[1] = 1.0; + rIs[2] = SQRT2; + rIs[3] = 1.0; + rIs[4] = 1.0; + rIs[5] = SQRT2; + rIs[6] = 1.0; + rIs[7] = SQRT2; + + loadIntoArray(depthNeighbors, colorNeighbors); + // If our depth value is invalid if (depth > 1.0 - EPS) { - float depthNeighbors[neighborhoodSize]; - vec4 colorNeighbors[neighborhoodSize]; - - int pastCenter = 0; - for (int j = -neighborhoodHalfWidth; j <= neighborhoodHalfWidth; j++) { - for (int i = -neighborhoodHalfWidth; i <= neighborhoodHalfWidth; i++) { - ivec2 d = ivec2(i, j); - if (d == ivec2(0, 0)) { - pastCenter = 1; - continue; - } - vec2 neighborCoords = vec2(vec2(d) + gl_FragCoord.xy) / czm_viewport.zw; - float neighbor = texture2D(pointCloud_depthTexture, neighborCoords).r; - vec4 colorNeighbor = texture2D(pointCloud_colorTexture, neighborCoords); - if (pastCenter == 1) { - depthNeighbors[(j + 1) * neighborhoodFullWidth + i] = - neighbor; - colorNeighbors[(j + 1) * neighborhoodFullWidth + i] = - colorNeighbor; - } else { - depthNeighbors[(j + 1) * neighborhoodFullWidth + i + 1] = - neighbor; - colorNeighbors[(j + 1) * neighborhoodFullWidth + i + 1] = - colorNeighbor; - } - } - } - #if neighborhoodFullWidth == 3 fastMedian3(depthNeighbors, colorNeighbors, finalDepth, finalColor); #else @@ -120,33 +135,28 @@ void main() { vec4 colorAccum = vec4(0); float normalization = 0.0; - for (int j = -neighborhoodHalfWidth; j <= neighborhoodHalfWidth; j++) { - for (int i = -neighborhoodHalfWidth; i <= neighborhoodHalfWidth; i++) { - ivec2 d = ivec2(i, j); - - // Does this even make sense? - /*if (d == ivec2(0, 0)) { - continue; - }*/ - - float rI = sqrt(float(d.x * d.x + d.y * d.y)); - - vec2 neighborCoords = vec2(vec2(d) + gl_FragCoord.xy) / czm_viewport.zw; - float neighbor = texture2D(pointCloud_depthTexture, neighborCoords).r; - vec4 colorNeighbor = texture2D(pointCloud_colorTexture, neighborCoords); + for (int i = 0; i < neighborhoodSize; i++) { + float neighbor = depthNeighbors[i]; + vec4 colorNeighbor = colorNeighbors[i]; + float rI = rIs[i]; + if (neighbor < 1.0 - EPS) { float depthDelta = abs(neighbor - depth); - float weight = (1.0 - rI / 2.0) * (1.0 - min(1.0, depthDelta / max(1e-5, - rangeParameter))); - depthAccum += weight * neighbor; - colorAccum += weight * colorNeighbor; + float weight = + (1.0 - rI / 2.0) * + (1.0 - min(1.0, depthDelta / max(1e-5, rangeParameter))); + + depthAccum += neighbor * weight; + colorAccum += colorNeighbor * weight; normalization += weight; } } - finalDepth = depthAccum / normalization; - finalColor = colorAccum / normalization; + if (depthAccum > EPS) { + finalDepth = depthAccum / normalization; + finalColor = colorAccum / normalization; + } } gl_FragColor = finalColor; From 03f2266c0ee258633830e192aeb6fd06717ab9d2 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Tue, 27 Jun 2017 15:52:42 -0400 Subject: [PATCH 030/240] Updates capability flags for WebGL 2 --- Source/Renderer/Context.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Source/Renderer/Context.js b/Source/Renderer/Context.js index d490e65eeea6..4658b7ac3182 100644 --- a/Source/Renderer/Context.js +++ b/Source/Renderer/Context.js @@ -195,7 +195,7 @@ define([ webglOptions.alpha = defaultValue(webglOptions.alpha, false); // WebGL default is true webglOptions.stencil = defaultValue(webglOptions.stencil, true); // WebGL default is false - var defaultToWebgl2 = false; + var defaultToWebgl2 = true; var requestWebgl2 = defaultToWebgl2 && (typeof WebGL2RenderingContext !== 'undefined'); var webgl2 = false; @@ -269,11 +269,11 @@ define([ this._antialias = gl.getContextAttributes().antialias; // Query and initialize extensions - this._standardDerivatives = !!getExtension(gl, ['OES_standard_derivatives']); - this._elementIndexUint = !!getExtension(gl, ['OES_element_index_uint']); - this._depthTexture = !!getExtension(gl, ['WEBGL_depth_texture', 'WEBKIT_WEBGL_depth_texture']); - this._textureFloat = !!getExtension(gl, ['OES_texture_float']); - this._fragDepth = !!getExtension(gl, ['EXT_frag_depth']); + this._standardDerivatives = !!getExtension(gl, ['OES_standard_derivatives']) || this._webgl2; + this._elementIndexUint = !!getExtension(gl, ['OES_element_index_uint']) || this._webgl2; + this._depthTexture = !!getExtension(gl, ['WEBGL_depth_texture', 'WEBKIT_WEBGL_depth_texture']) || this._webgl2; + this._textureFloat = !!getExtension(gl, ['OES_texture_float']) || this._webgl2; + this._fragDepth = !!getExtension(gl, ['EXT_frag_depth']) || this._webgl2; this._debugShaders = getExtension(gl, ['WEBGL_debug_shaders']); this._s3tc = !!getExtension(gl, ['WEBGL_compressed_texture_s3tc', 'MOZ_WEBGL_compressed_texture_s3tc', 'WEBKIT_WEBGL_compressed_texture_s3tc']); From d6b1869b288d6c622eef11c7178eb043c41c78d0 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Tue, 27 Jun 2017 15:53:46 -0400 Subject: [PATCH 031/240] Newline after version in ShaderSource --- Source/Renderer/ShaderSource.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Renderer/ShaderSource.js b/Source/Renderer/ShaderSource.js index 9d8a9ff6fd0d..8147b191277e 100644 --- a/Source/Renderer/ShaderSource.js +++ b/Source/Renderer/ShaderSource.js @@ -213,7 +213,7 @@ define([ // #version must be first // defaults to #version 100 if not specified if (defined(version)) { - result = '#version ' + version; + result = '#version ' + version + '\n'; } for (i = 0; i < extensions.length; i++) { From 5862b6ba3cb064c758ea5375003a6d4396454edb Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Tue, 27 Jun 2017 15:55:18 -0400 Subject: [PATCH 032/240] Updates pointcloud processor to WebGL 2.0 --- Source/Scene/PointCloudPostProcessor.js | 114 +++++++++++++++++- .../PointOcclusionPass.glsl | 12 +- .../PostProcessFilters/RegionGrowingPass.glsl | 17 +-- 3 files changed, 128 insertions(+), 15 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 0ed3f1c16167..a6ab86ada3b3 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -263,6 +263,21 @@ define([ drawCommands[i + 1] = regionGrowingStage(processor, context, i); } + for (i = 0; i < drawCommands.length; i++) { + var shaderProgram = drawCommands[i].shaderProgram; + var vsSource = shaderProgram.vertexShaderSource.clone(); + var fsSource = shaderProgram.fragmentShaderSource.clone(); + var attributeLocations = shaderProgram._attributeLocations; + for (var a = 0; a < vsSource.sources.length; a++) { + vsSource.sources[a] = glslModernize(vsSource.sources[a], false, true); + } + drawCommands[i].shaderProgram = context.shaderCache.getShaderProgram({ + vertexShaderSource : vsSource, + fragmentShaderSource : fsSource, + attributeLocations : attributeLocations + }); + } + // TODO : point cloud depth information is lost var blendFS = 'uniform sampler2D pointCloud_colorTexture; \n' + @@ -341,6 +356,92 @@ define([ return context.depthTexture; } + function glslModernize(source, isFragmentShader, first) { + var mainFunctionRegex = /void\s+main\(\)/; + var splitSource = source.split('\n'); + var mainFunctionLine; + for (var number = 0; number < splitSource.length; number++) { + var line = splitSource[number]; + if (mainFunctionRegex.exec(line)) { + mainFunctionLine = number; + } + }; + + function replaceInSource(regex, replacement) { + for (var number = 0; number < splitSource.length; number++) { + splitSource[number] = splitSource[number].replace(regex, replacement); + } + } + + function findInSource(regex) { + for (var number = 0; number < splitSource.length; number++) { + if (splitSource[number].search(regex) != -1) { + return true; + } + } + return false; + } + + function compileSource() { + var wholeSource = ""; + for (var number = 0; number < splitSource.length; number++) { + wholeSource += splitSource[number] + "\n"; + } + return wholeSource; + } + + function removeExtension(name) { + var regex = "#extension\\s+GL_" + name + "\\s+:\\s+[a-zA-Z0-9]+\\s*$"; + replaceInSource(new RegExp(regex, "g"), ""); + } + + for (var i = 0; i < 10; i++) { + var fragDataString = "gl_FragData\\[" + i + "\\]"; + var newOutput = 'czm_out' + i; + var regex = new RegExp(fragDataString, "g"); + if (source.search(fragDataString) != -1) { + replaceInSource(regex, newOutput); + splitSource.splice(mainFunctionLine, 0, + "layout(location = " + i + ") out vec4 " + + newOutput + ";"); + } + } + + if (findInSource(/gl_FragColor/)) { + replaceInSource(/gl_FragColor/, "czm_fragColor"); + splitSource.splice(mainFunctionLine, 0, "layout(location = 0) out vec4 czm_fragColor"); + } + + if (first === true) { + var versionThree = "#version 300 es"; + var foundVersion = false; + for (var number = 0; number < splitSource.length; number++) { + if (splitSource[number].search(/#version/) != -1) { + splitSource[number] = versionThree; + foundVersion = true; + } + } + + if (!foundVersion) { + splitSource.splice(0, 0, versionThree); + } + } + + removeExtension("EXT_draw_buffers"); + removeExtension("EXT_frag_depth"); + + replaceInSource(/texture2D/, "texture"); + + if (isFragmentShader) { + replaceInSource(/varying/, "in"); + } else { + replaceInSource(/attribute/, "in"); + replaceInSource(/varying/, "out"); + } + + return compileSource(); + } + function getECShaderProgram(context, shaderProgram) { var shader = context.shaderCache.getDerivedShaderProgram(shaderProgram, 'EC'); if (!defined(shader)) { @@ -375,7 +476,18 @@ define([ '{ \n' + ' czm_point_cloud_post_process_main(); \n' + ' gl_FragData[1] = vec4(v_positionECPS, 0); \n' + - '}'); + '}'); + + var modernized, i; + for (i = 0; i < vs.sources.length; i++) { + modernized = glslModernize(vs.sources[i], false, i === 0); + vs.sources[i] = modernized; + } + + for (i = 0; i < fs.sources.length; i++) { + modernized = glslModernize(fs.sources[i], true, i === 0); + fs.sources[i] = modernized; + } shader = context.shaderCache.createDerivedShaderProgram(shaderProgram, 'EC', { vertexShaderSource : vs, diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPass.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPass.glsl index 724fd19d8ae8..c38337fefd4c 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPass.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPass.glsl @@ -1,4 +1,4 @@ -#extension GL_EXT_frag_depth : enable +#version 300 es #define TAU 6.28318530718 #define PI 3.14159265359 @@ -14,7 +14,7 @@ uniform sampler2D pointCloud_colorTexture; uniform sampler2D pointCloud_ECTexture; uniform float occlusionAngle; -varying vec2 v_textureCoordinates; +in vec2 v_textureCoordinates; float acosFast(in float inX) { float x = abs(inX); @@ -130,7 +130,7 @@ void main() { ivec2 pos = ivec2(int(gl_FragCoord.x), int(gl_FragCoord.y)); // The position of this pixel in 3D (i.e the position of the point) - vec3 centerPosition = texture2D(pointCloud_ECTexture, v_textureCoordinates).xyz; + vec3 centerPosition = texture(pointCloud_ECTexture, v_textureCoordinates).xyz; // If the EC of this pixel is zero, that means that it's not a valid // pixel. We don't care about reprojecting it. @@ -169,8 +169,8 @@ void main() { ivec2 pI = pos + d; // We now calculate the actual 3D position of the horizon pixel (the horizon point) - vec3 neighborPosition = texture2D(pointCloud_ECTexture, - vec2(pI) / czm_viewport.zw).xyz; + vec3 neighborPosition = texture(pointCloud_ECTexture, + vec2(pI) / czm_viewport.zw).xyz; // If our horizon pixel doesn't exist, ignore it and move on if (length(neighborPosition) < EPS || pI == pos) { @@ -231,5 +231,5 @@ void main() { // This is the depth of this pixel... assuming that it's valid. float linearizedDepth = (-centerPosition.z - near) / (far - near); - gl_FragDepthEXT = linearizedDepth; + gl_FragDepth = linearizedDepth; } diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPass.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPass.glsl index 030267e0ab08..9a79787ccb18 100644 --- a/Source/Shaders/PostProcessFilters/RegionGrowingPass.glsl +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPass.glsl @@ -1,4 +1,4 @@ -#extension GL_EXT_frag_depth : enable +#version 300 es #define neighborhoodHalfWidth 1 // TUNABLE PARAMETER -- half-width of region-growing kernel #define neighborhoodFullWidth 3 @@ -10,7 +10,8 @@ uniform sampler2D pointCloud_colorTexture; uniform sampler2D pointCloud_depthTexture; uniform float rangeParameter; -varying vec2 v_textureCoordinates; +in vec2 v_textureCoordinates; +layout(location = 0) out vec4 colorOut; #define otherswap(a, b, aC, bC) if (a > b) { temp = a; a = b; b = temp; tempColor = aC; aC = bC; bC = tempColor; } @@ -83,8 +84,8 @@ void loadIntoArray(inout float[neighborhoodSize] depthNeighbors, continue; } vec2 neighborCoords = vec2(vec2(d) + gl_FragCoord.xy) / czm_viewport.zw; - float neighbor = texture2D(pointCloud_depthTexture, neighborCoords).r; - vec4 colorNeighbor = texture2D(pointCloud_colorTexture, neighborCoords); + float neighbor = texture(pointCloud_depthTexture, neighborCoords).r; + vec4 colorNeighbor = texture(pointCloud_colorTexture, neighborCoords); if (pastCenter) { depthNeighbors[(j + 1) * neighborhoodFullWidth + i] = neighbor; @@ -101,8 +102,8 @@ void loadIntoArray(inout float[neighborhoodSize] depthNeighbors, } void main() { - vec4 color = texture2D(pointCloud_colorTexture, v_textureCoordinates); - float depth = texture2D(pointCloud_depthTexture, v_textureCoordinates).r; + vec4 color = texture(pointCloud_colorTexture, v_textureCoordinates); + float depth = texture(pointCloud_depthTexture, v_textureCoordinates).r; vec4 finalColor = color; float finalDepth = depth; @@ -159,6 +160,6 @@ void main() { } } - gl_FragColor = finalColor; - gl_FragDepthEXT = finalDepth; + colorOut = finalColor; + gl_FragDepth = finalDepth; } From 37cef074bcb37d39516b95d7baf01b124da9346f Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 28 Jun 2017 09:14:45 -0400 Subject: [PATCH 033/240] Adds support for the EXT_color_buffer_float extension --- Source/Renderer/Context.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Source/Renderer/Context.js b/Source/Renderer/Context.js index 4658b7ac3182..3ef399b048f0 100644 --- a/Source/Renderer/Context.js +++ b/Source/Renderer/Context.js @@ -276,6 +276,10 @@ define([ this._fragDepth = !!getExtension(gl, ['EXT_frag_depth']) || this._webgl2; this._debugShaders = getExtension(gl, ['WEBGL_debug_shaders']); + if (this._webgl2) { + this._colorBufferFloat = !!getExtension(gl, ['EXT_color_buffer_float']); + } + this._s3tc = !!getExtension(gl, ['WEBGL_compressed_texture_s3tc', 'MOZ_WEBGL_compressed_texture_s3tc', 'WEBKIT_WEBGL_compressed_texture_s3tc']); this._pvrtc = !!getExtension(gl, ['WEBGL_compressed_texture_pvrtc', 'WEBKIT_WEBGL_compressed_texture_pvrtc']); this._etc1 = !!getExtension(gl, ['WEBGL_compressed_texture_etc1']); @@ -615,6 +619,20 @@ define([ } }, + /** + * true if the EXT_color_buffer_float extension is supported. This + * extension makes the formats gl.R16F, gl.RG16F, gl.RGBA16F, gl.R32F, gl.RG32F, + * gl.RGBA32F, gl.R11F_G11F_B10F color renderable. + * @memberof Context.prototype + * @type {Boolean} + * @see {@link https://www.khronos.org/registry/webgl/extensions/EXT_color_buffer_float/} + */ + colorBufferFloat : { + get : function() { + return this._colorBufferFloat; + } + }, + /** * true if the WEBGL_draw_buffers extension is supported. This * extensions provides support for multiple render targets. The framebuffer object can have mutiple From e9855c058a35d1124eaae6cc8677f961eb53d794 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 28 Jun 2017 10:04:09 -0400 Subject: [PATCH 034/240] Moves GLSLModernizer to its own file --- Source/Renderer/GLSLModernizer.js | 100 ++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 Source/Renderer/GLSLModernizer.js diff --git a/Source/Renderer/GLSLModernizer.js b/Source/Renderer/GLSLModernizer.js new file mode 100644 index 000000000000..e85ce03e827a --- /dev/null +++ b/Source/Renderer/GLSLModernizer.js @@ -0,0 +1,100 @@ +/*global define*/ +define([], function() { + 'use strict'; + + /** + * A function to port GLSL shaders from GLSL ES 1.00 to GLSL ES 2.00 + * + * This function is nowhere near comprehensive or complete. It just + * handles some common cases. + * + * @private + */ + function glslModernize(source, isFragmentShader, first) { + var mainFunctionRegex = /void\s+main\(\)/; + var splitSource = source.split('\n'); + var mainFunctionLine; + for (var number = 0; number < splitSource.length; number++) { + var line = splitSource[number]; + if (mainFunctionRegex.exec(line)) { + mainFunctionLine = number; + } + }; + + function replaceInSource(regex, replacement) { + for (var number = 0; number < splitSource.length; number++) { + splitSource[number] = splitSource[number].replace(regex, replacement); + } + } + + function findInSource(regex) { + for (var number = 0; number < splitSource.length; number++) { + if (splitSource[number].search(regex) != -1) { + return true; + } + } + return false; + } + + function compileSource() { + var wholeSource = ""; + for (var number = 0; number < splitSource.length; number++) { + wholeSource += splitSource[number] + "\n"; + } + return wholeSource; + } + + function removeExtension(name) { + var regex = "#extension\\s+GL_" + name + "\\s+:\\s+[a-zA-Z0-9]+\\s*$"; + replaceInSource(new RegExp(regex, "g"), ""); + } + + for (var i = 0; i < 10; i++) { + var fragDataString = "gl_FragData\\[" + i + "\\]"; + var newOutput = 'czm_out' + i; + var regex = new RegExp(fragDataString, "g"); + if (source.search(fragDataString) != -1) { + replaceInSource(regex, newOutput); + splitSource.splice(mainFunctionLine, 0, + "layout(location = " + i + ") out vec4 " + + newOutput + ";"); + } + } + + if (findInSource(/gl_FragColor/)) { + replaceInSource(/gl_FragColor/, "czm_fragColor"); + splitSource.splice(mainFunctionLine, 0, "layout(location = 0) out vec4 czm_fragColor"); + } + + if (first === true) { + var versionThree = "#version 300 es"; + var foundVersion = false; + for (var number = 0; number < splitSource.length; number++) { + if (splitSource[number].search(/#version/) != -1) { + splitSource[number] = versionThree; + foundVersion = true; + } + } + + if (!foundVersion) { + splitSource.splice(0, 0, versionThree); + } + } + + removeExtension("EXT_draw_buffers"); + removeExtension("EXT_frag_depth"); + + replaceInSource(/texture2D/, "texture"); + + if (isFragmentShader) { + replaceInSource(/varying/, "in"); + } else { + replaceInSource(/attribute/, "in"); + replaceInSource(/varying/, "out"); + } + + return compileSource(); + } + + return glslModernize; +}); From 4e9ad177dd80c9a76c586c533f53a8cff5bfc8b2 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 28 Jun 2017 10:24:58 -0400 Subject: [PATCH 035/240] Fixes issues where glslModernize does not add a semicolon when updating gl_FragColor --- Source/Renderer/GLSLModernizer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Renderer/GLSLModernizer.js b/Source/Renderer/GLSLModernizer.js index e85ce03e827a..568b48b11faa 100644 --- a/Source/Renderer/GLSLModernizer.js +++ b/Source/Renderer/GLSLModernizer.js @@ -63,7 +63,7 @@ define([], function() { if (findInSource(/gl_FragColor/)) { replaceInSource(/gl_FragColor/, "czm_fragColor"); - splitSource.splice(mainFunctionLine, 0, "layout(location = 0) out vec4 czm_fragColor"); + splitSource.splice(mainFunctionLine, 0, "layout(location = 0) out vec4 czm_fragColor;"); } if (first === true) { From 19251646036d8f6882f9a989532bbfb15bfa6e94 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 28 Jun 2017 10:42:37 -0400 Subject: [PATCH 036/240] Refactors GLSLModernizer --- Source/Renderer/GLSLModernizer.js | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/Source/Renderer/GLSLModernizer.js b/Source/Renderer/GLSLModernizer.js index 568b48b11faa..ab73b31a2aaa 100644 --- a/Source/Renderer/GLSLModernizer.js +++ b/Source/Renderer/GLSLModernizer.js @@ -96,5 +96,25 @@ define([], function() { return compileSource(); } - return glslModernize; + function glslModernizeShaderProgram(context, shaderProgram) { + var vsSource = shaderProgram.vertexShaderSource.clone(); + var fsSource = shaderProgram.fragmentShaderSource.clone(); + + var newShaderProgramOptions = { + vertexShaderSource : vsSource, + fragmentShaderSource : fsSource, + gl : shaderProgram._gl, + logShaderCompilation : shaderProgram._logShaderCompilation, + attributeLocations : shaderProgram._attributeLocations + }; + + return context.shaderCache.getShaderProgram(newShaderProgramOptions); + } + + var GLSLModernizer = { + glslModernize : glslModernize, + glslModernizeShaderProgram : glslModernizeShaderProgram + }; + + return GLSLModernizer; }); From 1196a06696873e1acfa1e2ee82bf9fa59fe88f3b Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 28 Jun 2017 11:14:18 -0400 Subject: [PATCH 037/240] Another refactor of GLSLModernizer -- now supports cleaning up ShaderSource(s) --- Source/Renderer/GLSLModernizer.js | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/Source/Renderer/GLSLModernizer.js b/Source/Renderer/GLSLModernizer.js index ab73b31a2aaa..f4e1b1bda8d9 100644 --- a/Source/Renderer/GLSLModernizer.js +++ b/Source/Renderer/GLSLModernizer.js @@ -10,7 +10,15 @@ define([], function() { * * @private */ - function glslModernize(source, isFragmentShader, first) { + function glslModernizeShaderSource(shaderSource, isFragmentShader) { + for (var i = 0; i < shaderSource.sources.length; i++) { + shaderSource.sources[i] = + glslModernizeShaderText(shaderSource.sources[i], isFragmentShader, i === 0); + } + shaderSource.defines.push("MODERNIZED"); + } + + function glslModernizeShaderText(source, isFragmentShader, first) { var mainFunctionRegex = /void\s+main\(\)/; var splitSource = source.split('\n'); var mainFunctionLine; @@ -100,6 +108,9 @@ define([], function() { var vsSource = shaderProgram.vertexShaderSource.clone(); var fsSource = shaderProgram.fragmentShaderSource.clone(); + glslModernizeShaderSource(vsSource, false); + glslModernizeShaderSource(fsSource, true); + var newShaderProgramOptions = { vertexShaderSource : vsSource, fragmentShaderSource : fsSource, @@ -112,7 +123,8 @@ define([], function() { } var GLSLModernizer = { - glslModernize : glslModernize, + glslModernizeShaderText : glslModernizeShaderText, + glslModernizeShaderSource : glslModernizeShaderSource, glslModernizeShaderProgram : glslModernizeShaderProgram }; From 99304d167fa938101c5adb1283871696bfc3fa58 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 28 Jun 2017 11:14:56 -0400 Subject: [PATCH 038/240] Modifies PointCloudPostProcessor so that it now uses the new GLSLModernizer --- Source/Scene/PointCloudPostProcessor.js | 102 ++---------------------- 1 file changed, 5 insertions(+), 97 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index a6ab86ada3b3..f15ae3e88842 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -7,6 +7,7 @@ define([ '../Renderer/ClearCommand', '../Renderer/DrawCommand', '../Renderer/Framebuffer', + '../Renderer/GLSLModernizer', '../Renderer/Pass', '../Renderer/PixelDatatype', '../Renderer/RenderState', @@ -28,6 +29,7 @@ define([ ClearCommand, DrawCommand, Framebuffer, + GLSLModernizer, Pass, PixelDatatype, RenderState, @@ -269,7 +271,7 @@ define([ var fsSource = shaderProgram.fragmentShaderSource.clone(); var attributeLocations = shaderProgram._attributeLocations; for (var a = 0; a < vsSource.sources.length; a++) { - vsSource.sources[a] = glslModernize(vsSource.sources[a], false, true); + vsSource.sources[a] = GLSLModernizer.glslModernizeShaderText(vsSource.sources[a], false, true); } drawCommands[i].shaderProgram = context.shaderCache.getShaderProgram({ vertexShaderSource : vsSource, @@ -356,92 +358,6 @@ define([ return context.depthTexture; } - function glslModernize(source, isFragmentShader, first) { - var mainFunctionRegex = /void\s+main\(\)/; - var splitSource = source.split('\n'); - var mainFunctionLine; - for (var number = 0; number < splitSource.length; number++) { - var line = splitSource[number]; - if (mainFunctionRegex.exec(line)) { - mainFunctionLine = number; - } - }; - - function replaceInSource(regex, replacement) { - for (var number = 0; number < splitSource.length; number++) { - splitSource[number] = splitSource[number].replace(regex, replacement); - } - } - - function findInSource(regex) { - for (var number = 0; number < splitSource.length; number++) { - if (splitSource[number].search(regex) != -1) { - return true; - } - } - return false; - } - - function compileSource() { - var wholeSource = ""; - for (var number = 0; number < splitSource.length; number++) { - wholeSource += splitSource[number] + "\n"; - } - return wholeSource; - } - - function removeExtension(name) { - var regex = "#extension\\s+GL_" + name + "\\s+:\\s+[a-zA-Z0-9]+\\s*$"; - replaceInSource(new RegExp(regex, "g"), ""); - } - - for (var i = 0; i < 10; i++) { - var fragDataString = "gl_FragData\\[" + i + "\\]"; - var newOutput = 'czm_out' + i; - var regex = new RegExp(fragDataString, "g"); - if (source.search(fragDataString) != -1) { - replaceInSource(regex, newOutput); - splitSource.splice(mainFunctionLine, 0, - "layout(location = " + i + ") out vec4 " + - newOutput + ";"); - } - } - - if (findInSource(/gl_FragColor/)) { - replaceInSource(/gl_FragColor/, "czm_fragColor"); - splitSource.splice(mainFunctionLine, 0, "layout(location = 0) out vec4 czm_fragColor"); - } - - if (first === true) { - var versionThree = "#version 300 es"; - var foundVersion = false; - for (var number = 0; number < splitSource.length; number++) { - if (splitSource[number].search(/#version/) != -1) { - splitSource[number] = versionThree; - foundVersion = true; - } - } - - if (!foundVersion) { - splitSource.splice(0, 0, versionThree); - } - } - - removeExtension("EXT_draw_buffers"); - removeExtension("EXT_frag_depth"); - - replaceInSource(/texture2D/, "texture"); - - if (isFragmentShader) { - replaceInSource(/varying/, "in"); - } else { - replaceInSource(/attribute/, "in"); - replaceInSource(/varying/, "out"); - } - - return compileSource(); - } - function getECShaderProgram(context, shaderProgram) { var shader = context.shaderCache.getDerivedShaderProgram(shaderProgram, 'EC'); if (!defined(shader)) { @@ -478,16 +394,8 @@ define([ ' gl_FragData[1] = vec4(v_positionECPS, 0); \n' + '}'); - var modernized, i; - for (i = 0; i < vs.sources.length; i++) { - modernized = glslModernize(vs.sources[i], false, i === 0); - vs.sources[i] = modernized; - } - - for (i = 0; i < fs.sources.length; i++) { - modernized = glslModernize(fs.sources[i], true, i === 0); - fs.sources[i] = modernized; - } + GLSLModernizer.glslModernizeShaderSource(vs, false); + GLSLModernizer.glslModernizeShaderSource(fs, true); shader = context.shaderCache.createDerivedShaderProgram(shaderProgram, 'EC', { vertexShaderSource : vs, From af64702ff9c8fcf7243c463941ac11afe8c8f080 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 28 Jun 2017 11:32:39 -0400 Subject: [PATCH 039/240] Uses the correct internal format for floating point RGBA textures in WebGL 2 --- Source/Renderer/Texture.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Source/Renderer/Texture.js b/Source/Renderer/Texture.js index a330e3aecfc0..69adb4baad96 100644 --- a/Source/Renderer/Texture.js +++ b/Source/Renderer/Texture.js @@ -72,6 +72,20 @@ define([ internalFormat = WebGLConstants.DEPTH_COMPONENT24; } } + + if (pixelDatatype == PixelDatatype.FLOAT) { + switch (pixelFormat) { + case PixelFormat.RGBA: + internalFormat = WebGLConstants.RGBA32F; + break; + case PixelFormat.RG: + internalFormat = WebGLConstants.RG32F; + break; + case PixelFormat.R: + internalFormat = WebGLConstants.R32F; + break; + } + } } //>>includeStart('debug', pragmas.debug); From 915442c9f8f4334dc30afbe8638c21958f2bcfd4 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 28 Jun 2017 16:00:44 -0400 Subject: [PATCH 040/240] GLSLModernizer is now preprocessor-branch aware --- Source/Renderer/GLSLModernizer.js | 140 +++++++++++++++++++++++++++++- 1 file changed, 137 insertions(+), 3 deletions(-) diff --git a/Source/Renderer/GLSLModernizer.js b/Source/Renderer/GLSLModernizer.js index f4e1b1bda8d9..ce41a6dace8b 100644 --- a/Source/Renderer/GLSLModernizer.js +++ b/Source/Renderer/GLSLModernizer.js @@ -17,7 +17,7 @@ define([], function() { } shaderSource.defines.push("MODERNIZED"); } - + function glslModernizeShaderText(source, isFragmentShader, first) { var mainFunctionRegex = /void\s+main\(\)/; var splitSource = source.split('\n'); @@ -37,7 +37,7 @@ define([], function() { function findInSource(regex) { for (var number = 0; number < splitSource.length; number++) { - if (splitSource[number].search(regex) != -1) { + if (splitSource[number].search(regex) !== -1) { return true; } } @@ -51,27 +51,161 @@ define([], function() { } return wholeSource; } + + function setAdd(variable, set1) { + if (set1.indexOf(variable) === -1) + set1.push(variable); + } + + function setUnion(set1, set2) { + for (var a = 0; a < set2.length; a++) { + setAdd(set2[a], set1); + } + } + + function getVariablePreprocessorBranch(variablesThatWeCareAbout) { + var variableMap = {}; + var negativeMap = {}; + + for (var a = 0; a < variablesThatWeCareAbout.length; a++) { + var variableThatWeCareAbout = variablesThatWeCareAbout[a]; + variableMap[variableThatWeCareAbout] = [null]; + } + + var stack = []; + for (var i = 0; i < splitSource.length; i++) { + var line = splitSource[i]; + var hasIF = line.search(/(#ifdef|#if)/g) !== -1; + var hasELSE = line.search(/#else/g) !== -1; + var hasENDIF = line.search(/#endif/g) !== -1; + + if (hasIF) { + stack.push(line); + } else if (hasELSE) { + var top = stack[stack.length - 1]; + var op = top.replace("ifdef", "ifndef"); + if (op.search(/if/g) !== -1) { + op = op.replace(/(#if\s+)(\S*)([^]*)/, "$1!($2)$3"); + } + stack.pop(); + stack.push(op); + + negativeMap[top] = op; + negativeMap[op] = top; + } else if (hasENDIF) { + stack.pop(); + } else if (line.search(/layout/g) === -1) { + for (a = 0; a < variablesThatWeCareAbout.length; a++) { + var care = variablesThatWeCareAbout[a]; + if (line.indexOf(care) !== -1) { + if (variableMap[care].length === 1 && + variableMap[care][0] === null) { + variableMap[care] = stack.slice(); + } else { + variableMap[care] = variableMap[care].filter( + function(x) { return stack.indexOf(x) >= 0; }); + } + } + } + } + } + + // This code is probably no longer needed... it was used to handle + // removing negative conditions + for (var care in variableMap) { + if (variableMap.hasOwnProperty(care)) { + var entry = variableMap[care]; + var toDelete = []; + for (var b = 0; b < entry.length; b++) { + var item = entry[b]; + if (entry.indexOf(negativeMap[item]) !== -1) { + toDelete.push(item); + toDelete.push(negativeMap[item]); + } + } + + for (var c = 0; c < toDelete.length; c++) { + var ind = entry.indexOf(toDelete[c]); + if (ind !== -1) { + entry.splice(ind, 1); + } + } + } + } + + for (var care in variableMap) { + if (variableMap.hasOwnProperty(care)) { + if (variableMap.length === 1 && + variableMap[0] === null) { + variableMap.splice(0, 1); + } + } + } + + return variableMap; + } function removeExtension(name) { var regex = "#extension\\s+GL_" + name + "\\s+:\\s+[a-zA-Z0-9]+\\s*$"; replaceInSource(new RegExp(regex, "g"), ""); } + var variableSet = []; + for (var i = 0; i < 10; i++) { var fragDataString = "gl_FragData\\[" + i + "\\]"; var newOutput = 'czm_out' + i; var regex = new RegExp(fragDataString, "g"); if (source.search(fragDataString) != -1) { + setAdd(newOutput, variableSet); replaceInSource(regex, newOutput); splitSource.splice(mainFunctionLine, 0, "layout(location = " + i + ") out vec4 " + newOutput + ";"); + mainFunctionLine += 1; } } + var czmFragColor = "czm_fragColor"; if (findInSource(/gl_FragColor/)) { - replaceInSource(/gl_FragColor/, "czm_fragColor"); + setAdd(czmFragColor, variableSet); + replaceInSource(/gl_FragColor/, czmFragColor); splitSource.splice(mainFunctionLine, 0, "layout(location = 0) out vec4 czm_fragColor;"); + mainFunctionLine += 1; + } + + var variableMap = getVariablePreprocessorBranch(variableSet); + console.log(variableMap); + var lineAdds = {}; + for (var c = 0; c < splitSource.length; c++) { + var l = splitSource[c]; + for (var care in variableMap) { + if (variableMap.hasOwnProperty(care)) { + var matchVar = + new RegExp("(layout)[^]+(out)[^]+(" + care + ")[^]+", "g"); + if (matchVar.exec(l) !== null) { + lineAdds[l] = care; + } + } + } + } + + for (var layoutDeclaration in lineAdds) { + if (lineAdds.hasOwnProperty(layoutDeclaration)) { + var variableName = lineAdds[layoutDeclaration]; + var lineNumber = splitSource.indexOf(layoutDeclaration); + var entry = variableMap[variableName]; + var depth = entry.length; + var d; + //console.log(entry); + for (d = 0; d < depth; d++) { + splitSource.splice(lineNumber, 0, entry[d]); + } + lineNumber += depth + 1; + for (d = depth - 1; d >= 0; d--) { + splitSource.splice(lineNumber, 0, "#endif //" + entry[d]); + } + } } if (first === true) { From c2cea4711f0d78460fa325289660b684d16ab53a Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 28 Jun 2017 16:10:44 -0400 Subject: [PATCH 041/240] Adds GLSLModernizer calls to OIT --- Source/Scene/OIT.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Source/Scene/OIT.js b/Source/Scene/OIT.js index 8f0131f6cae2..6bc03a584ba7 100644 --- a/Source/Scene/OIT.js +++ b/Source/Scene/OIT.js @@ -9,6 +9,7 @@ define([ '../Renderer/ClearCommand', '../Renderer/DrawCommand', '../Renderer/Framebuffer', + '../Renderer/GLSLModernizer', '../Renderer/PixelDatatype', '../Renderer/RenderState', '../Renderer/ShaderSource', @@ -27,6 +28,7 @@ define([ ClearCommand, DrawCommand, Framebuffer, + GLSLModernizer, PixelDatatype, RenderState, ShaderSource, @@ -255,6 +257,11 @@ define([ uniformMap : uniformMap, owner : this }); + if (context.webgl2) { + this._compositeCommand.shaderProgram = + GLSLModernizer.glslModernizeShaderProgram( + context, this._compositeCommand.shaderProgram); + } } if (!defined(this._adjustTranslucentCommand)) { @@ -277,6 +284,11 @@ define([ uniformMap : uniformMap, owner : this }); + if (context.webgl2) { + this._adjustTranslucentCommand.shaderProgram = + GLSLModernizer.glslModernizeShaderProgram( + context, this._adjustTranslucentCommand.shaderProgram); + } } else if (this._translucentMultipassSupport) { fs = new ShaderSource({ sources : [AdjustTranslucentFS] @@ -295,6 +307,11 @@ define([ uniformMap : uniformMap, owner : this }); + if (context.webgl2) { + this._adjustTranslucentCommand.shaderProgram = + GLSLModernizer.glslModernizeShaderProgram( + context, this._adjustTranslucentCommand.shaderProgram); + } uniformMap = { u_bgColor : function() { @@ -309,6 +326,11 @@ define([ uniformMap : uniformMap, owner : this }); + if (context.webgl2) { + this._adjustAlphaCommand.shaderProgram = + GLSLModernizer.glslModernizeShaderProgram( + context, this._adjustAlphaCommand.shaderProgram); + } } } From 5e66040c144f701976fda521d4b81f26b01eb166 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 28 Jun 2017 17:26:40 -0400 Subject: [PATCH 042/240] GLSLModernizer now ignores shaders that are already written in GLSL ES 3.00 --- Source/Renderer/GLSLModernizer.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Source/Renderer/GLSLModernizer.js b/Source/Renderer/GLSLModernizer.js index ce41a6dace8b..bf96157ef6bf 100644 --- a/Source/Renderer/GLSLModernizer.js +++ b/Source/Renderer/GLSLModernizer.js @@ -21,6 +21,11 @@ define([], function() { function glslModernizeShaderText(source, isFragmentShader, first) { var mainFunctionRegex = /void\s+main\(\)/; var splitSource = source.split('\n'); + + if (source.search(/#version 300 es/g) !== -1) { + return source; + } + var mainFunctionLine; for (var number = 0; number < splitSource.length; number++) { var line = splitSource[number]; From 5562f2430114301ab0640ba165e7e0c656780ce6 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Thu, 29 Jun 2017 09:46:26 -0400 Subject: [PATCH 043/240] Adds WebGL 2 checks --- Source/Scene/PointCloudPostProcessor.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index f15ae3e88842..3cfc7bc03707 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -271,7 +271,10 @@ define([ var fsSource = shaderProgram.fragmentShaderSource.clone(); var attributeLocations = shaderProgram._attributeLocations; for (var a = 0; a < vsSource.sources.length; a++) { - vsSource.sources[a] = GLSLModernizer.glslModernizeShaderText(vsSource.sources[a], false, true); + if (context.webgl2) { + vsSource.sources[a] = GLSLModernizer.glslModernizeShaderText( + vsSource.sources[a], false, true); + } } drawCommands[i].shaderProgram = context.shaderCache.getShaderProgram({ vertexShaderSource : vsSource, @@ -392,10 +395,12 @@ define([ '{ \n' + ' czm_point_cloud_post_process_main(); \n' + ' gl_FragData[1] = vec4(v_positionECPS, 0); \n' + - '}'); + '}'); - GLSLModernizer.glslModernizeShaderSource(vs, false); - GLSLModernizer.glslModernizeShaderSource(fs, true); + if (context.webgl2) { + GLSLModernizer.glslModernizeShaderSource(vs, false); + GLSLModernizer.glslModernizeShaderSource(fs, true); + } shader = context.shaderCache.createDerivedShaderProgram(shaderProgram, 'EC', { vertexShaderSource : vs, From a1db0a31ba572e6428ca9f78bf32ea266dac8a19 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Thu, 29 Jun 2017 10:00:09 -0400 Subject: [PATCH 044/240] PointCloudPostProcessor now loads different shaders depending on the WebGL version --- Source/Scene/PointCloudPostProcessor.js | 20 +- .../PointOcclusionPassGL1.glsl | 235 ++++++++++++++++++ ...onPass.glsl => PointOcclusionPassGL2.glsl} | 0 .../RegionGrowingPassGL1.glsl | 164 ++++++++++++ ...ingPass.glsl => RegionGrowingPassGL2.glsl} | 0 5 files changed, 413 insertions(+), 6 deletions(-) create mode 100644 Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl rename Source/Shaders/PostProcessFilters/{PointOcclusionPass.glsl => PointOcclusionPassGL2.glsl} (100%) create mode 100644 Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl rename Source/Shaders/PostProcessFilters/{RegionGrowingPass.glsl => RegionGrowingPassGL2.glsl} (100%) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 3cfc7bc03707..fa7826b3f5c5 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -19,8 +19,10 @@ define([ '../Renderer/TextureMinificationFilter', '../Renderer/TextureWrap', '../Scene/BlendingState', - '../Shaders/PostProcessFilters/PointOcclusionPass', - '../Shaders/PostProcessFilters/RegionGrowingPass' + '../Shaders/PostProcessFilters/PointOcclusionPassGL1', + '../Shaders/PostProcessFilters/RegionGrowingPassGL1', + '../Shaders/PostProcessFilters/PointOcclusionPassGL2', + '../Shaders/PostProcessFilters/RegionGrowingPassGL2' ], function( Color, defined, @@ -41,8 +43,11 @@ define([ TextureMinificationFilter, TextureWrap, BlendingState, - PointOcclusionPass, - RegionGrowingPass) { + PointOcclusionPassGL1, + RegionGrowingPassGL1, + PointOcclusionPassGL2, + RegionGrowingPassGL2, + ) { 'use strict'; /** @@ -202,7 +207,7 @@ define([ }; var pointOcclusionStr = replaceConstants( - PointOcclusionPass, + (context.webgl2) ? PointOcclusionPassGL2 : PointOcclusionPassGL1, "neighborhoodHalfWidth", processor.neighborhoodHalfWidth ); @@ -240,7 +245,10 @@ define([ processor._framebuffers.regionGrowingPassA : processor._framebuffers.regionGrowingPassB; - return context.createViewportQuadCommand(RegionGrowingPass, { + var regionGrowingPassStr = (context.webgl2) ? + RegionGrowingPassGL2 : + RegionGrowingPassGL1; + return context.createViewportQuadCommand(regionGrowingPassStr, { uniformMap : uniformMap, framebuffer : framebuffer, renderState : RenderState.fromCache({ diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl new file mode 100644 index 000000000000..724fd19d8ae8 --- /dev/null +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl @@ -0,0 +1,235 @@ +#extension GL_EXT_frag_depth : enable + +#define TAU 6.28318530718 +#define PI 3.14159265359 +#define PI_4 0.785398163 +#define C0 1.57073 +#define C1 -0.212053 +#define C2 0.0740935 +#define C3 -0.0186166 +#define EPS 1e-6 +#define neighborhoodHalfWidth 4 // TUNABLE PARAMETER -- half-width of point-occlusion neighborhood +#define numSectors 8 + +uniform sampler2D pointCloud_colorTexture; +uniform sampler2D pointCloud_ECTexture; +uniform float occlusionAngle; +varying vec2 v_textureCoordinates; + +float acosFast(in float inX) { + float x = abs(inX); + float res = ((C3 * x + C2) * x + C1) * x + C0; // p(x) + res *= sqrt(1.0 - x); + + return (inX >= 0.0) ? res : PI - res; +} + +float atanFast(in float x) { + return PI_4 * x - x * (abs(x) - 1.0) * (0.2447 + 0.0663 * abs(x)); +} + +float atan2(in float y, in float x) { + return x == 0.0 ? sign(y) * PI / 2.0 : atanFast(y / x); +} + +void modifySectorHistogram(in int index, + in float value, + inout vec4 shFirst, + inout vec4 shSecond) { + if (index < 4) { + if (index < 2) { + if (index == 0) { + shFirst.x = value; + } else { + shFirst.y = value; + } + } else { + if (index == 2) { + shFirst.z = value; + } else { + shFirst.w = value; + } + } + } else { + if (index < 6) { + if (index == 4) { + shSecond.x = value; + } else { + shSecond.y = value; + } + } else { + if (index == 6) { + shSecond.z = value; + } else { + shSecond.w = value; + } + } + } +} + +float readSectorHistogram(in int index, + in vec4 shFirst, + in vec4 shSecond) { + if (index < 4) { + if (index < 2) { + if (index == 0) { + return shFirst.x; + } else { + return shFirst.y; + } + } else { + if (index == 2) { + return shFirst.z; + } else { + return shFirst.w; + } + } + } else { + if (index < 6) { + if (index == 4) { + return shSecond.x; + } else { + return shSecond.y; + } + } else { + if (index == 6) { + return shSecond.z; + } else { + return shSecond.w; + } + } + } +} + +int getSector(in vec2 d) { + float angle = (atan2(float(d.y), float(d.x)) + PI) / TAU; + return int(angle * float(numSectors)); +} + +// Subsamples the neighbor pixel and stores the sector number +// in each component of the output +ivec4 getSectors(in vec2 vi) { + return ivec4(getSector(vi + vec2(-0.5, 0.5)), + getSector(vi + vec2(0.5, -0.5)), + getSector(vi + vec2(0.5, 0.5)), + getSector(vi + vec2(-0.5, -0.5))); +} + +ivec2 collapseSectors(in ivec4 sectors) { + int first = sectors[0]; + ivec2 collapsed = ivec2(first, first); + for (int i = 1; i < 4; i++) + if (sectors[i] != first) + collapsed.y = sectors[i]; + return collapsed; +} + +void main() { + float near = czm_currentFrustum.x; + float far = czm_currentFrustum.y; + ivec2 pos = ivec2(int(gl_FragCoord.x), int(gl_FragCoord.y)); + + // The position of this pixel in 3D (i.e the position of the point) + vec3 centerPosition = texture2D(pointCloud_ECTexture, v_textureCoordinates).xyz; + + // If the EC of this pixel is zero, that means that it's not a valid + // pixel. We don't care about reprojecting it. + if (length(centerPosition) == 0.) + discard; + + // We split our region of interest (the point of interest and its + // neighbors) + // into sectors. For the purposes of this shader, we have eight + // sectors. + // + // Each entry of sector_histogram contains the current best horizon + // pixel angle + ivec2 halfNeighborhood = ivec2(neighborhoodHalfWidth / 2, + neighborhoodHalfWidth / 2); + // Upper left corner of the neighborhood + ivec2 upperLeftCorner = pos - halfNeighborhood; + // Lower right corner of the neighborhood + ivec2 lowerRightCorner = pos + halfNeighborhood; + + // The widest the cone can be is 90 degrees + float maxAngle = PI / 2.0; + + vec4 shFirst = vec4(maxAngle); + vec4 shSecond = vec4(maxAngle); + + // Right now this is obvious because everything happens in eye space, + // but this kind of statement is nice for a reference implementation + vec3 viewer = vec3(0.0); + + for (int i = -neighborhoodHalfWidth; i <= neighborhoodHalfWidth; i++) { + for (int j = -neighborhoodHalfWidth; j <= neighborhoodHalfWidth; j++) { + // d is the relative offset from the horizon pixel to the center pixel + // in 2D + ivec2 d = ivec2(i, j); + ivec2 pI = pos + d; + + // We now calculate the actual 3D position of the horizon pixel (the horizon point) + vec3 neighborPosition = texture2D(pointCloud_ECTexture, + vec2(pI) / czm_viewport.zw).xyz; + + // If our horizon pixel doesn't exist, ignore it and move on + if (length(neighborPosition) < EPS || pI == pos) { + continue; + } + + // sectors contains both possible sectors that the + // neighbor pixel could be in + ivec2 sectors = collapseSectors(getSectors(vec2(d))); + + // This is the offset of the horizon point from the center in 3D + // (a 3D analog of d) + vec3 c = neighborPosition - centerPosition; + + // Now we calculate the dot product between the vector + // from the viewer to the center and the vector to the horizon pixel. + // We normalize both vectors first because we only care about their relative + // directions + // TODO: Redo the math and figure out whether the result should be negated or not + float dotProduct = dot(normalize(viewer - centerPosition), + normalize(c)); + + // We calculate the angle that this horizon pixel would make + // in the cone. The dot product is be equal to + // |vec_1| * |vec_2| * cos(angle_between), and in this case, + // the magnitude of both vectors is 1 because they are both + // normalized. + float angle = acosFast(dotProduct); + + // This horizon point is behind the current point. That means that it can't + // occlude the current point. So we ignore it and move on. + if (angle > maxAngle) + continue; + // If we've found a horizon pixel, store it in the histogram + if (readSectorHistogram(sectors.x, shFirst, shSecond) > angle) { + modifySectorHistogram(sectors.x, angle, shFirst, shSecond); + } + if (readSectorHistogram(sectors.y, shFirst, shSecond) > angle) { + modifySectorHistogram(sectors.y, angle, shFirst, shSecond); + } + } + } + + float accumulator = 0.0; + for (int i = 0; i < numSectors; i++) { + float angle = readSectorHistogram(i, shFirst, shSecond); + // If the z component is less than zero, + // that means that there is no valid horizon pixel + if (angle <= 0.0 || angle > maxAngle) + angle = maxAngle; + accumulator += angle; + } + + // The solid angle is too small, so we occlude this point + if (accumulator < (2.0 * PI) * (1.0 - occlusionAngle)) { + discard; + } + + // This is the depth of this pixel... assuming that it's valid. + float linearizedDepth = (-centerPosition.z - near) / (far - near); + gl_FragDepthEXT = linearizedDepth; +} diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPass.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl similarity index 100% rename from Source/Shaders/PostProcessFilters/PointOcclusionPass.glsl rename to Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl new file mode 100644 index 000000000000..030267e0ab08 --- /dev/null +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl @@ -0,0 +1,164 @@ +#extension GL_EXT_frag_depth : enable + +#define neighborhoodHalfWidth 1 // TUNABLE PARAMETER -- half-width of region-growing kernel +#define neighborhoodFullWidth 3 +#define neighborhoodSize 8 +#define EPS 1e-6 +#define SQRT2 1.414213562 + +uniform sampler2D pointCloud_colorTexture; +uniform sampler2D pointCloud_depthTexture; +uniform float rangeParameter; + +varying vec2 v_textureCoordinates; + +#define otherswap(a, b, aC, bC) if (a > b) { temp = a; a = b; b = temp; tempColor = aC; aC = bC; bC = tempColor; } + +void comparisonNetwork8(inout float[neighborhoodSize] neighbors, + inout vec4[neighborhoodSize] neighborsColor) { + float temp; + vec4 tempColor; + + otherswap(neighbors[0], neighbors[1], neighborsColor[0], neighborsColor[1]); + otherswap(neighbors[2], neighbors[3], neighborsColor[2], neighborsColor[3]); + otherswap(neighbors[0], neighbors[2], neighborsColor[0], neighborsColor[2]); + otherswap(neighbors[1], neighbors[3], neighborsColor[1], neighborsColor[3]); + otherswap(neighbors[1], neighbors[2], neighborsColor[1], neighborsColor[2]); + otherswap(neighbors[4], neighbors[5], neighborsColor[4], neighborsColor[5]); + otherswap(neighbors[6], neighbors[7], neighborsColor[6], neighborsColor[7]); + otherswap(neighbors[4], neighbors[6], neighborsColor[4], neighborsColor[6]); + otherswap(neighbors[5], neighbors[7], neighborsColor[5], neighborsColor[7]); + otherswap(neighbors[5], neighbors[6], neighborsColor[5], neighborsColor[6]); + otherswap(neighbors[0], neighbors[4], neighborsColor[0], neighborsColor[4]); + otherswap(neighbors[1], neighbors[5], neighborsColor[1], neighborsColor[5]); + otherswap(neighbors[1], neighbors[4], neighborsColor[1], neighborsColor[4]); + otherswap(neighbors[2], neighbors[6], neighborsColor[2], neighborsColor[6]); + otherswap(neighbors[3], neighbors[7], neighborsColor[3], neighborsColor[7]); + otherswap(neighbors[3], neighbors[6], neighborsColor[3], neighborsColor[6]); + otherswap(neighbors[2], neighbors[4], neighborsColor[2], neighborsColor[4]); + otherswap(neighbors[3], neighbors[5], neighborsColor[3], neighborsColor[5]); + otherswap(neighbors[3], neighbors[4], neighborsColor[3], neighborsColor[4]); +} + +// NOTE: This can be sped up a lot by replacing the depth +// primitive array with two vec4s and using swizzle operations! +// (assuming that the neighborhood is exactly 3x3) +void fastMedian3(in float[neighborhoodSize] neighbors, + in vec4[neighborhoodSize] colorNeighbors, + out float outDepth, + out vec4 outColor) { + comparisonNetwork8(neighbors, colorNeighbors); + + for (int i = neighborhoodSize - 1; i >= 0; i--) { + if (neighbors[i] <= 1.0 - EPS) { + outDepth = neighbors[i / 2]; + outColor = colorNeighbors[i / 2]; + return; + } + } + + outDepth = 1.0; + outColor = vec4(0, 0, 0, 0); +} + +void genericMedianFinder(in float[neighborhoodSize] neighbors, + in vec4[neighborhoodSize] colorNeighbors, + out float outDepth, + out vec4 outColor) { + // Perhaps we should have a valid way of handling the + // difficult-to-optimize cases. + // For now this does nothing. + outDepth = 0.0; + outColor = vec4(1, 0, 0, 1); +} + +void loadIntoArray(inout float[neighborhoodSize] depthNeighbors, + inout vec4[neighborhoodSize] colorNeighbors) { + bool pastCenter = false; + for (int j = -neighborhoodHalfWidth; j <= neighborhoodHalfWidth; j++) { + for (int i = -neighborhoodHalfWidth; i <= neighborhoodHalfWidth; i++) { + ivec2 d = ivec2(i, j); + if (d == ivec2(0, 0)) { + pastCenter = true; + continue; + } + vec2 neighborCoords = vec2(vec2(d) + gl_FragCoord.xy) / czm_viewport.zw; + float neighbor = texture2D(pointCloud_depthTexture, neighborCoords).r; + vec4 colorNeighbor = texture2D(pointCloud_colorTexture, neighborCoords); + if (pastCenter) { + depthNeighbors[(j + 1) * neighborhoodFullWidth + i] = + neighbor; + colorNeighbors[(j + 1) * neighborhoodFullWidth + i] = + colorNeighbor; + } else { + depthNeighbors[(j + 1) * neighborhoodFullWidth + i + 1] = + neighbor; + colorNeighbors[(j + 1) * neighborhoodFullWidth + i + 1] = + colorNeighbor; + } + } + } +} + +void main() { + vec4 color = texture2D(pointCloud_colorTexture, v_textureCoordinates); + float depth = texture2D(pointCloud_depthTexture, v_textureCoordinates).r; + + vec4 finalColor = color; + float finalDepth = depth; + + float depthNeighbors[neighborhoodSize]; + vec4 colorNeighbors[neighborhoodSize]; + float rIs[neighborhoodSize]; + rIs[0] = SQRT2; + rIs[1] = 1.0; + rIs[2] = SQRT2; + rIs[3] = 1.0; + rIs[4] = 1.0; + rIs[5] = SQRT2; + rIs[6] = 1.0; + rIs[7] = SQRT2; + + loadIntoArray(depthNeighbors, colorNeighbors); + + // If our depth value is invalid + if (depth > 1.0 - EPS) { +#if neighborhoodFullWidth == 3 + fastMedian3(depthNeighbors, colorNeighbors, finalDepth, finalColor); +#else + genericMedianFinder(depthNeighbors, colorNeighbors, finalDepth, finalColor); +#endif + } + // Otherwise if our depth value is valid + else { + float depthAccum = 0.0; + vec4 colorAccum = vec4(0); + float normalization = 0.0; + + for (int i = 0; i < neighborhoodSize; i++) { + float neighbor = depthNeighbors[i]; + vec4 colorNeighbor = colorNeighbors[i]; + float rI = rIs[i]; + + if (neighbor < 1.0 - EPS) { + float depthDelta = abs(neighbor - depth); + + float weight = + (1.0 - rI / 2.0) * + (1.0 - min(1.0, depthDelta / max(1e-5, rangeParameter))); + + depthAccum += neighbor * weight; + colorAccum += colorNeighbor * weight; + normalization += weight; + } + } + + if (depthAccum > EPS) { + finalDepth = depthAccum / normalization; + finalColor = colorAccum / normalization; + } + } + + gl_FragColor = finalColor; + gl_FragDepthEXT = finalDepth; +} diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPass.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl similarity index 100% rename from Source/Shaders/PostProcessFilters/RegionGrowingPass.glsl rename to Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl From 1c0f9ed6fe7c5968f2a5d12b7ebdf61fadba640a Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Thu, 29 Jun 2017 10:14:06 -0400 Subject: [PATCH 045/240] PointOcclusionPass now takes advantage of non-constant array indexing --- .../PointOcclusionPassGL2.glsl | 87 +++---------------- 1 file changed, 11 insertions(+), 76 deletions(-) diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl index c38337fefd4c..1780f02ba9be 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl @@ -32,75 +32,6 @@ float atan2(in float y, in float x) { return x == 0.0 ? sign(y) * PI / 2.0 : atanFast(y / x); } -void modifySectorHistogram(in int index, - in float value, - inout vec4 shFirst, - inout vec4 shSecond) { - if (index < 4) { - if (index < 2) { - if (index == 0) { - shFirst.x = value; - } else { - shFirst.y = value; - } - } else { - if (index == 2) { - shFirst.z = value; - } else { - shFirst.w = value; - } - } - } else { - if (index < 6) { - if (index == 4) { - shSecond.x = value; - } else { - shSecond.y = value; - } - } else { - if (index == 6) { - shSecond.z = value; - } else { - shSecond.w = value; - } - } - } -} - -float readSectorHistogram(in int index, - in vec4 shFirst, - in vec4 shSecond) { - if (index < 4) { - if (index < 2) { - if (index == 0) { - return shFirst.x; - } else { - return shFirst.y; - } - } else { - if (index == 2) { - return shFirst.z; - } else { - return shFirst.w; - } - } - } else { - if (index < 6) { - if (index == 4) { - return shSecond.x; - } else { - return shSecond.y; - } - } else { - if (index == 6) { - return shSecond.z; - } else { - return shSecond.w; - } - } - } -} - int getSector(in vec2 d) { float angle = (atan2(float(d.y), float(d.x)) + PI) / TAU; return int(angle * float(numSectors)); @@ -154,8 +85,12 @@ void main() { // The widest the cone can be is 90 degrees float maxAngle = PI / 2.0; - vec4 shFirst = vec4(maxAngle); - vec4 shSecond = vec4(maxAngle); + // Our sector array defaults to an angle of "maxAngle" in each sector + // (i.e no horizon pixels!) + float sh[numSectors]; + for (int i = 0; i < numSectors; i++) { + sh[i] = maxAngle; + } // Right now this is obvious because everything happens in eye space, // but this kind of statement is nice for a reference implementation @@ -205,18 +140,18 @@ void main() { if (angle > maxAngle) continue; // If we've found a horizon pixel, store it in the histogram - if (readSectorHistogram(sectors.x, shFirst, shSecond) > angle) { - modifySectorHistogram(sectors.x, angle, shFirst, shSecond); + if (sh[sectors.x] > angle) { + sh[sectors.x] = angle; } - if (readSectorHistogram(sectors.y, shFirst, shSecond) > angle) { - modifySectorHistogram(sectors.y, angle, shFirst, shSecond); + if (sh[sectors.y] > angle) { + sh[sectors.y] = angle; } } } float accumulator = 0.0; for (int i = 0; i < numSectors; i++) { - float angle = readSectorHistogram(i, shFirst, shSecond); + float angle = sh[i]; // If the z component is less than zero, // that means that there is no valid horizon pixel if (angle <= 0.0 || angle > maxAngle) From 33e680933dd45bc3ab266f8f65c15a0a15adc3bf Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Thu, 29 Jun 2017 13:54:52 -0400 Subject: [PATCH 046/240] Starts the transition over the multifrustrum support --- Source/Scene/Scene.js | 2 +- Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Scene/Scene.js b/Source/Scene/Scene.js index 48098c1b70d4..ac4532665287 100644 --- a/Source/Scene/Scene.js +++ b/Source/Scene/Scene.js @@ -436,7 +436,7 @@ define([ * @type {Number} * @default 1000.0 */ - this.farToNearRatio = 1e8; + this.farToNearRatio = 1000.0; /** * Determines the uniform depth size in meters of each frustum of the multifrustum in 2D. If a primitive or model close diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl index 1780f02ba9be..432b2f11a771 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl @@ -56,8 +56,8 @@ ivec2 collapseSectors(in ivec4 sectors) { } void main() { - float near = czm_currentFrustum.x; - float far = czm_currentFrustum.y; + float near = czm_entireFrustum.x; + float far = czm_entireFrustum.y; ivec2 pos = ivec2(int(gl_FragCoord.x), int(gl_FragCoord.y)); // The position of this pixel in 3D (i.e the position of the point) From 6ae66d22b714cab0eaeffde1e8691727e1653ad2 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Thu, 29 Jun 2017 16:17:52 -0400 Subject: [PATCH 047/240] Point occlusion operator now writes depth to a color attachment --- Source/Scene/PointCloudPostProcessor.js | 62 +++++++++---------- .../PointOcclusionPassGL2.glsl | 11 ++-- .../RegionGrowingPassGL2.glsl | 25 ++++---- 3 files changed, 51 insertions(+), 47 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index fa7826b3f5c5..c86bbdefa9b8 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -58,6 +58,7 @@ define([ this._colorTextures = undefined; this._ecTexture = undefined; this._depthTextures = undefined; + this._dirty = undefined; this._drawCommands = undefined; this._blendCommand = undefined; this._clearCommands = undefined; @@ -80,6 +81,7 @@ define([ function destroyFramebuffers(processor) { processor._depthTextures[0].destroy(); processor._depthTextures[1].destroy(); + processor._dirty.destroy(); processor._colorTextures[0].destroy(); processor._colorTextures[1].destroy(); processor._ecTexture.destroy(); @@ -112,24 +114,31 @@ define([ sampler : createSampler() }); - for (i = 0; i < 3; ++i) { - if (i < 2) { - colorTextures[i] = new Texture({ - context : context, - width : screenWidth, - height : screenHeight, - pixelFormat : PixelFormat.RGBA, - pixelDatatype : PixelDatatype.UNSIGNED_BYTE, - sampler : createSampler() - }); - } + var dirty = new Texture({ + context: context, + width: screenWidth, + height: screenHeight, + pixelFormat: PixelFormat.DEPTH_STENCIL, + pixelDatatype: PixelDatatype.UNSIGNED_INT_24_8, + sampler: createSampler() + }); + + for (i = 0; i < 2; ++i) { + colorTextures[i] = new Texture({ + context : context, + width : screenWidth, + height : screenHeight, + pixelFormat : PixelFormat.RGBA, + pixelDatatype : PixelDatatype.UNSIGNED_BYTE, + sampler : createSampler() + }); depthTextures[i] = new Texture({ context : context, width : screenWidth, height : screenHeight, - pixelFormat : PixelFormat.DEPTH_STENCIL, - pixelDatatype : PixelDatatype.UNSIGNED_INT_24_8, + pixelFormat : PixelFormat.RGBA, + pixelDatatype : PixelDatatype.UNSIGNED_BYTE, sampler : createSampler() }); } @@ -139,18 +148,18 @@ define([ * * 1. We render normally to our prior: * * Color -> 0 - * * Depth -> 2 ("dirty depth") + * * Depth -> dirty ("dirty depth") * * EC -> 0 * 2. Then we perform the screen-space point occlusion stage with color[0] and EC: * * No color - * * Depth -> 0 + * * Pseudo-depth -> 0 * * No EC * 3a. Then we perform the region growing stage with color[0] and depth[0]: * * Color -> 1 - * * Depth -> 1 + * * Pseudo-depth -> 1 * 3b. We do the region growing stage again with color[1] and depth[1]: * * Color -> 0 - * * Depth -> 0 + * * Pseudo-depth -> 0 * 3c. Repeat steps 3a and 3b until all holes are filled and/or we run * out of time. */ @@ -162,30 +171,29 @@ define([ colorTextures[0], ecTexture ], - depthStencilTexture : depthTextures[2], + depthStencilTexture : dirty, destroyAttachments : false }), "screenSpacePass": new Framebuffer({ context : context, - depthStencilTexture : depthTextures[0], + colorTextures : [depthTextures[0]], destroyAttachments : false }), "regionGrowingPassA": new Framebuffer({ context : context, - depthStencilTexture : depthTextures[1], - colorTextures : [colorTextures[1]], + colorTextures : [colorTextures[1], depthTextures[1]], destroyAttachments : false }), "regionGrowingPassB": new Framebuffer({ context: context, - depthStencilTexture: depthTextures[0], - colorTextures: [colorTextures[0]], + colorTextures: [colorTextures[0], depthTextures[0]], destroyAttachments: false }) }; processor._depthTextures = depthTextures; processor._colorTextures = colorTextures; processor._ecTexture = ecTexture; + processor._dirty = dirty; } function replaceConstants(sourceStr, constantName, replacement) { @@ -216,10 +224,6 @@ define([ uniformMap : uniformMap, framebuffer : processor._framebuffers.screenSpacePass, renderState : RenderState.fromCache({ - depthMask : true, - depthTest : { - enabled : true - } }), pass : Pass.CESIUM_3D_TILE, owner : processor @@ -252,10 +256,6 @@ define([ uniformMap : uniformMap, framebuffer : framebuffer, renderState : RenderState.fromCache({ - depthMask : true, - depthTest : { - enabled : true - } }), pass : Pass.CESIUM_3D_TILE, owner : processor diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl index 432b2f11a771..fc6abcd1c84f 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl @@ -16,6 +16,8 @@ uniform sampler2D pointCloud_ECTexture; uniform float occlusionAngle; in vec2 v_textureCoordinates; +layout(location = 0) out vec4 depthOut; + float acosFast(in float inX) { float x = abs(inX); float res = ((C3 * x + C2) * x + C1) * x + C0; // p(x) @@ -161,10 +163,11 @@ void main() { // The solid angle is too small, so we occlude this point if (accumulator < (2.0 * PI) * (1.0 - occlusionAngle)) { + depthOut = czm_packDepth(0.0); discard; + } else { + // This is the depth of this pixel... assuming that it's valid. + float linearizedDepth = (-centerPosition.z - near) / (far - near); + depthOut = czm_packDepth(linearizedDepth); } - - // This is the depth of this pixel... assuming that it's valid. - float linearizedDepth = (-centerPosition.z - near) / (far - near); - gl_FragDepth = linearizedDepth; } diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl index 9a79787ccb18..1b9b4b5077d2 100644 --- a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl @@ -3,7 +3,7 @@ #define neighborhoodHalfWidth 1 // TUNABLE PARAMETER -- half-width of region-growing kernel #define neighborhoodFullWidth 3 #define neighborhoodSize 8 -#define EPS 1e-6 +#define EPS 1e-8 #define SQRT2 1.414213562 uniform sampler2D pointCloud_colorTexture; @@ -12,6 +12,7 @@ uniform float rangeParameter; in vec2 v_textureCoordinates; layout(location = 0) out vec4 colorOut; +layout(location = 1) out vec4 depthOut; #define otherswap(a, b, aC, bC) if (a > b) { temp = a; a = b; b = temp; tempColor = aC; aC = bC; bC = tempColor; } @@ -50,15 +51,15 @@ void fastMedian3(in float[neighborhoodSize] neighbors, out vec4 outColor) { comparisonNetwork8(neighbors, colorNeighbors); - for (int i = neighborhoodSize - 1; i >= 0; i--) { - if (neighbors[i] <= 1.0 - EPS) { - outDepth = neighbors[i / 2]; - outColor = colorNeighbors[i / 2]; + for (int i = 0; i < neighborhoodSize; i++) { + if (neighbors[i] > EPS) { + outDepth = neighbors[i + (neighborhoodSize - 1 - i) / 2]; + outColor = colorNeighbors[i + (neighborhoodSize - 1 - i) / 2]; return; } } - outDepth = 1.0; + outDepth = 0.0; outColor = vec4(0, 0, 0, 0); } @@ -84,7 +85,7 @@ void loadIntoArray(inout float[neighborhoodSize] depthNeighbors, continue; } vec2 neighborCoords = vec2(vec2(d) + gl_FragCoord.xy) / czm_viewport.zw; - float neighbor = texture(pointCloud_depthTexture, neighborCoords).r; + float neighbor = czm_unpackDepth(texture(pointCloud_depthTexture, neighborCoords)); vec4 colorNeighbor = texture(pointCloud_colorTexture, neighborCoords); if (pastCenter) { depthNeighbors[(j + 1) * neighborhoodFullWidth + i] = @@ -103,7 +104,7 @@ void loadIntoArray(inout float[neighborhoodSize] depthNeighbors, void main() { vec4 color = texture(pointCloud_colorTexture, v_textureCoordinates); - float depth = texture(pointCloud_depthTexture, v_textureCoordinates).r; + float depth = czm_unpackDepth(texture(pointCloud_depthTexture, v_textureCoordinates)); vec4 finalColor = color; float finalDepth = depth; @@ -123,7 +124,7 @@ void main() { loadIntoArray(depthNeighbors, colorNeighbors); // If our depth value is invalid - if (depth > 1.0 - EPS) { + if (depth < EPS) { #if neighborhoodFullWidth == 3 fastMedian3(depthNeighbors, colorNeighbors, finalDepth, finalColor); #else @@ -141,12 +142,12 @@ void main() { vec4 colorNeighbor = colorNeighbors[i]; float rI = rIs[i]; - if (neighbor < 1.0 - EPS) { + if (neighbor > EPS) { float depthDelta = abs(neighbor - depth); float weight = (1.0 - rI / 2.0) * - (1.0 - min(1.0, depthDelta / max(1e-5, rangeParameter))); + (1.0 - min(1.0, depthDelta / max(1e-38, rangeParameter))); depthAccum += neighbor * weight; colorAccum += colorNeighbor * weight; @@ -161,5 +162,5 @@ void main() { } colorOut = finalColor; - gl_FragDepth = finalDepth; + depthOut = czm_packDepth(finalDepth); } From 636a423ce9f1754f837125b410d65490884b9795 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Thu, 29 Jun 2017 16:18:16 -0400 Subject: [PATCH 048/240] Adjusts defaults for the region growing parameter --- .../gallery/3D Tiles Point Cloud Post Processing.html | 2 +- Source/Scene/Cesium3DTileset.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html index a8ce046043c6..1ddf60c90bc0 100644 --- a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html +++ b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html @@ -49,7 +49,7 @@ Region Growing Range Parameter - + diff --git a/Source/Scene/Cesium3DTileset.js b/Source/Scene/Cesium3DTileset.js index 3f575fbdfa63..31f7cc8bbda3 100644 --- a/Source/Scene/Cesium3DTileset.js +++ b/Source/Scene/Cesium3DTileset.js @@ -731,7 +731,7 @@ define([ this.pointCloudPostProcessorOptions = { enabled : defaultValue(options.enabled, true), occlusionAngle : defaultValue(options.occlusionAngle, 0.1), - rangeParameter : defaultValue(options.rangeParameter, 0.01), + rangeParameter : defaultValue(options.rangeParameter, 2e-38), neighborhoodHalfWidth : defaultValue(options.neighborhoodHalfWidth, 4), numRegionGrowingPasses : defaultValue(options.numRegionGrowingPasses, 2) }; From 36665930907de2921d8f0054c4e0e574acb72c23 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Thu, 29 Jun 2017 16:32:12 -0400 Subject: [PATCH 049/240] Removes unnecessary write --- Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl index fc6abcd1c84f..ffb4526bff5e 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl @@ -163,7 +163,6 @@ void main() { // The solid angle is too small, so we occlude this point if (accumulator < (2.0 * PI) * (1.0 - occlusionAngle)) { - depthOut = czm_packDepth(0.0); discard; } else { // This is the depth of this pixel... assuming that it's valid. From dcaafafe9289663b4273c78da151d60d16555845 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Thu, 29 Jun 2017 16:37:34 -0400 Subject: [PATCH 050/240] Fixes the GLSL ES 1.00 shaders --- .../PointOcclusionPassGL1.glsl | 2 +- .../RegionGrowingPassGL1.glsl | 21 ++++++++++--------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl index 724fd19d8ae8..a83fb1957938 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl @@ -231,5 +231,5 @@ void main() { // This is the depth of this pixel... assuming that it's valid. float linearizedDepth = (-centerPosition.z - near) / (far - near); - gl_FragDepthEXT = linearizedDepth; + gl_FragData[0] = czm_packDepth(linearizedDepth); } diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl index 030267e0ab08..08f1dcf23238 100644 --- a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl @@ -1,9 +1,10 @@ #extension GL_EXT_frag_depth : enable +#extension GL_EXT_draw_buffers : enable #define neighborhoodHalfWidth 1 // TUNABLE PARAMETER -- half-width of region-growing kernel #define neighborhoodFullWidth 3 #define neighborhoodSize 8 -#define EPS 1e-6 +#define EPS 1e-8 #define SQRT2 1.414213562 uniform sampler2D pointCloud_colorTexture; @@ -49,15 +50,15 @@ void fastMedian3(in float[neighborhoodSize] neighbors, out vec4 outColor) { comparisonNetwork8(neighbors, colorNeighbors); - for (int i = neighborhoodSize - 1; i >= 0; i--) { - if (neighbors[i] <= 1.0 - EPS) { - outDepth = neighbors[i / 2]; - outColor = colorNeighbors[i / 2]; + for (int i = 0; i < neighborhoodSize; i++) { + if (neighbors[i] > EPS) { + outDepth = neighbors[i + (neighborhoodSize - 1 - i) / 2]; + outColor = colorNeighbors[i + (neighborhoodSize - 1 - i) / 2]; return; } } - outDepth = 1.0; + outDepth = 0.0; outColor = vec4(0, 0, 0, 0); } @@ -122,7 +123,7 @@ void main() { loadIntoArray(depthNeighbors, colorNeighbors); // If our depth value is invalid - if (depth > 1.0 - EPS) { + if (depth < EPS) { #if neighborhoodFullWidth == 3 fastMedian3(depthNeighbors, colorNeighbors, finalDepth, finalColor); #else @@ -140,7 +141,7 @@ void main() { vec4 colorNeighbor = colorNeighbors[i]; float rI = rIs[i]; - if (neighbor < 1.0 - EPS) { + if (neighbor > EPS) { float depthDelta = abs(neighbor - depth); float weight = @@ -159,6 +160,6 @@ void main() { } } - gl_FragColor = finalColor; - gl_FragDepthEXT = finalDepth; + gl_FragData[0] = finalColor; + gl_FragData[1] = czm_packDepth(finalDepth); } From f81d3569641a477fbbde9d49346a8f902b56e123 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Thu, 29 Jun 2017 16:51:06 -0400 Subject: [PATCH 051/240] Code review fixes --- Source/Scene/PointCloudPostProcessor.js | 56 ++++++++++++------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index c86bbdefa9b8..8e7fd406a620 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -143,29 +143,29 @@ define([ }); } - /* We want to reuse textures as much as possible, so here's the order - * of events: - * - * 1. We render normally to our prior: - * * Color -> 0 - * * Depth -> dirty ("dirty depth") - * * EC -> 0 - * 2. Then we perform the screen-space point occlusion stage with color[0] and EC: - * * No color - * * Pseudo-depth -> 0 - * * No EC - * 3a. Then we perform the region growing stage with color[0] and depth[0]: - * * Color -> 1 - * * Pseudo-depth -> 1 - * 3b. We do the region growing stage again with color[1] and depth[1]: - * * Color -> 0 - * * Pseudo-depth -> 0 - * 3c. Repeat steps 3a and 3b until all holes are filled and/or we run - * out of time. - */ - + // (EC stands for eye-space) + // + // We want to reuse textures as much as possible, so here's the order + // of events: + // + // 1. We render normally to our prior: + // * Color -> 0 + // * Depth -> dirty ("dirty depth") + // * EC -> 0 + // 2. Then we perform the screen-space point occlusion stage with color[0] and EC: + // * No color + // * Pseudo-depth -> 0 + // * No EC + // 3a. Then we perform the region growing stage with color[0] and depth[0]: + // * Color -> 1 + // * Pseudo-depth -> 1 + // 3b. We do the region growing stage again with color[1] and depth[1]: + // * Color -> 0 + // * Pseudo-depth -> 0 + // 3c. Repeat steps 3a and 3b until all holes are filled and/or we run + // out of time. processor._framebuffers = { - "prior": new Framebuffer({ + prior : new Framebuffer({ context : context, colorTextures : [ colorTextures[0], @@ -174,17 +174,17 @@ define([ depthStencilTexture : dirty, destroyAttachments : false }), - "screenSpacePass": new Framebuffer({ + screenSpacePass : new Framebuffer({ context : context, colorTextures : [depthTextures[0]], destroyAttachments : false }), - "regionGrowingPassA": new Framebuffer({ + regionGrowingPassA : new Framebuffer({ context : context, colorTextures : [colorTextures[1], depthTextures[1]], destroyAttachments : false }), - "regionGrowingPassB": new Framebuffer({ + regionGrowingPassB : new Framebuffer({ context: context, colorTextures: [colorTextures[0], depthTextures[0]], destroyAttachments: false @@ -197,8 +197,8 @@ define([ } function replaceConstants(sourceStr, constantName, replacement) { - var r = "#define\\s" + constantName + "\\s([0-9.]+)"; - return sourceStr.replace(new RegExp(r, "g"), "#define " + constantName + " " + replacement); + var r = '#define\\s' + constantName + '\\s([0-9.]+)'; + return sourceStr.replace(new RegExp(r, 'g'), '#define ' + constantName + ' ' + replacement); }; function pointOcclusionStage(processor, context) { @@ -216,7 +216,7 @@ define([ var pointOcclusionStr = replaceConstants( (context.webgl2) ? PointOcclusionPassGL2 : PointOcclusionPassGL1, - "neighborhoodHalfWidth", + 'neighborhoodHalfWidth', processor.neighborhoodHalfWidth ); From 92c042241eec855148614750025f2e608d1438e3 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Fri, 30 Jun 2017 14:24:03 -0400 Subject: [PATCH 052/240] Adds distance-based depth and triangle wave method --- LICENSE.md | 22 +++ Source/Scene/Cesium3DTileset.js | 2 +- Source/Scene/PointCloudPostProcessor.js | 3 + .../PointOcclusionPassGL2.glsl | 171 +++++++++++++++++- .../RegionGrowingPassGL2.glsl | 2 +- 5 files changed, 195 insertions(+), 5 deletions(-) diff --git a/LICENSE.md b/LICENSE.md index db1b62612992..2a76662d2bc5 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -451,6 +451,28 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +### deck.gl + +Copyright (c) 2015 - 2017 Uber Technologies, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + Tests ===== diff --git a/Source/Scene/Cesium3DTileset.js b/Source/Scene/Cesium3DTileset.js index 31f7cc8bbda3..513747710ef9 100644 --- a/Source/Scene/Cesium3DTileset.js +++ b/Source/Scene/Cesium3DTileset.js @@ -731,7 +731,7 @@ define([ this.pointCloudPostProcessorOptions = { enabled : defaultValue(options.enabled, true), occlusionAngle : defaultValue(options.occlusionAngle, 0.1), - rangeParameter : defaultValue(options.rangeParameter, 2e-38), + rangeParameter : defaultValue(options.rangeParameter, 0.001), neighborhoodHalfWidth : defaultValue(options.neighborhoodHalfWidth, 4), numRegionGrowingPasses : defaultValue(options.numRegionGrowingPasses, 2) }; diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 8e7fd406a620..7bb8f5791219 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -211,6 +211,9 @@ define([ }, occlusionAngle : function() { return processor.occlusionAngle; + }, + ONE : function() { + return 1.0; } }; diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl index ffb4526bff5e..0b854607597b 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl @@ -11,6 +11,11 @@ #define neighborhoodHalfWidth 4 // TUNABLE PARAMETER -- half-width of point-occlusion neighborhood #define numSectors 8 +#define PERIOD 1e-5 +#define USE_TRIANGLE + +uniform float ONE; + uniform sampler2D pointCloud_colorTexture; uniform sampler2D pointCloud_ECTexture; uniform float occlusionAngle; @@ -18,6 +23,118 @@ in vec2 v_textureCoordinates; layout(location = 0) out vec4 depthOut; +// TODO: Include Uber copyright + +vec2 split(float a) { + const float SPLIT = 4097.0; + float t = a * SPLIT; + float a_hi = t * ONE - (t - a); + float a_lo = a * ONE - a_hi; + return vec2(a_hi, a_lo); +} + +vec2 twoSub(float a, float b) { + float s = (a - b); + float v = (s * ONE - a) * ONE; + float err = (a - (s - v) * ONE) * ONE * ONE * ONE - (b + v); + return vec2(s, err); +} + +vec2 twoSum(float a, float b) { + float s = (a + b); + float v = (s * ONE - a) * ONE; + float err = (a - (s - v) * ONE) * ONE * ONE * ONE + (b - v); + return vec2(s, err); +} + +vec2 twoSqr(float a) { + float prod = a * a; + vec2 a_fp64 = split(a); + float err = ((a_fp64.x * a_fp64.x - prod) * ONE + 2.0 * a_fp64.x * + a_fp64.y * ONE * ONE) + a_fp64.y * a_fp64.y * ONE * ONE * ONE; + return vec2(prod, err); +} + +vec2 twoProd(float a, float b) { + float prod = a * b; + vec2 a_fp64 = split(a); + vec2 b_fp64 = split(b); + float err = ((a_fp64.x * b_fp64.x - prod) + a_fp64.x * b_fp64.y + + a_fp64.y * b_fp64.x) + a_fp64.y * b_fp64.y; + return vec2(prod, err); +} + +vec2 quickTwoSum(float a, float b) { + float sum = (a + b) * ONE; + float err = b - (sum - a) * ONE; + return vec2(sum, err); +} + +vec2 sum_fp64(vec2 a, vec2 b) { + vec2 s, t; + s = twoSum(a.x, b.x); + t = twoSum(a.y, b.y); + s.y += t.x; + s = quickTwoSum(s.x, s.y); + s.y += t.y; + s = quickTwoSum(s.x, s.y); + return s; +} + +vec2 sub_fp64(vec2 a, vec2 b) { + vec2 s, t; + s = twoSub(a.x, b.x); + t = twoSub(a.y, b.y); + s.y += t.x; + s = quickTwoSum(s.x, s.y); + s.y += t.y; + s = quickTwoSum(s.x, s.y); + return s; +} + +vec2 mul_fp64(vec2 a, vec2 b) { + vec2 prod = twoProd(a.x, b.x); + // y component is for the error + prod.y += a.x * b.y; + prod.y += a.y * b.x; + prod = quickTwoSum(prod.x, prod.y); + return prod; +} + +vec2 divFP64(in vec2 a, in vec2 b) { + float xn = 1.0 / b.x; + vec2 yn = a * xn; + float diff = (sub_fp64(a, mul_fp64(b, yn))).x; + vec2 prod = twoProd(xn, diff); + return sum_fp64(yn, prod); +} + +vec2 sqrt_fp64(vec2 a) { + if (a.x == 0.0 && a.y == 0.0) return vec2(0.0, 0.0); + if (a.x < 0.0) return vec2(0.0 / 0.0, 0.0 / 0.0); + float x = 1.0 / sqrt(a.x); + float yn = a.x * x; + vec2 yn_sqr = twoSqr(yn) * ONE; + float diff = sub_fp64(a, yn_sqr).x; + vec2 prod = twoProd(x * 0.5, diff); + return sum_fp64(vec2(yn, 0.0), prod); +} + +float triangle(in float x, in float period) { + return abs(mod(x, period) / period - 0.5) + EPS; +} + +float triangleFP64(in vec2 x, in float period) { + float lowPrecision = x.x + x.y; + vec2 floorTerm = split(floor(lowPrecision / period)); + vec2 periodHighPrecision = split(period); + vec2 term2 = mul_fp64(periodHighPrecision, floorTerm); + vec2 moduloTerm = sub_fp64(x, term2); + vec2 normalized = divFP64(moduloTerm, periodHighPrecision); + normalized = sub_fp64(normalized, split(0.5)); + return abs(normalized.x + normalized.y) + EPS; +} + float acosFast(in float inX) { float x = abs(inX); float res = ((C3 * x + C2) * x + C1) * x + C0; // p(x) @@ -165,8 +282,56 @@ void main() { if (accumulator < (2.0 * PI) * (1.0 - occlusionAngle)) { discard; } else { - // This is the depth of this pixel... assuming that it's valid. - float linearizedDepth = (-centerPosition.z - near) / (far - near); - depthOut = czm_packDepth(linearizedDepth); + // Write out the distance of the point + // + // We use the distance of the point rather than + // the linearized depth. This is because we want + // to encode as much information about position disparities + // between points as we can, and the z-values of + // neighboring points are usually very similar. + // On the other hand, the x-values and y-values are + // usually fairly different. +#ifdef USE_TRIANGLE + // We can get even more accuracy by passing the 64-bit + // distance into a triangle wave function that + // uses 64-bit primitives internally. The region + // growing pass only cares about deltas between + // different pixels, so we just have to ensure that + // the period of triangle function is greater than that + // of the largest possible delta can arise between + // different points. + // + // The triangle function is C0 continuous, which avoids + // artifacts from discontinuities. That said, I have noticed + // some inexplicable artifacts occasionally, so please + // disable this optimization if that becomes an issue. + // + // It's important that the period of the triangle function + // is at least two orders of magnitude greater than + // the average depth delta that we are likely to come + // across. The triangle function works because we have + // some assumption of locality in the depth domain. + // Massive deltas break that locality -- but that's + // actually not an issue. Deltas that are larger than + // the period function will be "wrapped around", and deltas + // that are much larger than the period function may be + // "wrapped around" many times. A similar process occurs + // in many random number generators. The resulting delta + // is usually at least an order of magnitude greater than + // the average delta, so it won't even be considered in + // the region growing pass. + vec2 highPrecisionX = split(centerPosition.x); + vec2 highPrecisionY = split(centerPosition.y); + vec2 highPrecisionZ = split(centerPosition.z); + vec2 highPrecisionLength = + sqrt_fp64(sum_fp64(sum_fp64( + mul_fp64(highPrecisionX, highPrecisionX), + mul_fp64(highPrecisionY, highPrecisionY)), + mul_fp64(highPrecisionZ, highPrecisionZ))); + float triangleResult = triangleFP64(highPrecisionLength, PERIOD); + depthOut = czm_packDepth(triangleResult); +#else + depthOut = czm_packDepth(length(centerPosition)); +#endif } } diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl index 1b9b4b5077d2..3a03a3fd9cb0 100644 --- a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl @@ -124,7 +124,7 @@ void main() { loadIntoArray(depthNeighbors, colorNeighbors); // If our depth value is invalid - if (depth < EPS) { + if (abs(depth) < EPS) { #if neighborhoodFullWidth == 3 fastMedian3(depthNeighbors, colorNeighbors, finalDepth, finalColor); #else From 2a8e8421af1c4ad616d7d057263bb7e88dd1cc32 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Fri, 30 Jun 2017 14:28:17 -0400 Subject: [PATCH 053/240] Adds abs() calls for checks against the depth --- Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl index 3a03a3fd9cb0..d2c018ffda12 100644 --- a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl @@ -52,7 +52,7 @@ void fastMedian3(in float[neighborhoodSize] neighbors, comparisonNetwork8(neighbors, colorNeighbors); for (int i = 0; i < neighborhoodSize; i++) { - if (neighbors[i] > EPS) { + if (abs(neighbors[i]) > EPS) { outDepth = neighbors[i + (neighborhoodSize - 1 - i) / 2]; outColor = colorNeighbors[i + (neighborhoodSize - 1 - i) / 2]; return; @@ -142,7 +142,7 @@ void main() { vec4 colorNeighbor = colorNeighbors[i]; float rI = rIs[i]; - if (neighbor > EPS) { + if (abs(neighbor) > EPS) { float depthDelta = abs(neighbor - depth); float weight = @@ -155,7 +155,7 @@ void main() { } } - if (depthAccum > EPS) { + if (abs(depthAccum) > EPS) { finalDepth = depthAccum / normalization; finalColor = colorAccum / normalization; } From f73ba356eec1911883eb2299b19d7e5aec4a9998 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Fri, 30 Jun 2017 14:32:53 -0400 Subject: [PATCH 054/240] Adds multifrustrum support to the GLSL ES 1.00 shaders --- .../PointOcclusionPassGL1.glsl | 174 +++++++++++++++++- .../RegionGrowingPassGL1.glsl | 8 +- 2 files changed, 174 insertions(+), 8 deletions(-) diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl index a83fb1957938..c6ef25e78f68 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl @@ -11,11 +11,129 @@ #define neighborhoodHalfWidth 4 // TUNABLE PARAMETER -- half-width of point-occlusion neighborhood #define numSectors 8 + +#define PERIOD 1e-5 +#define USE_TRIANGLE + +uniform float ONE; + uniform sampler2D pointCloud_colorTexture; uniform sampler2D pointCloud_ECTexture; uniform float occlusionAngle; varying vec2 v_textureCoordinates; +// TODO: Include Uber copyright + +vec2 split(float a) { + const float SPLIT = 4097.0; + float t = a * SPLIT; + float a_hi = t * ONE - (t - a); + float a_lo = a * ONE - a_hi; + return vec2(a_hi, a_lo); +} + +vec2 twoSub(float a, float b) { + float s = (a - b); + float v = (s * ONE - a) * ONE; + float err = (a - (s - v) * ONE) * ONE * ONE * ONE - (b + v); + return vec2(s, err); +} + +vec2 twoSum(float a, float b) { + float s = (a + b); + float v = (s * ONE - a) * ONE; + float err = (a - (s - v) * ONE) * ONE * ONE * ONE + (b - v); + return vec2(s, err); +} + +vec2 twoSqr(float a) { + float prod = a * a; + vec2 a_fp64 = split(a); + float err = ((a_fp64.x * a_fp64.x - prod) * ONE + 2.0 * a_fp64.x * + a_fp64.y * ONE * ONE) + a_fp64.y * a_fp64.y * ONE * ONE * ONE; + return vec2(prod, err); +} + +vec2 twoProd(float a, float b) { + float prod = a * b; + vec2 a_fp64 = split(a); + vec2 b_fp64 = split(b); + float err = ((a_fp64.x * b_fp64.x - prod) + a_fp64.x * b_fp64.y + + a_fp64.y * b_fp64.x) + a_fp64.y * b_fp64.y; + return vec2(prod, err); +} + +vec2 quickTwoSum(float a, float b) { + float sum = (a + b) * ONE; + float err = b - (sum - a) * ONE; + return vec2(sum, err); +} + +vec2 sum_fp64(vec2 a, vec2 b) { + vec2 s, t; + s = twoSum(a.x, b.x); + t = twoSum(a.y, b.y); + s.y += t.x; + s = quickTwoSum(s.x, s.y); + s.y += t.y; + s = quickTwoSum(s.x, s.y); + return s; +} + +vec2 sub_fp64(vec2 a, vec2 b) { + vec2 s, t; + s = twoSub(a.x, b.x); + t = twoSub(a.y, b.y); + s.y += t.x; + s = quickTwoSum(s.x, s.y); + s.y += t.y; + s = quickTwoSum(s.x, s.y); + return s; +} + +vec2 mul_fp64(vec2 a, vec2 b) { + vec2 prod = twoProd(a.x, b.x); + // y component is for the error + prod.y += a.x * b.y; + prod.y += a.y * b.x; + prod = quickTwoSum(prod.x, prod.y); + return prod; +} + +vec2 divFP64(in vec2 a, in vec2 b) { + float xn = 1.0 / b.x; + vec2 yn = a * xn; + float diff = (sub_fp64(a, mul_fp64(b, yn))).x; + vec2 prod = twoProd(xn, diff); + return sum_fp64(yn, prod); +} + +vec2 sqrt_fp64(vec2 a) { + if (a.x == 0.0 && a.y == 0.0) return vec2(0.0, 0.0); + if (a.x < 0.0) return vec2(0.0 / 0.0, 0.0 / 0.0); + float x = 1.0 / sqrt(a.x); + float yn = a.x * x; + vec2 yn_sqr = twoSqr(yn) * ONE; + float diff = sub_fp64(a, yn_sqr).x; + vec2 prod = twoProd(x * 0.5, diff); + return sum_fp64(vec2(yn, 0.0), prod); +} + +float triangle(in float x, in float period) { + return abs(mod(x, period) / period - 0.5) + EPS; +} + +float triangleFP64(in vec2 x, in float period) { + float lowPrecision = x.x + x.y; + vec2 floorTerm = split(floor(lowPrecision / period)); + vec2 periodHighPrecision = split(period); + vec2 term2 = mul_fp64(periodHighPrecision, floorTerm); + vec2 moduloTerm = sub_fp64(x, term2); + vec2 normalized = divFP64(moduloTerm, periodHighPrecision); + normalized = sub_fp64(normalized, split(0.5)); + return abs(normalized.x + normalized.y) + EPS; +} + float acosFast(in float inX) { float x = abs(inX); float res = ((C3 * x + C2) * x + C1) * x + C0; // p(x) @@ -227,9 +345,57 @@ void main() { // The solid angle is too small, so we occlude this point if (accumulator < (2.0 * PI) * (1.0 - occlusionAngle)) { discard; + } else { + // Write out the distance of the point + // + // We use the distance of the point rather than + // the linearized depth. This is because we want + // to encode as much information about position disparities + // between points as we can, and the z-values of + // neighboring points are usually very similar. + // On the other hand, the x-values and y-values are + // usually fairly different. +#ifdef USE_TRIANGLE + // We can get even more accuracy by passing the 64-bit + // distance into a triangle wave function that + // uses 64-bit primitives internally. The region + // growing pass only cares about deltas between + // different pixels, so we just have to ensure that + // the period of triangle function is greater than that + // of the largest possible delta can arise between + // different points. + // + // The triangle function is C0 continuous, which avoids + // artifacts from discontinuities. That said, I have noticed + // some inexplicable artifacts occasionally, so please + // disable this optimization if that becomes an issue. + // + // It's important that the period of the triangle function + // is at least two orders of magnitude greater than + // the average depth delta that we are likely to come + // across. The triangle function works because we have + // some assumption of locality in the depth domain. + // Massive deltas break that locality -- but that's + // actually not an issue. Deltas that are larger than + // the period function will be "wrapped around", and deltas + // that are much larger than the period function may be + // "wrapped around" many times. A similar process occurs + // in many random number generators. The resulting delta + // is usually at least an order of magnitude greater than + // the average delta, so it won't even be considered in + // the region growing pass. + vec2 highPrecisionX = split(centerPosition.x); + vec2 highPrecisionY = split(centerPosition.y); + vec2 highPrecisionZ = split(centerPosition.z); + vec2 highPrecisionLength = + sqrt_fp64(sum_fp64(sum_fp64( + mul_fp64(highPrecisionX, highPrecisionX), + mul_fp64(highPrecisionY, highPrecisionY)), + mul_fp64(highPrecisionZ, highPrecisionZ))); + float triangleResult = triangleFP64(highPrecisionLength, PERIOD); + gl_FragData[0] = czm_packDepth(triangleResult); +#else + gl_FragData[0] = czm_packDepth(length(centerPosition)); +#endif } - - // This is the depth of this pixel... assuming that it's valid. - float linearizedDepth = (-centerPosition.z - near) / (far - near); - gl_FragData[0] = czm_packDepth(linearizedDepth); } diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl index 08f1dcf23238..5ff240b54fb1 100644 --- a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl @@ -51,7 +51,7 @@ void fastMedian3(in float[neighborhoodSize] neighbors, comparisonNetwork8(neighbors, colorNeighbors); for (int i = 0; i < neighborhoodSize; i++) { - if (neighbors[i] > EPS) { + if (abs(neighbors[i]) > EPS) { outDepth = neighbors[i + (neighborhoodSize - 1 - i) / 2]; outColor = colorNeighbors[i + (neighborhoodSize - 1 - i) / 2]; return; @@ -123,7 +123,7 @@ void main() { loadIntoArray(depthNeighbors, colorNeighbors); // If our depth value is invalid - if (depth < EPS) { + if (abs(depth) < EPS) { #if neighborhoodFullWidth == 3 fastMedian3(depthNeighbors, colorNeighbors, finalDepth, finalColor); #else @@ -141,7 +141,7 @@ void main() { vec4 colorNeighbor = colorNeighbors[i]; float rI = rIs[i]; - if (neighbor > EPS) { + if (abs(neighbor) > EPS) { float depthDelta = abs(neighbor - depth); float weight = @@ -154,7 +154,7 @@ void main() { } } - if (depthAccum > EPS) { + if (abs(depthAccum) > EPS) { finalDepth = depthAccum / normalization; finalColor = colorAccum / normalization; } From 10a36b812730c25b481abb4da9c81c6ca02594d3 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Thu, 6 Jul 2017 14:54:02 -0400 Subject: [PATCH 055/240] Adds parameter tuning for the region growing operator --- Source/Scene/Cesium3DTileset.js | 10 +- Source/Scene/PointCloudPostProcessor.js | 117 +++++++++-- .../DensityEstimationPass.glsl | 47 +++++ .../PointOcclusionPassGL2.glsl | 198 +++++++++--------- .../RegionGrowingPassGL2.glsl | 28 ++- 5 files changed, 284 insertions(+), 116 deletions(-) create mode 100644 Source/Shaders/PostProcessFilters/DensityEstimationPass.glsl diff --git a/Source/Scene/Cesium3DTileset.js b/Source/Scene/Cesium3DTileset.js index 513747710ef9..5f3421319dce 100644 --- a/Source/Scene/Cesium3DTileset.js +++ b/Source/Scene/Cesium3DTileset.js @@ -733,7 +733,10 @@ define([ occlusionAngle : defaultValue(options.occlusionAngle, 0.1), rangeParameter : defaultValue(options.rangeParameter, 0.001), neighborhoodHalfWidth : defaultValue(options.neighborhoodHalfWidth, 4), - numRegionGrowingPasses : defaultValue(options.numRegionGrowingPasses, 2) + numRegionGrowingPasses : defaultValue(options.numRegionGrowingPasses, 4), + densityHalfWidth : defaultValue(options.densityHalfWidth, 4), + neighborhoodVectorSize : defaultValue(options.neighborhoodVectorSize, 10.0), + densityViewEnabled : defaultValue(options.densityViewEnabled, false) }; this._pointCloudPostProcessor = new PointCloudPostProcessor(this.pointCloudPostProcessorOptions); @@ -1619,7 +1622,10 @@ define([ occlusionAngle : tileset.pointCloudPostProcessorOptions.occlusionAngle, rangeParameter : tileset.pointCloudPostProcessorOptions.rangeParameter, neighborhoodHalfWidth : tileset.pointCloudPostProcessorOptions.neighborhoodHalfWidth, - numRegionGrowingPasses : tileset.pointCloudPostProcessorOptions.numRegionGrowingPasses + numRegionGrowingPasses : tileset.pointCloudPostProcessorOptions.numRegionGrowingPasses, + densityHalfWidth : tileset.pointCloudPostProcessorOptions.densityHalfWidth, + neighborhoodVectorSize : tileset.pointCloudPostProcessorOptions.neighborhoodVectorSize, + densityViewEnabled : tileset.pointCloudPostProcessorOptions.densityViewEnabled }); } diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 7bb8f5791219..3596d5106c2b 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -22,7 +22,8 @@ define([ '../Shaders/PostProcessFilters/PointOcclusionPassGL1', '../Shaders/PostProcessFilters/RegionGrowingPassGL1', '../Shaders/PostProcessFilters/PointOcclusionPassGL2', - '../Shaders/PostProcessFilters/RegionGrowingPassGL2' + '../Shaders/PostProcessFilters/RegionGrowingPassGL2', + '../Shaders/PostProcessFilters/DensityEstimationPass' ], function( Color, defined, @@ -47,6 +48,7 @@ define([ RegionGrowingPassGL1, PointOcclusionPassGL2, RegionGrowingPassGL2, + DensityEstimationPass ) { 'use strict'; @@ -58,6 +60,7 @@ define([ this._colorTextures = undefined; this._ecTexture = undefined; this._depthTextures = undefined; + this._densityTexture = undefined; this._dirty = undefined; this._drawCommands = undefined; this._blendCommand = undefined; @@ -67,6 +70,9 @@ define([ this.rangeParameter = options.rangeParameter; this.neighborhoodHalfWidth = options.neighborhoodHalfWidth; this.numRegionGrowingPasses = options.numRegionGrowingPasses; + this.densityHalfWidth = options.densityHalfWidth; + this.neighborhoodVectorSize = options.neighborhoodVectorSize; + this.densityViewEnabled = options.densityViewEnabled; } function createSampler() { @@ -81,6 +87,7 @@ define([ function destroyFramebuffers(processor) { processor._depthTextures[0].destroy(); processor._depthTextures[1].destroy(); + processor._densityTexture.destroy(); processor._dirty.destroy(); processor._colorTextures[0].destroy(); processor._colorTextures[1].destroy(); @@ -114,6 +121,15 @@ define([ sampler : createSampler() }); + var densityMap = new Texture({ + context : context, + width : screenWidth, + height : screenHeight, + pixelFormat : PixelFormat.RGBA, + pixelDatatype : PixelDatatype.UNSIGNED_BYTE, + sampler : createSampler() + }); + var dirty = new Texture({ context: context, width: screenWidth, @@ -179,6 +195,11 @@ define([ colorTextures : [depthTextures[0]], destroyAttachments : false }), + densityEstimationPass : new Framebuffer({ + context : context, + colorTextures : [densityMap], + destroyAttachments : false + }), regionGrowingPassA : new Framebuffer({ context : context, colorTextures : [colorTextures[1], depthTextures[1]], @@ -191,15 +212,26 @@ define([ }) }; processor._depthTextures = depthTextures; + processor._densityTexture = densityMap; processor._colorTextures = colorTextures; processor._ecTexture = ecTexture; processor._dirty = dirty; } function replaceConstants(sourceStr, constantName, replacement) { - var r = '#define\\s' + constantName + '\\s([0-9.]+)'; - return sourceStr.replace(new RegExp(r, 'g'), '#define ' + constantName + ' ' + replacement); - }; + var r; + if (typeof(replacement) === "boolean") { + if (replacement === false) { + r = '#define\\s' + constantName; + return sourceStr.replace(new RegExp(r, 'g'), '/*#define ' + constantName + '*/'); + } else { + return sourceStr; + } + } else { + r = '#define\\s' + constantName + '\\s([0-9.]+)'; + return sourceStr.replace(new RegExp(r, 'g'), '#define ' + constantName + ' ' + replacement); + } + } function pointOcclusionStage(processor, context) { var uniformMap = { @@ -233,6 +265,37 @@ define([ }); } + function densityEstimationStage(processor, context) { + var uniformMap = { + pointCloud_depthTexture : function() { + return processor._depthTextures[0]; + }, + neighborhoodVectorSize : function() { + return processor.neighborhoodVectorSize; + } + }; + + var densityEstimationStr = replaceConstants( + DensityEstimationPass, + 'neighborhoodHalfWidth', + processor.densityHalfWidth + ); + + if (context.webgl2) { + densityEstimationStr = GLSLModernizer. + glslModernizeShaderText(densityEstimationStr, true, true); + } + + return context.createViewportQuadCommand(densityEstimationStr, { + uniformMap : uniformMap, + framebuffer : processor._framebuffers.densityEstimationPass, + renderState : RenderState.fromCache({ + }), + pass : Pass.CESIUM_3D_TILE, + owner : processor + }); + } + function regionGrowingStage(processor, context, iteration) { var i = iteration % 2; @@ -243,8 +306,17 @@ define([ pointCloud_depthTexture : function() { return processor._depthTextures[i]; }, + pointCloud_densityTexture : function() { + return processor._densityTexture; + }, rangeParameter : function() { return processor.rangeParameter; + }, + densityHalfWidth : function() { + return processor.densityHalfWidth; + }, + iterationNumber : function() { + return iteration; } }; @@ -255,6 +327,13 @@ define([ var regionGrowingPassStr = (context.webgl2) ? RegionGrowingPassGL2 : RegionGrowingPassGL1; + + regionGrowingPassStr = replaceConstants( + regionGrowingPassStr, + 'DENSITY_VIEW', + processor.densityViewEnabled + ); + return context.createViewportQuadCommand(regionGrowingPassStr, { uniformMap : uniformMap, framebuffer : framebuffer, @@ -271,9 +350,10 @@ define([ var i; drawCommands[0] = pointOcclusionStage(processor, context); + drawCommands[1] = densityEstimationStage(processor, context); for (i = 0; i < numRegionGrowingPasses; i++) { - drawCommands[i + 1] = regionGrowingStage(processor, context, i); + drawCommands[i + 2] = regionGrowingStage(processor, context, i); } for (i = 0; i < drawCommands.length; i++) { @@ -294,7 +374,6 @@ define([ }); } - // TODO : point cloud depth information is lost var blendFS = 'uniform sampler2D pointCloud_colorTexture; \n' + 'varying vec2 v_textureCoordinates; \n' + @@ -430,14 +509,20 @@ define([ var dirty = false; // Set options here - if (options.occlusionAngle != this.occlusionAngle || - options.rangeParameter != this.rangeParameter || - options.neighborhoodHalfWidth != this.neighborhoodHalfWidth || - options.numRegionGrowingPasses != this.numRegionGrowingPasses) { + if (options.occlusionAngle !== this.occlusionAngle || + options.rangeParameter !== this.rangeParameter || + options.neighborhoodHalfWidth !== this.neighborhoodHalfWidth || + options.numRegionGrowingPasses !== this.numRegionGrowingPasses || + options.densityHalfWidth !== this.densityHalfWidth || + options.neighborhoodVectorSize !== this.neighborhoodVectorSize || + options.densityViewEnabled !== this.densityViewEnabled) { this.occlusionAngle = options.occlusionAngle; this.rangeParameter = options.rangeParameter; this.neighborhoodHalfWidth = options.neighborhoodHalfWidth; this.numRegionGrowingPasses = options.numRegionGrowingPasses; + this.densityHalfWidth = options.densityHalfWidth; + this.neighborhoodVectorSize = options.neighborhoodVectorSize; + this.densityViewEnabled = options.densityViewEnabled; dirty = true; } @@ -479,10 +564,14 @@ define([ if (i == 0) { commandList.push(clearCommands['screenSpacePass']); } else { - if (i % 2 == 1) - commandList.push(clearCommands['regionGrowingPassA']); - else - commandList.push(clearCommands['regionGrowingPassB']); + if (i == 1) { + commandList.push(clearCommands['densityEstimationPass']); + } else { + if (i % 2 == 0) + commandList.push(clearCommands['regionGrowingPassA']); + else + commandList.push(clearCommands['regionGrowingPassB']); + } } commandList.push(drawCommands[i]); diff --git a/Source/Shaders/PostProcessFilters/DensityEstimationPass.glsl b/Source/Shaders/PostProcessFilters/DensityEstimationPass.glsl new file mode 100644 index 000000000000..aeee1b062715 --- /dev/null +++ b/Source/Shaders/PostProcessFilters/DensityEstimationPass.glsl @@ -0,0 +1,47 @@ +#extension GL_EXT_draw_buffers : enable + +#define neighborhoodHalfWidth 4 // TUNABLE PARAMETER -- half-width of region-growing kernel + +#define EPS 1e-8 + +#define densityScaleFactor 32.0 + +uniform sampler2D pointCloud_depthTexture; +uniform float neighborhoodVectorSize; +varying vec2 v_textureCoordinates; + +void main() { + float center = czm_unpackDepth(texture2D(pointCloud_depthTexture, + v_textureCoordinates)); + ivec2 pos = ivec2(int(gl_FragCoord.x), int(gl_FragCoord.y)); + + int closestNeighbor = neighborhoodHalfWidth + 1; + vec2 neighborhoodAccum = vec2(0.0); + + if (center < EPS) { + for (int i = -neighborhoodHalfWidth; i <= neighborhoodHalfWidth; i++) { + for (int j = -neighborhoodHalfWidth; j <= neighborhoodHalfWidth; j++) { + ivec2 d = ivec2(i, j); + ivec2 pI = pos + d; + + float neighbor = czm_unpackDepth(texture2D(pointCloud_depthTexture, + vec2(pI) / czm_viewport.zw)); + if (neighbor < EPS || pI == pos) { + continue; + } + + neighborhoodAccum += vec2(d); + closestNeighbor = min(closestNeighbor, + max(abs(i), abs(j))); + } + } + + if (closestNeighbor <= neighborhoodHalfWidth && + length(neighborhoodAccum) < neighborhoodVectorSize) { + gl_FragData[0] = czm_packDepth(float(closestNeighbor) / + densityScaleFactor); + } else { + gl_FragData[0] = czm_packDepth(0.0); + } + } +} diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl index 0b854607597b..d4fb92a20f73 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl @@ -9,6 +9,7 @@ #define C3 -0.0186166 #define EPS 1e-6 #define neighborhoodHalfWidth 4 // TUNABLE PARAMETER -- half-width of point-occlusion neighborhood +#define neighborhoodSize 9 #define numSectors 8 #define PERIOD 1e-5 @@ -181,11 +182,12 @@ void main() { // The position of this pixel in 3D (i.e the position of the point) vec3 centerPosition = texture(pointCloud_ECTexture, v_textureCoordinates).xyz; + bool invalid = false; // If the EC of this pixel is zero, that means that it's not a valid // pixel. We don't care about reprojecting it. - if (length(centerPosition) == 0.) - discard; + if (length(centerPosition) < EPS) + invalid = true; // We split our region of interest (the point of interest and its // neighbors) @@ -231,107 +233,111 @@ void main() { continue; } - // sectors contains both possible sectors that the - // neighbor pixel could be in - ivec2 sectors = collapseSectors(getSectors(vec2(d))); - - // This is the offset of the horizon point from the center in 3D - // (a 3D analog of d) - vec3 c = neighborPosition - centerPosition; - - // Now we calculate the dot product between the vector - // from the viewer to the center and the vector to the horizon pixel. - // We normalize both vectors first because we only care about their relative - // directions - // TODO: Redo the math and figure out whether the result should be negated or not - float dotProduct = dot(normalize(viewer - centerPosition), - normalize(c)); - - // We calculate the angle that this horizon pixel would make - // in the cone. The dot product is be equal to - // |vec_1| * |vec_2| * cos(angle_between), and in this case, - // the magnitude of both vectors is 1 because they are both - // normalized. - float angle = acosFast(dotProduct); - - // This horizon point is behind the current point. That means that it can't - // occlude the current point. So we ignore it and move on. - if (angle > maxAngle) - continue; - // If we've found a horizon pixel, store it in the histogram - if (sh[sectors.x] > angle) { - sh[sectors.x] = angle; - } - if (sh[sectors.y] > angle) { - sh[sectors.y] = angle; + if (!invalid) { + // sectors contains both possible sectors that the + // neighbor pixel could be in + ivec2 sectors = collapseSectors(getSectors(vec2(d))); + + // This is the offset of the horizon point from the center in 3D + // (a 3D analog of d) + vec3 c = neighborPosition - centerPosition; + + // Now we calculate the dot product between the vector + // from the viewer to the center and the vector to the horizon pixel. + // We normalize both vectors first because we only care about their relative + // directions + // TODO: Redo the math and figure out whether the result should be negated or not + float dotProduct = dot(normalize(viewer - centerPosition), + normalize(c)); + + // We calculate the angle that this horizon pixel would make + // in the cone. The dot product is be equal to + // |vec_1| * |vec_2| * cos(angle_between), and in this case, + // the magnitude of both vectors is 1 because they are both + // normalized. + float angle = acosFast(dotProduct); + + // This horizon point is behind the current point. That means that it can't + // occlude the current point. So we ignore it and move on. + if (angle > maxAngle) + continue; + // If we've found a horizon pixel, store it in the histogram + if (sh[sectors.x] > angle) { + sh[sectors.x] = angle; + } + if (sh[sectors.y] > angle) { + sh[sectors.y] = angle; + } } } } - float accumulator = 0.0; - for (int i = 0; i < numSectors; i++) { - float angle = sh[i]; - // If the z component is less than zero, - // that means that there is no valid horizon pixel - if (angle <= 0.0 || angle > maxAngle) - angle = maxAngle; - accumulator += angle; - } + if (!invalid) { + float accumulator = 0.0; + for (int i = 0; i < numSectors; i++) { + float angle = sh[i]; + // If the z component is less than zero, + // that means that there is no valid horizon pixel + if (angle <= 0.0 || angle > maxAngle) + angle = maxAngle; + accumulator += angle; + } - // The solid angle is too small, so we occlude this point - if (accumulator < (2.0 * PI) * (1.0 - occlusionAngle)) { - discard; - } else { - // Write out the distance of the point - // - // We use the distance of the point rather than - // the linearized depth. This is because we want - // to encode as much information about position disparities - // between points as we can, and the z-values of - // neighboring points are usually very similar. - // On the other hand, the x-values and y-values are - // usually fairly different. + // The solid angle is too small, so we occlude this point + if (accumulator < (2.0 * PI) * (1.0 - occlusionAngle)) { + depthOut = czm_packDepth(0.0); + } else { + // Write out the distance of the point + // + // We use the distance of the point rather than + // the linearized depth. This is because we want + // to encode as much information about position disparities + // between points as we can, and the z-values of + // neighboring points are usually very similar. + // On the other hand, the x-values and y-values are + // usually fairly different. #ifdef USE_TRIANGLE - // We can get even more accuracy by passing the 64-bit - // distance into a triangle wave function that - // uses 64-bit primitives internally. The region - // growing pass only cares about deltas between - // different pixels, so we just have to ensure that - // the period of triangle function is greater than that - // of the largest possible delta can arise between - // different points. - // - // The triangle function is C0 continuous, which avoids - // artifacts from discontinuities. That said, I have noticed - // some inexplicable artifacts occasionally, so please - // disable this optimization if that becomes an issue. - // - // It's important that the period of the triangle function - // is at least two orders of magnitude greater than - // the average depth delta that we are likely to come - // across. The triangle function works because we have - // some assumption of locality in the depth domain. - // Massive deltas break that locality -- but that's - // actually not an issue. Deltas that are larger than - // the period function will be "wrapped around", and deltas - // that are much larger than the period function may be - // "wrapped around" many times. A similar process occurs - // in many random number generators. The resulting delta - // is usually at least an order of magnitude greater than - // the average delta, so it won't even be considered in - // the region growing pass. - vec2 highPrecisionX = split(centerPosition.x); - vec2 highPrecisionY = split(centerPosition.y); - vec2 highPrecisionZ = split(centerPosition.z); - vec2 highPrecisionLength = - sqrt_fp64(sum_fp64(sum_fp64( - mul_fp64(highPrecisionX, highPrecisionX), - mul_fp64(highPrecisionY, highPrecisionY)), - mul_fp64(highPrecisionZ, highPrecisionZ))); - float triangleResult = triangleFP64(highPrecisionLength, PERIOD); - depthOut = czm_packDepth(triangleResult); + // We can get even more accuracy by passing the 64-bit + // distance into a triangle wave function that + // uses 64-bit primitives internally. The region + // growing pass only cares about deltas between + // different pixels, so we just have to ensure that + // the period of triangle function is greater than that + // of the largest possible delta can arise between + // different points. + // + // The triangle function is C0 continuous, which avoids + // artifacts from discontinuities. That said, I have noticed + // some inexplicable artifacts occasionally, so please + // disable this optimization if that becomes an issue. + // + // It's important that the period of the triangle function + // is at least two orders of magnitude greater than + // the average depth delta that we are likely to come + // across. The triangle function works because we have + // some assumption of locality in the depth domain. + // Massive deltas break that locality -- but that's + // actually not an issue. Deltas that are larger than + // the period function will be "wrapped around", and deltas + // that are much larger than the period function may be + // "wrapped around" many times. A similar process occurs + // in many random number generators. The resulting delta + // is usually at least an order of magnitude greater than + // the average delta, so it won't even be considered in + // the region growing pass. + vec2 highPrecisionX = split(centerPosition.x); + vec2 highPrecisionY = split(centerPosition.y); + vec2 highPrecisionZ = split(centerPosition.z); + vec2 highPrecisionLength = + sqrt_fp64(sum_fp64(sum_fp64( + mul_fp64(highPrecisionX, highPrecisionX), + mul_fp64(highPrecisionY, highPrecisionY)), + mul_fp64(highPrecisionZ, highPrecisionZ))); + float triangleResult = triangleFP64(highPrecisionLength, PERIOD); + depthOut = czm_packDepth(triangleResult); #else - depthOut = czm_packDepth(length(centerPosition)); + depthOut = czm_packDepth(length(centerPosition)); #endif + } } } diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl index d2c018ffda12..65c98a9653b7 100644 --- a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl @@ -5,10 +5,15 @@ #define neighborhoodSize 8 #define EPS 1e-8 #define SQRT2 1.414213562 +#define densityScaleFactor 32.0 +#define DENSITY_VIEW uniform sampler2D pointCloud_colorTexture; +uniform sampler2D pointCloud_densityTexture; uniform sampler2D pointCloud_depthTexture; uniform float rangeParameter; +uniform int densityHalfWidth; +uniform int iterationNumber; in vec2 v_textureCoordinates; layout(location = 0) out vec4 colorOut; @@ -85,7 +90,8 @@ void loadIntoArray(inout float[neighborhoodSize] depthNeighbors, continue; } vec2 neighborCoords = vec2(vec2(d) + gl_FragCoord.xy) / czm_viewport.zw; - float neighbor = czm_unpackDepth(texture(pointCloud_depthTexture, neighborCoords)); + float neighbor = czm_unpackDepth(texture(pointCloud_depthTexture, + neighborCoords)); vec4 colorNeighbor = texture(pointCloud_colorTexture, neighborCoords); if (pastCenter) { depthNeighbors[(j + 1) * neighborhoodFullWidth + i] = @@ -104,7 +110,8 @@ void loadIntoArray(inout float[neighborhoodSize] depthNeighbors, void main() { vec4 color = texture(pointCloud_colorTexture, v_textureCoordinates); - float depth = czm_unpackDepth(texture(pointCloud_depthTexture, v_textureCoordinates)); + float depth = czm_unpackDepth(texture(pointCloud_depthTexture, + v_textureCoordinates)); vec4 finalColor = color; float finalDepth = depth; @@ -123,13 +130,22 @@ void main() { loadIntoArray(depthNeighbors, colorNeighbors); + float density = densityScaleFactor * czm_unpackDepth( + texture(pointCloud_densityTexture, v_textureCoordinates)); + // If our depth value is invalid if (abs(depth) < EPS) { + // If the area that we want to region grow is sufficently sparse + if (float(iterationNumber) <= density + EPS) { #if neighborhoodFullWidth == 3 - fastMedian3(depthNeighbors, colorNeighbors, finalDepth, finalColor); + fastMedian3(depthNeighbors, + colorNeighbors, + finalDepth, + finalColor); #else - genericMedianFinder(depthNeighbors, colorNeighbors, finalDepth, finalColor); + genericMedianFinder(depthNeighbors, colorNeighbors, finalDepth, finalColor); #endif + } } // Otherwise if our depth value is valid else { @@ -161,6 +177,10 @@ void main() { } } + #ifdef DENSITY_VIEW + colorOut = vec4(vec3(density / float(densityHalfWidth)), 1.0); + #else colorOut = finalColor; + #endif depthOut = czm_packDepth(finalDepth); } From cab382235919aa165242a116f12d398be39f4acd Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Thu, 6 Jul 2017 14:56:55 -0400 Subject: [PATCH 056/240] Updates sandcastle demo --- .../3D Tiles Point Cloud Post Processing.html | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html index 1ddf60c90bc0..006d652f250a 100644 --- a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html +++ b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html @@ -40,7 +40,7 @@ - Region Growing Iterations + Maximum Region Growing Iterations @@ -49,10 +49,17 @@ Region Growing Range Parameter - + + + Maximum Neighborhood Vector Size + + + + + @@ -93,6 +100,7 @@ rangeParameter: tileset.pointCloudPostProcessorOptions.rangeParameter, numRegionGrowingPasses: tileset.pointCloudPostProcessorOptions.numRegionGrowingPasses, neighborhoodHalfWidth: tileset.pointCloudPostProcessorOptions.neighborhoodHalfWidth, + neighborhoodVectorSize: tileset.pointCloudPostProcessorOptions.neighborhoodVectorSize, }; Cesium.knockout.track(viewModel); @@ -112,9 +120,14 @@ subscribeParameter('rangeParameter'); subscribeParameter('neighborhoodHalfWidth'); subscribeParameter('numRegionGrowingPasses'); +subscribeParameter('neighborhoodVectorSize'); Sandcastle.addToggleButton('Enabled', true, function(checked) { - tileset.pointCloudPostProcessorOptions['enabled'] = checked; + tileset.pointCloudPostProcessorOptions.enabled = checked; +}); + +Sandcastle.addToggleButton('Density View', false, function(checked) { + tileset.pointCloudPostProcessorOptions.densityViewEnabled = checked; }); /////////////////////////////////////////////////////////////////////////////// From 6ff1427fe0726d531594ae4e5ae8b3806ea3f0c3 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Thu, 6 Jul 2017 14:59:44 -0400 Subject: [PATCH 057/240] Formatting fixes --- Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl index 65c98a9653b7..e61e27140765 100644 --- a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl @@ -177,10 +177,10 @@ void main() { } } - #ifdef DENSITY_VIEW +#ifdef DENSITY_VIEW colorOut = vec4(vec3(density / float(densityHalfWidth)), 1.0); - #else +#else colorOut = finalColor; - #endif +#endif depthOut = czm_packDepth(finalDepth); } From 5e31651b1b78dd263e252a8d1c9493919f213557 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Thu, 6 Jul 2017 15:04:30 -0400 Subject: [PATCH 058/240] Adds WebGL1 support --- .../DensityEstimationPass.glsl | 11 ++++++----- .../RegionGrowingPassGL1.glsl | 18 ++++++++++++++++-- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/Source/Shaders/PostProcessFilters/DensityEstimationPass.glsl b/Source/Shaders/PostProcessFilters/DensityEstimationPass.glsl index aeee1b062715..124357dcb58c 100644 --- a/Source/Shaders/PostProcessFilters/DensityEstimationPass.glsl +++ b/Source/Shaders/PostProcessFilters/DensityEstimationPass.glsl @@ -15,7 +15,7 @@ void main() { v_textureCoordinates)); ivec2 pos = ivec2(int(gl_FragCoord.x), int(gl_FragCoord.y)); - int closestNeighbor = neighborhoodHalfWidth + 1; + float closestNeighbor = float(neighborhoodHalfWidth) + 1.0; vec2 neighborhoodAccum = vec2(0.0); if (center < EPS) { @@ -32,13 +32,14 @@ void main() { neighborhoodAccum += vec2(d); closestNeighbor = min(closestNeighbor, - max(abs(i), abs(j))); + max(abs(float(i)), + abs(float(j)))); } } - if (closestNeighbor <= neighborhoodHalfWidth && - length(neighborhoodAccum) < neighborhoodVectorSize) { - gl_FragData[0] = czm_packDepth(float(closestNeighbor) / + if (int(closestNeighbor) <= neighborhoodHalfWidth && + length(neighborhoodAccum) < neighborhoodVectorSize) { + gl_FragData[0] = czm_packDepth(closestNeighbor / densityScaleFactor); } else { gl_FragData[0] = czm_packDepth(0.0); diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl index 5ff240b54fb1..26a9c2a5ed66 100644 --- a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl @@ -6,10 +6,15 @@ #define neighborhoodSize 8 #define EPS 1e-8 #define SQRT2 1.414213562 +#define densityScaleFactor 32.0 +#define DENSITY_VIEW uniform sampler2D pointCloud_colorTexture; +uniform sampler2D pointCloud_densityTexture; uniform sampler2D pointCloud_depthTexture; uniform float rangeParameter; +uniform int densityHalfWidth; +uniform int iterationNumber; varying vec2 v_textureCoordinates; @@ -122,13 +127,18 @@ void main() { loadIntoArray(depthNeighbors, colorNeighbors); + float density = densityScaleFactor * czm_unpackDepth( + texture2D(pointCloud_densityTexture, v_textureCoordinates)); + // If our depth value is invalid if (abs(depth) < EPS) { + if (float(iterationNumber) <= density + EPS) { #if neighborhoodFullWidth == 3 - fastMedian3(depthNeighbors, colorNeighbors, finalDepth, finalColor); + fastMedian3(depthNeighbors, colorNeighbors, finalDepth, finalColor); #else - genericMedianFinder(depthNeighbors, colorNeighbors, finalDepth, finalColor); + genericMedianFinder(depthNeighbors, colorNeighbors, finalDepth, finalColor); #endif + } } // Otherwise if our depth value is valid else { @@ -160,6 +170,10 @@ void main() { } } +#ifdef DENSITY_VIEW + gl_FragData[0] = vec4(vec3(density / float(densityHalfWidth)), 1.0); +#else gl_FragData[0] = finalColor; +#endif gl_FragData[1] = czm_packDepth(finalDepth); } From fcb6008a7a86f28288676c2434d5b87146e58b68 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Thu, 6 Jul 2017 16:39:03 -0400 Subject: [PATCH 059/240] Now updates gl_FragDepthEXT to gl_FragDepth --- Source/Renderer/GLSLModernizer.js | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/Renderer/GLSLModernizer.js b/Source/Renderer/GLSLModernizer.js index bf96157ef6bf..f32403dddb89 100644 --- a/Source/Renderer/GLSLModernizer.js +++ b/Source/Renderer/GLSLModernizer.js @@ -232,6 +232,7 @@ define([], function() { removeExtension("EXT_frag_depth"); replaceInSource(/texture2D/, "texture"); + replaceInSource(/gl_FragDepthEXT/, "gl_FragDepth"); if (isFragmentShader) { replaceInSource(/varying/, "in"); From 8c103ae06a0c15f49c1d1d5682db01a6320f5566 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Thu, 6 Jul 2017 16:40:07 -0400 Subject: [PATCH 060/240] Point occlusion pass once again ignores invalid fragments --- Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl index d4fb92a20f73..3cda166c1bb4 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl @@ -285,7 +285,7 @@ void main() { // The solid angle is too small, so we occlude this point if (accumulator < (2.0 * PI) * (1.0 - occlusionAngle)) { - depthOut = czm_packDepth(0.0); + discard; } else { // Write out the distance of the point // From 4b57a807ef011533eb3b1babab85a12cc419c412 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Thu, 6 Jul 2017 16:42:37 -0400 Subject: [PATCH 061/240] Changes default neighborhood vector size parameter --- Source/Scene/Cesium3DTileset.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Scene/Cesium3DTileset.js b/Source/Scene/Cesium3DTileset.js index 5f3421319dce..380fbe8322f4 100644 --- a/Source/Scene/Cesium3DTileset.js +++ b/Source/Scene/Cesium3DTileset.js @@ -735,7 +735,7 @@ define([ neighborhoodHalfWidth : defaultValue(options.neighborhoodHalfWidth, 4), numRegionGrowingPasses : defaultValue(options.numRegionGrowingPasses, 4), densityHalfWidth : defaultValue(options.densityHalfWidth, 4), - neighborhoodVectorSize : defaultValue(options.neighborhoodVectorSize, 10.0), + neighborhoodVectorSize : defaultValue(options.neighborhoodVectorSize, 30.0), densityViewEnabled : defaultValue(options.densityViewEnabled, false) }; From 8a543b0c1e52eae833dff80e3a7da7ee1f42edb7 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Fri, 7 Jul 2017 15:13:17 -0400 Subject: [PATCH 062/240] Adds stencil operations --- .../3D Tiles Point Cloud Post Processing.html | 4 + Source/Scene/Cesium3DTileset.js | 6 +- Source/Scene/PointCloudPostProcessor.js | 229 +++++++++++++++--- .../DensityEstimationPass.glsl | 2 + .../RegionGrowingPassGL2.glsl | 33 ++- 5 files changed, 244 insertions(+), 30 deletions(-) diff --git a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html index 006d652f250a..0686da81ab08 100644 --- a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html +++ b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html @@ -130,6 +130,10 @@ tileset.pointCloudPostProcessorOptions.densityViewEnabled = checked; }); +Sandcastle.addToggleButton('Stencil View', false, function(checked) { + tileset.pointCloudPostProcessorOptions.stencilViewEnabled = checked; +}); + /////////////////////////////////////////////////////////////////////////////// //Sandcastle_End diff --git a/Source/Scene/Cesium3DTileset.js b/Source/Scene/Cesium3DTileset.js index 380fbe8322f4..ce8e53a8a32c 100644 --- a/Source/Scene/Cesium3DTileset.js +++ b/Source/Scene/Cesium3DTileset.js @@ -736,7 +736,8 @@ define([ numRegionGrowingPasses : defaultValue(options.numRegionGrowingPasses, 4), densityHalfWidth : defaultValue(options.densityHalfWidth, 4), neighborhoodVectorSize : defaultValue(options.neighborhoodVectorSize, 30.0), - densityViewEnabled : defaultValue(options.densityViewEnabled, false) + densityViewEnabled : defaultValue(options.densityViewEnabled, false), + stencilViewEnabled : defaultValue(options.stencilViewEnabled, false) }; this._pointCloudPostProcessor = new PointCloudPostProcessor(this.pointCloudPostProcessorOptions); @@ -1625,7 +1626,8 @@ define([ numRegionGrowingPasses : tileset.pointCloudPostProcessorOptions.numRegionGrowingPasses, densityHalfWidth : tileset.pointCloudPostProcessorOptions.densityHalfWidth, neighborhoodVectorSize : tileset.pointCloudPostProcessorOptions.neighborhoodVectorSize, - densityViewEnabled : tileset.pointCloudPostProcessorOptions.densityViewEnabled + densityViewEnabled : tileset.pointCloudPostProcessorOptions.densityViewEnabled, + stencilViewEnabled : tileset.pointCloudPostProcessorOptions.stencilViewEnabled }); } diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 3596d5106c2b..97b33698e1a3 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -19,6 +19,8 @@ define([ '../Renderer/TextureMinificationFilter', '../Renderer/TextureWrap', '../Scene/BlendingState', + '../Scene/StencilFunction', + '../Scene/StencilOperation', '../Shaders/PostProcessFilters/PointOcclusionPassGL1', '../Shaders/PostProcessFilters/RegionGrowingPassGL1', '../Shaders/PostProcessFilters/PointOcclusionPassGL2', @@ -44,6 +46,8 @@ define([ TextureMinificationFilter, TextureWrap, BlendingState, + StencilFunction, + StencilOperation, PointOcclusionPassGL1, RegionGrowingPassGL1, PointOcclusionPassGL2, @@ -62,7 +66,10 @@ define([ this._depthTextures = undefined; this._densityTexture = undefined; this._dirty = undefined; + this._clearStencil = undefined; this._drawCommands = undefined; + this._stencilCommands = undefined; + this._copyCommands = undefined; this._blendCommand = undefined; this._clearCommands = undefined; @@ -73,6 +80,7 @@ define([ this.densityHalfWidth = options.densityHalfWidth; this.neighborhoodVectorSize = options.neighborhoodVectorSize; this.densityViewEnabled = options.densityViewEnabled; + this.stencilViewEnabled = options.stencilViewEnabled; } function createSampler() { @@ -159,27 +167,10 @@ define([ }); } - // (EC stands for eye-space) - // - // We want to reuse textures as much as possible, so here's the order - // of events: - // - // 1. We render normally to our prior: - // * Color -> 0 - // * Depth -> dirty ("dirty depth") - // * EC -> 0 - // 2. Then we perform the screen-space point occlusion stage with color[0] and EC: - // * No color - // * Pseudo-depth -> 0 - // * No EC - // 3a. Then we perform the region growing stage with color[0] and depth[0]: - // * Color -> 1 - // * Pseudo-depth -> 1 - // 3b. We do the region growing stage again with color[1] and depth[1]: - // * Color -> 0 - // * Pseudo-depth -> 0 - // 3c. Repeat steps 3a and 3b until all holes are filled and/or we run - // out of time. + // There used to be an explanation of how this worked here + // but it got too long. + // TODO: Find a better place to put an explanation of what all + // the framebuffers are meant for. processor._framebuffers = { prior : new Framebuffer({ context : context, @@ -195,6 +186,11 @@ define([ colorTextures : [depthTextures[0]], destroyAttachments : false }), + stencilMask : new Framebuffer({ + context : context, + depthStencilTexture: dirty, + destroyAttachments : false + }), densityEstimationPass : new Framebuffer({ context : context, colorTextures : [densityMap], @@ -202,12 +198,16 @@ define([ }), regionGrowingPassA : new Framebuffer({ context : context, - colorTextures : [colorTextures[1], depthTextures[1]], + colorTextures : [colorTextures[1], + depthTextures[1]], + depthStencilTexture: dirty, destroyAttachments : false }), regionGrowingPassB : new Framebuffer({ context: context, - colorTextures: [colorTextures[0], depthTextures[0]], + colorTextures: [colorTextures[0], + depthTextures[0]], + depthStencilTexture: dirty, destroyAttachments: false }) }; @@ -333,8 +333,91 @@ define([ 'DENSITY_VIEW', processor.densityViewEnabled ); + + regionGrowingPassStr = replaceConstants( + regionGrowingPassStr, + 'STENCIL_VIEW', + processor.stencilViewEnabled + ); + console.log(regionGrowingPassStr); + + var func = StencilFunction.EQUAL; + var op = { + fail : StencilOperation.KEEP, + zFail : StencilOperation.KEEP, + zPass : StencilOperation.KEEP + }; return context.createViewportQuadCommand(regionGrowingPassStr, { + uniformMap : uniformMap, + framebuffer : framebuffer, + renderState : RenderState.fromCache({ + stencilTest : { + enabled : true, + reference : 0, + mask : 1, + frontFunction : func, + backFunction : func, + frontOperation : op, + backOperation : op + } + }), + pass : Pass.CESIUM_3D_TILE, + owner : processor + }); + } + + function copyRegionGrowingColorStage(processor, context, i) { + var uniformMap = { + pointCloud_colorTexture : function() { + return processor._colorTextures[i]; + }, + pointCloud_depthTexture : function() { + return processor._depthTextures[i]; + }, + pointCloud_densityTexture : function() { + return processor._densityTexture; + }, + densityHalfWidth : function() { + return processor.densityHalfWidth; + } + }; + + var framebuffer = (i === 0) ? + processor._framebuffers.regionGrowingPassA : + processor._framebuffers.regionGrowingPassB; + + var copyStageStr = + '#define DENSITY_VIEW \n' + + '#define densityScaleFactor 32.0 \n' + + 'uniform int densityHalfWidth; \n' + + 'uniform sampler2D pointCloud_colorTexture; \n' + + 'uniform sampler2D pointCloud_depthTexture; \n' + + 'uniform sampler2D pointCloud_densityTexture; \n' + + 'varying vec2 v_textureCoordinates; \n' + + 'void main() \n' + + '{ \n' + + ' #ifdef DENSITY_VIEW \n' + + ' float density = densityScaleFactor * czm_unpackDepth(texture2D(pointCloud_densityTexture, v_textureCoordinates)); \n' + + ' gl_FragData[0] = vec4(vec3(density / float(densityHalfWidth)), 1.0); \n' + + ' #else \n' + + ' gl_FragData[0] = texture2D(pointCloud_colorTexture, v_textureCoordinates); \n' + + ' #endif \n' + + ' gl_FragData[1] = texture2D(pointCloud_depthTexture, v_textureCoordinates); \n' + + '} \n'; + + if (context.webgl2) { + copyStageStr = GLSLModernizer. + glslModernizeShaderText(copyStageStr, + true, true); + } + copyStageStr = replaceConstants( + copyStageStr, + 'DENSITY_VIEW', + processor.densityViewEnabled + ); + + return context.createViewportQuadCommand(copyStageStr, { uniformMap : uniformMap, framebuffer : framebuffer, renderState : RenderState.fromCache({ @@ -344,9 +427,65 @@ define([ }); } + function stencilMaskStage(processor, context, iteration) { + var uniformMap = { + pointCloud_densityTexture : function() { + return processor._densityTexture; + } + }; + + var stencilMaskStageStr = + '#define EPS 1e-8 \n' + + '#define CUTOFF 0 \n' + + '#define DELAY 0 \n' + + '#define densityScaleFactor 32.0 \n' + + 'uniform sampler2D pointCloud_densityTexture; \n' + + 'varying vec2 v_textureCoordinates; \n' + + 'void main() \n' + + '{ \n' + + ' float density = densityScaleFactor * czm_unpackDepth(texture2D(pointCloud_densityTexture, v_textureCoordinates)); \n' + + ' if (float(CUTOFF - DELAY) + EPS > density) \n' + + ' discard; \n' + + '} \n'; + + stencilMaskStageStr = replaceConstants( + stencilMaskStageStr, + 'CUTOFF', + iteration + ); + + var framebuffer = processor._framebuffers.stencilMask; + + var func = StencilFunction.ALWAYS; + var op = { + fail : StencilOperation.KEEP, + zFail : StencilOperation.KEEP, + zPass : StencilOperation.ZERO + }; + return context.createViewportQuadCommand(stencilMaskStageStr, { + uniformMap : uniformMap, + framebuffer : framebuffer, + renderState : RenderState.fromCache({ + stencilTest : { + enabled : true, + reference : 1, + mask : 0, + frontFunction : func, + backFunction : func, + frontOperation : op, + backOperation : op + } + }), + pass : Pass.CESIUM_3D_TILE, + owner : processor + }); + } + function createCommands(processor, context) { var numRegionGrowingPasses = processor.numRegionGrowingPasses; - var drawCommands = new Array(numRegionGrowingPasses + 1); + var drawCommands = new Array(numRegionGrowingPasses + 2); + var stencilCommands = new Array(numRegionGrowingPasses); + var copyCommands = new Array(2); var i; drawCommands[0] = pointOcclusionStage(processor, context); @@ -354,8 +493,12 @@ define([ for (i = 0; i < numRegionGrowingPasses; i++) { drawCommands[i + 2] = regionGrowingStage(processor, context, i); + stencilCommands[i] = stencilMaskStage(processor, context, i); } + copyCommands[0] = copyRegionGrowingColorStage(processor, context, 0); + copyCommands[1] = copyRegionGrowingColorStage(processor, context, 1); + for (i = 0; i < drawCommands.length; i++) { var shaderProgram = drawCommands[i].shaderProgram; var vsSource = shaderProgram.vertexShaderSource.clone(); @@ -374,6 +517,26 @@ define([ }); } + for (i = 0; i < copyCommands.length; i++) { + var copyProgram = copyCommands[i].shaderProgram; + var vsSourceCopy = copyProgram.vertexShaderSource.clone(); + var fsSourceCopy = copyProgram.fragmentShaderSource.clone(); + var attributeLocationsCopy = + copyProgram._attributeLocations; + for (var b = 0; b < vsSource.sources.length; b++) { + if (context.webgl2) { + vsSourceCopy.sources[b] = GLSLModernizer.glslModernizeShaderText( + vsSourceCopy.sources[b], false, true); + } + } + + copyCommands[i].shaderProgram = context.shaderCache.getShaderProgram({ + vertexShaderSource : vsSourceCopy, + fragmentShaderSource : fsSourceCopy, + attributeLocations : attributeLocationsCopy + }); + } + var blendFS = 'uniform sampler2D pointCloud_colorTexture; \n' + 'varying vec2 v_textureCoordinates; \n' + @@ -411,6 +574,7 @@ define([ framebuffer : framebuffers[name], color : new Color(0.0, 0.0, 0.0, 0.0), depth : 1.0, + stencil : 1.0, renderState : RenderState.fromCache(), pass : Pass.CESIUM_3D_TILE, owner : processor @@ -419,8 +583,10 @@ define([ } processor._drawCommands = drawCommands; + processor._stencilCommands = stencilCommands; processor._blendCommand = blendCommand; processor._clearCommands = clearCommands; + processor._copyCommands = copyCommands; } function createResources(processor, context, dirty) { @@ -428,6 +594,7 @@ define([ var screenHeight = context.drawingBufferHeight; var colorTextures = processor._colorTextures; var drawCommands = processor._drawCommands; + var stencilCommands = processor._stencilCommands; var resized = defined(colorTextures) && ((colorTextures[0].width !== screenWidth) || (colorTextures[0].height !== screenHeight)); @@ -436,7 +603,7 @@ define([ createFramebuffers(processor, context); } - if (!defined(drawCommands) || dirty) { + if (!defined(drawCommands) || !defined(stencilCommands) || dirty) { createCommands(processor, context); } @@ -515,7 +682,8 @@ define([ options.numRegionGrowingPasses !== this.numRegionGrowingPasses || options.densityHalfWidth !== this.densityHalfWidth || options.neighborhoodVectorSize !== this.neighborhoodVectorSize || - options.densityViewEnabled !== this.densityViewEnabled) { + options.densityViewEnabled !== this.densityViewEnabled || + options.stencilViewEnabled !== this.stencilViewEnabled) { this.occlusionAngle = options.occlusionAngle; this.rangeParameter = options.rangeParameter; this.neighborhoodHalfWidth = options.neighborhoodHalfWidth; @@ -523,6 +691,7 @@ define([ this.densityHalfWidth = options.densityHalfWidth; this.neighborhoodVectorSize = options.neighborhoodVectorSize; this.densityViewEnabled = options.densityViewEnabled; + this.stencilViewEnabled = options.stencilViewEnabled; dirty = true; } @@ -556,6 +725,8 @@ define([ // Apply processing commands var drawCommands = this._drawCommands; + var copyCommands = this._copyCommands; + var stencilCommands = this._stencilCommands; var clearCommands = this._clearCommands; var length = drawCommands.length; for (i = 0; i < length; ++i) { @@ -573,7 +744,11 @@ define([ commandList.push(clearCommands['regionGrowingPassB']); } } - + + if (i >= 2) { + commandList.push(copyCommands[i % 2]); + commandList.push(stencilCommands[i - 2]); + } commandList.push(drawCommands[i]); } diff --git a/Source/Shaders/PostProcessFilters/DensityEstimationPass.glsl b/Source/Shaders/PostProcessFilters/DensityEstimationPass.glsl index 124357dcb58c..98c544f62ba4 100644 --- a/Source/Shaders/PostProcessFilters/DensityEstimationPass.glsl +++ b/Source/Shaders/PostProcessFilters/DensityEstimationPass.glsl @@ -44,5 +44,7 @@ void main() { } else { gl_FragData[0] = czm_packDepth(0.0); } + } else { + gl_FragData[0] = czm_packDepth(1.0 / densityScaleFactor); } } diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl index e61e27140765..fe05ec4c4459 100644 --- a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl @@ -7,6 +7,8 @@ #define SQRT2 1.414213562 #define densityScaleFactor 32.0 #define DENSITY_VIEW +#define STENCIL_VIEW +#define DELAY 1 uniform sampler2D pointCloud_colorTexture; uniform sampler2D pointCloud_densityTexture; @@ -21,6 +23,31 @@ layout(location = 1) out vec4 depthOut; #define otherswap(a, b, aC, bC) if (a > b) { temp = a; a = b; b = temp; tempColor = aC; aC = bC; bC = tempColor; } +vec4 testColor(in int value) { + switch (value) { + case 0: + return vec4(1.0, 0.0, 0.0, 1.0); + case 1: + return vec4(1.0, 0.5, 0.0, 1.0); + case 2: + return vec4(1.0, 1.0, 0.0, 1.0); + case 3: + return vec4(0.5, 1.0, 0.0, 1.0); + case 4: + return vec4(0.0, 1.0, 0.0, 1.0); + case 5: + return vec4(0.0, 1.0, 0.5, 1.0); + case 6: + return vec4(0.0, 1.0, 1.0, 1.0); + case 7: + return vec4(0.0, 0.5, 1.0, 1.0); + case 8: + return vec4(0.0, 0.0, 1.0, 1.0); + default: + return vec4(1.0, 1.0, 1.0, 1.0); + } +} + void comparisonNetwork8(inout float[neighborhoodSize] neighbors, inout vec4[neighborhoodSize] neighborsColor) { float temp; @@ -136,7 +163,7 @@ void main() { // If our depth value is invalid if (abs(depth) < EPS) { // If the area that we want to region grow is sufficently sparse - if (float(iterationNumber) <= density + EPS) { + if (float(iterationNumber - DELAY) <= density + EPS) { #if neighborhoodFullWidth == 3 fastMedian3(depthNeighbors, colorNeighbors, @@ -179,8 +206,12 @@ void main() { #ifdef DENSITY_VIEW colorOut = vec4(vec3(density / float(densityHalfWidth)), 1.0); +#else +#ifdef STENCIL_VIEW + colorOut = testColor(iterationNumber); #else colorOut = finalColor; +#endif #endif depthOut = czm_packDepth(finalDepth); } From 4d1b88acaa66624c530b1b07a957c04ebfb4a5f4 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Fri, 7 Jul 2017 15:17:06 -0400 Subject: [PATCH 063/240] Removes console.log() statement --- Source/Scene/PointCloudPostProcessor.js | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 97b33698e1a3..8647b67bd713 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -339,7 +339,6 @@ define([ 'STENCIL_VIEW', processor.stencilViewEnabled ); - console.log(regionGrowingPassStr); var func = StencilFunction.EQUAL; var op = { From b99a67eb672fa57762f61b33affd7c24991d09cd Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Fri, 7 Jul 2017 15:23:55 -0400 Subject: [PATCH 064/240] Adds WebGL1 support --- Source/Scene/PointCloudPostProcessor.js | 1 + .../RegionGrowingPassGL1.glsl | 33 ++++++++++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 8647b67bd713..9e6602446698 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -387,6 +387,7 @@ define([ processor._framebuffers.regionGrowingPassB; var copyStageStr = + '#extension GL_EXT_draw_buffers : enable \n' + '#define DENSITY_VIEW \n' + '#define densityScaleFactor 32.0 \n' + 'uniform int densityHalfWidth; \n' + diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl index 26a9c2a5ed66..64bcef3b1aa3 100644 --- a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl @@ -8,6 +8,8 @@ #define SQRT2 1.414213562 #define densityScaleFactor 32.0 #define DENSITY_VIEW +#define STENCIL_VIEW +#define DELAY 1 uniform sampler2D pointCloud_colorTexture; uniform sampler2D pointCloud_densityTexture; @@ -20,6 +22,31 @@ varying vec2 v_textureCoordinates; #define otherswap(a, b, aC, bC) if (a > b) { temp = a; a = b; b = temp; tempColor = aC; aC = bC; bC = tempColor; } +vec4 testColor(in int value) { + if (value == 0) { + return vec4(1.0, 0.0, 0.0, 1.0); + } else if (value == 1) { + return vec4(1.0, 0.5, 0.0, 1.0); + } else if (value == 2) { + return vec4(1.0, 1.0, 0.0, 1.0); + } else if (value == 3) { + return vec4(0.5, 1.0, 0.0, 1.0); + } else if (value == 4) { + return vec4(0.0, 1.0, 0.0, 1.0); + } else if (value == 5) { + return vec4(0.0, 1.0, 0.5, 1.0); + } else if (value == 6) { + return vec4(0.0, 1.0, 1.0, 1.0); + } else if (value == 7) { + return vec4(0.0, 0.5, 1.0, 1.0); + } else if (value == 8) { + return vec4(0.0, 0.0, 1.0, 1.0); + } else { + return vec4(1.0, 1.0, 1.0, 1.0); + } +} + + void comparisonNetwork8(inout float[neighborhoodSize] neighbors, inout vec4[neighborhoodSize] neighborsColor) { float temp; @@ -132,7 +159,7 @@ void main() { // If our depth value is invalid if (abs(depth) < EPS) { - if (float(iterationNumber) <= density + EPS) { + if (float(iterationNumber - DELAY) <= density + EPS) { #if neighborhoodFullWidth == 3 fastMedian3(depthNeighbors, colorNeighbors, finalDepth, finalColor); #else @@ -172,8 +199,12 @@ void main() { #ifdef DENSITY_VIEW gl_FragData[0] = vec4(vec3(density / float(densityHalfWidth)), 1.0); +#else +#ifdef STENCIL_VIEW + gl_FragData[0] = testColor(iterationNumber); #else gl_FragData[0] = finalColor; +#endif #endif gl_FragData[1] = czm_packDepth(finalDepth); } From ac12f735f4fd56e432dd24f67841a88ddbeb65bf Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Fri, 7 Jul 2017 15:31:53 -0400 Subject: [PATCH 065/240] Fixes issues where occluded points would still be copied --- Source/Scene/PointCloudPostProcessor.js | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 9e6602446698..e540be21f7e7 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -390,6 +390,7 @@ define([ '#extension GL_EXT_draw_buffers : enable \n' + '#define DENSITY_VIEW \n' + '#define densityScaleFactor 32.0 \n' + + '#define EPS 1e-6 \n' + 'uniform int densityHalfWidth; \n' + 'uniform sampler2D pointCloud_colorTexture; \n' + 'uniform sampler2D pointCloud_depthTexture; \n' + @@ -397,13 +398,17 @@ define([ 'varying vec2 v_textureCoordinates; \n' + 'void main() \n' + '{ \n' + - ' #ifdef DENSITY_VIEW \n' + - ' float density = densityScaleFactor * czm_unpackDepth(texture2D(pointCloud_densityTexture, v_textureCoordinates)); \n' + - ' gl_FragData[0] = vec4(vec3(density / float(densityHalfWidth)), 1.0); \n' + - ' #else \n' + - ' gl_FragData[0] = texture2D(pointCloud_colorTexture, v_textureCoordinates); \n' + - ' #endif \n' + - ' gl_FragData[1] = texture2D(pointCloud_depthTexture, v_textureCoordinates); \n' + + ' vec4 rawDepth = texture2D(pointCloud_depthTexture, v_textureCoordinates); \n' + + ' float depth = czm_unpackDepth(rawDepth); \n' + + ' if (depth > EPS) { \n' + + ' #ifdef DENSITY_VIEW \n' + + ' float density = densityScaleFactor * czm_unpackDepth(texture2D(pointCloud_densityTexture, v_textureCoordinates)); \n' + + ' gl_FragData[0] = vec4(vec3(density / float(densityHalfWidth)), 1.0); \n' + + ' #else \n' + + ' gl_FragData[0] = texture2D(pointCloud_colorTexture, v_textureCoordinates); \n' + + ' #endif \n' + + ' gl_FragData[1] = rawDepth; \n' + + ' } \n' + '} \n'; if (context.webgl2) { From 75f4bfc906072c893b357aa66620594a41c10d53 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Fri, 7 Jul 2017 15:43:23 -0400 Subject: [PATCH 066/240] Edge creep filter is based on absolute value ratio; much more effective and easier to tune --- .../gallery/3D Tiles Point Cloud Post Processing.html | 2 +- Source/Scene/Cesium3DTileset.js | 2 +- .../Shaders/PostProcessFilters/DensityEstimationPass.glsl | 6 +++++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html index 0686da81ab08..58da21aa2501 100644 --- a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html +++ b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html @@ -56,7 +56,7 @@ Maximum Neighborhood Vector Size - + diff --git a/Source/Scene/Cesium3DTileset.js b/Source/Scene/Cesium3DTileset.js index ce8e53a8a32c..9d2bcb0545c4 100644 --- a/Source/Scene/Cesium3DTileset.js +++ b/Source/Scene/Cesium3DTileset.js @@ -735,7 +735,7 @@ define([ neighborhoodHalfWidth : defaultValue(options.neighborhoodHalfWidth, 4), numRegionGrowingPasses : defaultValue(options.numRegionGrowingPasses, 4), densityHalfWidth : defaultValue(options.densityHalfWidth, 4), - neighborhoodVectorSize : defaultValue(options.neighborhoodVectorSize, 30.0), + neighborhoodVectorSize : defaultValue(options.neighborhoodVectorSize, 0.5), densityViewEnabled : defaultValue(options.densityViewEnabled, false), stencilViewEnabled : defaultValue(options.stencilViewEnabled, false) }; diff --git a/Source/Shaders/PostProcessFilters/DensityEstimationPass.glsl b/Source/Shaders/PostProcessFilters/DensityEstimationPass.glsl index 98c544f62ba4..1854ef538cd9 100644 --- a/Source/Shaders/PostProcessFilters/DensityEstimationPass.glsl +++ b/Source/Shaders/PostProcessFilters/DensityEstimationPass.glsl @@ -17,6 +17,7 @@ void main() { float closestNeighbor = float(neighborhoodHalfWidth) + 1.0; vec2 neighborhoodAccum = vec2(0.0); + vec2 absNeighborhoodAccum = vec2(0.0); if (center < EPS) { for (int i = -neighborhoodHalfWidth; i <= neighborhoodHalfWidth; i++) { @@ -31,14 +32,17 @@ void main() { } neighborhoodAccum += vec2(d); + absNeighborhoodAccum += abs(vec2(d)); closestNeighbor = min(closestNeighbor, max(abs(float(i)), abs(float(j)))); } } + float absRatio = length(neighborhoodAccum) / + length(absNeighborhoodAccum); if (int(closestNeighbor) <= neighborhoodHalfWidth && - length(neighborhoodAccum) < neighborhoodVectorSize) { + absRatio < neighborhoodVectorSize) { gl_FragData[0] = czm_packDepth(closestNeighbor / densityScaleFactor); } else { From eee584a45a957d8ef57029c3effa339313a6cd26 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Fri, 7 Jul 2017 16:26:29 -0400 Subject: [PATCH 067/240] Adds back the old edge-creep suppression parameter in conjunction with the new one --- .../gallery/3D Tiles Point Cloud Post Processing.html | 11 ++++++++++- Source/Scene/Cesium3DTileset.js | 4 +++- Source/Scene/PointCloudPostProcessor.js | 6 ++++++ .../PostProcessFilters/DensityEstimationPass.glsl | 4 +++- 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html index 58da21aa2501..20a57a87262f 100644 --- a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html +++ b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html @@ -56,10 +56,17 @@ Maximum Neighborhood Vector Size - + + + Max Neighborhood ABS ratio + + + + + @@ -101,6 +108,7 @@ numRegionGrowingPasses: tileset.pointCloudPostProcessorOptions.numRegionGrowingPasses, neighborhoodHalfWidth: tileset.pointCloudPostProcessorOptions.neighborhoodHalfWidth, neighborhoodVectorSize: tileset.pointCloudPostProcessorOptions.neighborhoodVectorSize, + maxAbsRatio: tileset.pointCloudPostProcessorOptions.maxAbsRatio, }; Cesium.knockout.track(viewModel); @@ -121,6 +129,7 @@ subscribeParameter('neighborhoodHalfWidth'); subscribeParameter('numRegionGrowingPasses'); subscribeParameter('neighborhoodVectorSize'); +subscribeParameter('maxAbsRatio'); Sandcastle.addToggleButton('Enabled', true, function(checked) { tileset.pointCloudPostProcessorOptions.enabled = checked; diff --git a/Source/Scene/Cesium3DTileset.js b/Source/Scene/Cesium3DTileset.js index 9d2bcb0545c4..3b36dd2b16ad 100644 --- a/Source/Scene/Cesium3DTileset.js +++ b/Source/Scene/Cesium3DTileset.js @@ -735,7 +735,8 @@ define([ neighborhoodHalfWidth : defaultValue(options.neighborhoodHalfWidth, 4), numRegionGrowingPasses : defaultValue(options.numRegionGrowingPasses, 4), densityHalfWidth : defaultValue(options.densityHalfWidth, 4), - neighborhoodVectorSize : defaultValue(options.neighborhoodVectorSize, 0.5), + neighborhoodVectorSize : defaultValue(options.neighborhoodVectorSize, 10.0), + maxAbsRatio : defaultValue(options.maxAbsRatio, 0.9), densityViewEnabled : defaultValue(options.densityViewEnabled, false), stencilViewEnabled : defaultValue(options.stencilViewEnabled, false) }; @@ -1626,6 +1627,7 @@ define([ numRegionGrowingPasses : tileset.pointCloudPostProcessorOptions.numRegionGrowingPasses, densityHalfWidth : tileset.pointCloudPostProcessorOptions.densityHalfWidth, neighborhoodVectorSize : tileset.pointCloudPostProcessorOptions.neighborhoodVectorSize, + maxAbsRatio : tileset.pointCloudPostProcessorOptions.maxAbsRatio, densityViewEnabled : tileset.pointCloudPostProcessorOptions.densityViewEnabled, stencilViewEnabled : tileset.pointCloudPostProcessorOptions.stencilViewEnabled }); diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index e540be21f7e7..821c19c59f43 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -79,6 +79,7 @@ define([ this.numRegionGrowingPasses = options.numRegionGrowingPasses; this.densityHalfWidth = options.densityHalfWidth; this.neighborhoodVectorSize = options.neighborhoodVectorSize; + this.maxAbsRatio = options.maxAbsRatio; this.densityViewEnabled = options.densityViewEnabled; this.stencilViewEnabled = options.stencilViewEnabled; } @@ -272,6 +273,9 @@ define([ }, neighborhoodVectorSize : function() { return processor.neighborhoodVectorSize; + }, + maxAbsRatio : function() { + return processor.maxAbsRatio; } }; @@ -687,6 +691,7 @@ define([ options.numRegionGrowingPasses !== this.numRegionGrowingPasses || options.densityHalfWidth !== this.densityHalfWidth || options.neighborhoodVectorSize !== this.neighborhoodVectorSize || + options.maxAbsRatio !== this.maxAbsRatio || options.densityViewEnabled !== this.densityViewEnabled || options.stencilViewEnabled !== this.stencilViewEnabled) { this.occlusionAngle = options.occlusionAngle; @@ -697,6 +702,7 @@ define([ this.neighborhoodVectorSize = options.neighborhoodVectorSize; this.densityViewEnabled = options.densityViewEnabled; this.stencilViewEnabled = options.stencilViewEnabled; + this.maxAbsRatio = options.maxAbsRatio; dirty = true; } diff --git a/Source/Shaders/PostProcessFilters/DensityEstimationPass.glsl b/Source/Shaders/PostProcessFilters/DensityEstimationPass.glsl index 1854ef538cd9..52e36fafb284 100644 --- a/Source/Shaders/PostProcessFilters/DensityEstimationPass.glsl +++ b/Source/Shaders/PostProcessFilters/DensityEstimationPass.glsl @@ -8,6 +8,7 @@ uniform sampler2D pointCloud_depthTexture; uniform float neighborhoodVectorSize; +uniform float maxAbsRatio; varying vec2 v_textureCoordinates; void main() { @@ -42,7 +43,8 @@ void main() { float absRatio = length(neighborhoodAccum) / length(absNeighborhoodAccum); if (int(closestNeighbor) <= neighborhoodHalfWidth && - absRatio < neighborhoodVectorSize) { + !(absRatio > maxAbsRatio && + length(neighborhoodAccum) > neighborhoodVectorSize)) { gl_FragData[0] = czm_packDepth(closestNeighbor / densityScaleFactor); } else { From d43fabd6a99356e51da3e8b037ec3a1217812817 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Thu, 29 Jun 2017 10:01:42 -0400 Subject: [PATCH 068/240] Disables WebGL 2 by default --- Source/Renderer/Context.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Renderer/Context.js b/Source/Renderer/Context.js index 3ef399b048f0..d76200db5852 100644 --- a/Source/Renderer/Context.js +++ b/Source/Renderer/Context.js @@ -195,7 +195,7 @@ define([ webglOptions.alpha = defaultValue(webglOptions.alpha, false); // WebGL default is true webglOptions.stencil = defaultValue(webglOptions.stencil, true); // WebGL default is false - var defaultToWebgl2 = true; + var defaultToWebgl2 = false; var requestWebgl2 = defaultToWebgl2 && (typeof WebGL2RenderingContext !== 'undefined'); var webgl2 = false; From 1c592c15d5a7a74cc6090fe33869d30dd05cb400 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Mon, 10 Jul 2017 10:12:50 -0400 Subject: [PATCH 069/240] Point occlusion operator is now stenciled --- Source/Scene/PointCloudPostProcessor.js | 70 ++++++++++++++++--- .../PointOcclusionPassGL1.glsl | 2 +- .../PointOcclusionPassGL2.glsl | 2 +- 3 files changed, 63 insertions(+), 11 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 821c19c59f43..ed4b44bd201f 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -185,6 +185,7 @@ define([ screenSpacePass : new Framebuffer({ context : context, colorTextures : [depthTextures[0]], + depthStencilTexture: dirty, destroyAttachments : false }), stencilMask : new Framebuffer({ @@ -255,11 +256,27 @@ define([ 'neighborhoodHalfWidth', processor.neighborhoodHalfWidth ); + + var func = StencilFunction.EQUAL; + var op = { + fail : StencilOperation.KEEP, + zFail : StencilOperation.KEEP, + zPass : StencilOperation.KEEP + }; return context.createViewportQuadCommand(pointOcclusionStr, { uniformMap : uniformMap, framebuffer : processor._framebuffers.screenSpacePass, renderState : RenderState.fromCache({ + stencilTest : { + enabled : true, + reference : 0, + mask : 1, + frontFunction : func, + backFunction : func, + frontOperation : op, + backOperation : op + } }), pass : Pass.CESIUM_3D_TILE, owner : processor @@ -579,15 +596,29 @@ define([ var clearCommands = {}; for (var name in framebuffers) { if (framebuffers.hasOwnProperty(name)) { - clearCommands[name] = new ClearCommand({ - framebuffer : framebuffers[name], - color : new Color(0.0, 0.0, 0.0, 0.0), - depth : 1.0, - stencil : 1.0, - renderState : RenderState.fromCache(), - pass : Pass.CESIUM_3D_TILE, - owner : processor - }); + // The screen space pass should consider + // the stencil value, so we don't clear it + // here + if (name === "screenSpacePass") { + clearCommands[name] = new ClearCommand({ + framebuffer : framebuffers[name], + color : new Color(0.0, 0.0, 0.0, 0.0), + depth : 1.0, + renderState : RenderState.fromCache(), + pass : Pass.CESIUM_3D_TILE, + owner : processor + }); + } else { + clearCommands[name] = new ClearCommand({ + framebuffer : framebuffers[name], + color : new Color(0.0, 0.0, 0.0, 0.0), + depth : 1.0, + stencil : 1.0, + renderState : RenderState.fromCache(), + pass : Pass.CESIUM_3D_TILE, + owner : processor + }); + } } } @@ -728,6 +759,27 @@ define([ derivedCommand.shaderProgram = getECShaderProgram(frameState.context, command.shaderProgram); derivedCommand.castShadows = false; derivedCommand.receiveShadows = false; + + var func = StencilFunction.ALWAYS; + var op = { + fail: StencilOperation.KEEP, + zFail: StencilOperation.KEEP, + zPass: StencilOperation.ZERO + }; + var derivedCommandRenderState = derivedCommand.renderState; + derivedCommandRenderState.stencilTest = { + enabled : true, + reference : 1, + mask : 0, + frontFunction : func, + backFunction : func, + frontOperation : op, + backOperation : op + }; + derivedCommand.renderState = RenderState.fromCache( + derivedCommandRenderState + ); + derivedCommand.pass = Pass.CESIUM_3D_TILE; // Overrides translucent commands } diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl index c6ef25e78f68..d64f4ced8ab7 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl @@ -344,7 +344,7 @@ void main() { // The solid angle is too small, so we occlude this point if (accumulator < (2.0 * PI) * (1.0 - occlusionAngle)) { - discard; + gl_FragData[0] = vec4(0.0); } else { // Write out the distance of the point // diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl index 3cda166c1bb4..9b50b32a1c14 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl @@ -285,7 +285,7 @@ void main() { // The solid angle is too small, so we occlude this point if (accumulator < (2.0 * PI) * (1.0 - occlusionAngle)) { - discard; + depthOut = vec4(0); } else { // Write out the distance of the point // From b1504729e65d78e725222c4504bb68cf8d44c94f Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Mon, 10 Jul 2017 16:58:55 -0400 Subject: [PATCH 070/240] Adds a new uniform that handles the "clamped" ends of the frustum --- Source/Renderer/AutomaticUniforms.js | 8 ++++++++ Source/Renderer/UniformState.js | 15 +++++++++++++++ Source/Scene/Scene.js | 3 +++ 3 files changed, 26 insertions(+) diff --git a/Source/Renderer/AutomaticUniforms.js b/Source/Renderer/AutomaticUniforms.js index b202f464fce4..c71ccef50342 100644 --- a/Source/Renderer/AutomaticUniforms.js +++ b/Source/Renderer/AutomaticUniforms.js @@ -1107,6 +1107,14 @@ define([ } }), + czm_frustumClamp : new AutomaticUniform({ + size : 1, + datatype : WebGLConstants.FLOAT_VEC2, + getValue : function(uniformState) { + return uniformState.frustumClamp; + } + }), + /** * The distances to the frustum planes. The top, bottom, left and right distances are * the x, y, z, and w components, respectively. diff --git a/Source/Renderer/UniformState.js b/Source/Renderer/UniformState.js index 3abe699ca767..d2781d8f2210 100644 --- a/Source/Renderer/UniformState.js +++ b/Source/Renderer/UniformState.js @@ -57,6 +57,7 @@ define([ this._infiniteProjection = Matrix4.clone(Matrix4.IDENTITY); this._entireFrustum = new Cartesian2(); this._currentFrustum = new Cartesian2(); + this._frustumClamp = new Cartesian2(); this._frustumPlanes = new Cartesian4(); this._frameState = undefined; @@ -633,6 +634,18 @@ define([ } }, + /** + * The distance to the clamped near and far planes. The nearest object determines the near + * plane and the farthest object determines the far plane. + * @memberof UniformState.prototype + * @type {Cartesian4} + */ + frustumClamp : { + get : function() { + return this._frustumClamp; + } + }, + /** * The the height (x) and the height squared (y) * in meters of the camera above the 2D world plane. This uniform is only valid @@ -963,6 +976,8 @@ define([ var camera = frameState.camera; this.updateCamera(camera); + this._frustumClamp.x = frameState.clampedNear; + this._frustumClamp.y = frameState.clampedFar; if (frameState.mode === SceneMode.SCENE2D) { this._frustum2DWidth = camera.frustum.right - camera.frustum.left; diff --git a/Source/Scene/Scene.js b/Source/Scene/Scene.js index ac4532665287..74d966ba0952 100644 --- a/Source/Scene/Scene.js +++ b/Source/Scene/Scene.js @@ -1492,6 +1492,9 @@ define([ } } + frameState.clampedNear = near; + frameState.clampedFar = far; + // Use the computed near and far for shadows if (shadowsEnabled) { frameState.shadowHints.nearPlane = shadowNear; From e142db92eb5f0be982e0d3490bce7dbc6375da3d Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Mon, 10 Jul 2017 17:00:17 -0400 Subject: [PATCH 071/240] Adds a new uniform that controls point attenuation --- Source/Scene/PointCloud3DTileContent.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/Source/Scene/PointCloud3DTileContent.js b/Source/Scene/PointCloud3DTileContent.js index 13aad77dc4b3..e9fc86f9dc1d 100644 --- a/Source/Scene/PointCloud3DTileContent.js +++ b/Source/Scene/PointCloud3DTileContent.js @@ -97,6 +97,9 @@ define([ this._hasNormals = false; this._hasBatchIds = false; + // Used to determine how to attenuate points + this._pointAttenuationMaxSize = 1.0; + // Use per-point normals to hide back-facing points. this.backFaceCulling = false; this._backFaceCulling = false; @@ -239,6 +242,15 @@ define([ get : function() { return this._batchTable; } + }, + + /** + * Part of the {@link Cesium3DTileContent} interface. + */ + pointAttenuationMaxSize : { + get : function() { + return this._pointAttenuationMaxSize; + } } }); @@ -507,6 +519,9 @@ define([ } var uniformMap = { + u_pointAttenuationMaxSize : function() { + return content._pointAttenuationMaxSize; + }, u_pointSize : function() { return content._pointSize; }, @@ -898,6 +913,7 @@ define([ var vs = 'attribute vec3 a_position; \n' + 'varying vec4 v_color; \n' + 'uniform float u_pointSize; \n' + + 'uniform float u_pointAttenuationMaxSize; \n' + 'uniform vec4 u_constantColor; \n' + 'uniform vec4 u_highlightColor; \n' + 'uniform float u_tilesetTime; \n'; @@ -1000,6 +1016,15 @@ define([ vs += ' gl_PointSize = u_pointSize; \n'; } + vs += ' vec4 position_EC = czm_view * vec4(position_absolute, 1); \n'; + vs += ' position_EC.z *= -1.0; \n'; + + vs += ' float attenuationFactor = \n' + + ' ((position_EC.z - czm_frustumClamp.x) /\n' + + ' (czm_frustumClamp.y - czm_frustumClamp.x)); \n'; + + vs += ' gl_PointSize *= mix(u_pointAttenuationMaxSize, 1.0, attenuationFactor);'; + vs += ' color = color * u_highlightColor; \n'; if (hasNormals) { From 348e16c34904fbba32cacc961f2308e5878a58b3 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Mon, 10 Jul 2017 17:03:13 -0400 Subject: [PATCH 072/240] Point Cloud Processor now modifies the point attenuation property --- .../3D Tiles Point Cloud Post Processing.html | 21 +++++++++++++------ Source/Scene/Cesium3DTileset.js | 6 ++++-- Source/Scene/PointCloudPostProcessor.js | 18 ++++++++++++++-- 3 files changed, 35 insertions(+), 10 deletions(-) diff --git a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html index 20a57a87262f..987b7cd2b467 100644 --- a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html +++ b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html @@ -67,6 +67,13 @@ + + Point Attenuation Multiplier + + + + + @@ -103,12 +110,13 @@ tileset.style = new Cesium.Cesium3DTileStyle(style); var viewModel = { - occlusionAngle: tileset.pointCloudPostProcessorOptions.occlusionAngle, - rangeParameter: tileset.pointCloudPostProcessorOptions.rangeParameter, - numRegionGrowingPasses: tileset.pointCloudPostProcessorOptions.numRegionGrowingPasses, - neighborhoodHalfWidth: tileset.pointCloudPostProcessorOptions.neighborhoodHalfWidth, - neighborhoodVectorSize: tileset.pointCloudPostProcessorOptions.neighborhoodVectorSize, - maxAbsRatio: tileset.pointCloudPostProcessorOptions.maxAbsRatio, + occlusionAngle : tileset.pointCloudPostProcessorOptions.occlusionAngle, + rangeParameter : tileset.pointCloudPostProcessorOptions.rangeParameter, + numRegionGrowingPasses : tileset.pointCloudPostProcessorOptions.numRegionGrowingPasses, + neighborhoodHalfWidth : tileset.pointCloudPostProcessorOptions.neighborhoodHalfWidth, + neighborhoodVectorSize : tileset.pointCloudPostProcessorOptions.neighborhoodVectorSize, + maxAbsRatio : tileset.pointCloudPostProcessorOptions.maxAbsRatio, + pointAttenuationMultiplier : tileset.pointCloudPostProcessorOptions.pointAttenuationMultiplier }; Cesium.knockout.track(viewModel); @@ -130,6 +138,7 @@ subscribeParameter('numRegionGrowingPasses'); subscribeParameter('neighborhoodVectorSize'); subscribeParameter('maxAbsRatio'); +subscribeParameter('pointAttenuationMultiplier'); Sandcastle.addToggleButton('Enabled', true, function(checked) { tileset.pointCloudPostProcessorOptions.enabled = checked; diff --git a/Source/Scene/Cesium3DTileset.js b/Source/Scene/Cesium3DTileset.js index 3b36dd2b16ad..be88abb31ce1 100644 --- a/Source/Scene/Cesium3DTileset.js +++ b/Source/Scene/Cesium3DTileset.js @@ -738,7 +738,8 @@ define([ neighborhoodVectorSize : defaultValue(options.neighborhoodVectorSize, 10.0), maxAbsRatio : defaultValue(options.maxAbsRatio, 0.9), densityViewEnabled : defaultValue(options.densityViewEnabled, false), - stencilViewEnabled : defaultValue(options.stencilViewEnabled, false) + stencilViewEnabled : defaultValue(options.stencilViewEnabled, false), + pointAttenuationMultiplier : defaultValue(options.pointAttenuationMultiplier, 2.0) }; this._pointCloudPostProcessor = new PointCloudPostProcessor(this.pointCloudPostProcessorOptions); @@ -1629,7 +1630,8 @@ define([ neighborhoodVectorSize : tileset.pointCloudPostProcessorOptions.neighborhoodVectorSize, maxAbsRatio : tileset.pointCloudPostProcessorOptions.maxAbsRatio, densityViewEnabled : tileset.pointCloudPostProcessorOptions.densityViewEnabled, - stencilViewEnabled : tileset.pointCloudPostProcessorOptions.stencilViewEnabled + stencilViewEnabled : tileset.pointCloudPostProcessorOptions.stencilViewEnabled, + pointAttenuationMultiplier : tileset.pointCloudPostProcessorOptions.pointAttenuationMultiplier }); } diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index ed4b44bd201f..d5f82bc9329d 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -82,6 +82,7 @@ define([ this.maxAbsRatio = options.maxAbsRatio; this.densityViewEnabled = options.densityViewEnabled; this.stencilViewEnabled = options.stencilViewEnabled; + this.pointAttenuationMultiplier = options.pointAttenuationMultiplier; } function createSampler() { @@ -724,7 +725,8 @@ define([ options.neighborhoodVectorSize !== this.neighborhoodVectorSize || options.maxAbsRatio !== this.maxAbsRatio || options.densityViewEnabled !== this.densityViewEnabled || - options.stencilViewEnabled !== this.stencilViewEnabled) { + options.stencilViewEnabled !== this.stencilViewEnabled || + options.pointAttenuationMultiplier !== this.pointAttenuationMultiplier) { this.occlusionAngle = options.occlusionAngle; this.rangeParameter = options.rangeParameter; this.neighborhoodHalfWidth = options.neighborhoodHalfWidth; @@ -734,6 +736,7 @@ define([ this.densityViewEnabled = options.densityViewEnabled; this.stencilViewEnabled = options.stencilViewEnabled; this.maxAbsRatio = options.maxAbsRatio; + this.pointAttenuationMultiplier = options.pointAttenuationMultiplier; dirty = true; } @@ -751,7 +754,8 @@ define([ var command = commandList[i]; var derivedCommand = command.derivedCommands.pointCloudProcessor; - if (!defined(derivedCommand) || command.dirty) { + if (!defined(derivedCommand) || command.dirty || dirty) { + console.log(command.dirty); derivedCommand = DrawCommand.shallowClone(command); command.derivedCommands.pointCloudProcessor = derivedCommand; @@ -779,8 +783,18 @@ define([ derivedCommand.renderState = RenderState.fromCache( derivedCommandRenderState ); + + // TODO: Even if the filter is disabled, + // point attenuation settings are not! Fix this behavior. + var derivedCommandUniformMap = derivedCommand.uniformMap; + var attenuationMultiplier = this.pointAttenuationMultiplier; + derivedCommandUniformMap['u_pointAttenuationMaxSize'] = function() { + return attenuationMultiplier; + }; + derivedCommand.uniformMap = derivedCommandUniformMap; derivedCommand.pass = Pass.CESIUM_3D_TILE; // Overrides translucent commands + command.dirty = false; } commandList[i] = derivedCommand; From 8c34023e5c67a40196eb86e1f008bf01734babca Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Tue, 11 Jul 2017 12:11:54 -0400 Subject: [PATCH 073/240] GLSLModernizer is now called by ShaderSource no matter what --- Source/Renderer/GLSLModernizer.js | 74 ++++++++++++++++++++++++------- Source/Renderer/ShaderSource.js | 9 ++++ 2 files changed, 68 insertions(+), 15 deletions(-) diff --git a/Source/Renderer/GLSLModernizer.js b/Source/Renderer/GLSLModernizer.js index f32403dddb89..89c39e6d6334 100644 --- a/Source/Renderer/GLSLModernizer.js +++ b/Source/Renderer/GLSLModernizer.js @@ -1,5 +1,8 @@ /*global define*/ -define([], function() { +define([ + '../Core/DeveloperError', + ], function( + DeveloperError) { 'use strict'; /** @@ -18,31 +21,72 @@ define([], function() { shaderSource.defines.push("MODERNIZED"); } + // Note that this function requires the presence of the + // "#define OUTPUT_DECLARATION" line that is appended + // by ShaderSource function glslModernizeShaderText(source, isFragmentShader, first) { - var mainFunctionRegex = /void\s+main\(\)/; + var mainFunctionRegex = /void\s+main\s*\((void)?\)/; + var outputDeclarationRegex = /#define OUTPUT_DECLARATION/; var splitSource = source.split('\n'); if (source.search(/#version 300 es/g) !== -1) { return source; } - var mainFunctionLine; - for (var number = 0; number < splitSource.length; number++) { + var outputDeclarationLine = -1; + var number; + for (number = 0; number < splitSource.length; number++) { var line = splitSource[number]; - if (mainFunctionRegex.exec(line)) { - mainFunctionLine = number; + if (outputDeclarationRegex.exec(line)) { + outputDeclarationLine = number; + break; } }; + + if (outputDeclarationLine == -1) { + for (number = 0; number < splitSource.length; number++) { + var line = splitSource[number]; + if (mainFunctionRegex.exec(line)) { + outputDeclarationLine = number; + } + }; + } + + if (outputDeclarationLine == -1) { + throw new DeveloperError('Could not find a ' + + '#define OUTPUT_DECLARATION ' + + 'nor a main function!'); + } + + function safeNameFind(regex, str) { + if (str.search(regex) !== -1) { + var regExpStr = regex.toString(); + regExpStr = regExpStr.match(/\/([^\/]+)(\/.)?/)[1]; + var somethingBadInString = + new RegExp("[a-zA-Z0-9_]+" + regExpStr, 'g'); + if (str.search(somethingBadInString) === -1) { + return true; + } + } + return false; + } function replaceInSource(regex, replacement) { + var replaceAll = function(target, search, replacement) { + return target.split(search).join(replacement); + }; for (var number = 0; number < splitSource.length; number++) { - splitSource[number] = splitSource[number].replace(regex, replacement); + var line = splitSource[number]; + if (safeNameFind(regex, line)) { + splitSource[number] = replaceAll(line, regex, replacement); + } } } function findInSource(regex) { for (var number = 0; number < splitSource.length; number++) { - if (splitSource[number].search(regex) !== -1) { + var line = splitSource[number]; + if (safeNameFind(regex, line)) { return true; } } @@ -164,10 +208,10 @@ define([], function() { if (source.search(fragDataString) != -1) { setAdd(newOutput, variableSet); replaceInSource(regex, newOutput); - splitSource.splice(mainFunctionLine, 0, + splitSource.splice(outputDeclarationLine, 0, "layout(location = " + i + ") out vec4 " + newOutput + ";"); - mainFunctionLine += 1; + outputDeclarationLine += 1; } } @@ -175,12 +219,11 @@ define([], function() { if (findInSource(/gl_FragColor/)) { setAdd(czmFragColor, variableSet); replaceInSource(/gl_FragColor/, czmFragColor); - splitSource.splice(mainFunctionLine, 0, "layout(location = 0) out vec4 czm_fragColor;"); - mainFunctionLine += 1; + splitSource.splice(outputDeclarationLine, 0, "layout(location = 0) out vec4 czm_fragColor;"); + outputDeclarationLine += 1; } var variableMap = getVariablePreprocessorBranch(variableSet); - console.log(variableMap); var lineAdds = {}; for (var c = 0; c < splitSource.length; c++) { var l = splitSource[c]; @@ -202,7 +245,6 @@ define([], function() { var entry = variableMap[variableName]; var depth = entry.length; var d; - //console.log(entry); for (d = 0; d < depth; d++) { splitSource.splice(lineNumber, 0, entry[d]); } @@ -216,7 +258,7 @@ define([], function() { if (first === true) { var versionThree = "#version 300 es"; var foundVersion = false; - for (var number = 0; number < splitSource.length; number++) { + for (number = 0; number < splitSource.length; number++) { if (splitSource[number].search(/#version/) != -1) { splitSource[number] = versionThree; foundVersion = true; @@ -232,6 +274,8 @@ define([], function() { removeExtension("EXT_frag_depth"); replaceInSource(/texture2D/, "texture"); + replaceInSource(/texture3D/, "texture"); + replaceInSource(/textureCube/, "texture"); replaceInSource(/gl_FragDepthEXT/, "gl_FragDepth"); if (isFragmentShader) { diff --git a/Source/Renderer/ShaderSource.js b/Source/Renderer/ShaderSource.js index 8147b191277e..62e8bc97086d 100644 --- a/Source/Renderer/ShaderSource.js +++ b/Source/Renderer/ShaderSource.js @@ -3,12 +3,14 @@ define([ '../Core/defaultValue', '../Core/defined', '../Core/DeveloperError', + '../Renderer/GLSLModernizer', '../Shaders/Builtin/CzmBuiltins', './AutomaticUniforms' ], function( defaultValue, defined, DeveloperError, + GLSLModernizer, CzmBuiltins, AutomaticUniforms) { 'use strict'; @@ -240,6 +242,8 @@ define([ } } + result += '#define OUTPUT_DECLARATION\n\n'; + // append built-ins if (shaderSource.includeBuiltIns) { result += getBuiltinsAndAutomaticUniforms(combinedSources); @@ -251,6 +255,11 @@ define([ // append actual source result += combinedSources; + // modernize the source + result = GLSLModernizer.glslModernizeShaderText(result, + isFragmentShader, + true); + return result; } From e0c32d83aff72d13d30dd0ba4086f89ae2fcec4c Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Tue, 11 Jul 2017 12:12:36 -0400 Subject: [PATCH 074/240] Renames the variable "texture" so that it no longer breaks GLSLModernizer --- Source/Shaders/GlobeFS.glsl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Shaders/GlobeFS.glsl b/Source/Shaders/GlobeFS.glsl index c36fc9737286..34f8bc02c4ca 100644 --- a/Source/Shaders/GlobeFS.glsl +++ b/Source/Shaders/GlobeFS.glsl @@ -66,7 +66,7 @@ varying vec3 v_mieColor; vec4 sampleAndBlend( vec4 previousColor, - sampler2D texture, + sampler2D textureToSample, vec2 tileTextureCoordinates, vec4 textureCoordinateRectangle, vec4 textureCoordinateTranslationAndScale, @@ -94,7 +94,7 @@ vec4 sampleAndBlend( vec2 translation = textureCoordinateTranslationAndScale.xy; vec2 scale = textureCoordinateTranslationAndScale.zw; vec2 textureCoordinates = tileTextureCoordinates * scale + translation; - vec4 value = texture2D(texture, textureCoordinates); + vec4 value = texture2D(textureToSample, textureCoordinates); vec3 color = value.rgb; float alpha = value.a; From 40e0fe186c533d831cac20569ee8a36ca71d6ae5 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Tue, 11 Jul 2017 12:12:51 -0400 Subject: [PATCH 075/240] No longer calling GLSLModernizer --- Source/Scene/OIT.js | 22 --------- Source/Scene/PointCloudPostProcessor.js | 60 +++---------------------- 2 files changed, 5 insertions(+), 77 deletions(-) diff --git a/Source/Scene/OIT.js b/Source/Scene/OIT.js index 6bc03a584ba7..8f0131f6cae2 100644 --- a/Source/Scene/OIT.js +++ b/Source/Scene/OIT.js @@ -9,7 +9,6 @@ define([ '../Renderer/ClearCommand', '../Renderer/DrawCommand', '../Renderer/Framebuffer', - '../Renderer/GLSLModernizer', '../Renderer/PixelDatatype', '../Renderer/RenderState', '../Renderer/ShaderSource', @@ -28,7 +27,6 @@ define([ ClearCommand, DrawCommand, Framebuffer, - GLSLModernizer, PixelDatatype, RenderState, ShaderSource, @@ -257,11 +255,6 @@ define([ uniformMap : uniformMap, owner : this }); - if (context.webgl2) { - this._compositeCommand.shaderProgram = - GLSLModernizer.glslModernizeShaderProgram( - context, this._compositeCommand.shaderProgram); - } } if (!defined(this._adjustTranslucentCommand)) { @@ -284,11 +277,6 @@ define([ uniformMap : uniformMap, owner : this }); - if (context.webgl2) { - this._adjustTranslucentCommand.shaderProgram = - GLSLModernizer.glslModernizeShaderProgram( - context, this._adjustTranslucentCommand.shaderProgram); - } } else if (this._translucentMultipassSupport) { fs = new ShaderSource({ sources : [AdjustTranslucentFS] @@ -307,11 +295,6 @@ define([ uniformMap : uniformMap, owner : this }); - if (context.webgl2) { - this._adjustTranslucentCommand.shaderProgram = - GLSLModernizer.glslModernizeShaderProgram( - context, this._adjustTranslucentCommand.shaderProgram); - } uniformMap = { u_bgColor : function() { @@ -326,11 +309,6 @@ define([ uniformMap : uniformMap, owner : this }); - if (context.webgl2) { - this._adjustAlphaCommand.shaderProgram = - GLSLModernizer.glslModernizeShaderProgram( - context, this._adjustAlphaCommand.shaderProgram); - } } } diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index d5f82bc9329d..0944ccae7d51 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -4,10 +4,10 @@ define([ '../Core/defined', '../Core/destroyObject', '../Core/PixelFormat', + '../Core/PrimitiveType', '../Renderer/ClearCommand', '../Renderer/DrawCommand', '../Renderer/Framebuffer', - '../Renderer/GLSLModernizer', '../Renderer/Pass', '../Renderer/PixelDatatype', '../Renderer/RenderState', @@ -31,10 +31,10 @@ define([ defined, destroyObject, PixelFormat, + PrimitiveType, ClearCommand, DrawCommand, Framebuffer, - GLSLModernizer, Pass, PixelDatatype, RenderState, @@ -303,11 +303,6 @@ define([ processor.densityHalfWidth ); - if (context.webgl2) { - densityEstimationStr = GLSLModernizer. - glslModernizeShaderText(densityEstimationStr, true, true); - } - return context.createViewportQuadCommand(densityEstimationStr, { uniformMap : uniformMap, framebuffer : processor._framebuffers.densityEstimationPass, @@ -433,11 +428,6 @@ define([ ' } \n' + '} \n'; - if (context.webgl2) { - copyStageStr = GLSLModernizer. - glslModernizeShaderText(copyStageStr, - true, true); - } copyStageStr = replaceConstants( copyStageStr, 'DENSITY_VIEW', @@ -525,44 +515,6 @@ define([ copyCommands[0] = copyRegionGrowingColorStage(processor, context, 0); copyCommands[1] = copyRegionGrowingColorStage(processor, context, 1); - - for (i = 0; i < drawCommands.length; i++) { - var shaderProgram = drawCommands[i].shaderProgram; - var vsSource = shaderProgram.vertexShaderSource.clone(); - var fsSource = shaderProgram.fragmentShaderSource.clone(); - var attributeLocations = shaderProgram._attributeLocations; - for (var a = 0; a < vsSource.sources.length; a++) { - if (context.webgl2) { - vsSource.sources[a] = GLSLModernizer.glslModernizeShaderText( - vsSource.sources[a], false, true); - } - } - drawCommands[i].shaderProgram = context.shaderCache.getShaderProgram({ - vertexShaderSource : vsSource, - fragmentShaderSource : fsSource, - attributeLocations : attributeLocations - }); - } - - for (i = 0; i < copyCommands.length; i++) { - var copyProgram = copyCommands[i].shaderProgram; - var vsSourceCopy = copyProgram.vertexShaderSource.clone(); - var fsSourceCopy = copyProgram.fragmentShaderSource.clone(); - var attributeLocationsCopy = - copyProgram._attributeLocations; - for (var b = 0; b < vsSource.sources.length; b++) { - if (context.webgl2) { - vsSourceCopy.sources[b] = GLSLModernizer.glslModernizeShaderText( - vsSourceCopy.sources[b], false, true); - } - } - - copyCommands[i].shaderProgram = context.shaderCache.getShaderProgram({ - vertexShaderSource : vsSourceCopy, - fragmentShaderSource : fsSourceCopy, - attributeLocations : attributeLocationsCopy - }); - } var blendFS = 'uniform sampler2D pointCloud_colorTexture; \n' + @@ -695,11 +647,6 @@ define([ ' gl_FragData[1] = vec4(v_positionECPS, 0); \n' + '}'); - if (context.webgl2) { - GLSLModernizer.glslModernizeShaderSource(vs, false); - GLSLModernizer.glslModernizeShaderSource(fs, true); - } - shader = context.shaderCache.createDerivedShaderProgram(shaderProgram, 'EC', { vertexShaderSource : vs, fragmentShaderSource : fs, @@ -752,6 +699,9 @@ define([ var commandEnd = commandList.length; for (i = commandStart; i < commandEnd; ++i) { var command = commandList[i]; + if (command.primitiveType !== PrimitiveType.POINTS) { + continue; + } var derivedCommand = command.derivedCommands.pointCloudProcessor; if (!defined(derivedCommand) || command.dirty || dirty) { From aa6b8285fd8ddabf6cabd40c5a73d8e3ae530dbd Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Tue, 11 Jul 2017 12:14:12 -0400 Subject: [PATCH 076/240] Removes old console.log statement --- Source/Scene/PointCloudPostProcessor.js | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 0944ccae7d51..2df12eb05288 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -705,7 +705,6 @@ define([ var derivedCommand = command.derivedCommands.pointCloudProcessor; if (!defined(derivedCommand) || command.dirty || dirty) { - console.log(command.dirty); derivedCommand = DrawCommand.shallowClone(command); command.derivedCommands.pointCloudProcessor = derivedCommand; From 2cab7426bec3abcbae5a9db5784bfbcd8360489b Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Tue, 11 Jul 2017 13:06:12 -0400 Subject: [PATCH 077/240] GLSLModernizer is now only called in WebGL 2 contexts --- Source/Renderer/ShaderCache.js | 11 ++++++----- Source/Renderer/ShaderSource.js | 18 ++++++++++++------ Specs/Renderer/ShaderProgramSpec.js | 4 ++-- Specs/Renderer/ShaderSourceSpec.js | 10 +++++----- 4 files changed, 25 insertions(+), 18 deletions(-) diff --git a/Source/Renderer/ShaderCache.js b/Source/Renderer/ShaderCache.js index d02724bdfedc..68adf065ef8f 100644 --- a/Source/Renderer/ShaderCache.js +++ b/Source/Renderer/ShaderCache.js @@ -97,8 +97,8 @@ define([ }); } - var vertexShaderText = vertexShaderSource.createCombinedVertexShader(); - var fragmentShaderText = fragmentShaderSource.createCombinedFragmentShader(); + var vertexShaderText = vertexShaderSource.createCombinedVertexShader(this._context.webgl2); + var fragmentShaderText = fragmentShaderSource.createCombinedFragmentShader(this._context.webgl2); var keyword = vertexShaderText + fragmentShaderText + JSON.stringify(attributeLocations); var cachedShader; @@ -170,10 +170,11 @@ define([ }); } - var vertexShaderText = vertexShaderSource.createCombinedVertexShader(); - var fragmentShaderText = fragmentShaderSource.createCombinedFragmentShader(); - var context = this._context; + + var vertexShaderText = vertexShaderSource.createCombinedVertexShader(context.webgl2); + var fragmentShaderText = fragmentShaderSource.createCombinedFragmentShader(context.webgl2); + var derivedShaderProgram = new ShaderProgram({ gl : context._gl, logShaderCompilation : context.logShaderCompilation, diff --git a/Source/Renderer/ShaderSource.js b/Source/Renderer/ShaderSource.js index 62e8bc97086d..25e70feee6b1 100644 --- a/Source/Renderer/ShaderSource.js +++ b/Source/Renderer/ShaderSource.js @@ -154,7 +154,7 @@ define([ return builtinsSource.replace(root.glslSource, ''); } - function combineShader(shaderSource, isFragmentShader) { + function combineShader(shaderSource, isFragmentShader, webgl2) { var i; var length; @@ -256,9 +256,11 @@ define([ result += combinedSources; // modernize the source - result = GLSLModernizer.glslModernizeShaderText(result, + if (webgl2) { + result = GLSLModernizer.glslModernizeShaderText(result, isFragmentShader, true); + } return result; } @@ -322,19 +324,23 @@ define([ /** * Create a single string containing the full, combined vertex shader with all dependencies and defines. * + * @param {Boolean} [webgl2] A boolean parameter which is true if the context is using WebGL 2, false otherwise + * * @returns {String} The combined shader string. */ - ShaderSource.prototype.createCombinedVertexShader = function() { - return combineShader(this, false); + ShaderSource.prototype.createCombinedVertexShader = function(webgl2) { + return combineShader(this, false, webgl2); }; /** * Create a single string containing the full, combined fragment shader with all dependencies and defines. * + * @param {Boolean} [webgl2] A boolean parameter which is true if the context is using WebGL 2, false otherwise + * * @returns {String} The combined shader string. */ - ShaderSource.prototype.createCombinedFragmentShader = function() { - return combineShader(this, true); + ShaderSource.prototype.createCombinedFragmentShader = function(webgl2) { + return combineShader(this, true, webgl2); }; /** diff --git a/Specs/Renderer/ShaderProgramSpec.js b/Specs/Renderer/ShaderProgramSpec.js index 374460e21fd7..1ce1d5b716a9 100644 --- a/Specs/Renderer/ShaderProgramSpec.js +++ b/Specs/Renderer/ShaderProgramSpec.js @@ -66,13 +66,13 @@ defineSuite([ var expectedVSText = new ShaderSource({ sources : [vs] - }).createCombinedVertexShader(); + }).createCombinedVertexShader(context.webgl2); expect(sp._vertexShaderText).toEqual(expectedVSText); var expectedFSText = new ShaderSource({ sources : [fs] - }).createCombinedFragmentShader(); + }).createCombinedFragmentShader(context.webgl2); expect(sp._fragmentShaderText).toEqual(expectedFSText); }); diff --git a/Specs/Renderer/ShaderSourceSpec.js b/Specs/Renderer/ShaderSourceSpec.js index f46cd84eca29..2dbe3530e0ff 100644 --- a/Specs/Renderer/ShaderSourceSpec.js +++ b/Specs/Renderer/ShaderSourceSpec.js @@ -10,7 +10,7 @@ defineSuite([ defines : ['A', 'B', ''] }); - var shaderText = source.createCombinedVertexShader(); + var shaderText = source.createCombinedVertexShader(false); expect(shaderText).toContain('#define A'); expect(shaderText).toContain('#define B'); expect(shaderText.match(/#define/g).length).toEqual(2); @@ -20,7 +20,7 @@ defineSuite([ var source = new ShaderSource({ sources : ['void func() {}', 'void main() {}'] }); - var shaderText = source.createCombinedVertexShader(); + var shaderText = source.createCombinedVertexShader(false); expect(shaderText).toContain('#line 0\nvoid func() {}'); expect(shaderText).toContain('#line 0\nvoid main() {}'); }); @@ -30,7 +30,7 @@ defineSuite([ defines : ['A', 'B', ''], sources : ['void func() {}', 'void main() {}'] }); - var shaderText = source.createCombinedVertexShader(); + var shaderText = source.createCombinedVertexShader(false); expect(shaderText).toContain('#define A'); expect(shaderText).toContain('#define B'); expect(shaderText.match(/#define/g).length).toEqual(2); @@ -43,7 +43,7 @@ defineSuite([ sources : ['void main() { gl_FragColor = vec4(1.0); }'], pickColorQualifier : 'uniform' }); - var shaderText = source.createCombinedVertexShader(); + var shaderText = source.createCombinedVertexShader(false); expect(shaderText).toContain('uniform vec4 czm_pickColor;'); expect(shaderText).toContain('gl_FragColor = czm_pickColor;'); }); @@ -53,7 +53,7 @@ defineSuite([ sources : ['void main() { gl_FragColor = vec4(1.0); }'], pickColorQualifier : 'varying' }); - var shaderText = source.createCombinedVertexShader(); + var shaderText = source.createCombinedVertexShader(false); expect(shaderText).toContain('varying vec4 czm_pickColor;'); expect(shaderText).toContain('gl_FragColor = czm_pickColor;'); }); From 86742db21156368f51f3894b3ddd53d6ad796223 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Thu, 29 Jun 2017 10:01:42 -0400 Subject: [PATCH 078/240] Disables WebGL 2 by default --- Source/Renderer/Context.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Renderer/Context.js b/Source/Renderer/Context.js index cb77be85aca0..e8af2d025cf2 100644 --- a/Source/Renderer/Context.js +++ b/Source/Renderer/Context.js @@ -194,7 +194,7 @@ define([ webglOptions.alpha = defaultValue(webglOptions.alpha, false); // WebGL default is true webglOptions.stencil = defaultValue(webglOptions.stencil, true); // WebGL default is false - var defaultToWebgl2 = true; + var defaultToWebgl2 = false; var requestWebgl2 = defaultToWebgl2 && (typeof WebGL2RenderingContext !== 'undefined'); var webgl2 = false; From 8144fe8d70d2931162dfa4964d3be1fdca73eaa3 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Tue, 11 Jul 2017 15:53:58 -0400 Subject: [PATCH 079/240] Now using church tileset --- .../3D Tiles Point Cloud Post Processing.html | 3 +-- .../3D Tiles Point Cloud Post Processing.jpg | Bin 4946 -> 16828 bytes 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html index 987b7cd2b467..b05eb0445020 100644 --- a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html +++ b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html @@ -83,7 +83,6 @@ //Sandcastle_Begin var viewer = new Cesium.Viewer('cesiumContainer', { - globe : false }); viewer.extend(Cesium.viewerCesium3DTilesInspectorMixin); var inspectorViewModel = viewer.cesium3DTilesInspector.viewModel; @@ -92,7 +91,7 @@ viewer.clock.currentTime = new Cesium.JulianDate(2457522.154792); var scene = viewer.scene; -var url = '../../../Specs/Data/Cesium3DTiles/PointCloud/PointCloudWithPerPointProperties/'; +var url = 'https://beta.cesium.com/api/assets/1460?access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIyMzk2YzJiOS1jZGFmLTRlZmYtYmQ4MS00NTA3NjEwMzViZTkiLCJpZCI6NDQsImFzc2V0cyI6WzE0NjBdLCJpYXQiOjE0OTkyNjQ3NTV9.oWjvN52CRQ-dk3xtvD4e8ZnOHZhoWSpJLlw115mbQJM'; var tileset = scene.primitives.add(new Cesium.Cesium3DTileset({ url : url })); diff --git a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.jpg b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.jpg index f4deeb0976a904889e26cebbcdab615fc1aec145..c47189c97346876f96a49c60ed7be81035f4bec6 100644 GIT binary patch literal 16828 zcmb5VV{j)?yS@F3ZQHhO+fF97ZQHgnvF%KpiEVpgJDE50oadbSe|>lNhpyVSci&ZA zb=B&1ul;xR?=ApQT3kvT00aaCko>*?e>VUk01#l{fA{wQ{l38Fuq5YZ8lP*Bm(&|ncTFws#lkx|i5|7`*U^1TKW3228Oz8PVE{QTL4M z@^gpG!%cA$QKO|>q^=p5+FxNe2a9o@9W1j)?#=n-GW#+ZmboyXg~;%pMR%{^#+WV| zub4^E>vxCSzE7x17Y`=7;BM~_&0Dr=KG@zdJ9=Wk{7~;)tT&mN?RY2u3qTK|jlO7k z9cFmu9G*W^bu9|1P`~AFl+en{K=0_Z?9hgd?EBp-jWXkC_0Y$6@u5G@B~xj^XGGgm zk*-jGNTRmYc*1%NxS|Vl-D-TQw`klJ zDq5?3ze|Aef~)Za8a5{TxXs}3S}R4Rp)=}d+vFc33tbg#)T+6)K|QvUZZBsf>B{n2i9`9Y_1{@HYArJO zVKszeNTdm*$I6sNbXcxjG?rGwR+1CG=&M6U%{YucWlNp-LT7$vX6O25X>N40EHg-y zhZUqrveRm?RKG*^O(LL7r$9m|HKa5X)#u84*wH7SiR3$W*sg{TJ0IY;ELr>-j!`aEFZJN}HX^qBR7gcIAz#+{jNC|CCrr4*|SFqNj*!6{e$GVd&?!Wl$L>hsj zZz14vRNcTq(6DA%UHsZ#Q`3Dkc}_BIfp576L3R?4>+nIWn9Y+r9_@VH;BaKJs@B%Ju;ANI(?~g3SogotAfo`ghBA1xzalE zi~XG^n<-D3b|^OMtb5g-#Qt*3%vN=jNXwvmPLpIxG0J$)QY4PYvK~u~Dy@b;sni6mN*zDfiqZho9zIn-|b#OU6 z!3IRl#5pF}G1!E2vM4v8#aM${ma67`?tshjpb14nq1jZLzze~k84it-hgx9UIM&)& zm2vD<9n?$_N4qG~3FL+)9*`1jVhV)L}hXpNJK)xz&UKXXFA8tds3SQ zPg76XOIP|IgmL%II)1E7#GdJrC7x)m3C4OwcLEwg6JGFYv6;Z2|JDUWowc62U<=6Z z^Ilas&eV{9c+)KQ{OH%@6DNHva?2VDve{APdnV#Q zlNz2;#iP`AfTt2wZdzPSBGHDgoH0k<)4x@2Hb0Rir!AB5H zRHPLOkzkzm#5LX2zQzN?TW4hLGcgM^`@l>sIy384Z8L`G!uh>SXtt?J-}#TOUY|lq zsut2WljsluK%n2(H%Wm({zEMgAYf2105}pd3MwKR5iuhZItjB71R*Io%QvMUzu5)^ z2CPTHt}tTFk1@o8ol%)e4{THC>oplVAs0B|`D#bGA0PHiks$4433M0Nfb{A=)9lUY| zd58DLUxg|e;h-g^XcZ~s@JIq1leoP^HPVVqDieMAta#(bUgqK}Vb705OCJQ~zM?=L zzjRw^V6~-!p(q^w6Zr-;rK~jGREQYnV5J06jLM{9(bU&O9~-Avok|Mdq6OEOdpmp! z(8;{cnp#c;T!?FWHxssiTVn_|QExE_ z)vZJ4oUcO6fX3rm)ZG~Si(ZP<>NRvkUOm$W^Q5FffG7O7qS=gncrc1uIeR4~#4zym zbgL^P)v$^w8?RQaE2v|8460hZJJdkz-tRhG#B$p|zSW>Ki+=g=QeJkQ>L?OpFg>+z zG-!Suk0 z`3e&@4`^twwKRoy&{_JFT9DxjY%1ut);^HVXZSVH#$7dRWBhTci^%lW44?;2mxUiU zeBLzK+nP8C)5oTUF3zp?#hvzJ|K#%^itzAKc2tb4NVAnBr*D>A>Qee5EFtyj=&BdFJNEmJCvN<%^GbAn^G5YI z#E6O;j_Jn=6V*@Mi4>hLEH6m(4I+2mz&@_@x16w}E+1Z#9};zJH#NyytFu?Rw{1Z4 zn_c}mKBO)=B|^W+((`4Z)LDV%uh@ik>1G?d#dLNg(e(#oP|A1;zDv9Sx!3-P4?DYT zO>Bc^4pXk9h`LFD@5WMuK_%cH23+jAo9z44(~-iR0G7x>&u>0L(BM7qsBu3@Y=lAQeb z=FLDVy@;-Tub_TzVJ}58{ylXo@)8lx>*L+OfPiy|0a8mpIz#$DKU^ z9D4t6(6b@|fIxsjK|w(v|0_Yi^(GPsGAJSu6Bwb85(+9YBeS6+xNu-%VZ+=FiE{tm ze|Qf91S9~|?xI1s8$l^Nhe1WHHrmNEu*S0(5sF+x1_6E*_eNjdKgXOyxS5N^uPR=s z;*@F?gkH|o58{MPjDCh*(Pr-k}RnU0V_*{xfT8JN_#d z396b9hOZDwIn!>ULK&9*q90gWR+A>mEb9~(8(BVZW=K7 zs>@^fc>bts4|Sk)n|aIe^cOHJmj)#wMh)Fu#>Ae;L!nH!rM0BJ|8r1M`{^WvmAe8t zTDt}>EjL*kQUL&m0Xg^@qaz_y@xii>DH2kv&3;;U6+9}6t3)%eF=u~EBPdikY)*Tp zjaG<<3aKvbOyrw4@ZyrIx8rSJ>Z1?t=;1Fhv?Xy9ssV=)0lx>)3FmGkpc>(3>=!VsV;ks-pzun7GqVc_D`! zkqV=%xu#~}t8!D#MN8A%$2Y=R47?I66%%)bf+vgJXtc^DXjIB^B?&cX#A6`of_Lhc z9e!m))u0`ePuH(67}t?{xC)ukQa+JK7&TgT_^5$u>iJ-`^5Sf#P-tdU>YlcSPFe=o zA){l~xO1R>%LR;mHuuxk-;Fc!uRg*ke*r_IT!F0Gv&{RL&N9ePsk>l%Iyot_G#wBe zFni68thmqD??iGL4peP-*Y{ti6+z%dT*j5wbmzZg_8uBSxIWRTBL~%8sWP-vVNB%) zkX$NogR_I@$|rfdWa2;MEDXYqS0FAgkcgp&9l}=}D_6Wyedu&qYAQ*H4OJa+7#MH5 z`!6r%nuhEno6j=rt@ScN>YAUS{mN|Gx9SGM<6hArLe9W&dC~)}HXGY?h-jdsTB=&J z-)fpCGoB(+ho#)G2H1nj_*C;Gl@f&<+V5jhkN><3#CyJ3CYQp}vbil5%)@?jbECXv z${S((i%7l1Vv&}&wOp}AJ=F+KJv6M~>=6XJ+~7|bV`AHBs|JP-bS}0_X+Qo(SLg^M z9W7^={Ysi@)k;L2c%cU2QNN`!DzCVm`K zf@gh~Yy(D0+576zY50}O_0mDX2u=t<7+Z}fbF4pdHWWb%&?MH;6LKIqKu0%GLaL-w zDf`6&xuOkse&uvL$y{Qm2l|E20b}j zTc+nLw%J!^95-u-3fzf#W^d&3DuE%ba#omDh_p&Jd?dj)0P%vIJXl~`23grt6i{sml7fnUw~96Z#&tb4?8Rxim7w22vOHDZ_l zUV@PYo3upKpv6o6Lxa1}*kZjM0@m5kRa^v)VpXWDx*0+Vy=0+Ioe~^EBHE^y1rXqa0j~-@iCApSkcS1E?#*%gUx3ah%BB@(&qm%TP^H#T9ka}EugKuweF~*I@z61s zjv~!jt#wyAM?YH|*tl+qL(X&!$>hKiY$XOe-L;_b zZbq2lt!Vcz!mqDil|DKUDo2$&mk_~?sU8{?BAluZ(5e+`2wkhxipafsD=3CF!Ig7c zPb-Zs3PBt1jk`IbdzH`#uL$X{+B}Lm^Gdejnb2>6up(inMi8p&1+@mM(^0CS)TLvg zSSgM#R`9LGdq$j3sJc||L%tGQ#+*&Jf{l5xQ;l29TRfla>8#`t0Mmh6`l=AKM)8P6 zs=6*$=-F5<;iRLOBGhB27Vz-{&GqVd@I&cpe zV=rI)c}Gd~w8Bh6VM^%f=*XLB-ZHMr;?!6)ubA^NQyAc`#lF8>?6l%NG{vqGrZb^e zQKh^X_p6Fw8U;1(Cf|IevkdI`lei&feA-Y`$rkwZVv}Xpk%hMmg3gozrhnbS92JU% zSgosraiQsHqwAJmo=;XIfn6qiX*{!dM7BeHE&y8#7tLw)QAXgp4NnQwA|Ab}zip%60(DH%Ejf+3PHvj``m5;7_~70#iNvWgfbCHD{9umuGd zHSDQ4yUhRhR~B3V*!g&9Kw;TA(*1)_Kel(IwJ*zY(5UIRYmzj2)}*ZLI#RhiVnsaM z#cmI4tid7Pl=<%r0&l`^QpFk(53T?ax<3Sk=~Ei^xv6|YgHJ_8zHZ}mw7^##*{WpR zPKBFmD>V1w-ZkiSw*(#hZnE4uU0lsi6Q6ABk8_~KeQ}mcvk{d?@DoZ=HpaU-jCKon zIu!+$fKT^DprnhPwCon2mR1t3Zms<^NF+kP)huzZeT76iaf&;NMHkwvtz;c`{@{&(o??(TjrZ}+U1u{BwS~3e z(w3#I9!r0tMHV2*&1Y-ulCWIL=#0=~-(;qsmXx#i40@d`md$|MjAS{G>?8HF3pSS5 zwuDND9&LsJyZ!gD1XP?Xg%D-4(fAgv!x`3^h9tHMy+Xhnp#&b3IA6d@O>8 z-bxupI;g=**6uY%#KSFlxl^nwP8cucgN=tN38VU`j+_-uh6j5%zWc4OTDW4%W5204 z@P|{+jwf43rO5XDHKtG;-Wv%l%Sd0!OvPDebbi|MCP$m_HX^8gK?W^P&W-5)x!Esr z>%E0E9HHfx>F#gSi(VFJ4~8{}?om$+3+(5b8EiQ`YZ}FMVvSn;{SoD@7tZMkSq0A; z=7H%QO9-yJP3^$8&O#}^8}b)W!lwGf(wKpM8uKh(Da%X$7a&VC(+OLKo&c?KICd2M1JoCT0XJ4*R)(G%2-%R%S)l2|Ejt?iw!`* zV#!9;)%^oU?3OtS)Oc8B?pw#MvfiIMgEM^`%5x9I zNKOK+UjYl`AF=;M@DR7aq+eYJR_oPl&9{Pw##MKTiWbOfchX4Y)ik+X4Ltf>WK8P) zWZ;;-$u{4j0^10F!X@bzqVE9+!A?BR-CYRY;r=XC^AyqhJXEy4aMwn4o8%Y)9g z7iOK2qxDjW*5h)?FB;-zJ<=txtb_9epYlyz`0gtrnQg5S#ROddjbdh&V{Y7G=fL!p9CBV$;V{$)qd4U9X`LX+=y6* zdh@FPock=Tw4=-H#KR~~;&|rrDos}a8@+-wEj?FN^ElI} z*41k_B2=)*W!Fv6;e2n;{`GJ(=5Ud5<6Q_wFzL`JIm-D}zHZU&V_ZOn z(KMdS%x{<23HHT7a7ErQmkE=d)i2g$U>>%t^1>j#Dq5U&6Yrr8MTjy-pH8cA3ek7)h`ygQR3dv;a=Kx zmdhCoH)SC*^M!mVa?=zs`y4tBGc4b!KF+#Y>D$j_m&{t;iijxe(naf%f3R%juBEB` zvmVTN!jed~A**z-T1;=JJ6flo+xQnS#+=~t^>~ka2{wb}e6QW+@hDFl4M&daRajdT zog13tj(GI8jK4ZwQ-7-+)?wAZC9_KTr)=%vQs~x`>m9dQE17~{*S||nAi0Flu?r<-P#t!JHB z`;PS8dZX_p`W$G=;u2lI!_1*+jCyagg_}XOL&b&qES_{t&z|BO)Wlb_PI9l`;zZyn z_ue`Qr{;!$=@;P2tF-5q^%(y~rv?@;&#np@)6IrqX^JY0ajp3=xJAFH!}MS|9UBj+ zhDSYGo_Yp9+FRsNc&?&VUg@gla({x=!%6+X&)0>IKLBZ%EmK|)ytqS0FT*olEKNE^ zznjjCQ*vXrN$gDECDa1_MyIn@2*fCrc5@CqO&k7JnI+cpWFf6jEVXEB7K}vCc5Cn8 zn1DP^Aql7=MtjG)Zw8M#jr>`U!Sw5KaAwJhAEpI;v|HFY2i$m!gvA98Lkz|1b-I^8 z9NxNn3g5UA9sBC0R+m=(FM#?JULdGMSGbq7l2;AX?oq73@j1#*8CNy<$)l#w*>CFn z7^7b*Etmy=uWoMOiieM8WOl{nV@vwDO;f>Yp16(i$bJN8zZ|`-b#^AwSeQR)b*@&8 z1jsrZc4>5~ug+K+(4N5Miv>&&%CP~}u+3f8i5FYv7@DG|R_B=EPegaG`XKZZo~ zKY9}J+Y;-ayCG!UyZzrDhyc;Ik-NjRa!mR-HBN7F{2{N7&l ziLfY{Z3%QANC>PmI)YK3;lZU}0J+?Hhsa6t5Jv7|p5Uxdg3I_vqh4w(LyfraVwx>d zwjVB)-f>-bM?QYy5y7Rg2*OAwwX^?~Sjda%LdzY;=u>rJh^=xs#)i5AQzcPIe6gun zMo#Kl#{hb0X02Ozcpl3mjT!pp0K8ZEb3gY7PKE1{;YoPn+&?E}0E9|JG#yCx zm=yc0fQQO2a~Kn9k5B^`0HrXv8JOQZr*zKG4L;ddvbb)I?(ttKF|BDlQLp3T)}Sj` zO-!YC-kY5H!>M;#EqCu^f#F}78AuRnnea#655JmVXdBzRsO^ZOGL4*V!@KB=6)Zj; zA#&_d;F5HydktGP-HGGv)fAdBFJgI6YkoA8lNX4gtg=vbMX(Q>*MK|Kp_yNT-(vCz zXWg(AQPPJJ@llDo;7m!2BaP?o_Bzb$X6DWv%C$6eoxm z{KC6*eVwQ^mRo8{>z$hzYA_bV53Z&J>wiGjD;EU5QAL>uGJpiG|_KVnez= z4&-d!m)$ok$)*9r6@a3oem6~gW<#PiBlB)*k!22&#x?m^X3PZk@}zEx?n@D)3XbxO?j_Kp6>7Mpcc@sNTWFOe1|OijhWwp;aXpvYh^-M_ezs9khi}u(D?d z{{Y9F5U%!OA855unW?+zAk)LUQVQvX9rx#ih7u(no$daNH?lG&TC-98Zua%9C?BN_= z1YHn6F({*}Lp|^^kF8c^0+|RvDs=sq2#WL>3V0YkbEqEb^?ii}VteyVW3J7fLp%Xa z54yFCUS9r2CZD&HPeS#`C4nOYY_UuV(YgAjjfH#>P(#9K)Id)-Iw91sf`P(3`(=W=$D8S3+#^M>z~t0y0RmPt%MWZ z(CMMnj#Fs_lTah%EW#1?dzivuT81BUc;;Px0s@Fj_J|YR`A-c{ znB0BBBj_xwoE=$;Tj57M1;q;O!fW&=Yk~a_`kc-*m8p-;lueap{O3NT>|+%y$8a@p z+A-IU4D?YwuIy-85Tx{xA{n`v$EGyQ5c{e%D_m*F288H^HGNWMyt7cesI&Zqp8Gdn zj+7t1XK$;`Vf(%$8Y(dfQaFBn(@gjfngw9QSLt|h6w0ZtE#AbFusySH%kcB|2P zOC!K06GbCUHk4{HqY*z@^0dmw?^qDwC1aW%_4?4s$+UJf?W$7Gk$Z_X8HVU}3h1$x zdvMVCHh;E@@40&SXw=wEfWhT^_A%c1UFZ{ZiX4#RQI^|2IXRH8jaa3kxnq&Gl-qkn;Nv|>{MJ5)9wy`UduC~za|qmsG3!Ai)$9n{;UbG zP+P$5QnG2ZPGS6EEE~9JrAO9}y0y-aS2;zOHU4zjvs?m?o2f7$e~*0w-&>wkycV zV{qz3fDR5ROPKqy%Q#pO$BBPqr5a(6`4`ZjT4gPBhdu0meiUH0c^eV2hUf0A zaNzfCjaFY<-XOg7HVZNzOrXoBbQ=*UkLD_Q8*NpdK1`(hj(b=IQxbgK7WPJ!zHZ(!rI2} zaih+z#0G;iHo!Doxwh4W5v$SO2tqNnG3!itwqn#{>whA28Z6hh!w5mipYB7(#u)DF zLpGLHJKuPc;g;`yU4Io`>zfHXKfO;Fz|_?UIAd#?TuEn2F88`Z1a&fAd`b2q>5i)< zo=yOaJswqeiMCgg0ch1D?pFH&ila(eA98s!IoQizz)^Y2d!POlc*$B?xCW(Pb>l|2 zEaM}m6j{6?O9F6NzC;W;xEMG@2M*F$>C7K>v=-J}gt_~Mt$3%_cI`S*0fpKb%a|sK5#0A&lvC(nvZg> z+wV`@2{zZnZU1(MaRD7NL=@j7@RcLzlGe-~UWmzYdykKM%$+r|0oQL|?m2s}21~|{ zZhK2?gB?QtBZ0)@efTc`)E%-YNVGIgP~dFb=mn}@%l^A#@fYxUfLLoCjc@qx`7hvU zn#+J-8-@Qb;Q24$_zf8uXYXL@f2Q81{Aaoo4z2v({{kM#$&GmFWxk*K{sJyv%DxpS z1=4>M=)WM&e-ng2fPV@U@t>vntw6u^XaC;Z|21V1Ed!q3)0{c#km!DC2e8rK!Z^c} zhjc&!4WSNVP>l(qpitV>?y?E*kK>${)5W>d?8EKTLne}j+KvyalK{!NjBduL%04@y zZNuNAM1obD(Ui2L0e(|UQw1VInU+U+;c5h@L4Yt)T|yT-r?=x~K#wt4Jd>F*(F(R| zU?sR%Ax)}@M!*;|%2Eel0NZZ*Lmp@#11!T%U{NUx7%hL=+TNej%d3sRKEdIW;r&ul z4m2jx5)9^E6clFJW&=9e{DSF=>et=gMB^v>S5@H=F$YRJCH-vUDR>r>!HYE zY7piQVZkGa^er`|KN62fCzXYnFCBeHoa*&I+_BGprH_PTjL#4FhQ36fC~{^5N4|u; zIg+^Ch%H?A#JwWBEQCwtFKBXDq+TnpH&xx?6tCHfc+z`mgU0t?IGDg=zZ$D%cP3uW zDvmsP-eWzXHW5dP)QJX-#~ubpG_@;KkP_WLfXb_2B_M?|o&ptr90XVRfFr7F51Sw` z&|@za*B5-j)YGEcg2-kV2BurqHcxm(oawqv z+3JClIAl6?$5cKT>uf}f+n}eS(kA`L->Cx7Bryp)THE~vP z8l?O%%9d`Ur!U@!^h&#&OZ&;3;hfQiynQ?hoDlYdemK z4l{!_N7{0LYSCT>mFSMEzd%2o1PqO?-gndAY$W!X<9=sSvDBCub7-;qpah1V`;Y0A z>v9Duxv@2e;Aei9Z+AZlU~0 zef_t6KeVlz85F`d)EP#HFJHqq%!drj}&qSRofB8(N z1(VSZ$|&u5+7Tq-uvb(A){p1otoM~1p;7n1>fAuL)ZsiYo0P?lqQI+wKHd9T`~35j zmg`N!TfgdktcSN$n(mGWv8jp9v}hS5xQXnb(HdidUINK+@Nzb*rUVYRc+O?wpe<3$ z;4SQzfiK?uQlPcA@qRpiMaTY^V}J+$UeRa%_$|7=>;R&8Cq>Z@V7O??qn6^tF54R3Hq0C5MnG`iSG|MrV)PfDGY~k z{`C_Q`hDl@r*=lt*k?o^C<4>(UrNsQMsO5}6pV`?^qjCZ_y%O5GYu>|rSSXsgolyL zkTQ$xcNRrQA2Hw|>uai&LDD3!s6~!lL21oWMSlvAdgbD6#})U`Y)sf0qt+C111lq# zdCG4Jfs^)RQKh*~t!NJl@F^%)Nkm{@rJ+UXR*^%tL3K_OLsd(}M1d0^H-J0KIl7sB za#CI`VBUOfBb-xolu)B_gCY$M3!r8%=*A#mqhu7AfJ<|jesbAppk#%V!=~O26((|I z9+?8m{ zA71rg#jk4S0(z&9&o&&nhdDUGhBM5OJ{8U`*{DMHPTDh`n(RvX7@5%-R(t42KU)-+ zpTI>K#=lJju|(Nj7_|-ik~B$Ba8CSnT#U#p#_xYuF=0)!fjx4J+>f3m1dd!^_4_7~u^Euepe8U$xd z!0uTHMr%XBR;EAT`x;a^7}%unNCl zhFBDj!e`K@D!>c+#EKxX95gY_s=wZImad6BZ4?z0qS+a~Oq9HxHN)DnNEA8@IY{MK zNk42WsKVKT76s#hSV-L*a|x>xPci}Xs=3b>?#6QtvnAU>HX>H#C{H+S(_}&rdeai+&LphNXv*a-5MT(2o8C==hQ(x z)pVRie`lu5X?X7B`St^#HprzGXY?a^+LnRKa5%|1@z96&v(v3Mi}=ExNr!J01!{7% z=olq!Lb>zo9JuWQ$B*yq&gJv!Julctw5>~^k6VQ#czI3|uf z3*A&quQxgt&U$l2@5ej!i(OFA)tf`h@G6Ee(77Vl@^t^>{oUVT-Dn;3p5fVRD6xJ? zT976)&hk$6hFfjtz_%7Dk!9N5=Uu}~r3+O6W$dQnE2{UMxK&ftoHY<1`soh5AQrUW zia-C@xK@PaAU2B} z)6||)Gmb>9Y7qe82Hex~fQ?brUr$_pdwc)#=6<>dr@!*@Yd2?|xP#JtpPUmLM_U7K zt7t1S)G`%0{~w>f?bCni^`C?KUqFAKi}|m8nuz#MyxubYFQC68Ga!J94Kz>WU1NioF<~BT9 zd^RhBR$5^Y=A{`G;4HUhHV>p=^X!1^_6Gt}Z%gaA(nO6b3vsWixuu3{kuO@Wqz?=6 zH~emQ?e#>)N7?G1q`TtJWu+S`S?UJZ)E2II(!lKQ*u4;Un`Y!3q})%OR97y*n9dUU zvOurf5#iWt?4LtH1aU8PEUw1q@IhZF5M$Wpw>oamrz{NZ5_o01$KVqgozwSW7K$({t)M)h5O*37NX9RK8f7>nV#I`=148B_Pzn|aPhxl`TpCFe z^qR5VgD+_d36;@yt|_!%gv$(TNV!=}4pmLfx;(7W2Am@bA2p^QFx$5MU;|*_UiUZn54ypwqb$?ltBO`ddCER!) zyW#Hp`~;s<@TX8nJt`ZoK8N1{+6z#JtLp>kNpbADX6i0@ea?@}LbD0x+of@L@eDZa z)P*$shOVD*yXw}v8Bx2Wlp=1OTLVt!tm=t!mgZ5goeM!tV=zb)Gn&DMMesjxk2nF# zgt8fs)gmY~qj-m}O@acdBDZGRDw8oLY4k&D%lb}=G=_-$A}1IpL6nsG!AIk~@V)DR zU_QT9>+(|eZekG*($R&KozZQn!Xj5e%eoPGJ}H2j#o$_)m`f1|fJzD@CXfP8T~(q{ zquZ*!A^52#JluI(Vj-JOI)HU`MH3#xJj0Is>CF5&hQ1aRx9~XPzAG5{2|fY~_$9|d zHc3i&479V8v|;N6uEarA=ldwYV;?=p^(;uq9MX(Kmy!@dzVzFTjt`i-!u#bUiir)ler3Ae-xW)nIbLV&*4cyEAZWDl4o zSBt@crZ7#mst?|#kAo8fYRZ$*6sWb016(iK#xgXd7;gRH?eIui>e~$-kY{LSkw+$+ zBKvt;FRW>QjC(Nrhw(gXhUk-=I=Q8M_UbZa2pQN@3%)C^(E}+RgTveVP^2Pg-FK&5 zSwCYk}>lnybMy*CAHA&H85Ga36$aE2nL7Cegs>Y zZHAznznflDkT?9h#BJ`#r+{&8T9)hwQSxm411Xb4qK2wd4j6F#Lo6YX_9W|BCNHgS7YLOmdy)glj%Q&zVqu^82<0zOXhBYYS_9S% zgn3N$O5*7H9|$q4Mv}94h41ybs7!d>eweaUX%Af+LOil0wkXMa4A;4D?7&^)Z%zlc zNUExwF~Xhx{Pn?5z37=AC z3v>`8n}LrjZ!J0~x!@a3I0Uy7Jn?@2`U;9=-47Kvuzf%oAq+I?8amb z$g*vC?bDi|B#RJLB@qm8Tu^Tz%@bO-myr5Knk}ue9_9G*43^2NYfswZi#+TX{0pa~Yai1_PHD;&(g*mHq%Pc%L z>&NcBv$3ojg~S<+KqR+k!JGgNe=wn?YAE@9+85{OhyzU>ot$uNyG%}=uoM!uWw~=1 zofx1g5lhB@5J4XCquU4)kv;ZcqHc34$JRV3&@Ri*#gI%Nz&}ZuMdIQU#I^VB@Cf|c z`?FJGorBdSYKDc7MVs6n-Rosw%1EULico-Xqh+~Ph;fLsh7Q++!>Xk16W8Y>2-lOJ zj#=Kz8{$WKVz(aR2W%D{ar6$PF>P<$@D~8w3qk9S2I1(!Uw>|yl>10g2yUqGowe^6_oa-A|ya@%xRW2UqSYIL<` zH($1Z7PzB9Cv;yh(GxRP2}quI(~8Al$OC^Z-a0nu+tW}*h-$t^gXNmcwMP$TQRI^@ ziKN=hoCHdelK00XPVy zm_}C@jiy=W=$GoYR%0o?&22B`&-E{sK-D40fwQK%{4(}2>S~3J;B(5@O-X}URhOL+ zEX)BYkujLN<03Li_Mq4lnTgs#9M_A}#n>~tewftbqa}Xk32fn+Fm4!!B7XO7NAD<# z`#9+L_=6~6O3!L2AV(nmX%?|gj@$fA|M#?eQDFLjDGqYxZK}n$qH8f!r(02KYVig% z;9xeUwj5^DQiKbbKsMOYa0q#+uAUKWN{A=cL zegp{ca2^3p2`XC-(Lv>~5Ql6;9&|8RMX<5*+JV3sN5@LL zhzCPGr2Ep(LJ{QL5h6>&1{k)TAO6z#|f8072if4T2ZY1lS&%f@Ick;0_hLsochj5(s`^ zVuNOdD=dqUs8o|F(p-N4as-D(P2^oJKiA6nD6{2NmU|4;(d+edf>G%{sIEufQaE| z&EpbNhG$cbt=b;apI6F||^9mMO6F29Kvg*$# zV=kJ17;^d8*8M)KK}n`A=60eOavkoDD_9z&vghaY2e|WQ7pz+B#*}n3o0xy1K1qiZS= zuSM-6`~+Q(w@(aMroI(JGzG_-yXk}LF96S^fnzmM048uZLkT5%;MaW=Xj5d&k~UV^ z2}VUZ#MAGJdI|lQzW|wuK>X?sEUG`ghDgUbpj>pp;`$<+bqAElL`*|J&`dQW)x#-r zO4s#?sZ`T2d~TC$Zk0x0Kw*_qlOHIv^?+m=zq?yikVxQ)Md2pFGJgSxiZ{VR2*F;w z22%$0Z#=9+avnp17JsghB#l54^EZw4l1C{JmB>?Ng?J_enTCwl_&2dsgrxm$p+%HV zU#7bv+>8l@PV{4n1b_++y&#%?Om;3QLIWy*Bo{oldCUQ7KR^)n6Xskc`Qd!+cB?r@ z=N*g#kc8IeRX&t`JpTglB}e3InDKsxBwYv{Kk)? zcGRf4TueIspDOpER2~2(8=%4@D!*^1G literal 4946 zcmb7H2{e>%+kc)}>@>rWJ%bp#u_gW(gRw6|Swo2=%Vd|bjARR0B72r>5!sb2V@c?r ztx^femL*$ADc&jn-t(UGedjyxcR%;J&vSnF?|RO4U)O#A?&~>tbMOH`7!dRc00@GB z9`ykZ#sMt=3W5CU)CQw=I2{}ggTWbSX=&(~7?_wC85kLvSy&OwEJzkcMg#`}$%bNQ zXJI+$%D}W_{CUY9#^JRo^lF5 z_3FS$rr&*9N3b4WA~HUnHlwmJeKYF{^rJ7X|MVoS0(F1Op#eJ zqb1(J*fWQxi9Qqe8-(AnjkVOS3ve~R@cyk!&moanWHnXUzVCM9XQz3i*M~%~ctq;C z{t2%VUvs-l4uJx{nNaV?-D#eR{;~aycf>}o)g}Ex?*XXA3&-z?dAta;u64coJp4Bm z@UNZAc79-(@v2Vj!uFu-FAy#OEF~FA)j|x8KVCRw{nsNcHO|5a076YJ6rhInuz?UH zfX1>4%Hg1zcs7BvLe!wsQF8>sA^T3ldj!hmLR>2YQK8U)UR+U**>u#_c1yWDP77vr zD{IboRF1X~E!cV5(ywwX#!$pcO-`X4@i;(-Fyxfx9F(n9mRFcyw=lEt^8lbOTnGt(FbD_-pnu{80th4;r-_BI3J}koz3lya-B1wJ0DnaA zA5Rd9hh=DXB~R#0Vg$-8o0#pqs>F<>gL=lNZg?JPE_U1B<3{JSqI6{M^ZRbgYHd^;Xyw6`kEq)~GFyZ4;l!JD9 z_)&pYpN{857iZ}YSo*`zibcVC)2AMHl|d*i-x&qO`NO%sr<%a*lYF)kHXIek=Y z)rahyDQ&fu1mR8Bf4L=#06-`N4uL`G|7;hk zTUa7Q^PD#sfn$}!4+|z!1kBG~jwq;^UjJw7&}cw@$f{4aJP0K06~?LBdk381eG7)z zfW85r<>nN8hlV+6{iXVAQ9n=F__Xes#!i$G?4fP3qu))EYOn%kwLO+@E*V@8{d1W) z&U+0dSoiP05@}cp)!VB++H=gWMprX*h;ah0>5_svwNN5y8YS(5a)T<nG=SA4p2K-37p#+OC<3y>(;NR}pL!@Y z&<8+AWPU#F|>&NSCEq5a(mrO_np=G;I?SV_ud(Ta+&xRbE$*Iv7cH+Ag)G4w?DVG(Oq^(H$uqmpVu2MR9;(2*V zfQebreZsz_5uSC5m^@Ch>$eurx$!B4f3gIgHhLxCp5?~kt8e9$A-8wR>*v&J=IF1R zafuFTJ1|I^S71o~xfIhnO1K+Y zU{LCqa-WFdEX&sU5o{&l!y}>KcC(~v+?!Gq;vTdk*;h#WO*ubc4}^QmQ@h}t;oqT`Iwy|M2T81hZ7XKfSuM=cknEuaf@?z zPpnej8AT<0&eARXkrEGjP*s#)o4}|YuCS$IG&PP$%G>nKMyD*Kx3%mp+`h+a@l)ON z>3z*tiXrX6oEcT^#ag~ES=RZ&Q;hT%BIsB$dnMV>E-W``_>^ouC!3Ru+SNH@a=T>M z7hhOO@R@)kdV%e!Ne$74v2}D0;sWQUMFj*@J{Yk((L8DOaY6KFc23C2%YSJkbia&Q z+8ipmmnif-CkvF=ahy>BpQTp(a4uyHcw84}j^HzI51CqA^na(GzVxk&vZgyRmS<lEA3N>LuUqQ$4M22rOlE=GU)u?3W(TYld5@&OPYM%9_$b-`~j zN2KTr|KFWeUr1}PVDpfsxkp2EKIG?ENLBY8+S1?~LJz@Ivm4g*hoIn-_rc{==h!T)*`rOJXBk}3-z z6r}y53cqgytmZlqN7dZ|$}}RmX84aP{JOFb2Y^OBYuSf|BW3jlr^<$1E!?MCz7$kM zSYuxV;}gzVpre3)1-pSFj zy+MNgR(W8NBXc<2a!o@dGB_xmmXc>H9(=* z3v#O5B_=-;A`Q~A}re&Y%HxFJ?EI8j#MjHuG3n!a1~FwMvh3auGoq%OX@mY z>yQeJxY;-=v$9|*~NhfH5WFO4ux8hd=f#kdN2Ch9zPqTb#&owlN%im;B z;f&y{Z0E13JXK^$m{9O4(QVOT&WKBNHDJ2=gDo%T@Xjx!Ajx!F)#Hs3Uq;N% zUV_(a+Xo9eh(xLA4>r2^tR=XQvCp`Kb!bpG0ft&QLm&Vg_V1#AT1um_nmFP)@;V~9 zfZ|CH#UV@iYH1{tREFgTv5`${O|0)+%xyLQ#kbHZl{1t%{@ zrndylc~J=QusDNBdEnC zvVZiZRxSAG+tvUpW>*{Q4cDrWr~depjY{?tgC_Ia#1UmYQP9 zKULN5Q~s0_;#sy8Ik>!kE{IP@yJPj!%VlK|LI-UmZDZT9G3dK|RN~C|2htP_p^b_N zoVxO1`Zyno%soD7?iyCbj~0WAw0?~M@270Vl9_E`SzpKOTe)*+aLFUG?^UinRy-*= z?8FG~pgE1dqB`sDplkI0)*Y6q?vQYX`bbuj;nyLzXHz)fkM%=$S&EolVhTmn}NIl!z z9KbTY&u^u-cwOSjxW$v#r&SlRyN=y0dJ2`4A^WoTAw&G2IhkB~S0+?h z(F1;=r&-YZxgj~jl`9=g*bru>tLtwYLO5^Lh^dF^VYGOeg4GsuGuKtD*=xj@Y|3XU z#;&PY0bG9LPWdle0}N5RG#-Qe2LQ7UhG_6N?noLm-P}4canFm?TjjiTZIqPLre?~2 zMS0!j6V$*pWtfP0ks$S6D_PngLv=PM>Qa6Qob3^hU$g$gQ7-UP)ZAi8Y5d}x0Y|bC z;~5=2tTuny^Vc`t9St_M+q|5ue)TQDqfHKJ#^>{x5kwnK49`V+{7`j~ZP=B8DWOa? zA8lAAv14)J+!9J--?lqhrpX_!)_I2AJ<|g7XDqlm8N5Du=H8ZpWSk@HFT1(<^pYgm z^DgXL%TA*&sjDfUeQ4s@?%GZa zJF7EL?p48wySgZ1g`(lEwuW3v5T5bbBWf|sO08zj-`%`t%N^;Ia(89_0Eo?trKfAP zKLDzL=gt*P>}_HTSyDhFMqbOL?Ro1L=TAqtFR~Q_#AsDH0^@1DsgpiC-d1n*kE#TB z3b22E?IUG}LqCLVuBZkp^#rZ9(7!Qd3+&5SPh%A^DW(x0jwy4X?ptfRDlzt~u`~fku=zEw{m1 zqZbK77Y<+~;*#}5iavUKjhC_CA1Mttz7;zFnX-V1>UJ(^$lYW_<`X}KRh1h)(H%QN zE-F0dcqOJg^4>!*e?`>o0Okr_hRq61UPwj?9AM;N6LEfj@Y z(va Date: Tue, 11 Jul 2017 16:25:25 -0400 Subject: [PATCH 080/240] Fixes a problem that arose during merging --- Source/Scene/Cesium3DTileset.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Scene/Cesium3DTileset.js b/Source/Scene/Cesium3DTileset.js index 8b94a4cb2118..19f74e33ab0f 100644 --- a/Source/Scene/Cesium3DTileset.js +++ b/Source/Scene/Cesium3DTileset.js @@ -1543,7 +1543,7 @@ define([ ++statistics.selected; } } - var addedCommandsLength = commandList.length - lengthBeforeUpdate; + var lengthAfterUpdate = commandList.length; tileset._backfaceCommands.trim(); From d998194590b23e8bba33b4c8e291306cdc2ab7c9 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 12 Jul 2017 11:15:56 -0400 Subject: [PATCH 081/240] Replaces the hacky "replace-all" function in GLSLModernizer with a recursive replace --- Source/Renderer/GLSLModernizer.js | 64 ++++++++++++++++++++++--------- 1 file changed, 46 insertions(+), 18 deletions(-) diff --git a/Source/Renderer/GLSLModernizer.js b/Source/Renderer/GLSLModernizer.js index 89c39e6d6334..97263ac0eea4 100644 --- a/Source/Renderer/GLSLModernizer.js +++ b/Source/Renderer/GLSLModernizer.js @@ -57,36 +57,64 @@ define([ '#define OUTPUT_DECLARATION ' + 'nor a main function!'); } + + function safeNameFalseNegative(regex, region) { + var regExpStr = regex.toString(); + regExpStr = regExpStr.match(/\/([^\/]+)(\/.)?/)[1]; + var somethingBadInString = + new RegExp("[a-zA-Z0-9_]+" + regExpStr, 'g'); + var searchResult = region.search(somethingBadInString); + if (searchResult === -1) { + return true; + } else { + return false; + } + } function safeNameFind(regex, str) { - if (str.search(regex) !== -1) { - var regExpStr = regex.toString(); - regExpStr = regExpStr.match(/\/([^\/]+)(\/.)?/)[1]; - var somethingBadInString = - new RegExp("[a-zA-Z0-9_]+" + regExpStr, 'g'); - if (str.search(somethingBadInString) === -1) { - return true; - } + var originalMatch = regex.exec(str); + if (originalMatch == null) { + return -1; + } + var endPos = originalMatch.index + originalMatch[0].length; + var region = str.substring(0, endPos); + + var possiblyFalseNegative = safeNameFalseNegative(regex, region); + if (possiblyFalseNegative) { + return endPos; + } else { + return endPos + safeNameFind(regex, str.substring(endPos)); + } + } + + function safeNameReplace(regex, str, replacement) { + var originalMatch = regex.exec(str); + if (originalMatch == null) { + return str; + } + var endPos = originalMatch.index + originalMatch[0].length; + var region = str.substring(0, endPos); + + var possiblyFalseNegative = safeNameFalseNegative(regex, region); + if (possiblyFalseNegative) { + return region.replace(regex, replacement) + + safeNameReplace(regex, str.substr(endPos), replacement); + } else { + return region + + safeNameReplace(regex, str.substr(endPos), replacement); } - return false; } function replaceInSource(regex, replacement) { - var replaceAll = function(target, search, replacement) { - return target.split(search).join(replacement); - }; for (var number = 0; number < splitSource.length; number++) { - var line = splitSource[number]; - if (safeNameFind(regex, line)) { - splitSource[number] = replaceAll(line, regex, replacement); - } + splitSource[number] = safeNameReplace(regex, splitSource[number], replacement); } } - + function findInSource(regex) { for (var number = 0; number < splitSource.length; number++) { var line = splitSource[number]; - if (safeNameFind(regex, line)) { + if (safeNameFind(regex, line) !== -1) { return true; } } From 4f5aeead4ae1ca3083958ab01f90d112fbb37c79 Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Wed, 12 Jul 2017 11:58:17 -0400 Subject: [PATCH 082/240] Fix for updating the point cloud processor --- Source/Scene/Cesium3DTileset.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Scene/Cesium3DTileset.js b/Source/Scene/Cesium3DTileset.js index 19f74e33ab0f..0295036cbae4 100644 --- a/Source/Scene/Cesium3DTileset.js +++ b/Source/Scene/Cesium3DTileset.js @@ -1544,6 +1544,7 @@ define([ } } var lengthAfterUpdate = commandList.length; + var addedCommandsLength = lengthAfterUpdate - lengthBeforeUpdate; tileset._backfaceCommands.trim(); @@ -1573,7 +1574,6 @@ define([ */ var backfaceCommands = tileset._backfaceCommands.values; - var addedCommandsLength = (lengthAfterUpdate - lengthBeforeUpdate); var backfaceCommandsLength = backfaceCommands.length; commandList.length += backfaceCommands.length; From de7615755ad376a0f677263c028edc79a1c852c9 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 12 Jul 2017 12:00:03 -0400 Subject: [PATCH 083/240] Fixes find function --- Source/Renderer/GLSLModernizer.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Source/Renderer/GLSLModernizer.js b/Source/Renderer/GLSLModernizer.js index 97263ac0eea4..95c373455510 100644 --- a/Source/Renderer/GLSLModernizer.js +++ b/Source/Renderer/GLSLModernizer.js @@ -83,7 +83,12 @@ define([ if (possiblyFalseNegative) { return endPos; } else { - return endPos + safeNameFind(regex, str.substring(endPos)); + var childResult = safeNameFind(regex, str.substring(endPos)); + if (childResult == -1) { + return -1; + } else { + return endPos + childResult; + } } } @@ -283,6 +288,8 @@ define([ } } + console.log(compileSource()); + if (first === true) { var versionThree = "#version 300 es"; var foundVersion = false; From 0d711a447d409daa0e0d0b495ff87667f8fc4a72 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 12 Jul 2017 15:55:19 -0400 Subject: [PATCH 084/240] Renamed frustumClamp to clampedFrustum --- Source/Renderer/AutomaticUniforms.js | 4 ++-- Source/Renderer/UniformState.js | 10 +++++----- Source/Scene/PointCloud3DTileContent.js | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Source/Renderer/AutomaticUniforms.js b/Source/Renderer/AutomaticUniforms.js index c5281638c359..79d6b444a27f 100644 --- a/Source/Renderer/AutomaticUniforms.js +++ b/Source/Renderer/AutomaticUniforms.js @@ -1106,11 +1106,11 @@ define([ } }), - czm_frustumClamp : new AutomaticUniform({ + czm_clampedFrustum : new AutomaticUniform({ size : 1, datatype : WebGLConstants.FLOAT_VEC2, getValue : function(uniformState) { - return uniformState.frustumClamp; + return uniformState.clampedFrustum; } }), diff --git a/Source/Renderer/UniformState.js b/Source/Renderer/UniformState.js index 687e7a0f1273..9646f7f9d2e4 100644 --- a/Source/Renderer/UniformState.js +++ b/Source/Renderer/UniformState.js @@ -56,7 +56,7 @@ define([ this._infiniteProjection = Matrix4.clone(Matrix4.IDENTITY); this._entireFrustum = new Cartesian2(); this._currentFrustum = new Cartesian2(); - this._frustumClamp = new Cartesian2(); + this._clampedFrustum = new Cartesian2(); this._frustumPlanes = new Cartesian4(); this._frameState = undefined; @@ -639,9 +639,9 @@ define([ * @memberof UniformState.prototype * @type {Cartesian4} */ - frustumClamp : { + clampedFrustum : { get : function() { - return this._frustumClamp; + return this._clampedFrustum; } }, @@ -975,8 +975,8 @@ define([ var camera = frameState.camera; this.updateCamera(camera); - this._frustumClamp.x = frameState.clampedNear; - this._frustumClamp.y = frameState.clampedFar; + this._clampedFrustum.x = frameState.clampedNear; + this._clampedFrustum.y = frameState.clampedFar; if (frameState.mode === SceneMode.SCENE2D) { this._frustum2DWidth = camera.frustum.right - camera.frustum.left; diff --git a/Source/Scene/PointCloud3DTileContent.js b/Source/Scene/PointCloud3DTileContent.js index a2485011cd22..f3120efef963 100644 --- a/Source/Scene/PointCloud3DTileContent.js +++ b/Source/Scene/PointCloud3DTileContent.js @@ -1024,8 +1024,8 @@ define([ vs += ' position_EC.z *= -1.0; \n'; vs += ' float attenuationFactor = \n' + - ' ((position_EC.z - czm_frustumClamp.x) /\n' + - ' (czm_frustumClamp.y - czm_frustumClamp.x)); \n'; + ' ((position_EC.z - czm_clampedFrustum.x) /\n' + + ' (czm_clampedFrustum.y - czm_clampedFrustum.x)); \n'; vs += ' gl_PointSize *= mix(u_pointAttenuationMaxSize, 1.0, attenuationFactor);'; From 64ec737f8f6baad66c8d29315a4030d483d41ad0 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 12 Jul 2017 16:00:20 -0400 Subject: [PATCH 085/240] Fixes Cartesian naming typo --- Source/Renderer/UniformState.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Renderer/UniformState.js b/Source/Renderer/UniformState.js index 9646f7f9d2e4..e1ee31165256 100644 --- a/Source/Renderer/UniformState.js +++ b/Source/Renderer/UniformState.js @@ -637,7 +637,7 @@ define([ * The distance to the clamped near and far planes. The nearest object determines the near * plane and the farthest object determines the far plane. * @memberof UniformState.prototype - * @type {Cartesian4} + * @type {Cartesian2} */ clampedFrustum : { get : function() { From d9af53d032897ae46907b40909dd9ffab68e392c Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 12 Jul 2017 16:01:28 -0400 Subject: [PATCH 086/240] Indents tag --- .../gallery/3D Tiles Point Cloud Post Processing.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html index b05eb0445020..9173f2b52a5a 100644 --- a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html +++ b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html @@ -24,7 +24,7 @@

Loading...

-
+
+ + + + + + + +
Occlusion Angle From 7c7c63cb35ad55c6f72db11cb8259ef6b030536a Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 12 Jul 2017 16:04:15 -0400 Subject: [PATCH 087/240] Removes date function --- .../gallery/3D Tiles Point Cloud Post Processing.html | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html index 9173f2b52a5a..58e6919bab3a 100644 --- a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html +++ b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html @@ -82,14 +82,11 @@ 'use strict'; //Sandcastle_Begin -var viewer = new Cesium.Viewer('cesiumContainer', { -}); +var viewer = new Cesium.Viewer('cesiumContainer'); viewer.extend(Cesium.viewerCesium3DTilesInspectorMixin); var inspectorViewModel = viewer.cesium3DTilesInspector.viewModel; inspectorViewModel.picking = false; -viewer.clock.currentTime = new Cesium.JulianDate(2457522.154792); - var scene = viewer.scene; var url = 'https://beta.cesium.com/api/assets/1460?access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIyMzk2YzJiOS1jZGFmLTRlZmYtYmQ4MS00NTA3NjEwMzViZTkiLCJpZCI6NDQsImFzc2V0cyI6WzE0NjBdLCJpYXQiOjE0OTkyNjQ3NTV9.oWjvN52CRQ-dk3xtvD4e8ZnOHZhoWSpJLlw115mbQJM'; var tileset = scene.primitives.add(new Cesium.Cesium3DTileset({ From 4dbe8de89f8c9cd397b142b254826c794a237493 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 12 Jul 2017 16:05:04 -0400 Subject: [PATCH 088/240] Removes useless style --- .../gallery/3D Tiles Point Cloud Post Processing.html | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html index 58e6919bab3a..2b9bcd0a90d4 100644 --- a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html +++ b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html @@ -100,11 +100,6 @@ viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY); }); -var style = { -}; -style.pointSize = Cesium.defaultValue(style.pointSize, 1.0); -tileset.style = new Cesium.Cesium3DTileStyle(style); - var viewModel = { occlusionAngle : tileset.pointCloudPostProcessorOptions.occlusionAngle, rangeParameter : tileset.pointCloudPostProcessorOptions.rangeParameter, From 4f644458a272d4407f7c6341d7247f2a265ca575 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 12 Jul 2017 16:06:01 -0400 Subject: [PATCH 089/240] Removes unnecessary comment --- .../gallery/3D Tiles Point Cloud Post Processing.html | 2 -- 1 file changed, 2 deletions(-) diff --git a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html index 2b9bcd0a90d4..554b15e64898 100644 --- a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html +++ b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html @@ -143,8 +143,6 @@ tileset.pointCloudPostProcessorOptions.stencilViewEnabled = checked; }); -/////////////////////////////////////////////////////////////////////////////// - //Sandcastle_End Sandcastle.finishedLoading(); } From 9300fa81c98f242322eded693e5ca50c2e50d4b0 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 12 Jul 2017 16:08:50 -0400 Subject: [PATCH 090/240] Adds more of the documentation for the parameters into PointCloudPostProcessor --- Source/Scene/Cesium3DTileset.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Source/Scene/Cesium3DTileset.js b/Source/Scene/Cesium3DTileset.js index 0295036cbae4..876f51a219ff 100644 --- a/Source/Scene/Cesium3DTileset.js +++ b/Source/Scene/Cesium3DTileset.js @@ -724,8 +724,10 @@ define([ * TODO: Write documentation for these properties *

* - * @type {Event} - * @default {enabled : true, occlusionAngle : 0.1, rangeParameter : 1.0} + * @type {Object} + * @default {enabled : true, occlusionAngle : 0.1, rangeParameter : 1.0, neighborhoodHalfWidth : 4 + * numRegionGrowingPasses : 4, densityHalfWidth : 4, neighborhoodVectorSize : 10.0, maxAbsRatio : 0.9 + * densityViewEnabled : false, stencilViewEnabled : false, pointAttenuationMultiplier : 2.0} */ this.pointCloudPostProcessorOptions = { enabled : defaultValue(options.enabled, true), From 512da5a1bbfce01e3dba26f08f193a09ec3d1e89 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 12 Jul 2017 16:11:07 -0400 Subject: [PATCH 091/240] Removes defaultValue statements --- Source/Scene/Cesium3DTileset.js | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/Source/Scene/Cesium3DTileset.js b/Source/Scene/Cesium3DTileset.js index 876f51a219ff..f969f4594284 100644 --- a/Source/Scene/Cesium3DTileset.js +++ b/Source/Scene/Cesium3DTileset.js @@ -730,17 +730,17 @@ define([ * densityViewEnabled : false, stencilViewEnabled : false, pointAttenuationMultiplier : 2.0} */ this.pointCloudPostProcessorOptions = { - enabled : defaultValue(options.enabled, true), - occlusionAngle : defaultValue(options.occlusionAngle, 0.1), - rangeParameter : defaultValue(options.rangeParameter, 0.001), - neighborhoodHalfWidth : defaultValue(options.neighborhoodHalfWidth, 4), - numRegionGrowingPasses : defaultValue(options.numRegionGrowingPasses, 4), - densityHalfWidth : defaultValue(options.densityHalfWidth, 4), - neighborhoodVectorSize : defaultValue(options.neighborhoodVectorSize, 10.0), - maxAbsRatio : defaultValue(options.maxAbsRatio, 0.9), - densityViewEnabled : defaultValue(options.densityViewEnabled, false), - stencilViewEnabled : defaultValue(options.stencilViewEnabled, false), - pointAttenuationMultiplier : defaultValue(options.pointAttenuationMultiplier, 2.0) + enabled : true, + occlusionAngle : 0.1, + rangeParameter : 0.001, + neighborhoodHalfWidth : 4, + numRegionGrowingPasses : 4, + densityHalfWidth : 4, + neighborhoodVectorSize : 10.0, + maxAbsRatio : 0.9, + densityViewEnabled : false, + stencilViewEnabled : false, + pointAttenuationMultiplier : 2.0 }; this._pointCloudPostProcessor = new PointCloudPostProcessor(this.pointCloudPostProcessorOptions); From d90233af0fda02f36258b54833f55b8d0aba763e Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 12 Jul 2017 16:13:13 -0400 Subject: [PATCH 092/240] Removes some obsolete TODO statements --- Source/Scene/Cesium3DTileset.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/Source/Scene/Cesium3DTileset.js b/Source/Scene/Cesium3DTileset.js index f969f4594284..378dbf06566e 100644 --- a/Source/Scene/Cesium3DTileset.js +++ b/Source/Scene/Cesium3DTileset.js @@ -1596,8 +1596,6 @@ define([ if (addedCommandsLength > 0) { // TODO : only do this if the tileset is purely point clouds. - // TODO : this may not work well if point cloud spans multiple frustums - // TODO : make the processor a static class so it can be used by multiple tilesets? tileset._pointCloudPostProcessor.update(frameState, numberOfInitialCommands, { enabled : tileset.pointCloudPostProcessorOptions.enabled, occlusionAngle : tileset.pointCloudPostProcessorOptions.occlusionAngle, From 630c9c238e62c746699605c347612d5321051102 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 12 Jul 2017 16:22:00 -0400 Subject: [PATCH 093/240] Now passing the tileset into PointCloudPostProcessor --- Source/Scene/Cesium3DTileset.js | 14 +------- Source/Scene/PointCloudPostProcessor.js | 44 ++++++++++++------------- 2 files changed, 23 insertions(+), 35 deletions(-) diff --git a/Source/Scene/Cesium3DTileset.js b/Source/Scene/Cesium3DTileset.js index 378dbf06566e..b38fe54617bc 100644 --- a/Source/Scene/Cesium3DTileset.js +++ b/Source/Scene/Cesium3DTileset.js @@ -1596,19 +1596,7 @@ define([ if (addedCommandsLength > 0) { // TODO : only do this if the tileset is purely point clouds. - tileset._pointCloudPostProcessor.update(frameState, numberOfInitialCommands, { - enabled : tileset.pointCloudPostProcessorOptions.enabled, - occlusionAngle : tileset.pointCloudPostProcessorOptions.occlusionAngle, - rangeParameter : tileset.pointCloudPostProcessorOptions.rangeParameter, - neighborhoodHalfWidth : tileset.pointCloudPostProcessorOptions.neighborhoodHalfWidth, - numRegionGrowingPasses : tileset.pointCloudPostProcessorOptions.numRegionGrowingPasses, - densityHalfWidth : tileset.pointCloudPostProcessorOptions.densityHalfWidth, - neighborhoodVectorSize : tileset.pointCloudPostProcessorOptions.neighborhoodVectorSize, - maxAbsRatio : tileset.pointCloudPostProcessorOptions.maxAbsRatio, - densityViewEnabled : tileset.pointCloudPostProcessorOptions.densityViewEnabled, - stencilViewEnabled : tileset.pointCloudPostProcessorOptions.stencilViewEnabled, - pointAttenuationMultiplier : tileset.pointCloudPostProcessorOptions.pointAttenuationMultiplier - }); + tileset._pointCloudPostProcessor.update(frameState, numberOfInitialCommands, tileset); } if (tileset.debugShowGeometricError || tileset.debugShowRenderingStatistics || tileset.debugShowMemoryUsage) { diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 2df12eb05288..13c5c92afa02 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -657,37 +657,37 @@ define([ return shader; } - PointCloudPostProcessor.prototype.update = function(frameState, commandStart, options) { + PointCloudPostProcessor.prototype.update = function(frameState, commandStart, tileset) { if (!processingSupported(frameState.context)) { return; } var dirty = false; // Set options here - if (options.occlusionAngle !== this.occlusionAngle || - options.rangeParameter !== this.rangeParameter || - options.neighborhoodHalfWidth !== this.neighborhoodHalfWidth || - options.numRegionGrowingPasses !== this.numRegionGrowingPasses || - options.densityHalfWidth !== this.densityHalfWidth || - options.neighborhoodVectorSize !== this.neighborhoodVectorSize || - options.maxAbsRatio !== this.maxAbsRatio || - options.densityViewEnabled !== this.densityViewEnabled || - options.stencilViewEnabled !== this.stencilViewEnabled || - options.pointAttenuationMultiplier !== this.pointAttenuationMultiplier) { - this.occlusionAngle = options.occlusionAngle; - this.rangeParameter = options.rangeParameter; - this.neighborhoodHalfWidth = options.neighborhoodHalfWidth; - this.numRegionGrowingPasses = options.numRegionGrowingPasses; - this.densityHalfWidth = options.densityHalfWidth; - this.neighborhoodVectorSize = options.neighborhoodVectorSize; - this.densityViewEnabled = options.densityViewEnabled; - this.stencilViewEnabled = options.stencilViewEnabled; - this.maxAbsRatio = options.maxAbsRatio; - this.pointAttenuationMultiplier = options.pointAttenuationMultiplier; + if (tileset.pointCloudPostProcessorOptions.occlusionAngle !== this.occlusionAngle || + tileset.pointCloudPostProcessorOptions.rangeParameter !== this.rangeParameter || + tileset.pointCloudPostProcessorOptions.neighborhoodHalfWidth !== this.neighborhoodHalfWidth || + tileset.pointCloudPostProcessorOptions.numRegionGrowingPasses !== this.numRegionGrowingPasses || + tileset.pointCloudPostProcessorOptions.densityHalfWidth !== this.densityHalfWidth || + tileset.pointCloudPostProcessorOptions.neighborhoodVectorSize !== this.neighborhoodVectorSize || + tileset.pointCloudPostProcessorOptions.maxAbsRatio !== this.maxAbsRatio || + tileset.pointCloudPostProcessorOptions.densityViewEnabled !== this.densityViewEnabled || + tileset.pointCloudPostProcessorOptions.stencilViewEnabled !== this.stencilViewEnabled || + tileset.pointCloudPostProcessorOptions.pointAttenuationMultiplier !== this.pointAttenuationMultiplier) { + this.occlusionAngle = tileset.pointCloudPostProcessorOptions.occlusionAngle; + this.rangeParameter = tileset.pointCloudPostProcessorOptions.rangeParameter; + this.neighborhoodHalfWidth = tileset.pointCloudPostProcessorOptions.neighborhoodHalfWidth; + this.numRegionGrowingPasses = tileset.pointCloudPostProcessorOptions.numRegionGrowingPasses; + this.densityHalfWidth = tileset.pointCloudPostProcessorOptions.densityHalfWidth; + this.neighborhoodVectorSize = tileset.pointCloudPostProcessorOptions.neighborhoodVectorSize; + this.densityViewEnabled = tileset.pointCloudPostProcessorOptions.densityViewEnabled; + this.stencilViewEnabled = tileset.pointCloudPostProcessorOptions.stencilViewEnabled; + this.maxAbsRatio = tileset.pointCloudPostProcessorOptions.maxAbsRatio; + this.pointAttenuationMultiplier = tileset.pointCloudPostProcessorOptions.pointAttenuationMultiplier; dirty = true; } - if (!options.enabled) { + if (!tileset.pointCloudPostProcessorOptions.enabled) { return; } From d270f4a38e87d8f289f713bcf3a58a5be0fff348 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 12 Jul 2017 16:24:00 -0400 Subject: [PATCH 094/240] Fixes documentation string on pointAttenuationMaxSize --- Source/Scene/PointCloud3DTileContent.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Scene/PointCloud3DTileContent.js b/Source/Scene/PointCloud3DTileContent.js index f3120efef963..01cc81c6b1ab 100644 --- a/Source/Scene/PointCloud3DTileContent.js +++ b/Source/Scene/PointCloud3DTileContent.js @@ -261,7 +261,7 @@ define([ }, /** - * Part of the {@link Cesium3DTileContent} interface. + * @private */ pointAttenuationMaxSize : { get : function() { From e371e5475292d7f58d97af61288f8e059332bee8 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 12 Jul 2017 16:25:12 -0400 Subject: [PATCH 095/240] Fixes floating point type in GLSL code --- Source/Scene/PointCloud3DTileContent.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Scene/PointCloud3DTileContent.js b/Source/Scene/PointCloud3DTileContent.js index 01cc81c6b1ab..7f967dc36db1 100644 --- a/Source/Scene/PointCloud3DTileContent.js +++ b/Source/Scene/PointCloud3DTileContent.js @@ -1020,7 +1020,7 @@ define([ vs += ' gl_PointSize = u_pointSize; \n'; } - vs += ' vec4 position_EC = czm_view * vec4(position_absolute, 1); \n'; + vs += ' vec4 position_EC = czm_view * vec4(position_absolute, 1.0); \n'; vs += ' position_EC.z *= -1.0; \n'; vs += ' float attenuationFactor = \n' + From 4b0e6f3d441e29932a0da4099fdf078ef10fa1f2 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 12 Jul 2017 16:28:01 -0400 Subject: [PATCH 096/240] Combines multiple vertex shader lines into one --- Source/Scene/PointCloud3DTileContent.js | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/Source/Scene/PointCloud3DTileContent.js b/Source/Scene/PointCloud3DTileContent.js index 7f967dc36db1..845ef01da8e5 100644 --- a/Source/Scene/PointCloud3DTileContent.js +++ b/Source/Scene/PointCloud3DTileContent.js @@ -1020,16 +1020,13 @@ define([ vs += ' gl_PointSize = u_pointSize; \n'; } - vs += ' vec4 position_EC = czm_view * vec4(position_absolute, 1.0); \n'; - vs += ' position_EC.z *= -1.0; \n'; - - vs += ' float attenuationFactor = \n' + + vs += ' vec4 position_EC = czm_view * vec4(position_absolute, 1.0); \n' + + ' position_EC.z *= -1.0; \n\n' + + ' float attenuationFactor = \n' + ' ((position_EC.z - czm_clampedFrustum.x) /\n' + - ' (czm_clampedFrustum.y - czm_clampedFrustum.x)); \n'; - - vs += ' gl_PointSize *= mix(u_pointAttenuationMaxSize, 1.0, attenuationFactor);'; - - vs += ' color = color * u_highlightColor; \n'; + ' (czm_clampedFrustum.y - czm_clampedFrustum.x)); \n' + + ' gl_PointSize *= mix(u_pointAttenuationMaxSize, 1.0, attenuationFactor); \n\n' + + ' color = color * u_highlightColor; \n'; if (hasNormals) { vs += ' normal = czm_normal * normal; \n' + From 83da840d2cecb7e25f8d0b2e7023f2e804611a07 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 12 Jul 2017 16:40:32 -0400 Subject: [PATCH 097/240] Renames DENSITY_VIEW to densityView and STENCIL_VIEW to stencilView --- Source/Scene/PointCloudPostProcessor.js | 16 ++++++++-------- .../PostProcessFilters/RegionGrowingPassGL1.glsl | 8 ++++---- .../PostProcessFilters/RegionGrowingPassGL2.glsl | 8 ++++---- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 13c5c92afa02..e585ba8897a3 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -347,13 +347,13 @@ define([ regionGrowingPassStr = replaceConstants( regionGrowingPassStr, - 'DENSITY_VIEW', + 'densityView', processor.densityViewEnabled ); regionGrowingPassStr = replaceConstants( regionGrowingPassStr, - 'STENCIL_VIEW', + 'stencilView', processor.stencilViewEnabled ); @@ -405,7 +405,7 @@ define([ var copyStageStr = '#extension GL_EXT_draw_buffers : enable \n' + - '#define DENSITY_VIEW \n' + + '#define densityView \n' + '#define densityScaleFactor 32.0 \n' + '#define EPS 1e-6 \n' + 'uniform int densityHalfWidth; \n' + @@ -418,7 +418,7 @@ define([ ' vec4 rawDepth = texture2D(pointCloud_depthTexture, v_textureCoordinates); \n' + ' float depth = czm_unpackDepth(rawDepth); \n' + ' if (depth > EPS) { \n' + - ' #ifdef DENSITY_VIEW \n' + + ' #ifdef densityView \n' + ' float density = densityScaleFactor * czm_unpackDepth(texture2D(pointCloud_densityTexture, v_textureCoordinates)); \n' + ' gl_FragData[0] = vec4(vec3(density / float(densityHalfWidth)), 1.0); \n' + ' #else \n' + @@ -430,7 +430,7 @@ define([ copyStageStr = replaceConstants( copyStageStr, - 'DENSITY_VIEW', + 'densityView', processor.densityViewEnabled ); @@ -453,7 +453,7 @@ define([ var stencilMaskStageStr = '#define EPS 1e-8 \n' + - '#define CUTOFF 0 \n' + + '#define cutoff 0 \n' + '#define DELAY 0 \n' + '#define densityScaleFactor 32.0 \n' + 'uniform sampler2D pointCloud_densityTexture; \n' + @@ -461,13 +461,13 @@ define([ 'void main() \n' + '{ \n' + ' float density = densityScaleFactor * czm_unpackDepth(texture2D(pointCloud_densityTexture, v_textureCoordinates)); \n' + - ' if (float(CUTOFF - DELAY) + EPS > density) \n' + + ' if (float(cutoff - DELAY) + EPS > density) \n' + ' discard; \n' + '} \n'; stencilMaskStageStr = replaceConstants( stencilMaskStageStr, - 'CUTOFF', + 'cutoff', iteration ); diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl index 64bcef3b1aa3..6c36779a70ba 100644 --- a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl @@ -7,8 +7,8 @@ #define EPS 1e-8 #define SQRT2 1.414213562 #define densityScaleFactor 32.0 -#define DENSITY_VIEW -#define STENCIL_VIEW +#define densityView +#define stencilView #define DELAY 1 uniform sampler2D pointCloud_colorTexture; @@ -197,10 +197,10 @@ void main() { } } -#ifdef DENSITY_VIEW +#ifdef densityView gl_FragData[0] = vec4(vec3(density / float(densityHalfWidth)), 1.0); #else -#ifdef STENCIL_VIEW +#ifdef stencilView gl_FragData[0] = testColor(iterationNumber); #else gl_FragData[0] = finalColor; diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl index fe05ec4c4459..d4bf48150762 100644 --- a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl @@ -6,8 +6,8 @@ #define EPS 1e-8 #define SQRT2 1.414213562 #define densityScaleFactor 32.0 -#define DENSITY_VIEW -#define STENCIL_VIEW +#define densityView +#define stencilView #define DELAY 1 uniform sampler2D pointCloud_colorTexture; @@ -204,10 +204,10 @@ void main() { } } -#ifdef DENSITY_VIEW +#ifdef densityView colorOut = vec4(vec3(density / float(densityHalfWidth)), 1.0); #else -#ifdef STENCIL_VIEW +#ifdef stencilView colorOut = testColor(iterationNumber); #else colorOut = finalColor; From 91bb5852730db6df690ce11a390ac18830b0674b Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Fri, 14 Jul 2017 10:44:46 -0400 Subject: [PATCH 098/240] Adds option to enable/disable the triangle wave --- .../gallery/3D Tiles Point Cloud Post Processing.html | 4 ++++ Source/Scene/Cesium3DTileset.js | 3 ++- Source/Scene/PointCloudPostProcessor.js | 11 ++++++++++- .../PostProcessFilters/PointOcclusionPassGL2.glsl | 8 ++++---- 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html index 554b15e64898..6179e34fa8a9 100644 --- a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html +++ b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html @@ -135,6 +135,10 @@ tileset.pointCloudPostProcessorOptions.enabled = checked; }); +Sandcastle.addToggleButton('Use Triangle Wave', true, function(checked) { + tileset.pointCloudPostProcessorOptions.useTriangle = checked; +}); + Sandcastle.addToggleButton('Density View', false, function(checked) { tileset.pointCloudPostProcessorOptions.densityViewEnabled = checked; }); diff --git a/Source/Scene/Cesium3DTileset.js b/Source/Scene/Cesium3DTileset.js index 2197b2369bba..21ed62a86963 100644 --- a/Source/Scene/Cesium3DTileset.js +++ b/Source/Scene/Cesium3DTileset.js @@ -636,7 +636,8 @@ define([ maxAbsRatio : 0.9, densityViewEnabled : false, stencilViewEnabled : false, - pointAttenuationMultiplier : 2.0 + pointAttenuationMultiplier : 2.0, + useTriangle : false }; this._pointCloudPostProcessor = new PointCloudPostProcessor(this.pointCloudPostProcessorOptions); diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index e585ba8897a3..ebb0069d63c9 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -83,6 +83,7 @@ define([ this.densityViewEnabled = options.densityViewEnabled; this.stencilViewEnabled = options.stencilViewEnabled; this.pointAttenuationMultiplier = options.pointAttenuationMultiplier; + this.useTriangle = options.useTriangle; } function createSampler() { @@ -258,6 +259,12 @@ define([ processor.neighborhoodHalfWidth ); + pointOcclusionStr = replaceConstants( + pointOcclusionStr, + 'useTriangle', + processor.useTriangle + ); + var func = StencilFunction.EQUAL; var op = { fail : StencilOperation.KEEP, @@ -673,7 +680,8 @@ define([ tileset.pointCloudPostProcessorOptions.maxAbsRatio !== this.maxAbsRatio || tileset.pointCloudPostProcessorOptions.densityViewEnabled !== this.densityViewEnabled || tileset.pointCloudPostProcessorOptions.stencilViewEnabled !== this.stencilViewEnabled || - tileset.pointCloudPostProcessorOptions.pointAttenuationMultiplier !== this.pointAttenuationMultiplier) { + tileset.pointCloudPostProcessorOptions.pointAttenuationMultiplier !== this.pointAttenuationMultiplier || + tileset.pointCloudPostProcessorOptions.useTriangle !== this.useTriangle) { this.occlusionAngle = tileset.pointCloudPostProcessorOptions.occlusionAngle; this.rangeParameter = tileset.pointCloudPostProcessorOptions.rangeParameter; this.neighborhoodHalfWidth = tileset.pointCloudPostProcessorOptions.neighborhoodHalfWidth; @@ -684,6 +692,7 @@ define([ this.stencilViewEnabled = tileset.pointCloudPostProcessorOptions.stencilViewEnabled; this.maxAbsRatio = tileset.pointCloudPostProcessorOptions.maxAbsRatio; this.pointAttenuationMultiplier = tileset.pointCloudPostProcessorOptions.pointAttenuationMultiplier; + this.useTriangle = tileset.pointCloudPostProcessorOptions.useTriangle; dirty = true; } diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl index 9b50b32a1c14..660859dcd7ac 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl @@ -12,8 +12,8 @@ #define neighborhoodSize 9 #define numSectors 8 -#define PERIOD 1e-5 -#define USE_TRIANGLE +#define trianglePeriod 1e-5 +#define useTriangle uniform float ONE; @@ -296,7 +296,7 @@ void main() { // neighboring points are usually very similar. // On the other hand, the x-values and y-values are // usually fairly different. -#ifdef USE_TRIANGLE +#ifdef useTriangle // We can get even more accuracy by passing the 64-bit // distance into a triangle wave function that // uses 64-bit primitives internally. The region @@ -333,7 +333,7 @@ void main() { mul_fp64(highPrecisionX, highPrecisionX), mul_fp64(highPrecisionY, highPrecisionY)), mul_fp64(highPrecisionZ, highPrecisionZ))); - float triangleResult = triangleFP64(highPrecisionLength, PERIOD); + float triangleResult = triangleFP64(highPrecisionLength, trianglePeriod); depthOut = czm_packDepth(triangleResult); #else depthOut = czm_packDepth(length(centerPosition)); From 0f0cf367b2bbdca08e9b7aa85660234d5c28ea52 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Fri, 14 Jul 2017 11:13:20 -0400 Subject: [PATCH 099/240] Now rescaling the range parameter before it is passed into the shader --- Source/Scene/PointCloudPostProcessor.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index ebb0069d63c9..ffa5c90b167c 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -84,6 +84,9 @@ define([ this.stencilViewEnabled = options.stencilViewEnabled; this.pointAttenuationMultiplier = options.pointAttenuationMultiplier; this.useTriangle = options.useTriangle; + + this.rangeMin = 1e-6; + this.rangeMax = 5e-2; } function createSampler() { @@ -322,6 +325,8 @@ define([ function regionGrowingStage(processor, context, iteration) { var i = iteration % 2; + var rangeMin = processor.rangeMin; + var rangeMax = processor.rangeMax; var uniformMap = { pointCloud_colorTexture : function() { @@ -334,7 +339,15 @@ define([ return processor._densityTexture; }, rangeParameter : function() { - return processor.rangeParameter; + if (processor.useTriangle) { + return processor.rangeParameter; + } else { + if (processor.rangeParameter < rangeMin) { + return 0.0; + } else { + return processor.rangeParameter * (rangeMax - rangeMin) + rangeMin; + } + } }, densityHalfWidth : function() { return processor.densityHalfWidth; From 981ebfb940fc4cb6af9da92d684052dd5d07e395 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Fri, 14 Jul 2017 11:13:50 -0400 Subject: [PATCH 100/240] USE_TRIANGLE_WAVE is off by default now --- .../gallery/3D Tiles Point Cloud Post Processing.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html index 6179e34fa8a9..1517f49b2ec1 100644 --- a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html +++ b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html @@ -135,7 +135,7 @@ tileset.pointCloudPostProcessorOptions.enabled = checked; }); -Sandcastle.addToggleButton('Use Triangle Wave', true, function(checked) { +Sandcastle.addToggleButton('Use Triangle Wave', false, function(checked) { tileset.pointCloudPostProcessorOptions.useTriangle = checked; }); From 6a38b49c09deefebe3d91443c792afc5aa155e2e Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Fri, 14 Jul 2017 13:52:19 -0400 Subject: [PATCH 101/240] Now using rescaled ray distances --- .../PointOcclusionPassGL2.glsl | 56 +++++++++++-------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl index 660859dcd7ac..a1c427c5791a 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl @@ -12,7 +12,7 @@ #define neighborhoodSize 9 #define numSectors 8 -#define trianglePeriod 1e-5 +#define trianglePeriod 1e-2 #define useTriangle uniform float ONE; @@ -71,7 +71,7 @@ vec2 quickTwoSum(float a, float b) { return vec2(sum, err); } -vec2 sum_fp64(vec2 a, vec2 b) { +vec2 sumFP64(vec2 a, vec2 b) { vec2 s, t; s = twoSum(a.x, b.x); t = twoSum(a.y, b.y); @@ -82,7 +82,7 @@ vec2 sum_fp64(vec2 a, vec2 b) { return s; } -vec2 sub_fp64(vec2 a, vec2 b) { +vec2 subFP64(vec2 a, vec2 b) { vec2 s, t; s = twoSub(a.x, b.x); t = twoSub(a.y, b.y); @@ -93,7 +93,7 @@ vec2 sub_fp64(vec2 a, vec2 b) { return s; } -vec2 mul_fp64(vec2 a, vec2 b) { +vec2 mulFP64(vec2 a, vec2 b) { vec2 prod = twoProd(a.x, b.x); // y component is for the error prod.y += a.x * b.y; @@ -105,20 +105,32 @@ vec2 mul_fp64(vec2 a, vec2 b) { vec2 divFP64(in vec2 a, in vec2 b) { float xn = 1.0 / b.x; vec2 yn = a * xn; - float diff = (sub_fp64(a, mul_fp64(b, yn))).x; + float diff = (subFP64(a, mulFP64(b, yn))).x; vec2 prod = twoProd(xn, diff); - return sum_fp64(yn, prod); + return sumFP64(yn, prod); } -vec2 sqrt_fp64(vec2 a) { +vec2 sqrtFP64(in vec2 a) { if (a.x == 0.0 && a.y == 0.0) return vec2(0.0, 0.0); if (a.x < 0.0) return vec2(0.0 / 0.0, 0.0 / 0.0); float x = 1.0 / sqrt(a.x); float yn = a.x * x; vec2 yn_sqr = twoSqr(yn) * ONE; - float diff = sub_fp64(a, yn_sqr).x; + float diff = subFP64(a, yn_sqr).x; vec2 prod = twoProd(x * 0.5, diff); - return sum_fp64(vec2(yn, 0.0), prod); + return sumFP64(vec2(yn, 0.0), prod); +} + +vec2 lengthFP64(in vec3 vec) { + vec2 highPrecisionX = split(vec.x); + vec2 highPrecisionY = split(vec.y); + vec2 highPrecisionZ = split(vec.z); + vec2 highPrecision = + sqrtFP64(sumFP64(sumFP64( + mulFP64(highPrecisionX, highPrecisionX), + mulFP64(highPrecisionY, highPrecisionY)), + mulFP64(highPrecisionZ, highPrecisionZ))); + return highPrecision; } float triangle(in float x, in float period) { @@ -129,10 +141,10 @@ float triangleFP64(in vec2 x, in float period) { float lowPrecision = x.x + x.y; vec2 floorTerm = split(floor(lowPrecision / period)); vec2 periodHighPrecision = split(period); - vec2 term2 = mul_fp64(periodHighPrecision, floorTerm); - vec2 moduloTerm = sub_fp64(x, term2); + vec2 term2 = mulFP64(periodHighPrecision, floorTerm); + vec2 moduloTerm = subFP64(x, term2); vec2 normalized = divFP64(moduloTerm, periodHighPrecision); - normalized = sub_fp64(normalized, split(0.5)); + normalized = subFP64(normalized, split(0.5)); return abs(normalized.x + normalized.y) + EPS; } @@ -325,18 +337,18 @@ void main() { // is usually at least an order of magnitude greater than // the average delta, so it won't even be considered in // the region growing pass. - vec2 highPrecisionX = split(centerPosition.x); - vec2 highPrecisionY = split(centerPosition.y); - vec2 highPrecisionZ = split(centerPosition.z); - vec2 highPrecisionLength = - sqrt_fp64(sum_fp64(sum_fp64( - mul_fp64(highPrecisionX, highPrecisionX), - mul_fp64(highPrecisionY, highPrecisionY)), - mul_fp64(highPrecisionZ, highPrecisionZ))); - float triangleResult = triangleFP64(highPrecisionLength, trianglePeriod); + vec2 hpl = lengthFP64(centerPosition); + float triangleResult = triangleFP64(hpl, trianglePeriod); depthOut = czm_packDepth(triangleResult); #else - depthOut = czm_packDepth(length(centerPosition)); + vec2 lengthOfFrustum = subFP64(split(czm_clampedFrustum.y), + split(czm_clampedFrustum.x)); + vec2 frustumStart = split(czm_clampedFrustum.x); + vec2 centerPositionLength = lengthFP64(centerPosition); + vec2 normalizedDepthFP64 = sumFP64(divFP64(centerPositionLength, + lengthOfFrustum), + frustumStart); + depthOut = czm_packDepth(normalizedDepthFP64.x + normalizedDepthFP64.y); #endif } } From 29c1cf84ca2728829c7246ac68d5fb5d14fb42b7 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Fri, 14 Jul 2017 14:31:50 -0400 Subject: [PATCH 102/240] Blending is now depth-aware --- Source/Scene/PointCloudPostProcessor.js | 15 ++++- .../PointOcclusionPassGL1.glsl | 63 +++++++++++-------- 2 files changed, 51 insertions(+), 27 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index ffa5c90b167c..088df6ae02d3 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -537,12 +537,25 @@ define([ copyCommands[1] = copyRegionGrowingColorStage(processor, context, 1); var blendFS = + '#define EPS 1e-8 \n' + + '#extension GL_EXT_frag_depth : enable \n' + 'uniform sampler2D pointCloud_colorTexture; \n' + + 'uniform sampler2D pointCloud_depthTexture; \n' + 'varying vec2 v_textureCoordinates; \n' + 'void main() \n' + '{ \n' + ' vec4 color = texture2D(pointCloud_colorTexture, v_textureCoordinates); \n' + - ' gl_FragColor = color; \n' + + ' float rayDist = czm_unpackDepth(texture2D(pointCloud_depthTexture, v_textureCoordinates)); \n' + + ' if (length(rayDist) < EPS) { \n' + + ' discard;' + + ' } else { \n' + + ' float frustumLength = czm_clampedFrustum.y - czm_clampedFrustum.x; \n' + + ' float scaledRayDist = rayDist * frustumLength + czm_clampedFrustum.x; \n' + + ' vec4 ray = normalize(czm_windowToEyeCoordinates(vec4(gl_FragCoord))); \n' + + ' float depth = czm_eyeToWindowCoordinates(ray * scaledRayDist).z; \n' + + ' gl_FragColor = color; \n' + + ' gl_FragDepthEXT = depth; \n' + + ' }' + '} \n'; var blendRenderState = RenderState.fromCache({ diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl index d64f4ced8ab7..507c03b64621 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl @@ -11,9 +11,8 @@ #define neighborhoodHalfWidth 4 // TUNABLE PARAMETER -- half-width of point-occlusion neighborhood #define numSectors 8 - -#define PERIOD 1e-5 -#define USE_TRIANGLE +#define trianglePeriod 1e-5 +#define useTriangle uniform float ONE; @@ -69,7 +68,7 @@ vec2 quickTwoSum(float a, float b) { return vec2(sum, err); } -vec2 sum_fp64(vec2 a, vec2 b) { +vec2 sumFP64(vec2 a, vec2 b) { vec2 s, t; s = twoSum(a.x, b.x); t = twoSum(a.y, b.y); @@ -80,7 +79,7 @@ vec2 sum_fp64(vec2 a, vec2 b) { return s; } -vec2 sub_fp64(vec2 a, vec2 b) { +vec2 subFP64(vec2 a, vec2 b) { vec2 s, t; s = twoSub(a.x, b.x); t = twoSub(a.y, b.y); @@ -91,7 +90,7 @@ vec2 sub_fp64(vec2 a, vec2 b) { return s; } -vec2 mul_fp64(vec2 a, vec2 b) { +vec2 mulFP64(vec2 a, vec2 b) { vec2 prod = twoProd(a.x, b.x); // y component is for the error prod.y += a.x * b.y; @@ -103,20 +102,32 @@ vec2 mul_fp64(vec2 a, vec2 b) { vec2 divFP64(in vec2 a, in vec2 b) { float xn = 1.0 / b.x; vec2 yn = a * xn; - float diff = (sub_fp64(a, mul_fp64(b, yn))).x; + float diff = (subFP64(a, mulFP64(b, yn))).x; vec2 prod = twoProd(xn, diff); - return sum_fp64(yn, prod); + return sumFP64(yn, prod); } -vec2 sqrt_fp64(vec2 a) { +vec2 sqrtFP64(in vec2 a) { if (a.x == 0.0 && a.y == 0.0) return vec2(0.0, 0.0); if (a.x < 0.0) return vec2(0.0 / 0.0, 0.0 / 0.0); float x = 1.0 / sqrt(a.x); float yn = a.x * x; vec2 yn_sqr = twoSqr(yn) * ONE; - float diff = sub_fp64(a, yn_sqr).x; + float diff = subFP64(a, yn_sqr).x; vec2 prod = twoProd(x * 0.5, diff); - return sum_fp64(vec2(yn, 0.0), prod); + return sumFP64(vec2(yn, 0.0), prod); +} + +vec2 lengthFP64(in vec3 vec) { + vec2 highPrecisionX = split(vec.x); + vec2 highPrecisionY = split(vec.y); + vec2 highPrecisionZ = split(vec.z); + vec2 highPrecision = + sqrtFP64(sumFP64(sumFP64( + mulFP64(highPrecisionX, highPrecisionX), + mulFP64(highPrecisionY, highPrecisionY)), + mulFP64(highPrecisionZ, highPrecisionZ))); + return highPrecision; } float triangle(in float x, in float period) { @@ -127,10 +138,10 @@ float triangleFP64(in vec2 x, in float period) { float lowPrecision = x.x + x.y; vec2 floorTerm = split(floor(lowPrecision / period)); vec2 periodHighPrecision = split(period); - vec2 term2 = mul_fp64(periodHighPrecision, floorTerm); - vec2 moduloTerm = sub_fp64(x, term2); + vec2 term2 = mulFP64(periodHighPrecision, floorTerm); + vec2 moduloTerm = subFP64(x, term2); vec2 normalized = divFP64(moduloTerm, periodHighPrecision); - normalized = sub_fp64(normalized, split(0.5)); + normalized = subFP64(normalized, split(0.5)); return abs(normalized.x + normalized.y) + EPS; } @@ -355,7 +366,7 @@ void main() { // neighboring points are usually very similar. // On the other hand, the x-values and y-values are // usually fairly different. -#ifdef USE_TRIANGLE +#ifdef useTriangle // We can get even more accuracy by passing the 64-bit // distance into a triangle wave function that // uses 64-bit primitives internally. The region @@ -384,18 +395,18 @@ void main() { // is usually at least an order of magnitude greater than // the average delta, so it won't even be considered in // the region growing pass. - vec2 highPrecisionX = split(centerPosition.x); - vec2 highPrecisionY = split(centerPosition.y); - vec2 highPrecisionZ = split(centerPosition.z); - vec2 highPrecisionLength = - sqrt_fp64(sum_fp64(sum_fp64( - mul_fp64(highPrecisionX, highPrecisionX), - mul_fp64(highPrecisionY, highPrecisionY)), - mul_fp64(highPrecisionZ, highPrecisionZ))); - float triangleResult = triangleFP64(highPrecisionLength, PERIOD); - gl_FragData[0] = czm_packDepth(triangleResult); + vec2 hpl = lengthFP64(centerPosition); + float triangleResult = triangleFP64(hpl, trianglePeriod); + gl_FragData[0] = czm_packDepth(triangleResult); #else - gl_FragData[0] = czm_packDepth(length(centerPosition)); + vec2 lengthOfFrustum = subFP64(split(czm_clampedFrustum.y), + split(czm_clampedFrustum.x)); + vec2 frustumStart = split(czm_clampedFrustum.x); + vec2 centerPositionLength = lengthFP64(centerPosition); + vec2 normalizedDepthFP64 = sumFP64(divFP64(centerPositionLength, + lengthOfFrustum), + frustumStart); + gl_FragData[0] = czm_packDepth(normalizedDepthFP64.x + normalizedDepthFP64.y); #endif } } From a5255a046f455029c512eeba8b13294ca58cf917 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Mon, 17 Jul 2017 13:19:06 -0400 Subject: [PATCH 103/240] Disables point cloud post processing by default --- .../gallery/3D Tiles Point Cloud Post Processing.html | 1 + Source/Scene/Cesium3DTileset.js | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html index 1517f49b2ec1..01ec646a4207 100644 --- a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html +++ b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html @@ -92,6 +92,7 @@ var tileset = scene.primitives.add(new Cesium.Cesium3DTileset({ url : url })); +tileset.pointCloudPostProcessorOptions.enabled = true; inspectorViewModel.tileset = tileset; tileset.readyPromise.then(function() { diff --git a/Source/Scene/Cesium3DTileset.js b/Source/Scene/Cesium3DTileset.js index 21ed62a86963..e96816df50e0 100644 --- a/Source/Scene/Cesium3DTileset.js +++ b/Source/Scene/Cesium3DTileset.js @@ -626,7 +626,7 @@ define([ * densityViewEnabled : false, stencilViewEnabled : false, pointAttenuationMultiplier : 2.0} */ this.pointCloudPostProcessorOptions = { - enabled : true, + enabled : false, occlusionAngle : 0.1, rangeParameter : 0.001, neighborhoodHalfWidth : 4, @@ -641,7 +641,7 @@ define([ }; this._pointCloudPostProcessor = new PointCloudPostProcessor(this.pointCloudPostProcessorOptions); - + /** * This property is for debugging only; it is not optimized for production use. *

From dfa8179cdd96155336d2ebf8aac0099f19342ee7 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Mon, 17 Jul 2017 13:30:07 -0400 Subject: [PATCH 104/240] Fixes eslint issues in PointCloudPostProcessor --- Source/Scene/PointCloudPostProcessor.js | 63 ++++++++++++------------- 1 file changed, 31 insertions(+), 32 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 088df6ae02d3..7e3853a6817a 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -152,7 +152,7 @@ define([ pixelDatatype: PixelDatatype.UNSIGNED_INT_24_8, sampler: createSampler() }); - + for (i = 0; i < 2; ++i) { colorTextures[i] = new Texture({ context : context, @@ -227,17 +227,17 @@ define([ function replaceConstants(sourceStr, constantName, replacement) { var r; - if (typeof(replacement) === "boolean") { + if (typeof(replacement) === 'boolean') { if (replacement === false) { r = '#define\\s' + constantName; return sourceStr.replace(new RegExp(r, 'g'), '/*#define ' + constantName + '*/'); - } else { - return sourceStr; } - } else { + return sourceStr; + + } r = '#define\\s' + constantName + '\\s([0-9.]+)'; return sourceStr.replace(new RegExp(r, 'g'), '#define ' + constantName + ' ' + replacement); - } + } function pointOcclusionStage(processor, context) { @@ -274,7 +274,7 @@ define([ zFail : StencilOperation.KEEP, zPass : StencilOperation.KEEP }; - + return context.createViewportQuadCommand(pointOcclusionStr, { uniformMap : uniformMap, framebuffer : processor._framebuffers.screenSpacePass, @@ -341,13 +341,13 @@ define([ rangeParameter : function() { if (processor.useTriangle) { return processor.rangeParameter; - } else { + } if (processor.rangeParameter < rangeMin) { return 0.0; - } else { - return processor.rangeParameter * (rangeMax - rangeMin) + rangeMin; } - } + return processor.rangeParameter * (rangeMax - rangeMin) + rangeMin; + + }, densityHalfWidth : function() { return processor.densityHalfWidth; @@ -383,7 +383,7 @@ define([ zFail : StencilOperation.KEEP, zPass : StencilOperation.KEEP }; - + return context.createViewportQuadCommand(regionGrowingPassStr, { uniformMap : uniformMap, framebuffer : framebuffer, @@ -585,7 +585,7 @@ define([ // The screen space pass should consider // the stencil value, so we don't clear it // here - if (name === "screenSpacePass") { + if (name === 'screenSpacePass') { clearCommands[name] = new ClearCommand({ framebuffer : framebuffers[name], color : new Color(0.0, 0.0, 0.0, 0.0), @@ -648,7 +648,7 @@ define([ var shader = context.shaderCache.getDerivedShaderProgram(shaderProgram, 'EC'); if (!defined(shader)) { var attributeLocations = shaderProgram._attributeLocations; - + var vs = shaderProgram.vertexShaderSource.clone(); var fs = shaderProgram.fragmentShaderSource.clone(); @@ -656,7 +656,7 @@ define([ source = ShaderSource.replaceMain(source, 'czm_point_cloud_post_process_main'); return source; }); - + 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]'); @@ -686,7 +686,7 @@ define([ attributeLocations : attributeLocations }); } - + return shader; } @@ -732,6 +732,12 @@ define([ var i; var commandList = frameState.commandList; var commandEnd = commandList.length; + + var attenuationMultiplier = this.pointAttenuationMultiplier; + var attenuationUniformFunction = function() { + return attenuationMultiplier; + }; + for (i = commandStart; i < commandEnd; ++i) { var command = commandList[i]; if (command.primitiveType !== PrimitiveType.POINTS) { @@ -771,16 +777,13 @@ define([ // TODO: Even if the filter is disabled, // point attenuation settings are not! Fix this behavior. var derivedCommandUniformMap = derivedCommand.uniformMap; - var attenuationMultiplier = this.pointAttenuationMultiplier; - derivedCommandUniformMap['u_pointAttenuationMaxSize'] = function() { - return attenuationMultiplier; - }; + derivedCommandUniformMap['u_pointAttenuationMaxSize'] = attenuationUniformFunction; derivedCommand.uniformMap = derivedCommandUniformMap; - + derivedCommand.pass = Pass.CESIUM_3D_TILE; // Overrides translucent commands command.dirty = false; } - + commandList[i] = derivedCommand; } @@ -793,18 +796,14 @@ define([ for (i = 0; i < length; ++i) { // So before each draw call, we should clean up the dirty // framebuffers that we left behind on the *previous* pass - if (i == 0) { + if (i === 0) { commandList.push(clearCommands['screenSpacePass']); - } else { - if (i == 1) { + } else if (i === 1) { commandList.push(clearCommands['densityEstimationPass']); - } else { - if (i % 2 == 0) - commandList.push(clearCommands['regionGrowingPassA']); + } else if (i % 2 === 0) + {commandList.push(clearCommands['regionGrowingPassA']);} else - commandList.push(clearCommands['regionGrowingPassB']); - } - } + {commandList.push(clearCommands['regionGrowingPassB']);} if (i >= 2) { commandList.push(copyCommands[i % 2]); @@ -815,7 +814,7 @@ define([ // Blend final result back into the main FBO commandList.push(this._blendCommand); - + commandList.push(clearCommands['prior']); }; From 7e012de54b6b7dd3d550366d0e0f4b3287f557fc Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Mon, 17 Jul 2017 16:54:11 -0400 Subject: [PATCH 105/240] Fixes the Cesium3DTileset test by changing the zoom level --- Specs/Scene/Cesium3DTilesetSpec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Specs/Scene/Cesium3DTilesetSpec.js b/Specs/Scene/Cesium3DTilesetSpec.js index 1f21d699218c..68a1f0078367 100644 --- a/Specs/Scene/Cesium3DTilesetSpec.js +++ b/Specs/Scene/Cesium3DTilesetSpec.js @@ -183,7 +183,7 @@ defineSuite([ } function viewPointCloud() { - setZoom(5.0); + setZoom(10.0); } it('throws with undefined url', function() { From 28c322e7d7ef21327859aea85ce92c8e8a79aee0 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Mon, 17 Jul 2017 17:15:48 -0400 Subject: [PATCH 106/240] First PointCloudPostProcessor test --- Specs/Scene/PointCloudPostProcessorSpec.js | 85 ++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 Specs/Scene/PointCloudPostProcessorSpec.js diff --git a/Specs/Scene/PointCloudPostProcessorSpec.js b/Specs/Scene/PointCloudPostProcessorSpec.js new file mode 100644 index 000000000000..527a0994d090 --- /dev/null +++ b/Specs/Scene/PointCloudPostProcessorSpec.js @@ -0,0 +1,85 @@ +defineSuite([ + 'Scene/PointCloudPostProcessor', + 'Core/Cartesian3', + 'Core/Color', + 'Core/ComponentDatatype', + 'Core/defined', + 'Core/HeadingPitchRange', + 'Core/HeadingPitchRoll', + 'Core/Math', + 'Core/Transforms', + 'Scene/Cesium3DTileStyle', + 'Scene/Expression', + 'Scene/PerspectiveFrustum', + 'Scene/PointCloud3DTileContent', + 'Specs/Cesium3DTilesTester', + 'Specs/createScene', + 'ThirdParty/when' + ], function( + PointCloudPostProcessor, + Cartesian3, + Color, + ComponentDatatype, + defined, + HeadingPitchRange, + HeadingPitchRoll, + CesiumMath, + Transforms, + Cesium3DTileStyle, + Expression, + PerspectiveFrustum, + PointCloud3DTileContent, + Cesium3DTilesTester, + createScene, + when) { + 'use strict'; + + var scene; + var centerLongitude = -1.31968; + var centerLatitude = 0.698874; + + var pointCloudRGBUrl = './Data/Cesium3DTiles/PointCloud/PointCloudRGB'; + + function setCamera(longitude, latitude) { + // Point the camera to the center of the tile + var center = Cartesian3.fromRadians(longitude, latitude, 5.0); + scene.camera.lookAt(center, new HeadingPitchRange(0.0, -1.57, 5.0)); + } + + beforeAll(function() { + scene = createScene(); + scene.frameState.passes.render = true; + }); + + afterAll(function() { + scene.destroyForSpecs(); + }); + + beforeEach(function() { + scene.morphTo3D(0.0); + + var camera = scene.camera; + camera.frustum = new PerspectiveFrustum(); + camera.frustum.aspectRatio = scene.drawingBufferWidth / scene.drawingBufferHeight; + camera.frustum.fov = CesiumMath.toRadians(60.0); + + setCamera(centerLongitude, centerLatitude); + }); + + afterEach(function() { + scene.primitives.removeAll(); + }); + + it('enabling the point cloud post processor increases the number of draw calls', function() { + return Cesium3DTilesTester.loadTileset(scene, pointCloudRGBUrl).then(function(tileset) { + scene.renderForSpecs(); + var originalLength = scene.frameState.commandList.length; + + + tileset.pointCloudPostProcessorOptions.enabled = true; + scene.renderForSpecs(); + var newLength = scene.frameState.commandList.length; + expect(newLength).toBeGreaterThan(originalLength); + }); + }); +}, 'WebGL'); From 211d68760846a15883b876cabfe46094f831eff6 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Tue, 18 Jul 2017 10:47:49 -0400 Subject: [PATCH 107/240] Creates functions for point array commands --- Source/Scene/PointCloudPostProcessor.js | 77 +++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 7e3853a6817a..af2fd228b9e9 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -3,8 +3,12 @@ define([ '../Core/Color', '../Core/defined', '../Core/destroyObject', + '../Core/ComponentDatatype', + '../Core/Geometry', + '../Core/GeometryAttribute', '../Core/PixelFormat', '../Core/PrimitiveType', + '../Renderer/BufferUsage', '../Renderer/ClearCommand', '../Renderer/DrawCommand', '../Renderer/Framebuffer', @@ -18,6 +22,7 @@ define([ '../Renderer/TextureMagnificationFilter', '../Renderer/TextureMinificationFilter', '../Renderer/TextureWrap', + '../Renderer/VertexArray', '../Scene/BlendingState', '../Scene/StencilFunction', '../Scene/StencilOperation', @@ -28,10 +33,14 @@ define([ '../Shaders/PostProcessFilters/DensityEstimationPass' ], function( Color, + ComponentDatatype, defined, destroyObject, + Geometry, + GeometryAttribute, PixelFormat, PrimitiveType, + BufferUsage, ClearCommand, DrawCommand, Framebuffer, @@ -45,6 +54,7 @@ define([ TextureMagnificationFilter, TextureMinificationFilter, TextureWrap, + VertexArray, BlendingState, StencilFunction, StencilOperation, @@ -85,6 +95,8 @@ define([ this.pointAttenuationMultiplier = options.pointAttenuationMultiplier; this.useTriangle = options.useTriangle; + this.pointArray = undefined; + this.rangeMin = 1e-6; this.rangeMax = 5e-2; } @@ -225,6 +237,71 @@ define([ processor._dirty = dirty; } + function createPointArray(processor, context) { + var screenWidth = context.drawingBufferWidth; + var screenHeight = context.drawingBufferHeight; + + var pointArray = processor.pointArray; + + var vertexArr = new Float32Array(screenWidth * screenHeight); + + var xIncrement = 2.0 / screenWidth; + var yIncrement = 2.0 / screenHeight; + + var baryOffsetX = xIncrement / 2.0; + var baryOffsetY = yIncrement / 2.0; + + var k = 0; + for (var i = -1.0; i < 1.0; i += xIncrement) { + for (var j = -1.0; j < 1.0; j += yIncrement) { + vertexArr[k++] = i + baryOffsetX; + vertexArr[k++] = j + baryOffsetY; + } + } + + var geometry = new Geometry({ + attributes: { + position : new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 2, + values : vertexArr + }) + }, + primitiveType : PrimitiveType.POINTS + }); + + pointArray = VertexArray.fromGeometry({ + context : this, + geometry : geometry, + attributeLocations : { + position : 0 + }, + bufferUsage : BufferUsage.STATIC_DRAW, + interleave : true + }); + + processor.pointArray = pointArray; + } + + function createPointArrayCommand(vertexShaderSource, fragmentShaderSource, processor, context) { + if (!defined(processor.pointArray)) { + createPointArray(processor, context); + } + + return new DrawCommand({ + vertexArray : this.pointArray, + primitiveType : PrimitiveType.POINTS, + shaderProgram : ShaderProgram.fromCache({ + context : this, + vertexShaderSource : vertexShaderSource, + fragmentShaderSource : fragmentShaderSource, + attributeLocations : { + position : 0 + } + }) + }); + } + function replaceConstants(sourceStr, constantName, replacement) { var r; if (typeof(replacement) === 'boolean') { From b1cc8792cd48f9e60294546a60e9e74fb4486665 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Tue, 18 Jul 2017 12:09:40 -0400 Subject: [PATCH 108/240] Fixes defines --- Source/Scene/PointCloudPostProcessor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index af2fd228b9e9..4348616fc7d9 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -1,9 +1,9 @@ /*global define*/ define([ '../Core/Color', + '../Core/ComponentDatatype', '../Core/defined', '../Core/destroyObject', - '../Core/ComponentDatatype', '../Core/Geometry', '../Core/GeometryAttribute', '../Core/PixelFormat', From 109d1112c4e58ff94a4564f4d79ab6595a0f2e4e Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Tue, 18 Jul 2017 12:11:19 -0400 Subject: [PATCH 109/240] Fixes variable typo --- Source/Scene/PointCloudPostProcessor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 4348616fc7d9..2aea5412aaac 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -271,7 +271,7 @@ define([ }); pointArray = VertexArray.fromGeometry({ - context : this, + context : context, geometry : geometry, attributeLocations : { position : 0 From fea418e98acbf63d66e5a2c277635010ebae27c9 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Tue, 18 Jul 2017 12:12:15 -0400 Subject: [PATCH 110/240] Now constructing the point array upon resize --- Source/Scene/PointCloudPostProcessor.js | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 2aea5412aaac..e125eb21cad4 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -704,6 +704,7 @@ define([ if (!defined(colorTextures)) { createFramebuffers(processor, context); + createPointArray(processor, context); } if (!defined(drawCommands) || !defined(stencilCommands) || dirty) { From 2e8c30bc47f6e41df2b2ff05be4a2e958b426975 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Tue, 18 Jul 2017 14:29:07 -0400 Subject: [PATCH 111/240] Adds support for the EXT_blend_minmax extension --- Source/Renderer/Context.js | 15 +++++++++++++++ Source/Renderer/RenderState.js | 4 +++- Source/Scene/BlendEquation.js | 22 ++++++++++++++++++++-- 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/Source/Renderer/Context.js b/Source/Renderer/Context.js index e8af2d025cf2..0a61c4beb205 100644 --- a/Source/Renderer/Context.js +++ b/Source/Renderer/Context.js @@ -269,6 +269,7 @@ define([ // Query and initialize extensions this._standardDerivatives = !!getExtension(gl, ['OES_standard_derivatives']) || this._webgl2; + this._blendMinmax = !!getExtension(gl, ['EXT_blend_minmax']); this._elementIndexUint = !!getExtension(gl, ['OES_element_index_uint']) || this._webgl2; this._depthTexture = !!getExtension(gl, ['WEBGL_depth_texture', 'WEBKIT_WEBGL_depth_texture']) || this._webgl2; this._textureFloat = !!getExtension(gl, ['OES_texture_float']) || this._webgl2; @@ -491,6 +492,20 @@ define([ } }, + /** + * true if the EXT_blend_minmax extension is supported. This + * extension extends blending capabilities by adding two new blend equations: + * the minimum or maximum color components of the source and destination colors. + * @memberof Context.prototype + * @type {Boolean} + * @see {@link https://www.khronos.org/registry/webgl/extensions/EXT_blend_minmax/} + */ + blendMinmax : { + get : function() { + return this._blendMinmax || this._webgl2; + } + }, + /** * true if the OES_element_index_uint extension is supported. This * extension allows the use of unsigned int indices, which can improve performance by diff --git a/Source/Renderer/RenderState.js b/Source/Renderer/RenderState.js index 3b30bebbd290..07ab7633fe12 100644 --- a/Source/Renderer/RenderState.js +++ b/Source/Renderer/RenderState.js @@ -21,7 +21,9 @@ define([ function validateBlendEquation(blendEquation) { return ((blendEquation === WebGLConstants.FUNC_ADD) || (blendEquation === WebGLConstants.FUNC_SUBTRACT) || - (blendEquation === WebGLConstants.FUNC_REVERSE_SUBTRACT)); + (blendEquation === WebGLConstants.FUNC_REVERSE_SUBTRACT) || + (blendEquation === WebGLConstants.MIN) || + (blendEquation === WebGLConstants.MAX)); } function validateBlendFunction(blendFunction) { diff --git a/Source/Scene/BlendEquation.js b/Source/Scene/BlendEquation.js index 27bf019d21eb..e589beeae418 100644 --- a/Source/Scene/BlendEquation.js +++ b/Source/Scene/BlendEquation.js @@ -34,9 +34,27 @@ define([ * @type {Number} * @constant */ - REVERSE_SUBTRACT : WebGLConstants.FUNC_REVERSE_SUBTRACT + REVERSE_SUBTRACT : WebGLConstants.FUNC_REVERSE_SUBTRACT, - // No min and max like in ColladaFX GLES2 profile + /** + * Pixel values are given to the minimum function (min(source, destination)). + * + * This equation operates on each pixel color component. + * + * @type {Number} + * @constant + */ + MIN : WebGLConstants.MIN, + + /** + * Pixel values are given to the maximum function (max(source, destination)). + * + * This equation operates on each pixel color component. + * + * @type {Number} + * @constant + */ + MAX : WebGLConstants.MAX }; return freezeObject(BlendEquation); From 6cbb3fb0f4ab2185a1d2357e8a3cf90b7bed5e74 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Tue, 18 Jul 2017 14:41:31 -0400 Subject: [PATCH 112/240] Adds example for reference --- Source/Scene/PointCloudPostProcessor.js | 71 +++++++++++++++++++++---- 1 file changed, 60 insertions(+), 11 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index e125eb21cad4..6e62de92ad52 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -23,6 +23,8 @@ define([ '../Renderer/TextureMinificationFilter', '../Renderer/TextureWrap', '../Renderer/VertexArray', + '../Scene/BlendEquation', + '../Scene/BlendFunction', '../Scene/BlendingState', '../Scene/StencilFunction', '../Scene/StencilOperation', @@ -55,6 +57,8 @@ define([ TextureMinificationFilter, TextureWrap, VertexArray, + BlendEquation, + BlendFunction, BlendingState, StencilFunction, StencilOperation, @@ -83,6 +87,8 @@ define([ this._blendCommand = undefined; this._clearCommands = undefined; + this._testPointArrayCommand = undefined; + this.occlusionAngle = options.occlusionAngle; this.rangeParameter = options.rangeParameter; this.neighborhoodHalfWidth = options.neighborhoodHalfWidth; @@ -95,7 +101,7 @@ define([ this.pointAttenuationMultiplier = options.pointAttenuationMultiplier; this.useTriangle = options.useTriangle; - this.pointArray = undefined; + this._pointArray = undefined; this.rangeMin = 1e-6; this.rangeMax = 5e-2; @@ -241,9 +247,7 @@ define([ var screenWidth = context.drawingBufferWidth; var screenHeight = context.drawingBufferHeight; - var pointArray = processor.pointArray; - - var vertexArr = new Float32Array(screenWidth * screenHeight); + var vertexArr = new Float32Array(screenWidth * screenHeight * 2); var xIncrement = 2.0 / screenWidth; var yIncrement = 2.0 / screenHeight; @@ -270,7 +274,7 @@ define([ primitiveType : PrimitiveType.POINTS }); - pointArray = VertexArray.fromGeometry({ + var pointArray = VertexArray.fromGeometry({ context : context, geometry : geometry, attributeLocations : { @@ -280,25 +284,30 @@ define([ interleave : true }); - processor.pointArray = pointArray; + processor._pointArray = pointArray; } - function createPointArrayCommand(vertexShaderSource, fragmentShaderSource, processor, context) { - if (!defined(processor.pointArray)) { + function createPointArrayCommand(vertexShaderSource, fragmentShaderSource, processor, context, overrides) { + if (!defined(processor._pointArray)) { createPointArray(processor, context); } return new DrawCommand({ - vertexArray : this.pointArray, + vertexArray : processor._pointArray, primitiveType : PrimitiveType.POINTS, + renderState : overrides.renderState, shaderProgram : ShaderProgram.fromCache({ - context : this, + context : context, vertexShaderSource : vertexShaderSource, fragmentShaderSource : fragmentShaderSource, attributeLocations : { position : 0 } - }) + }), + uniformMap : overrides.uniformMap, + owner : overrides.owner, + framebuffer : overrides.framebuffer, + pass : overrides.pass }); } @@ -685,11 +694,49 @@ define([ } } + var testVS = 'attribute vec4 position; \n\n' + + 'varying vec2 v_textureCoordinates; \n\n' + + 'void main() \n' + + '{ \n' + + ' gl_Position = position; \n' + + ' v_textureCoordinates = position.xy / 2.0 + vec2(0.5); \n' + + ' gl_PointSize = 10.0; \n' + + '} \n'; + var testFS = 'varying vec2 v_textureCoordinates; \n\n' + + 'void main() \n' + + '{ \n' + + ' gl_FragColor = vec4(vec3(v_textureCoordinates.x), 1.0); \n' + + '} \n' + + ' \n'; + + var testBlendRenderState = RenderState.fromCache({ + blending : { + enabled : true, + equationRgb : BlendEquation.MIN, + equationAlpha : BlendEquation.ADD, + functionSourceRgb : BlendFunction.ONE, + functionSourceAlpha : BlendFunction.ONE, + functionDestinationRgb : BlendFunction.ONE, + functionDestinationAlpha : BlendFunction.ZERO + } + }); + + var testPointArrayCommand = createPointArrayCommand( + testVS, testFS, processor, context, { + uniformMap : { + }, + renderState : testBlendRenderState, + pass : Pass.CESIUM_3D_TILE, + owner : processor + } + ); + processor._drawCommands = drawCommands; processor._stencilCommands = stencilCommands; processor._blendCommand = blendCommand; processor._clearCommands = clearCommands; processor._copyCommands = copyCommands; + processor._testPointArrayCommand = testPointArrayCommand; } function createResources(processor, context, dirty) { @@ -893,6 +940,8 @@ define([ // Blend final result back into the main FBO commandList.push(this._blendCommand); + commandList.push(this._testPointArrayCommand); + commandList.push(clearCommands['prior']); }; From bb9bac28370e856c8b0224b04d75cdf58a77e185 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Tue, 18 Jul 2017 15:10:25 -0400 Subject: [PATCH 113/240] No longer passing v_textureCoordinates around --- Source/Scene/PointCloudPostProcessor.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 6e62de92ad52..640cc2e4ca1f 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -695,17 +695,15 @@ define([ } var testVS = 'attribute vec4 position; \n\n' + - 'varying vec2 v_textureCoordinates; \n\n' + 'void main() \n' + '{ \n' + ' gl_Position = position; \n' + - ' v_textureCoordinates = position.xy / 2.0 + vec2(0.5); \n' + ' gl_PointSize = 10.0; \n' + '} \n'; - var testFS = 'varying vec2 v_textureCoordinates; \n\n' + - 'void main() \n' + + var testFS = 'void main() \n' + '{ \n' + - ' gl_FragColor = vec4(vec3(v_textureCoordinates.x), 1.0); \n' + + ' vec2 textureCoordinates = gl_FragCoord.xy / czm_viewport.zw; \n' + + ' gl_FragColor = vec4(vec3(textureCoordinates.x), 1.0); \n' + '} \n' + ' \n'; From 69d551f78ea9f8d7dbeb1b5323385b6883f39382 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Tue, 18 Jul 2017 16:32:03 -0400 Subject: [PATCH 114/240] No longer using czm_packDepth and czm_unpackDepth for density --- Source/Scene/PointCloudPostProcessor.js | 10 +++++----- .../PostProcessFilters/DensityEstimationPass.glsl | 14 +++++++------- .../PostProcessFilters/RegionGrowingPassGL1.glsl | 7 ++++--- .../PostProcessFilters/RegionGrowingPassGL2.glsl | 6 +++--- 4 files changed, 19 insertions(+), 18 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 640cc2e4ca1f..ec5a9b8fa588 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -512,7 +512,7 @@ define([ var copyStageStr = '#extension GL_EXT_draw_buffers : enable \n' + '#define densityView \n' + - '#define densityScaleFactor 32.0 \n' + + '#define densityScaleFactor 10.0 \n' + '#define EPS 1e-6 \n' + 'uniform int densityHalfWidth; \n' + 'uniform sampler2D pointCloud_colorTexture; \n' + @@ -525,7 +525,7 @@ define([ ' float depth = czm_unpackDepth(rawDepth); \n' + ' if (depth > EPS) { \n' + ' #ifdef densityView \n' + - ' float density = densityScaleFactor * czm_unpackDepth(texture2D(pointCloud_densityTexture, v_textureCoordinates)); \n' + + ' float density = ceil(densityScaleFactor * texture2D(pointCloud_densityTexture, v_textureCoordinates).r); \n' + ' gl_FragData[0] = vec4(vec3(density / float(densityHalfWidth)), 1.0); \n' + ' #else \n' + ' gl_FragData[0] = texture2D(pointCloud_colorTexture, v_textureCoordinates); \n' + @@ -561,12 +561,12 @@ define([ '#define EPS 1e-8 \n' + '#define cutoff 0 \n' + '#define DELAY 0 \n' + - '#define densityScaleFactor 32.0 \n' + + '#define densityScaleFactor 10.0 \n' + 'uniform sampler2D pointCloud_densityTexture; \n' + 'varying vec2 v_textureCoordinates; \n' + 'void main() \n' + '{ \n' + - ' float density = densityScaleFactor * czm_unpackDepth(texture2D(pointCloud_densityTexture, v_textureCoordinates)); \n' + + ' float density = ceil(densityScaleFactor * texture2D(pointCloud_densityTexture, v_textureCoordinates).r); \n' + ' if (float(cutoff - DELAY) + EPS > density) \n' + ' discard; \n' + '} \n'; @@ -938,7 +938,7 @@ define([ // Blend final result back into the main FBO commandList.push(this._blendCommand); - commandList.push(this._testPointArrayCommand); + //commandList.push(this._testPointArrayCommand); commandList.push(clearCommands['prior']); }; diff --git a/Source/Shaders/PostProcessFilters/DensityEstimationPass.glsl b/Source/Shaders/PostProcessFilters/DensityEstimationPass.glsl index 52e36fafb284..1a1586087c24 100644 --- a/Source/Shaders/PostProcessFilters/DensityEstimationPass.glsl +++ b/Source/Shaders/PostProcessFilters/DensityEstimationPass.glsl @@ -4,7 +4,7 @@ #define EPS 1e-8 -#define densityScaleFactor 32.0 +#define densityScaleFactor 10.0 uniform sampler2D pointCloud_depthTexture; uniform float neighborhoodVectorSize; @@ -43,14 +43,14 @@ void main() { float absRatio = length(neighborhoodAccum) / length(absNeighborhoodAccum); if (int(closestNeighbor) <= neighborhoodHalfWidth && - !(absRatio > maxAbsRatio && - length(neighborhoodAccum) > neighborhoodVectorSize)) { - gl_FragData[0] = czm_packDepth(closestNeighbor / - densityScaleFactor); + !(absRatio > maxAbsRatio && + length(neighborhoodAccum) > neighborhoodVectorSize)) { + gl_FragData[0] = vec4(vec3(closestNeighbor / + densityScaleFactor), 1.0); } else { - gl_FragData[0] = czm_packDepth(0.0); + gl_FragData[0] = vec4(vec3(0.0), 1.0); } } else { - gl_FragData[0] = czm_packDepth(1.0 / densityScaleFactor); + gl_FragData[0] = vec4(vec3(1.0 / densityScaleFactor), 1.0); } } diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl index 6c36779a70ba..0fc51c57f348 100644 --- a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl @@ -6,7 +6,7 @@ #define neighborhoodSize 8 #define EPS 1e-8 #define SQRT2 1.414213562 -#define densityScaleFactor 32.0 +#define densityScaleFactor 10.0 #define densityView #define stencilView #define DELAY 1 @@ -154,11 +154,12 @@ void main() { loadIntoArray(depthNeighbors, colorNeighbors); - float density = densityScaleFactor * czm_unpackDepth( - texture2D(pointCloud_densityTexture, v_textureCoordinates)); + float density = ceil(densityScaleFactor * + texture2D(pointCloud_densityTexture, v_textureCoordinates).r); // If our depth value is invalid if (abs(depth) < EPS) { + // If the area that we want to region grow is sufficently sparse if (float(iterationNumber - DELAY) <= density + EPS) { #if neighborhoodFullWidth == 3 fastMedian3(depthNeighbors, colorNeighbors, finalDepth, finalColor); diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl index d4bf48150762..4ad93efdd5be 100644 --- a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl @@ -5,7 +5,7 @@ #define neighborhoodSize 8 #define EPS 1e-8 #define SQRT2 1.414213562 -#define densityScaleFactor 32.0 +#define densityScaleFactor 10.0 #define densityView #define stencilView #define DELAY 1 @@ -157,8 +157,8 @@ void main() { loadIntoArray(depthNeighbors, colorNeighbors); - float density = densityScaleFactor * czm_unpackDepth( - texture(pointCloud_densityTexture, v_textureCoordinates)); + float density = ceil(densityScaleFactor * + texture(pointCloud_densityTexture, v_textureCoordinates).r); // If our depth value is invalid if (abs(depth) < EPS) { From f6f4a80271dc25b337e4a5c26b347488173d33e6 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Tue, 18 Jul 2017 16:54:32 -0400 Subject: [PATCH 115/240] Adds some example code that does a vertex texture fetch --- Source/Scene/PointCloudPostProcessor.js | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index ec5a9b8fa588..fc22f2074482 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -694,11 +694,18 @@ define([ } } - var testVS = 'attribute vec4 position; \n\n' + + var testVS = '#define EPS 1e-8 \n' + + 'attribute vec4 position; \n\n' + + 'uniform sampler2D pointCloud_depthTexture; \n' + 'void main() \n' + '{ \n' + - ' gl_Position = position; \n' + - ' gl_PointSize = 10.0; \n' + + ' vec2 textureCoordinates = 0.5 * position.xy + vec2(0.5); \n' + + ' if (czm_unpackDepth(texture2D(pointCloud_depthTexture, textureCoordinates)) > EPS) { \n' + + ' gl_Position = position; \n' + + ' gl_PointSize = 10.0; \n' + + ' } else {\n' + + ' gl_Position = vec4(-10); \n' + + ' } \n' + '} \n'; var testFS = 'void main() \n' + '{ \n' + @@ -722,6 +729,9 @@ define([ var testPointArrayCommand = createPointArrayCommand( testVS, testFS, processor, context, { uniformMap : { + pointCloud_depthTexture: function() { + return processor._depthTextures[1 - drawCommands.length % 2]; + } }, renderState : testBlendRenderState, pass : Pass.CESIUM_3D_TILE, @@ -938,7 +948,7 @@ define([ // Blend final result back into the main FBO commandList.push(this._blendCommand); - //commandList.push(this._testPointArrayCommand); + commandList.push(this._testPointArrayCommand); commandList.push(clearCommands['prior']); }; From e5a91c56d02edbd3995f317dfb732978a7b15118 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 19 Jul 2017 09:47:03 -0400 Subject: [PATCH 116/240] Now replacing constants in example --- Source/Scene/PointCloudPostProcessor.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index fc22f2074482..5b55947dd46c 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -694,15 +694,16 @@ define([ } } - var testVS = '#define EPS 1e-8 \n' + + var testVS = '#define EPS 1e-6 \n' + + '#define kernelSize 9.0 \n\n' + 'attribute vec4 position; \n\n' + 'uniform sampler2D pointCloud_depthTexture; \n' + 'void main() \n' + '{ \n' + ' vec2 textureCoordinates = 0.5 * position.xy + vec2(0.5); \n' + - ' if (czm_unpackDepth(texture2D(pointCloud_depthTexture, textureCoordinates)) > EPS) { \n' + + ' if (length(texture2D(pointCloud_depthTexture, textureCoordinates)) > EPS) { \n' + ' gl_Position = position; \n' + - ' gl_PointSize = 10.0; \n' + + ' gl_PointSize = kernelSize; \n' + ' } else {\n' + ' gl_Position = vec4(-10); \n' + ' } \n' + @@ -714,6 +715,12 @@ define([ '} \n' + ' \n'; + testVS = replaceConstants( + testVS, + 'kernelSize', + '10.0' + ); + var testBlendRenderState = RenderState.fromCache({ blending : { enabled : true, From 442011e9259bd7fb0e38d2f3c4616bbb482edce4 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 19 Jul 2017 10:56:24 -0400 Subject: [PATCH 117/240] createPointArrayCommand is a lot easier to use now --- Source/Scene/PointCloudPostProcessor.js | 114 +++++++++++++++--------- 1 file changed, 73 insertions(+), 41 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 5b55947dd46c..42418f3aac74 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -287,15 +287,69 @@ define([ processor._pointArray = pointArray; } - function createPointArrayCommand(vertexShaderSource, fragmentShaderSource, processor, context, overrides) { + function createPointArrayCommand(depthTexture, + kernelSize, + useStencil, + blendingState, + fragmentShaderSource, + processor, + context, + overrides) { if (!defined(processor._pointArray)) { createPointArray(processor, context); } + var vertexShaderSource = + '#define EPS 1e-6 \n' + + '#define kernelSize 9.0 \n\n' + + 'attribute vec4 position; \n\n' + + 'uniform sampler2D pointCloud_depthTexture; \n' + + 'void main() \n' + + '{ \n' + + ' vec2 textureCoordinates = 0.5 * position.xy + vec2(0.5); \n' + + ' if (length(texture2D(pointCloud_depthTexture, textureCoordinates)) > EPS) { \n' + + ' gl_Position = position; \n' + + ' gl_PointSize = kernelSize; \n' + + ' } else {\n' + + ' gl_Position = vec4(-10); \n' + + ' } \n' + + '} \n'; + + var uniformMap = (defined(overrides.uniformMap)) ? overrides.uniformMap : {}; + uniformMap.pointCloud_depthTexture = function () { + return depthTexture; + }; + + vertexShaderSource = replaceConstants(vertexShaderSource, 'kernelSize', kernelSize.toString()); + + var renderState = overrides.renderState; + + if (!defined(overrides.renderState)) { + var func = StencilFunction.EQUAL; + var op = { + fail : StencilOperation.KEEP, + zFail : StencilOperation.KEEP, + zPass : StencilOperation.KEEP + }; + var stencilTest = { + enabled : true, + reference : 0, + mask : 1, + frontFunction : func, + backFunction : func, + frontOperation : op, + backOperation : op + }; + renderState = RenderState.fromCache({ + stencilTest : stencilTest, + blending : blendingState + }); + } + return new DrawCommand({ vertexArray : processor._pointArray, primitiveType : PrimitiveType.POINTS, - renderState : overrides.renderState, + renderState : renderState, shaderProgram : ShaderProgram.fromCache({ context : context, vertexShaderSource : vertexShaderSource, @@ -304,7 +358,7 @@ define([ position : 0 } }), - uniformMap : overrides.uniformMap, + uniformMap : uniformMap, owner : overrides.owner, framebuffer : overrides.framebuffer, pass : overrides.pass @@ -694,20 +748,6 @@ define([ } } - var testVS = '#define EPS 1e-6 \n' + - '#define kernelSize 9.0 \n\n' + - 'attribute vec4 position; \n\n' + - 'uniform sampler2D pointCloud_depthTexture; \n' + - 'void main() \n' + - '{ \n' + - ' vec2 textureCoordinates = 0.5 * position.xy + vec2(0.5); \n' + - ' if (length(texture2D(pointCloud_depthTexture, textureCoordinates)) > EPS) { \n' + - ' gl_Position = position; \n' + - ' gl_PointSize = kernelSize; \n' + - ' } else {\n' + - ' gl_Position = vec4(-10); \n' + - ' } \n' + - '} \n'; var testFS = 'void main() \n' + '{ \n' + ' vec2 textureCoordinates = gl_FragCoord.xy / czm_viewport.zw; \n' + @@ -715,32 +755,24 @@ define([ '} \n' + ' \n'; - testVS = replaceConstants( - testVS, - 'kernelSize', - '10.0' - ); - - var testBlendRenderState = RenderState.fromCache({ - blending : { - enabled : true, - equationRgb : BlendEquation.MIN, - equationAlpha : BlendEquation.ADD, - functionSourceRgb : BlendFunction.ONE, - functionSourceAlpha : BlendFunction.ONE, - functionDestinationRgb : BlendFunction.ONE, - functionDestinationAlpha : BlendFunction.ZERO - } - }); + var testBlendRenderState = { + enabled : true, + equationRgb : BlendEquation.MIN, + equationAlpha : BlendEquation.ADD, + functionSourceRgb : BlendFunction.ONE, + functionSourceAlpha : BlendFunction.ONE, + functionDestinationRgb : BlendFunction.ONE, + functionDestinationAlpha : BlendFunction.ZERO + }; var testPointArrayCommand = createPointArrayCommand( - testVS, testFS, processor, context, { - uniformMap : { - pointCloud_depthTexture: function() { - return processor._depthTextures[1 - drawCommands.length % 2]; - } - }, - renderState : testBlendRenderState, + processor._depthTextures[1 - drawCommands.length % 2], + '9.0', + false, + testBlendRenderState, + testFS, + processor, + context, { pass : Pass.CESIUM_3D_TILE, owner : processor } From efa898e8be3afae8892361fe499b11aa8cfecea0 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 19 Jul 2017 10:59:47 -0400 Subject: [PATCH 118/240] useStencil is actually used now --- Source/Scene/PointCloudPostProcessor.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 42418f3aac74..bfccf8293549 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -340,10 +340,16 @@ define([ frontOperation : op, backOperation : op }; - renderState = RenderState.fromCache({ - stencilTest : stencilTest, - blending : blendingState - }); + if (useStencil) { + renderState = RenderState.fromCache({ + stencilTest : stencilTest, + blending : blendingState + }); + } else { + renderState = RenderState.fromCache({ + blending : blendingState + }); + } } return new DrawCommand({ From 1039d2cd767317b3a7072f91625604083130a024 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 19 Jul 2017 11:10:13 -0400 Subject: [PATCH 119/240] Adds random uniform to the example --- Source/Scene/PointCloudPostProcessor.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index bfccf8293549..8fbf05cafd3d 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -754,10 +754,11 @@ define([ } } - var testFS = 'void main() \n' + + var testFS = 'uniform float testUniform; \n' + + 'void main() \n' + '{ \n' + ' vec2 textureCoordinates = gl_FragCoord.xy / czm_viewport.zw; \n' + - ' gl_FragColor = vec4(vec3(textureCoordinates.x), 1.0); \n' + + ' gl_FragColor = vec4(vec3(textureCoordinates.x), 1.0) + vec4(testUniform, 0.0, 0.0, 0.0); \n' + '} \n' + ' \n'; @@ -779,6 +780,9 @@ define([ testFS, processor, context, { + uniformMap : { + testUniform : function () { return 0.5; } + }, pass : Pass.CESIUM_3D_TILE, owner : processor } From 6c642c39028215cee60f6796c4c7897a6a14567b Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 19 Jul 2017 12:22:34 -0400 Subject: [PATCH 120/240] Density estimation now uses the neighbor distribution method; edge culling removed temporarily --- Source/Scene/PointCloudPostProcessor.js | 58 ++++++++++++++----- .../DensityEstimationPass.glsl | 49 ++++------------ 2 files changed, 55 insertions(+), 52 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 8fbf05cafd3d..eca7fad0d9ac 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -302,16 +302,20 @@ define([ var vertexShaderSource = '#define EPS 1e-6 \n' + '#define kernelSize 9.0 \n\n' + - 'attribute vec4 position; \n\n' + - 'uniform sampler2D pointCloud_depthTexture; \n' + + 'attribute vec4 position; \n' + + 'varying float centerPos; \n\n' + + 'uniform sampler2D pointCloud_depthTexture; \n\n' + 'void main() \n' + '{ \n' + ' vec2 textureCoordinates = 0.5 * position.xy + vec2(0.5); \n' + + ' ivec2 screenSpaceCoordinates = ivec2(textureCoordinates * czm_viewport.zw); \n' + ' if (length(texture2D(pointCloud_depthTexture, textureCoordinates)) > EPS) { \n' + ' gl_Position = position; \n' + ' gl_PointSize = kernelSize; \n' + + ' centerPos = float(screenSpaceCoordinates.x + screenSpaceCoordinates.y * int(czm_viewport.z)); \n' + ' } else {\n' + ' gl_Position = vec4(-10); \n' + + ' centerPos = 0.0; \n' + ' } \n' + '} \n'; @@ -442,9 +446,6 @@ define([ function densityEstimationStage(processor, context) { var uniformMap = { - pointCloud_depthTexture : function() { - return processor._depthTextures[0]; - }, neighborhoodVectorSize : function() { return processor.neighborhoodVectorSize; }, @@ -459,14 +460,30 @@ define([ processor.densityHalfWidth ); - return context.createViewportQuadCommand(densityEstimationStr, { - uniformMap : uniformMap, - framebuffer : processor._framebuffers.densityEstimationPass, - renderState : RenderState.fromCache({ - }), - pass : Pass.CESIUM_3D_TILE, - owner : processor - }); + var densityBlendRenderState = { + enabled : true, + equationRgb : BlendEquation.MIN, + equationAlpha : BlendEquation.ADD, + functionSourceRgb : BlendFunction.ONE, + functionSourceAlpha : BlendFunction.ONE, + functionDestinationRgb : BlendFunction.ONE, + functionDestinationAlpha : BlendFunction.ZERO + }; + + return createPointArrayCommand( + processor._depthTextures[0], + '9.0', + false, + densityBlendRenderState, + densityEstimationStr, + processor, + context, { + uniformMap : uniformMap, + framebuffer : processor._framebuffers.densityEstimationPass, + pass : Pass.CESIUM_3D_TILE, + owner : processor + } + ); } function regionGrowingStage(processor, context, iteration) { @@ -730,7 +747,9 @@ define([ if (framebuffers.hasOwnProperty(name)) { // The screen space pass should consider // the stencil value, so we don't clear it - // here + // here. The density estimation pass uses + // min blending, so we need to set the default + // value to the maximum possible value if (name === 'screenSpacePass') { clearCommands[name] = new ClearCommand({ framebuffer : framebuffers[name], @@ -740,6 +759,15 @@ define([ pass : Pass.CESIUM_3D_TILE, owner : processor }); + } else if (name === 'densityEstimationPass') { + clearCommands[name] = new ClearCommand({ + framebuffer : framebuffers[name], + color : new Color(1.0, 1.0, 1.0, 1.0), + depth : 1.0, + renderState : RenderState.fromCache(), + pass : Pass.CESIUM_3D_TILE, + owner : processor + }); } else { clearCommands[name] = new ClearCommand({ framebuffer : framebuffers[name], @@ -997,7 +1025,7 @@ define([ // Blend final result back into the main FBO commandList.push(this._blendCommand); - commandList.push(this._testPointArrayCommand); + //commandList.push(this._testPointArrayCommand); commandList.push(clearCommands['prior']); }; diff --git a/Source/Shaders/PostProcessFilters/DensityEstimationPass.glsl b/Source/Shaders/PostProcessFilters/DensityEstimationPass.glsl index 1a1586087c24..90657d72ad06 100644 --- a/Source/Shaders/PostProcessFilters/DensityEstimationPass.glsl +++ b/Source/Shaders/PostProcessFilters/DensityEstimationPass.glsl @@ -1,56 +1,31 @@ #extension GL_EXT_draw_buffers : enable -#define neighborhoodHalfWidth 4 // TUNABLE PARAMETER -- half-width of region-growing kernel - #define EPS 1e-8 #define densityScaleFactor 10.0 +varying float centerPos; + uniform sampler2D pointCloud_depthTexture; uniform float neighborhoodVectorSize; uniform float maxAbsRatio; -varying vec2 v_textureCoordinates; void main() { + vec2 v_textureCoordinates = gl_FragCoord.xy / czm_viewport.zw; float center = czm_unpackDepth(texture2D(pointCloud_depthTexture, v_textureCoordinates)); ivec2 pos = ivec2(int(gl_FragCoord.x), int(gl_FragCoord.y)); - - float closestNeighbor = float(neighborhoodHalfWidth) + 1.0; - vec2 neighborhoodAccum = vec2(0.0); - vec2 absNeighborhoodAccum = vec2(0.0); + int densityValue = 0; if (center < EPS) { - for (int i = -neighborhoodHalfWidth; i <= neighborhoodHalfWidth; i++) { - for (int j = -neighborhoodHalfWidth; j <= neighborhoodHalfWidth; j++) { - ivec2 d = ivec2(i, j); - ivec2 pI = pos + d; - - float neighbor = czm_unpackDepth(texture2D(pointCloud_depthTexture, - vec2(pI) / czm_viewport.zw)); - if (neighbor < EPS || pI == pos) { - continue; - } - - neighborhoodAccum += vec2(d); - absNeighborhoodAccum += abs(vec2(d)); - closestNeighbor = min(closestNeighbor, - max(abs(float(i)), - abs(float(j)))); - } - } - - float absRatio = length(neighborhoodAccum) / - length(absNeighborhoodAccum); - if (int(closestNeighbor) <= neighborhoodHalfWidth && - !(absRatio > maxAbsRatio && - length(neighborhoodAccum) > neighborhoodVectorSize)) { - gl_FragData[0] = vec4(vec3(closestNeighbor / - densityScaleFactor), 1.0); - } else { - gl_FragData[0] = vec4(vec3(0.0), 1.0); - } + ivec2 centerValue = ivec2(int(mod(centerPos, czm_viewport.z)), + int(centerPos) / int(czm_viewport.z)); + vec2 diff = vec2(pos - centerValue); + densityValue = int(max(abs(diff.x), abs(diff.y))); } else { - gl_FragData[0] = vec4(vec3(1.0 / densityScaleFactor), 1.0); + densityValue = 1; } + + gl_FragData[0] = + vec4(vec3(float(densityValue) / densityScaleFactor), 1.0); } From f5783a1c37ea6781b401fd08420540a7f809df0e Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 19 Jul 2017 12:24:55 -0400 Subject: [PATCH 121/240] Removes cruft --- Source/Scene/PointCloudPostProcessor.js | 61 +++++-------------------- 1 file changed, 11 insertions(+), 50 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index eca7fad0d9ac..55d65dc8876a 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -87,8 +87,6 @@ define([ this._blendCommand = undefined; this._clearCommands = undefined; - this._testPointArrayCommand = undefined; - this.occlusionAngle = options.occlusionAngle; this.rangeParameter = options.rangeParameter; this.neighborhoodHalfWidth = options.neighborhoodHalfWidth; @@ -103,6 +101,16 @@ define([ this._pointArray = undefined; + this._minBlend = { + enabled : true, + equationRgb : BlendEquation.MIN, + equationAlpha : BlendEquation.ADD, + functionSourceRgb : BlendFunction.ONE, + functionSourceAlpha : BlendFunction.ONE, + functionDestinationRgb : BlendFunction.ONE, + functionDestinationAlpha : BlendFunction.ZERO + }; + this.rangeMin = 1e-6; this.rangeMax = 5e-2; } @@ -460,21 +468,11 @@ define([ processor.densityHalfWidth ); - var densityBlendRenderState = { - enabled : true, - equationRgb : BlendEquation.MIN, - equationAlpha : BlendEquation.ADD, - functionSourceRgb : BlendFunction.ONE, - functionSourceAlpha : BlendFunction.ONE, - functionDestinationRgb : BlendFunction.ONE, - functionDestinationAlpha : BlendFunction.ZERO - }; - return createPointArrayCommand( processor._depthTextures[0], '9.0', false, - densityBlendRenderState, + processor._minBlend, densityEstimationStr, processor, context, { @@ -782,46 +780,11 @@ define([ } } - var testFS = 'uniform float testUniform; \n' + - 'void main() \n' + - '{ \n' + - ' vec2 textureCoordinates = gl_FragCoord.xy / czm_viewport.zw; \n' + - ' gl_FragColor = vec4(vec3(textureCoordinates.x), 1.0) + vec4(testUniform, 0.0, 0.0, 0.0); \n' + - '} \n' + - ' \n'; - - var testBlendRenderState = { - enabled : true, - equationRgb : BlendEquation.MIN, - equationAlpha : BlendEquation.ADD, - functionSourceRgb : BlendFunction.ONE, - functionSourceAlpha : BlendFunction.ONE, - functionDestinationRgb : BlendFunction.ONE, - functionDestinationAlpha : BlendFunction.ZERO - }; - - var testPointArrayCommand = createPointArrayCommand( - processor._depthTextures[1 - drawCommands.length % 2], - '9.0', - false, - testBlendRenderState, - testFS, - processor, - context, { - uniformMap : { - testUniform : function () { return 0.5; } - }, - pass : Pass.CESIUM_3D_TILE, - owner : processor - } - ); - processor._drawCommands = drawCommands; processor._stencilCommands = stencilCommands; processor._blendCommand = blendCommand; processor._clearCommands = clearCommands; processor._copyCommands = copyCommands; - processor._testPointArrayCommand = testPointArrayCommand; } function createResources(processor, context, dirty) { @@ -1025,8 +988,6 @@ define([ // Blend final result back into the main FBO commandList.push(this._blendCommand); - //commandList.push(this._testPointArrayCommand); - commandList.push(clearCommands['prior']); }; From 25f838c615219d32ea49d25c5d5a4b89d0082487 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 19 Jul 2017 13:20:10 -0400 Subject: [PATCH 122/240] Refactor of how commands are stored --- Source/Scene/PointCloudPostProcessor.js | 59 +++++++++++++------------ 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 55d65dc8876a..c2cd1bccc0cc 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -81,7 +81,9 @@ define([ this._densityTexture = undefined; this._dirty = undefined; this._clearStencil = undefined; - this._drawCommands = undefined; + this._pointOcclusionCommand = undefined; + this._densityEstimationCommand = undefined; + this._regionGrowingCommands = undefined; this._stencilCommands = undefined; this._copyCommands = undefined; this._blendCommand = undefined; @@ -681,16 +683,16 @@ define([ function createCommands(processor, context) { var numRegionGrowingPasses = processor.numRegionGrowingPasses; - var drawCommands = new Array(numRegionGrowingPasses + 2); + var regionGrowingCommands = new Array(numRegionGrowingPasses); var stencilCommands = new Array(numRegionGrowingPasses); var copyCommands = new Array(2); var i; - drawCommands[0] = pointOcclusionStage(processor, context); - drawCommands[1] = densityEstimationStage(processor, context); + processor._pointOcclusionCommand = pointOcclusionStage(processor, context); + processor._densityEstimationCommand = densityEstimationStage(processor, context); for (i = 0; i < numRegionGrowingPasses; i++) { - drawCommands[i + 2] = regionGrowingStage(processor, context, i); + regionGrowingCommands[i] = regionGrowingStage(processor, context, i); stencilCommands[i] = stencilMaskStage(processor, context, i); } @@ -725,10 +727,10 @@ define([ var blendUniformMap = { pointCloud_colorTexture: function() { - return processor._colorTextures[1 - drawCommands.length % 2]; + return processor._colorTextures[1 - numRegionGrowingPasses % 2]; }, pointCloud_depthTexture: function() { - return processor._depthTextures[1 - drawCommands.length % 2]; + return processor._depthTextures[1 - numRegionGrowingPasses % 2]; } }; @@ -780,7 +782,7 @@ define([ } } - processor._drawCommands = drawCommands; + processor._regionGrowingCommands = regionGrowingCommands; processor._stencilCommands = stencilCommands; processor._blendCommand = blendCommand; processor._clearCommands = clearCommands; @@ -791,7 +793,7 @@ define([ var screenWidth = context.drawingBufferWidth; var screenHeight = context.drawingBufferHeight; var colorTextures = processor._colorTextures; - var drawCommands = processor._drawCommands; + var regionGrowingCommands = processor._regionGrowingCommands; var stencilCommands = processor._stencilCommands; var resized = defined(colorTextures) && ((colorTextures[0].width !== screenWidth) || @@ -802,7 +804,7 @@ define([ createPointArray(processor, context); } - if (!defined(drawCommands) || !defined(stencilCommands) || dirty) { + if (!defined(regionGrowingCommands) || !defined(stencilCommands) || dirty) { createCommands(processor, context); } @@ -961,28 +963,29 @@ define([ } // Apply processing commands - var drawCommands = this._drawCommands; + var pointOcclusionCommand = this._pointOcclusionCommand; + var densityEstimationCommand = this._densityEstimationCommand; + var regionGrowingCommands = this._regionGrowingCommands; var copyCommands = this._copyCommands; var stencilCommands = this._stencilCommands; var clearCommands = this._clearCommands; - var length = drawCommands.length; - for (i = 0; i < length; ++i) { - // So before each draw call, we should clean up the dirty - // framebuffers that we left behind on the *previous* pass - if (i === 0) { - commandList.push(clearCommands['screenSpacePass']); - } else if (i === 1) { - commandList.push(clearCommands['densityEstimationPass']); - } else if (i % 2 === 0) - {commandList.push(clearCommands['regionGrowingPassA']);} - else - {commandList.push(clearCommands['regionGrowingPassB']);} - - if (i >= 2) { - commandList.push(copyCommands[i % 2]); - commandList.push(stencilCommands[i - 2]); + var numRegionGrowingCommands = regionGrowingCommands.length; + + commandList.push(clearCommands['screenSpacePass']); + commandList.push(pointOcclusionCommand); + commandList.push(clearCommands['densityEstimationPass']); + commandList.push(densityEstimationCommand); + + for (i = 0; i < numRegionGrowingCommands; i++) { + if (i % 2 === 0) { + commandList.push(clearCommands['regionGrowingPassA']); + } else { + commandList.push(clearCommands['regionGrowingPassB']); } - commandList.push(drawCommands[i]); + + commandList.push(copyCommands[i % 2]); + commandList.push(stencilCommands[i]); + commandList.push(regionGrowingCommands[i]); } // Blend final result back into the main FBO From d7f34c7c5b6f77cdee93a92005e6eef2f859cd4a Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 19 Jul 2017 13:40:46 -0400 Subject: [PATCH 123/240] Fixes bug where WebGL 1 hardware wouldn't perform an early fragment test for the point occlusion operator --- .../Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl index 507c03b64621..59fc0d094915 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl @@ -263,8 +263,10 @@ void main() { // If the EC of this pixel is zero, that means that it's not a valid // pixel. We don't care about reprojecting it. - if (length(centerPosition) == 0.) - discard; + if (length(centerPosition) == 0.) { + gl_FragData[0] = vec4(0.0); + return; + } // We split our region of interest (the point of interest and its // neighbors) From bd01fe5a7af316a2d584115bfabb40d849ef5d3d Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 19 Jul 2017 13:45:04 -0400 Subject: [PATCH 124/240] Renames misleading variable --- .../Shaders/PostProcessFilters/DensityEstimationPass.glsl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Shaders/PostProcessFilters/DensityEstimationPass.glsl b/Source/Shaders/PostProcessFilters/DensityEstimationPass.glsl index 90657d72ad06..e68d25295858 100644 --- a/Source/Shaders/PostProcessFilters/DensityEstimationPass.glsl +++ b/Source/Shaders/PostProcessFilters/DensityEstimationPass.glsl @@ -12,12 +12,12 @@ uniform float maxAbsRatio; void main() { vec2 v_textureCoordinates = gl_FragCoord.xy / czm_viewport.zw; - float center = czm_unpackDepth(texture2D(pointCloud_depthTexture, - v_textureCoordinates)); + float depth = czm_unpackDepth(texture2D(pointCloud_depthTexture, + v_textureCoordinates)); ivec2 pos = ivec2(int(gl_FragCoord.x), int(gl_FragCoord.y)); int densityValue = 0; - if (center < EPS) { + if (depth < EPS) { ivec2 centerValue = ivec2(int(mod(centerPos, czm_viewport.z)), int(centerPos) / int(czm_viewport.z)); vec2 diff = vec2(pos - centerValue); From d5768ed331ad87c9d8b748bbe8d16a41c6e4ecf1 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 19 Jul 2017 17:24:05 -0400 Subject: [PATCH 125/240] Somewhat functional point occlusion operator --- Source/Scene/PointCloudPostProcessor.js | 160 ++++++++++++- .../PointOcclusionPassGL1.glsl | 23 +- .../PointOcclusionPassGL2.glsl | 3 +- .../SectorGatheringPass.glsl | 215 ++++++++++++++++++ .../SectorHistogramPass.glsl | 173 ++++++++++++++ 5 files changed, 551 insertions(+), 23 deletions(-) create mode 100644 Source/Shaders/PostProcessFilters/SectorGatheringPass.glsl create mode 100644 Source/Shaders/PostProcessFilters/SectorHistogramPass.glsl diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index c2cd1bccc0cc..3dee66ff5998 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -32,6 +32,8 @@ define([ '../Shaders/PostProcessFilters/RegionGrowingPassGL1', '../Shaders/PostProcessFilters/PointOcclusionPassGL2', '../Shaders/PostProcessFilters/RegionGrowingPassGL2', + '../Shaders/PostProcessFilters/SectorHistogramPass', + '../Shaders/PostProcessFilters/SectorGatheringPass', '../Shaders/PostProcessFilters/DensityEstimationPass' ], function( Color, @@ -66,6 +68,8 @@ define([ RegionGrowingPassGL1, PointOcclusionPassGL2, RegionGrowingPassGL2, + SectorHistogramPass, + SectorGatheringPass, DensityEstimationPass ) { 'use strict'; @@ -78,13 +82,17 @@ define([ this._colorTextures = undefined; this._ecTexture = undefined; this._depthTextures = undefined; + this._sectorTextures = undefined; this._densityTexture = undefined; this._dirty = undefined; this._clearStencil = undefined; this._pointOcclusionCommand = undefined; this._densityEstimationCommand = undefined; + this._sectorHistogramCommand = undefined; + this._sectorGatheringCommand = undefined; this._regionGrowingCommands = undefined; this._stencilCommands = undefined; + this._debugCommand = undefined; this._copyCommands = undefined; this._blendCommand = undefined; this._clearCommands = undefined; @@ -112,6 +120,14 @@ define([ functionDestinationRgb : BlendFunction.ONE, functionDestinationAlpha : BlendFunction.ZERO }; + this._addBlend = { + equationRgb : BlendEquation.ADD, + equationAlpha : BlendEquation.ADD, + functionSourceRgb : BlendFunction.ONE, + functionSourceAlpha : BlendFunction.ONE, + functionDestinationRgb : BlendFunction.ONE, + functionDestinationAlpha : BlendFunction.ZERO + }; this.rangeMin = 1e-6; this.rangeMax = 5e-2; @@ -129,6 +145,8 @@ define([ function destroyFramebuffers(processor) { processor._depthTextures[0].destroy(); processor._depthTextures[1].destroy(); + processor._sectorTextures[0].destroy(); + processor._sectorTextures[1].destroy(); processor._densityTexture.destroy(); processor._dirty.destroy(); processor._colorTextures[0].destroy(); @@ -152,6 +170,7 @@ define([ var screenHeight = context.drawingBufferHeight; var colorTextures = new Array(2); + var sectorTextures = new Array(2); var depthTextures = new Array(3); var ecTexture = new Texture({ @@ -191,6 +210,15 @@ define([ sampler : createSampler() }); + sectorTextures[i] = new Texture({ + context : context, + width : screenWidth, + height : screenHeight, + pixelFormat : PixelFormat.RGBA, + pixelDatatype : PixelDatatype.FLOAT, + sampler : createSampler() + }); + depthTextures[i] = new Texture({ context : context, width : screenWidth, @@ -221,6 +249,12 @@ define([ depthStencilTexture: dirty, destroyAttachments : false }), + sectorHistogramPass : new Framebuffer({ + context : context, + colorTextures : [sectorTextures[0], sectorTextures[1]], + depthStencilTexture: dirty, + destroyAttachments : false + }), stencilMask : new Framebuffer({ context : context, depthStencilTexture: dirty, @@ -247,6 +281,7 @@ define([ }) }; processor._depthTextures = depthTextures; + processor._sectorTextures = sectorTextures; processor._densityTexture = densityMap; processor._colorTextures = colorTextures; processor._ecTexture = ecTexture; @@ -393,18 +428,13 @@ define([ return sourceStr.replace(new RegExp(r, 'g'), '/*#define ' + constantName + '*/'); } return sourceStr; - } - r = '#define\\s' + constantName + '\\s([0-9.]+)'; - return sourceStr.replace(new RegExp(r, 'g'), '#define ' + constantName + ' ' + replacement); - + r = '#define\\s' + constantName + '\\s([0-9.]+)'; + return sourceStr.replace(new RegExp(r, 'g'), '#define ' + constantName + ' ' + replacement); } function pointOcclusionStage(processor, context) { var uniformMap = { - pointCloud_colorTexture : function() { - return processor._colorTextures[0]; - }, pointCloud_ECTexture : function() { return processor._ecTexture; }, @@ -454,6 +484,77 @@ define([ }); } + function sectorHistogramStage(processor, context) { + var uniformMap = { + }; + + return createPointArrayCommand( + processor._ecTexture, + '9.0', + true, + processor._minBlend, + SectorHistogramPass, + processor, + context, { + uniformMap : uniformMap, + framebuffer : processor._framebuffers.sectorHistogramPass, + pass : Pass.CESIUM_3D_TILE, + owner : processor + } + ); + } + + function sectorGatheringStage(processor, context) { + var uniformMap = { + pointCloud_ECTexture : function() { + return processor._ecTexture; + }, + sectorFirst : function() { + return processor._sectorTextures[0]; + }, + sectorSecond : function() { + return processor._sectorTextures[1]; + }, + occlusionAngle : function() { + return processor.occlusionAngle; + }, + ONE : function() { + return 1.0; + } + }; + + var sectorGatheringStr = replaceConstants( + SectorGatheringPass, + 'useTriangle', + processor.useTriangle + ); + + var func = StencilFunction.EQUAL; + var op = { + fail : StencilOperation.KEEP, + zFail : StencilOperation.KEEP, + zPass : StencilOperation.KEEP + }; + + return context.createViewportQuadCommand(sectorGatheringStr, { + uniformMap : uniformMap, + framebuffer : processor._framebuffers.screenSpacePass, + renderState : RenderState.fromCache({ + stencilTest : { + enabled : true, + reference : 0, + mask : 1, + frontFunction : func, + backFunction : func, + frontOperation : op, + backOperation : op + } + }), + pass : Pass.CESIUM_3D_TILE, + owner : processor + }); + } + function densityEstimationStage(processor, context) { var uniformMap = { neighborhoodVectorSize : function() { @@ -681,6 +782,35 @@ define([ }); } + function debugStage(processor, context) { + var uniformMap = { + debugTexture : function() { + return processor._sectorTextures[0]; + }, + debugTexture1 : function() { + return processor._sectorTextures[1]; + } + }; + + var debugStageStr = + 'uniform sampler2D debugTexture; \n' + + 'uniform sampler2D debugTexture1; \n' + + 'varying vec2 v_textureCoordinates; \n' + + 'void main() \n' + + '{ \n' + + ' vec4 sh0 = texture2D(debugTexture, v_textureCoordinates); \n' + + ' gl_FragColor = sh0; \n' + + '} \n'; + + return context.createViewportQuadCommand(debugStageStr, { + uniformMap : uniformMap, + renderState : RenderState.fromCache({ + }), + pass : Pass.CESIUM_3D_TILE, + owner : processor + }); + } + function createCommands(processor, context) { var numRegionGrowingPasses = processor.numRegionGrowingPasses; var regionGrowingCommands = new Array(numRegionGrowingPasses); @@ -690,6 +820,8 @@ define([ var i; processor._pointOcclusionCommand = pointOcclusionStage(processor, context); processor._densityEstimationCommand = densityEstimationStage(processor, context); + processor._sectorHistogramCommand = sectorHistogramStage(processor, context); + processor._sectorGatheringCommand = sectorGatheringStage(processor, context); for (i = 0; i < numRegionGrowingPasses; i++) { regionGrowingCommands[i] = regionGrowingStage(processor, context, i); @@ -741,6 +873,8 @@ define([ owner : processor }); + var debugCommand = debugStage(processor, context, processor._sectorTextures[0]); + var framebuffers = processor._framebuffers; var clearCommands = {}; for (var name in framebuffers) { @@ -759,7 +893,8 @@ define([ pass : Pass.CESIUM_3D_TILE, owner : processor }); - } else if (name === 'densityEstimationPass') { + } else if (name === 'densityEstimationPass' || + name === 'sectorHistogramPass') { clearCommands[name] = new ClearCommand({ framebuffer : framebuffers[name], color : new Color(1.0, 1.0, 1.0, 1.0), @@ -787,6 +922,7 @@ define([ processor._blendCommand = blendCommand; processor._clearCommands = clearCommands; processor._copyCommands = copyCommands; + processor._debugCommand = debugCommand; } function createResources(processor, context, dirty) { @@ -965,6 +1101,8 @@ define([ // Apply processing commands var pointOcclusionCommand = this._pointOcclusionCommand; var densityEstimationCommand = this._densityEstimationCommand; + var sectorHistogramCommand = this._sectorHistogramCommand; + var sectorGatheringCommand = this._sectorGatheringCommand; var regionGrowingCommands = this._regionGrowingCommands; var copyCommands = this._copyCommands; var stencilCommands = this._stencilCommands; @@ -972,7 +1110,10 @@ define([ var numRegionGrowingCommands = regionGrowingCommands.length; commandList.push(clearCommands['screenSpacePass']); - commandList.push(pointOcclusionCommand); + //commandList.push(pointOcclusionCommand); + commandList.push(clearCommands['sectorHistogramPass']); + commandList.push(sectorHistogramCommand); + commandList.push(sectorGatheringCommand); commandList.push(clearCommands['densityEstimationPass']); commandList.push(densityEstimationCommand); @@ -990,6 +1131,7 @@ define([ // Blend final result back into the main FBO commandList.push(this._blendCommand); + //commandList.push(this._debugCommand); commandList.push(clearCommands['prior']); }; diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl index 507c03b64621..aae28db6cf1d 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl @@ -16,7 +16,6 @@ uniform float ONE; -uniform sampler2D pointCloud_colorTexture; uniform sampler2D pointCloud_ECTexture; uniform float occlusionAngle; varying vec2 v_textureCoordinates; @@ -331,7 +330,7 @@ void main() { // This horizon point is behind the current point. That means that it can't // occlude the current point. So we ignore it and move on. - if (angle > maxAngle) + if (angle > maxAngle || angle <= 0.0) continue; // If we've found a horizon pixel, store it in the histogram if (readSectorHistogram(sectors.x, shFirst, shSecond) > angle) { @@ -396,17 +395,17 @@ void main() { // the average delta, so it won't even be considered in // the region growing pass. vec2 hpl = lengthFP64(centerPosition); - float triangleResult = triangleFP64(hpl, trianglePeriod); - gl_FragData[0] = czm_packDepth(triangleResult); + float triangleResult = triangleFP64(hpl, trianglePeriod); + gl_FragData[0] = czm_packDepth(triangleResult); #else - vec2 lengthOfFrustum = subFP64(split(czm_clampedFrustum.y), - split(czm_clampedFrustum.x)); - vec2 frustumStart = split(czm_clampedFrustum.x); - vec2 centerPositionLength = lengthFP64(centerPosition); - vec2 normalizedDepthFP64 = sumFP64(divFP64(centerPositionLength, - lengthOfFrustum), - frustumStart); - gl_FragData[0] = czm_packDepth(normalizedDepthFP64.x + normalizedDepthFP64.y); + vec2 lengthOfFrustum = subFP64(split(czm_clampedFrustum.y), + split(czm_clampedFrustum.x)); + vec2 frustumStart = split(czm_clampedFrustum.x); + vec2 centerPositionLength = lengthFP64(centerPosition); + vec2 normalizedDepthFP64 = sumFP64(divFP64(centerPositionLength, + lengthOfFrustum), + frustumStart); + gl_FragData[0] = czm_packDepth(normalizedDepthFP64.x + normalizedDepthFP64.y); #endif } } diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl index a1c427c5791a..f25f052a6db3 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl @@ -17,7 +17,6 @@ uniform float ONE; -uniform sampler2D pointCloud_colorTexture; uniform sampler2D pointCloud_ECTexture; uniform float occlusionAngle; in vec2 v_textureCoordinates; @@ -271,7 +270,7 @@ void main() { // This horizon point is behind the current point. That means that it can't // occlude the current point. So we ignore it and move on. - if (angle > maxAngle) + if (angle > maxAngle || angle <= 0.0) continue; // If we've found a horizon pixel, store it in the histogram if (sh[sectors.x] > angle) { diff --git a/Source/Shaders/PostProcessFilters/SectorGatheringPass.glsl b/Source/Shaders/PostProcessFilters/SectorGatheringPass.glsl new file mode 100644 index 000000000000..47c85c7d9b6a --- /dev/null +++ b/Source/Shaders/PostProcessFilters/SectorGatheringPass.glsl @@ -0,0 +1,215 @@ +#define TAU 6.28318530718 +#define PI 3.14159265359 +#define EPS 1e-6 +#define numSectors 8 +#define maxAngle 1.57079632679 // The maximum sector angle is PI / 2 + +#define trianglePeriod 1e-5 +#define useTriangle + +#define boundsCheckAndAccumulate(angle) if (angle <= 0.0 || angle > maxAngle) { accumulator += maxAngle; } else { accumulator += angle; } + +uniform sampler2D sectorFirst; +uniform sampler2D sectorSecond; +uniform sampler2D pointCloud_ECTexture; +uniform float occlusionAngle; +uniform float ONE; + +varying vec2 v_textureCoordinates; + +// TODO: Include Uber copyright + +vec2 split(float a) { + const float SPLIT = 4097.0; + float t = a * SPLIT; + float a_hi = t * ONE - (t - a); + float a_lo = a * ONE - a_hi; + return vec2(a_hi, a_lo); +} + +vec2 twoSub(float a, float b) { + float s = (a - b); + float v = (s * ONE - a) * ONE; + float err = (a - (s - v) * ONE) * ONE * ONE * ONE - (b + v); + return vec2(s, err); +} + +vec2 twoSum(float a, float b) { + float s = (a + b); + float v = (s * ONE - a) * ONE; + float err = (a - (s - v) * ONE) * ONE * ONE * ONE + (b - v); + return vec2(s, err); +} + +vec2 twoSqr(float a) { + float prod = a * a; + vec2 a_fp64 = split(a); + float err = ((a_fp64.x * a_fp64.x - prod) * ONE + 2.0 * a_fp64.x * + a_fp64.y * ONE * ONE) + a_fp64.y * a_fp64.y * ONE * ONE * ONE; + return vec2(prod, err); +} + +vec2 twoProd(float a, float b) { + float prod = a * b; + vec2 a_fp64 = split(a); + vec2 b_fp64 = split(b); + float err = ((a_fp64.x * b_fp64.x - prod) + a_fp64.x * b_fp64.y + + a_fp64.y * b_fp64.x) + a_fp64.y * b_fp64.y; + return vec2(prod, err); +} + +vec2 quickTwoSum(float a, float b) { + float sum = (a + b) * ONE; + float err = b - (sum - a) * ONE; + return vec2(sum, err); +} + +vec2 sumFP64(vec2 a, vec2 b) { + vec2 s, t; + s = twoSum(a.x, b.x); + t = twoSum(a.y, b.y); + s.y += t.x; + s = quickTwoSum(s.x, s.y); + s.y += t.y; + s = quickTwoSum(s.x, s.y); + return s; +} + +vec2 subFP64(vec2 a, vec2 b) { + vec2 s, t; + s = twoSub(a.x, b.x); + t = twoSub(a.y, b.y); + s.y += t.x; + s = quickTwoSum(s.x, s.y); + s.y += t.y; + s = quickTwoSum(s.x, s.y); + return s; +} + +vec2 mulFP64(vec2 a, vec2 b) { + vec2 prod = twoProd(a.x, b.x); + // y component is for the error + prod.y += a.x * b.y; + prod.y += a.y * b.x; + prod = quickTwoSum(prod.x, prod.y); + return prod; +} + +vec2 divFP64(in vec2 a, in vec2 b) { + float xn = 1.0 / b.x; + vec2 yn = a * xn; + float diff = (subFP64(a, mulFP64(b, yn))).x; + vec2 prod = twoProd(xn, diff); + return sumFP64(yn, prod); +} + +vec2 sqrtFP64(in vec2 a) { + if (a.x == 0.0 && a.y == 0.0) return vec2(0.0, 0.0); + if (a.x < 0.0) return vec2(0.0 / 0.0, 0.0 / 0.0); + float x = 1.0 / sqrt(a.x); + float yn = a.x * x; + vec2 yn_sqr = twoSqr(yn) * ONE; + float diff = subFP64(a, yn_sqr).x; + vec2 prod = twoProd(x * 0.5, diff); + return sumFP64(vec2(yn, 0.0), prod); +} + +vec2 lengthFP64(in vec3 vec) { + vec2 highPrecisionX = split(vec.x); + vec2 highPrecisionY = split(vec.y); + vec2 highPrecisionZ = split(vec.z); + vec2 highPrecision = + sqrtFP64(sumFP64(sumFP64( + mulFP64(highPrecisionX, highPrecisionX), + mulFP64(highPrecisionY, highPrecisionY)), + mulFP64(highPrecisionZ, highPrecisionZ))); + return highPrecision; +} + +float triangle(in float x, in float period) { + return abs(mod(x, period) / period - 0.5) + EPS; +} + +float triangleFP64(in vec2 x, in float period) { + float lowPrecision = x.x + x.y; + vec2 floorTerm = split(floor(lowPrecision / period)); + vec2 periodHighPrecision = split(period); + vec2 term2 = mulFP64(periodHighPrecision, floorTerm); + vec2 moduloTerm = subFP64(x, term2); + vec2 normalized = divFP64(moduloTerm, periodHighPrecision); + normalized = subFP64(normalized, split(0.5)); + return abs(normalized.x + normalized.y) + EPS; +} + +void main() { + vec4 sh1 = texture2D(sectorFirst, v_textureCoordinates) * maxAngle; + vec4 sh2 = texture2D(sectorSecond, v_textureCoordinates) * maxAngle; + + float accumulator = 0.0; + boundsCheckAndAccumulate(sh1.x); + boundsCheckAndAccumulate(sh1.y); + boundsCheckAndAccumulate(sh1.z); + boundsCheckAndAccumulate(sh1.w); + boundsCheckAndAccumulate(sh2.x); + boundsCheckAndAccumulate(sh2.y); + boundsCheckAndAccumulate(sh2.z); + boundsCheckAndAccumulate(sh2.w); + + // The solid angle is too small, so we occlude this point + if (accumulator < (2.0 * PI) * (1.0 - occlusionAngle)) { + gl_FragData[0] = vec4(0.0); + } else { + vec3 centerPosition = texture2D(pointCloud_ECTexture, v_textureCoordinates).xyz; + // Write out the distance of the point + // + // We use the distance of the point rather than + // the linearized depth. This is because we want + // to encode as much information about position disparities + // between points as we can, and the z-values of + // neighboring points are usually very similar. + // On the other hand, the x-values and y-values are + // usually fairly different. +#ifdef useTriangle + // We can get even more accuracy by passing the 64-bit + // distance into a triangle wave function that + // uses 64-bit primitives internally. The region + // growing pass only cares about deltas between + // different pixels, so we just have to ensure that + // the period of triangle function is greater than that + // of the largest possible delta can arise between + // different points. + // + // The triangle function is C0 continuous, which avoids + // artifacts from discontinuities. That said, I have noticed + // some inexplicable artifacts occasionally, so please + // disable this optimization if that becomes an issue. + // + // It's important that the period of the triangle function + // is at least two orders of magnitude greater than + // the average depth delta that we are likely to come + // across. The triangle function works because we have + // some assumption of locality in the depth domain. + // Massive deltas break that locality -- but that's + // actually not an issue. Deltas that are larger than + // the period function will be "wrapped around", and deltas + // that are much larger than the period function may be + // "wrapped around" many times. A similar process occurs + // in many random number generators. The resulting delta + // is usually at least an order of magnitude greater than + // the average delta, so it won't even be considered in + // the region growing pass. + vec2 hpl = lengthFP64(centerPosition); + float triangleResult = triangleFP64(hpl, trianglePeriod); + gl_FragData[0] = czm_packDepth(triangleResult); +#else + vec2 lengthOfFrustum = subFP64(split(czm_clampedFrustum.y), + split(czm_clampedFrustum.x)); + vec2 frustumStart = split(czm_clampedFrustum.x); + vec2 centerPositionLength = lengthFP64(centerPosition); + vec2 normalizedDepthFP64 = sumFP64(divFP64(centerPositionLength, + lengthOfFrustum), + frustumStart); + gl_FragData[0] = czm_packDepth(normalizedDepthFP64.x + normalizedDepthFP64.y); +#endif + } +} diff --git a/Source/Shaders/PostProcessFilters/SectorHistogramPass.glsl b/Source/Shaders/PostProcessFilters/SectorHistogramPass.glsl new file mode 100644 index 000000000000..0ef9d7e878b2 --- /dev/null +++ b/Source/Shaders/PostProcessFilters/SectorHistogramPass.glsl @@ -0,0 +1,173 @@ +#extension GL_EXT_frag_depth : enable +#extension GL_EXT_draw_buffers : enable + +#define TAU 6.28318530718 +#define PI 3.14159265359 +#define PI_4 0.785398163 +#define C0 1.57073 +#define C1 -0.212053 +#define C2 0.0740935 +#define C3 -0.0186166 +#define EPS 1e-6 +#define maxAngle 1.57079632679 // The maximum sector angle is PI / 2 +#define numSectors 8 + +varying float centerPos; + +// This texture actually contains eye-space coordinates, +// it just has to be called `pointCloud_depthTexture` +uniform sampler2D pointCloud_depthTexture; + +float acosFast(in float inX) { + float x = abs(inX); + float res = ((C3 * x + C2) * x + C1) * x + C0; // p(x) + res *= sqrt(1.0 - x); + + return (inX >= 0.0) ? res : PI - res; +} + +float atanFast(in float x) { + return PI_4 * x - x * (abs(x) - 1.0) * (0.2447 + 0.0663 * abs(x)); +} + +float atan2(in float y, in float x) { + return x == 0.0 ? sign(y) * PI / 2.0 : atanFast(y / x); +} + +int getSector(in vec2 d) { + float angle = (atan2(float(d.y), float(d.x)) + PI) / TAU; + return int(angle * float(numSectors)); +} + +// Subsamples the neighbor pixel and stores the sector number +// in each component of the output +ivec4 getSectors(in vec2 vi) { + return ivec4(getSector(vi + vec2(-0.5, 0.5)), + getSector(vi + vec2(0.5, -0.5)), + getSector(vi + vec2(0.5, 0.5)), + getSector(vi + vec2(-0.5, -0.5))); +} + +ivec2 collapseSectors(in ivec4 sectors) { + int first = sectors[0]; + ivec2 collapsed = ivec2(first, first); + for (int i = 1; i < 4; i++) + if (sectors[i] != first) + collapsed.y = sectors[i]; + return collapsed; +} + +void updateOutput(in int index, + in float value, + inout vec4 sh0, + inout vec4 sh1) { + // We could conditionally write out to gl_FragData here, + // however on hardware that doesn't support dynamic branching + // that would perform 8 writes instead of 1! So we write out + // to a dummy variable and then copy that over + if (index < 4) { + if (index < 2) { + if (index == 0) { + sh0.x = value; + } else { + sh0.y = value; + } + } else { + if (index == 2) { + sh0.z = value; + } else { + sh0.w = value; + } + } + } else { + if (index < 6) { + if (index == 4) { + sh1.x = value; + } else { + sh1.y = value; + } + } else { + if (index == 6) { + sh1.z = value; + } else { + sh1.w = value; + } + } + } +} + +void main() { + vec2 v_textureCoordinates = gl_FragCoord.xy / czm_viewport.zw; + + ivec2 centerScreenSpace = ivec2(gl_FragCoord.xy); + + // The position of the neighbor in 3D (eye space) + vec3 centerPosition = texture2D(pointCloud_depthTexture, + v_textureCoordinates).xyz; + + ivec2 neighborScreenSpace = ivec2(int(mod(centerPos, czm_viewport.z)), + int(centerPos) / int(czm_viewport.z)); + vec2 neighborTextureSpace = vec2(neighborScreenSpace) / czm_viewport.zw; + + // The position of this neighborhood center in 3D (eye space) + vec3 neighborPosition = texture2D(pointCloud_depthTexture, + neighborTextureSpace).xyz; + + // If our horizon pixel doesn't exist, ignore it and move on + if (length(neighborPosition) < EPS || + neighborScreenSpace == centerScreenSpace) { + gl_FragData[0] = vec4(1.0); + gl_FragData[1] = vec4(1.0); + return; + } + + // Right now this is obvious because everything happens in eye space, + // but this kind of statement is nice for a reference implementation + vec3 viewer = vec3(0.0); + + // d is the relative offset from the horizon pixel to the center pixel + // in 2D + ivec2 d = neighborScreenSpace - centerScreenSpace; + + // sectors contains both possible sectors that the + // neighbor pixel could be in + ivec2 sectors = collapseSectors(getSectors(vec2(d))); + + // This is the offset of the horizon point from the center in 3D + // (a 3D analog of d) + vec3 c = neighborPosition - centerPosition; + + // Now we calculate the dot product between the vector + // from the viewer to the center and the vector to the horizon pixel. + // We normalize both vectors first because we only care about their relative + // directions + // TODO: Redo the math and figure out whether the result should be negated or not + float dotProduct = dot(normalize(viewer - centerPosition), + normalize(c)); + + // We calculate the angle that this horizon pixel would make + // in the cone. The dot product is be equal to + // |vec_1| * |vec_2| * cos(angle_between), and in this case, + // the magnitude of both vectors is 1 because they are both + // normalized. + float angle = acosFast(dotProduct); + + // This horizon point is behind the current point. That means that it can't + // occlude the current point. So we ignore it and move on. + if (angle > maxAngle || angle < 0.0) { + gl_FragData[0] = vec4(1.0); + gl_FragData[1] = vec4(1.0); + } + + // Normalize to [0, 1] + angle /= maxAngle; + + vec4 sh0 = vec4(1.0); + vec4 sh1 = vec4(1.0); + + updateOutput(sectors.x, angle, sh0, sh1); + updateOutput(sectors.y, angle, sh0, sh1); + + gl_FragData[0] = sh0; + gl_FragData[1] = sh1; +} From 9f38a754a5ba1cc5a84d36e04ff440d3f173c329 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Thu, 20 Jul 2017 11:17:43 -0400 Subject: [PATCH 126/240] Fixes bug with atan2; ignores optimized version for now --- Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl | 2 +- Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl index 59fc0d094915..264d5559cbd1 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl @@ -158,7 +158,7 @@ float atanFast(in float x) { } float atan2(in float y, in float x) { - return x == 0.0 ? sign(y) * PI / 2.0 : atanFast(y / x); + return x == 0.0 ? sign(y) * PI / 2.0 : atan2(y, x); } void modifySectorHistogram(in int index, diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl index a1c427c5791a..cc3f4cc77bba 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl @@ -161,7 +161,7 @@ float atanFast(in float x) { } float atan2(in float y, in float x) { - return x == 0.0 ? sign(y) * PI / 2.0 : atanFast(y / x); + return x == 0.0 ? sign(y) * PI / 2.0 : atan(y, x); } int getSector(in vec2 d) { From bcae5c4b606739a6bae4b5ea13c3be097004c03c Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Thu, 20 Jul 2017 11:28:27 -0400 Subject: [PATCH 127/240] Point occlusion operator now works with point arrays --- Source/Scene/PointCloudPostProcessor.js | 8 +++++--- .../PostProcessFilters/PointOcclusionPassGL1.glsl | 2 +- .../PostProcessFilters/PointOcclusionPassGL2.glsl | 2 +- .../Shaders/PostProcessFilters/SectorHistogramPass.glsl | 9 +++++---- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 3dee66ff5998..8aaf4db2cf47 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -114,11 +114,11 @@ define([ this._minBlend = { enabled : true, equationRgb : BlendEquation.MIN, - equationAlpha : BlendEquation.ADD, + equationAlpha : BlendEquation.MIN, functionSourceRgb : BlendFunction.ONE, functionSourceAlpha : BlendFunction.ONE, functionDestinationRgb : BlendFunction.ONE, - functionDestinationAlpha : BlendFunction.ZERO + functionDestinationAlpha : BlendFunction.ONE }; this._addBlend = { equationRgb : BlendEquation.ADD, @@ -799,7 +799,9 @@ define([ 'void main() \n' + '{ \n' + ' vec4 sh0 = texture2D(debugTexture, v_textureCoordinates); \n' + - ' gl_FragColor = sh0; \n' + + ' vec4 sh1 = texture2D(debugTexture1, v_textureCoordinates); \n' + + ' gl_FragColor = 0.1 * vec4(sh0.x + sh0.y + sh0.z * sh0.w + sh1.x + sh1.y + sh1.z + sh1.w); \n' + + //' gl_FragColor = sh0; \n' + '} \n'; return context.createViewportQuadCommand(debugStageStr, { diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl index aae28db6cf1d..7cfd004a0f76 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl @@ -157,7 +157,7 @@ float atanFast(in float x) { } float atan2(in float y, in float x) { - return x == 0.0 ? sign(y) * PI / 2.0 : atanFast(y / x); + return x == 0.0 ? sign(y) * PI / 2.0 : atan(y, x); } void modifySectorHistogram(in int index, diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl index f25f052a6db3..2067d8e40695 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl @@ -160,7 +160,7 @@ float atanFast(in float x) { } float atan2(in float y, in float x) { - return x == 0.0 ? sign(y) * PI / 2.0 : atanFast(y / x); + return x == 0.0 ? sign(y) * PI / 2.0 : atanFast(y, x); } int getSector(in vec2 d) { diff --git a/Source/Shaders/PostProcessFilters/SectorHistogramPass.glsl b/Source/Shaders/PostProcessFilters/SectorHistogramPass.glsl index 0ef9d7e878b2..3eea6f84092e 100644 --- a/Source/Shaders/PostProcessFilters/SectorHistogramPass.glsl +++ b/Source/Shaders/PostProcessFilters/SectorHistogramPass.glsl @@ -31,7 +31,7 @@ float atanFast(in float x) { } float atan2(in float y, in float x) { - return x == 0.0 ? sign(y) * PI / 2.0 : atanFast(y / x); + return x == 0.0 ? sign(y) * PI / 2.0 : atan(y, x); } int getSector(in vec2 d) { @@ -150,13 +150,14 @@ void main() { // |vec_1| * |vec_2| * cos(angle_between), and in this case, // the magnitude of both vectors is 1 because they are both // normalized. - float angle = acosFast(dotProduct); + float angle = acos(dotProduct); // This horizon point is behind the current point. That means that it can't // occlude the current point. So we ignore it and move on. if (angle > maxAngle || angle < 0.0) { gl_FragData[0] = vec4(1.0); gl_FragData[1] = vec4(1.0); + return; } // Normalize to [0, 1] @@ -168,6 +169,6 @@ void main() { updateOutput(sectors.x, angle, sh0, sh1); updateOutput(sectors.y, angle, sh0, sh1); - gl_FragData[0] = sh0; - gl_FragData[1] = sh1; + gl_FragData[0] = vec4(sh0); + gl_FragData[1] = vec4(sh1); } From 4fa34a474155bde91efb6b692e9b514dec2db7a7 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Thu, 20 Jul 2017 12:28:32 -0400 Subject: [PATCH 128/240] Simplifies accumulation --- .../PostProcessFilters/SectorGatheringPass.glsl | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/Source/Shaders/PostProcessFilters/SectorGatheringPass.glsl b/Source/Shaders/PostProcessFilters/SectorGatheringPass.glsl index 47c85c7d9b6a..af1a23d7fb34 100644 --- a/Source/Shaders/PostProcessFilters/SectorGatheringPass.glsl +++ b/Source/Shaders/PostProcessFilters/SectorGatheringPass.glsl @@ -7,8 +7,6 @@ #define trianglePeriod 1e-5 #define useTriangle -#define boundsCheckAndAccumulate(angle) if (angle <= 0.0 || angle > maxAngle) { accumulator += maxAngle; } else { accumulator += angle; } - uniform sampler2D sectorFirst; uniform sampler2D sectorSecond; uniform sampler2D pointCloud_ECTexture; @@ -145,15 +143,8 @@ void main() { vec4 sh1 = texture2D(sectorFirst, v_textureCoordinates) * maxAngle; vec4 sh2 = texture2D(sectorSecond, v_textureCoordinates) * maxAngle; - float accumulator = 0.0; - boundsCheckAndAccumulate(sh1.x); - boundsCheckAndAccumulate(sh1.y); - boundsCheckAndAccumulate(sh1.z); - boundsCheckAndAccumulate(sh1.w); - boundsCheckAndAccumulate(sh2.x); - boundsCheckAndAccumulate(sh2.y); - boundsCheckAndAccumulate(sh2.z); - boundsCheckAndAccumulate(sh2.w); + float accumulator = sh1.x + sh1.y + sh1.z + sh1.w + + sh2.x + sh2.y + sh2.z + sh2.w; // The solid angle is too small, so we occlude this point if (accumulator < (2.0 * PI) * (1.0 - occlusionAngle)) { From b8b1841ab75ffd67923b1a6bccf34fff5f4842e9 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Fri, 21 Jul 2017 12:39:09 -0400 Subject: [PATCH 129/240] Much faster sector lookup --- Source/Scene/PointCloudPostProcessor.js | 74 ++++++++++++++++++- .../SectorHistogramPass.glsl | 52 +++---------- 2 files changed, 82 insertions(+), 44 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 8aaf4db2cf47..811ff2a302af 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -84,6 +84,7 @@ define([ this._depthTextures = undefined; this._sectorTextures = undefined; this._densityTexture = undefined; + this._sectorLUTTexture = undefined; this._dirty = undefined; this._clearStencil = undefined; this._pointOcclusionCommand = undefined; @@ -147,6 +148,7 @@ define([ processor._depthTextures[1].destroy(); processor._sectorTextures[0].destroy(); processor._sectorTextures[1].destroy(); + processor._sectorLUTTexture.destroy(); processor._densityTexture.destroy(); processor._dirty.destroy(); processor._colorTextures[0].destroy(); @@ -164,6 +166,46 @@ define([ processor._framebuffers = undefined; } + function generateSectorLUT(processor) { + function getSector(dx, dy, numSectors) { + var angle = (Math.atan2(dy, dx) + Math.PI) / (2.0 * Math.PI) - 1e-6; + return Math.trunc(angle * numSectors); + } + + function collapseSectors(dx, dy, numSectors) { + var sectors = new Uint8Array(4); + sectors[0] = getSector(dx - 0.5, dy + 0.5, numSectors); + sectors[1] = getSector(dx + 0.5, dy - 0.5, numSectors); + sectors[2] = getSector(dx + 0.5, dy + 0.5, numSectors); + sectors[3] = getSector(dx - 0.5, dy - 0.5, numSectors); + + var first = sectors[0]; + var second = sectors[0]; + sectors.forEach(function(element) { + if (element !== first) { + second = element; + } + }); + return new Array(first, second); + } + + var numSectors = 8; + var lutSize = processor.neighborhoodHalfWidth * 2 + 1; + var lut = new Uint8Array(lutSize * lutSize * 4); + var start = -Math.trunc(lutSize / 2); + var end = -start; + for (var i = start; i <= end; i++) { + for (var j = start; j <= end; j++) { + var offset = ((i + end) + (j + end) * lutSize) * 4; + var sectors = collapseSectors(i, j, numSectors); + lut[offset] = Math.trunc(256 * (sectors[0] / 8)); + lut[offset + 1] = Math.trunc(256 * (sectors[1] / 8)); + } + } + + return lut; + } + function createFramebuffers(processor, context) { var i; var screenWidth = context.drawingBufferWidth; @@ -191,6 +233,23 @@ define([ sampler : createSampler() }); + // Load the sector LUT that the point occlusion pass needs + var lutSize = processor.neighborhoodHalfWidth * 2 + 1; + var sectorLUTTexture = new Texture({ + context : context, + width : lutSize, + height : lutSize, + pixelFormat : PixelFormat.RGBA, + pixelDatatype : PixelDatatype.UNSIGNED_BYTE, + sampler : createSampler() + }); + var lutData = generateSectorLUT(processor); + sectorLUTTexture.copyFrom({ + width : lutSize, + height : lutSize, + arrayBufferView : lutData + }); + var dirty = new Texture({ context: context, width: screenWidth, @@ -283,6 +342,7 @@ define([ processor._depthTextures = depthTextures; processor._sectorTextures = sectorTextures; processor._densityTexture = densityMap; + processor._sectorLUTTexture = sectorLUTTexture; processor._colorTextures = colorTextures; processor._ecTexture = ecTexture; processor._dirty = dirty; @@ -369,7 +429,7 @@ define([ return depthTexture; }; - vertexShaderSource = replaceConstants(vertexShaderSource, 'kernelSize', kernelSize.toString()); + vertexShaderSource = replaceConstants(vertexShaderSource, 'kernelSize', kernelSize.toFixed(1)); var renderState = overrides.renderState; @@ -485,12 +545,19 @@ define([ } function sectorHistogramStage(processor, context) { + var neighborhoodSize = processor.neighborhoodHalfWidth * 2 + 1; var uniformMap = { + sectorLUT : function() { + return processor._sectorLUTTexture; + }, + neighborhoodSize : function() { + return neighborhoodSize; + } }; return createPointArrayCommand( processor._ecTexture, - '9.0', + neighborhoodSize, true, processor._minBlend, SectorHistogramPass, @@ -573,7 +640,7 @@ define([ return createPointArrayCommand( processor._depthTextures[0], - '9.0', + processor.densityHalfWidth * 2 + 1, false, processor._minBlend, densityEstimationStr, @@ -801,7 +868,6 @@ define([ ' vec4 sh0 = texture2D(debugTexture, v_textureCoordinates); \n' + ' vec4 sh1 = texture2D(debugTexture1, v_textureCoordinates); \n' + ' gl_FragColor = 0.1 * vec4(sh0.x + sh0.y + sh0.z * sh0.w + sh1.x + sh1.y + sh1.z + sh1.w); \n' + - //' gl_FragColor = sh0; \n' + '} \n'; return context.createViewportQuadCommand(debugStageStr, { diff --git a/Source/Shaders/PostProcessFilters/SectorHistogramPass.glsl b/Source/Shaders/PostProcessFilters/SectorHistogramPass.glsl index 3eea6f84092e..714eea1540ca 100644 --- a/Source/Shaders/PostProcessFilters/SectorHistogramPass.glsl +++ b/Source/Shaders/PostProcessFilters/SectorHistogramPass.glsl @@ -17,44 +17,15 @@ varying float centerPos; // This texture actually contains eye-space coordinates, // it just has to be called `pointCloud_depthTexture` uniform sampler2D pointCloud_depthTexture; - -float acosFast(in float inX) { - float x = abs(inX); - float res = ((C3 * x + C2) * x + C1) * x + C0; // p(x) - res *= sqrt(1.0 - x); - - return (inX >= 0.0) ? res : PI - res; -} - -float atanFast(in float x) { - return PI_4 * x - x * (abs(x) - 1.0) * (0.2447 + 0.0663 * abs(x)); -} - -float atan2(in float y, in float x) { - return x == 0.0 ? sign(y) * PI / 2.0 : atan(y, x); -} - -int getSector(in vec2 d) { - float angle = (atan2(float(d.y), float(d.x)) + PI) / TAU; - return int(angle * float(numSectors)); -} - -// Subsamples the neighbor pixel and stores the sector number -// in each component of the output -ivec4 getSectors(in vec2 vi) { - return ivec4(getSector(vi + vec2(-0.5, 0.5)), - getSector(vi + vec2(0.5, -0.5)), - getSector(vi + vec2(0.5, 0.5)), - getSector(vi + vec2(-0.5, -0.5))); -} - -ivec2 collapseSectors(in ivec4 sectors) { - int first = sectors[0]; - ivec2 collapsed = ivec2(first, first); - for (int i = 1; i < 4; i++) - if (sectors[i] != first) - collapsed.y = sectors[i]; - return collapsed; +uniform sampler2D sectorLUT; +uniform float neighborhoodSize; + +ivec2 readSectors(in ivec2 sectorPosition) { + int halfSize = int(neighborhoodSize / 2.0); + vec2 texCoordinate = vec2(sectorPosition + ivec2(halfSize)) / + float(halfSize * 2); + vec2 unscaled = texture2D(sectorLUT, texCoordinate).rg; + return ivec2(unscaled * float(numSectors)); } void updateOutput(in int index, @@ -131,7 +102,8 @@ void main() { // sectors contains both possible sectors that the // neighbor pixel could be in - ivec2 sectors = collapseSectors(getSectors(vec2(d))); + //ivec2 sectors = collapseSectors(getSectors(vec2(d))); + ivec2 sectors = readSectors(d); // This is the offset of the horizon point from the center in 3D // (a 3D analog of d) @@ -150,7 +122,7 @@ void main() { // |vec_1| * |vec_2| * cos(angle_between), and in this case, // the magnitude of both vectors is 1 because they are both // normalized. - float angle = acos(dotProduct); + float angle = acosFast(dotProduct); // This horizon point is behind the current point. That means that it can't // occlude the current point. So we ignore it and move on. From 8df82f0b1a6cc88428042480d2a3c288c73d5168 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Fri, 21 Jul 2017 12:49:47 -0400 Subject: [PATCH 130/240] Removes old code --- Source/Scene/PointCloudPostProcessor.js | 61 +-- .../PointOcclusionPassGL1.glsl | 411 ------------------ .../PointOcclusionPassGL2.glsl | 354 --------------- .../SectorHistogramPass.glsl | 8 + 4 files changed, 9 insertions(+), 825 deletions(-) delete mode 100644 Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl delete mode 100644 Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 811ff2a302af..e4860a9e7177 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -28,9 +28,7 @@ define([ '../Scene/BlendingState', '../Scene/StencilFunction', '../Scene/StencilOperation', - '../Shaders/PostProcessFilters/PointOcclusionPassGL1', '../Shaders/PostProcessFilters/RegionGrowingPassGL1', - '../Shaders/PostProcessFilters/PointOcclusionPassGL2', '../Shaders/PostProcessFilters/RegionGrowingPassGL2', '../Shaders/PostProcessFilters/SectorHistogramPass', '../Shaders/PostProcessFilters/SectorGatheringPass', @@ -64,9 +62,7 @@ define([ BlendingState, StencilFunction, StencilOperation, - PointOcclusionPassGL1, RegionGrowingPassGL1, - PointOcclusionPassGL2, RegionGrowingPassGL2, SectorHistogramPass, SectorGatheringPass, @@ -87,7 +83,6 @@ define([ this._sectorLUTTexture = undefined; this._dirty = undefined; this._clearStencil = undefined; - this._pointOcclusionCommand = undefined; this._densityEstimationCommand = undefined; this._sectorHistogramCommand = undefined; this._sectorGatheringCommand = undefined; @@ -493,57 +488,6 @@ define([ return sourceStr.replace(new RegExp(r, 'g'), '#define ' + constantName + ' ' + replacement); } - function pointOcclusionStage(processor, context) { - var uniformMap = { - pointCloud_ECTexture : function() { - return processor._ecTexture; - }, - occlusionAngle : function() { - return processor.occlusionAngle; - }, - ONE : function() { - return 1.0; - } - }; - - var pointOcclusionStr = replaceConstants( - (context.webgl2) ? PointOcclusionPassGL2 : PointOcclusionPassGL1, - 'neighborhoodHalfWidth', - processor.neighborhoodHalfWidth - ); - - pointOcclusionStr = replaceConstants( - pointOcclusionStr, - 'useTriangle', - processor.useTriangle - ); - - var func = StencilFunction.EQUAL; - var op = { - fail : StencilOperation.KEEP, - zFail : StencilOperation.KEEP, - zPass : StencilOperation.KEEP - }; - - return context.createViewportQuadCommand(pointOcclusionStr, { - uniformMap : uniformMap, - framebuffer : processor._framebuffers.screenSpacePass, - renderState : RenderState.fromCache({ - stencilTest : { - enabled : true, - reference : 0, - mask : 1, - frontFunction : func, - backFunction : func, - frontOperation : op, - backOperation : op - } - }), - pass : Pass.CESIUM_3D_TILE, - owner : processor - }); - } - function sectorHistogramStage(processor, context) { var neighborhoodSize = processor.neighborhoodHalfWidth * 2 + 1; var uniformMap = { @@ -886,7 +830,6 @@ define([ var copyCommands = new Array(2); var i; - processor._pointOcclusionCommand = pointOcclusionStage(processor, context); processor._densityEstimationCommand = densityEstimationStage(processor, context); processor._sectorHistogramCommand = sectorHistogramStage(processor, context); processor._sectorGatheringCommand = sectorGatheringStage(processor, context); @@ -1167,7 +1110,6 @@ define([ } // Apply processing commands - var pointOcclusionCommand = this._pointOcclusionCommand; var densityEstimationCommand = this._densityEstimationCommand; var sectorHistogramCommand = this._sectorHistogramCommand; var sectorGatheringCommand = this._sectorGatheringCommand; @@ -1178,7 +1120,6 @@ define([ var numRegionGrowingCommands = regionGrowingCommands.length; commandList.push(clearCommands['screenSpacePass']); - //commandList.push(pointOcclusionCommand); commandList.push(clearCommands['sectorHistogramPass']); commandList.push(sectorHistogramCommand); commandList.push(sectorGatheringCommand); @@ -1199,7 +1140,7 @@ define([ // Blend final result back into the main FBO commandList.push(this._blendCommand); - //commandList.push(this._debugCommand); + commandList.push(this._debugCommand); commandList.push(clearCommands['prior']); }; diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl deleted file mode 100644 index 7cfd004a0f76..000000000000 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl +++ /dev/null @@ -1,411 +0,0 @@ -#extension GL_EXT_frag_depth : enable - -#define TAU 6.28318530718 -#define PI 3.14159265359 -#define PI_4 0.785398163 -#define C0 1.57073 -#define C1 -0.212053 -#define C2 0.0740935 -#define C3 -0.0186166 -#define EPS 1e-6 -#define neighborhoodHalfWidth 4 // TUNABLE PARAMETER -- half-width of point-occlusion neighborhood -#define numSectors 8 - -#define trianglePeriod 1e-5 -#define useTriangle - -uniform float ONE; - -uniform sampler2D pointCloud_ECTexture; -uniform float occlusionAngle; -varying vec2 v_textureCoordinates; - -// TODO: Include Uber copyright - -vec2 split(float a) { - const float SPLIT = 4097.0; - float t = a * SPLIT; - float a_hi = t * ONE - (t - a); - float a_lo = a * ONE - a_hi; - return vec2(a_hi, a_lo); -} - -vec2 twoSub(float a, float b) { - float s = (a - b); - float v = (s * ONE - a) * ONE; - float err = (a - (s - v) * ONE) * ONE * ONE * ONE - (b + v); - return vec2(s, err); -} - -vec2 twoSum(float a, float b) { - float s = (a + b); - float v = (s * ONE - a) * ONE; - float err = (a - (s - v) * ONE) * ONE * ONE * ONE + (b - v); - return vec2(s, err); -} - -vec2 twoSqr(float a) { - float prod = a * a; - vec2 a_fp64 = split(a); - float err = ((a_fp64.x * a_fp64.x - prod) * ONE + 2.0 * a_fp64.x * - a_fp64.y * ONE * ONE) + a_fp64.y * a_fp64.y * ONE * ONE * ONE; - return vec2(prod, err); -} - -vec2 twoProd(float a, float b) { - float prod = a * b; - vec2 a_fp64 = split(a); - vec2 b_fp64 = split(b); - float err = ((a_fp64.x * b_fp64.x - prod) + a_fp64.x * b_fp64.y + - a_fp64.y * b_fp64.x) + a_fp64.y * b_fp64.y; - return vec2(prod, err); -} - -vec2 quickTwoSum(float a, float b) { - float sum = (a + b) * ONE; - float err = b - (sum - a) * ONE; - return vec2(sum, err); -} - -vec2 sumFP64(vec2 a, vec2 b) { - vec2 s, t; - s = twoSum(a.x, b.x); - t = twoSum(a.y, b.y); - s.y += t.x; - s = quickTwoSum(s.x, s.y); - s.y += t.y; - s = quickTwoSum(s.x, s.y); - return s; -} - -vec2 subFP64(vec2 a, vec2 b) { - vec2 s, t; - s = twoSub(a.x, b.x); - t = twoSub(a.y, b.y); - s.y += t.x; - s = quickTwoSum(s.x, s.y); - s.y += t.y; - s = quickTwoSum(s.x, s.y); - return s; -} - -vec2 mulFP64(vec2 a, vec2 b) { - vec2 prod = twoProd(a.x, b.x); - // y component is for the error - prod.y += a.x * b.y; - prod.y += a.y * b.x; - prod = quickTwoSum(prod.x, prod.y); - return prod; -} - -vec2 divFP64(in vec2 a, in vec2 b) { - float xn = 1.0 / b.x; - vec2 yn = a * xn; - float diff = (subFP64(a, mulFP64(b, yn))).x; - vec2 prod = twoProd(xn, diff); - return sumFP64(yn, prod); -} - -vec2 sqrtFP64(in vec2 a) { - if (a.x == 0.0 && a.y == 0.0) return vec2(0.0, 0.0); - if (a.x < 0.0) return vec2(0.0 / 0.0, 0.0 / 0.0); - float x = 1.0 / sqrt(a.x); - float yn = a.x * x; - vec2 yn_sqr = twoSqr(yn) * ONE; - float diff = subFP64(a, yn_sqr).x; - vec2 prod = twoProd(x * 0.5, diff); - return sumFP64(vec2(yn, 0.0), prod); -} - -vec2 lengthFP64(in vec3 vec) { - vec2 highPrecisionX = split(vec.x); - vec2 highPrecisionY = split(vec.y); - vec2 highPrecisionZ = split(vec.z); - vec2 highPrecision = - sqrtFP64(sumFP64(sumFP64( - mulFP64(highPrecisionX, highPrecisionX), - mulFP64(highPrecisionY, highPrecisionY)), - mulFP64(highPrecisionZ, highPrecisionZ))); - return highPrecision; -} - -float triangle(in float x, in float period) { - return abs(mod(x, period) / period - 0.5) + EPS; -} - -float triangleFP64(in vec2 x, in float period) { - float lowPrecision = x.x + x.y; - vec2 floorTerm = split(floor(lowPrecision / period)); - vec2 periodHighPrecision = split(period); - vec2 term2 = mulFP64(periodHighPrecision, floorTerm); - vec2 moduloTerm = subFP64(x, term2); - vec2 normalized = divFP64(moduloTerm, periodHighPrecision); - normalized = subFP64(normalized, split(0.5)); - return abs(normalized.x + normalized.y) + EPS; -} - -float acosFast(in float inX) { - float x = abs(inX); - float res = ((C3 * x + C2) * x + C1) * x + C0; // p(x) - res *= sqrt(1.0 - x); - - return (inX >= 0.0) ? res : PI - res; -} - -float atanFast(in float x) { - return PI_4 * x - x * (abs(x) - 1.0) * (0.2447 + 0.0663 * abs(x)); -} - -float atan2(in float y, in float x) { - return x == 0.0 ? sign(y) * PI / 2.0 : atan(y, x); -} - -void modifySectorHistogram(in int index, - in float value, - inout vec4 shFirst, - inout vec4 shSecond) { - if (index < 4) { - if (index < 2) { - if (index == 0) { - shFirst.x = value; - } else { - shFirst.y = value; - } - } else { - if (index == 2) { - shFirst.z = value; - } else { - shFirst.w = value; - } - } - } else { - if (index < 6) { - if (index == 4) { - shSecond.x = value; - } else { - shSecond.y = value; - } - } else { - if (index == 6) { - shSecond.z = value; - } else { - shSecond.w = value; - } - } - } -} - -float readSectorHistogram(in int index, - in vec4 shFirst, - in vec4 shSecond) { - if (index < 4) { - if (index < 2) { - if (index == 0) { - return shFirst.x; - } else { - return shFirst.y; - } - } else { - if (index == 2) { - return shFirst.z; - } else { - return shFirst.w; - } - } - } else { - if (index < 6) { - if (index == 4) { - return shSecond.x; - } else { - return shSecond.y; - } - } else { - if (index == 6) { - return shSecond.z; - } else { - return shSecond.w; - } - } - } -} - -int getSector(in vec2 d) { - float angle = (atan2(float(d.y), float(d.x)) + PI) / TAU; - return int(angle * float(numSectors)); -} - -// Subsamples the neighbor pixel and stores the sector number -// in each component of the output -ivec4 getSectors(in vec2 vi) { - return ivec4(getSector(vi + vec2(-0.5, 0.5)), - getSector(vi + vec2(0.5, -0.5)), - getSector(vi + vec2(0.5, 0.5)), - getSector(vi + vec2(-0.5, -0.5))); -} - -ivec2 collapseSectors(in ivec4 sectors) { - int first = sectors[0]; - ivec2 collapsed = ivec2(first, first); - for (int i = 1; i < 4; i++) - if (sectors[i] != first) - collapsed.y = sectors[i]; - return collapsed; -} - -void main() { - float near = czm_currentFrustum.x; - float far = czm_currentFrustum.y; - ivec2 pos = ivec2(int(gl_FragCoord.x), int(gl_FragCoord.y)); - - // The position of this pixel in 3D (i.e the position of the point) - vec3 centerPosition = texture2D(pointCloud_ECTexture, v_textureCoordinates).xyz; - - // If the EC of this pixel is zero, that means that it's not a valid - // pixel. We don't care about reprojecting it. - if (length(centerPosition) == 0.) - discard; - - // We split our region of interest (the point of interest and its - // neighbors) - // into sectors. For the purposes of this shader, we have eight - // sectors. - // - // Each entry of sector_histogram contains the current best horizon - // pixel angle - ivec2 halfNeighborhood = ivec2(neighborhoodHalfWidth / 2, - neighborhoodHalfWidth / 2); - // Upper left corner of the neighborhood - ivec2 upperLeftCorner = pos - halfNeighborhood; - // Lower right corner of the neighborhood - ivec2 lowerRightCorner = pos + halfNeighborhood; - - // The widest the cone can be is 90 degrees - float maxAngle = PI / 2.0; - - vec4 shFirst = vec4(maxAngle); - vec4 shSecond = vec4(maxAngle); - - // Right now this is obvious because everything happens in eye space, - // but this kind of statement is nice for a reference implementation - vec3 viewer = vec3(0.0); - - for (int i = -neighborhoodHalfWidth; i <= neighborhoodHalfWidth; i++) { - for (int j = -neighborhoodHalfWidth; j <= neighborhoodHalfWidth; j++) { - // d is the relative offset from the horizon pixel to the center pixel - // in 2D - ivec2 d = ivec2(i, j); - ivec2 pI = pos + d; - - // We now calculate the actual 3D position of the horizon pixel (the horizon point) - vec3 neighborPosition = texture2D(pointCloud_ECTexture, - vec2(pI) / czm_viewport.zw).xyz; - - // If our horizon pixel doesn't exist, ignore it and move on - if (length(neighborPosition) < EPS || pI == pos) { - continue; - } - - // sectors contains both possible sectors that the - // neighbor pixel could be in - ivec2 sectors = collapseSectors(getSectors(vec2(d))); - - // This is the offset of the horizon point from the center in 3D - // (a 3D analog of d) - vec3 c = neighborPosition - centerPosition; - - // Now we calculate the dot product between the vector - // from the viewer to the center and the vector to the horizon pixel. - // We normalize both vectors first because we only care about their relative - // directions - // TODO: Redo the math and figure out whether the result should be negated or not - float dotProduct = dot(normalize(viewer - centerPosition), - normalize(c)); - - // We calculate the angle that this horizon pixel would make - // in the cone. The dot product is be equal to - // |vec_1| * |vec_2| * cos(angle_between), and in this case, - // the magnitude of both vectors is 1 because they are both - // normalized. - float angle = acosFast(dotProduct); - - // This horizon point is behind the current point. That means that it can't - // occlude the current point. So we ignore it and move on. - if (angle > maxAngle || angle <= 0.0) - continue; - // If we've found a horizon pixel, store it in the histogram - if (readSectorHistogram(sectors.x, shFirst, shSecond) > angle) { - modifySectorHistogram(sectors.x, angle, shFirst, shSecond); - } - if (readSectorHistogram(sectors.y, shFirst, shSecond) > angle) { - modifySectorHistogram(sectors.y, angle, shFirst, shSecond); - } - } - } - - float accumulator = 0.0; - for (int i = 0; i < numSectors; i++) { - float angle = readSectorHistogram(i, shFirst, shSecond); - // If the z component is less than zero, - // that means that there is no valid horizon pixel - if (angle <= 0.0 || angle > maxAngle) - angle = maxAngle; - accumulator += angle; - } - - // The solid angle is too small, so we occlude this point - if (accumulator < (2.0 * PI) * (1.0 - occlusionAngle)) { - gl_FragData[0] = vec4(0.0); - } else { - // Write out the distance of the point - // - // We use the distance of the point rather than - // the linearized depth. This is because we want - // to encode as much information about position disparities - // between points as we can, and the z-values of - // neighboring points are usually very similar. - // On the other hand, the x-values and y-values are - // usually fairly different. -#ifdef useTriangle - // We can get even more accuracy by passing the 64-bit - // distance into a triangle wave function that - // uses 64-bit primitives internally. The region - // growing pass only cares about deltas between - // different pixels, so we just have to ensure that - // the period of triangle function is greater than that - // of the largest possible delta can arise between - // different points. - // - // The triangle function is C0 continuous, which avoids - // artifacts from discontinuities. That said, I have noticed - // some inexplicable artifacts occasionally, so please - // disable this optimization if that becomes an issue. - // - // It's important that the period of the triangle function - // is at least two orders of magnitude greater than - // the average depth delta that we are likely to come - // across. The triangle function works because we have - // some assumption of locality in the depth domain. - // Massive deltas break that locality -- but that's - // actually not an issue. Deltas that are larger than - // the period function will be "wrapped around", and deltas - // that are much larger than the period function may be - // "wrapped around" many times. A similar process occurs - // in many random number generators. The resulting delta - // is usually at least an order of magnitude greater than - // the average delta, so it won't even be considered in - // the region growing pass. - vec2 hpl = lengthFP64(centerPosition); - float triangleResult = triangleFP64(hpl, trianglePeriod); - gl_FragData[0] = czm_packDepth(triangleResult); -#else - vec2 lengthOfFrustum = subFP64(split(czm_clampedFrustum.y), - split(czm_clampedFrustum.x)); - vec2 frustumStart = split(czm_clampedFrustum.x); - vec2 centerPositionLength = lengthFP64(centerPosition); - vec2 normalizedDepthFP64 = sumFP64(divFP64(centerPositionLength, - lengthOfFrustum), - frustumStart); - gl_FragData[0] = czm_packDepth(normalizedDepthFP64.x + normalizedDepthFP64.y); -#endif - } -} diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl deleted file mode 100644 index 2067d8e40695..000000000000 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl +++ /dev/null @@ -1,354 +0,0 @@ -#version 300 es - -#define TAU 6.28318530718 -#define PI 3.14159265359 -#define PI_4 0.785398163 -#define C0 1.57073 -#define C1 -0.212053 -#define C2 0.0740935 -#define C3 -0.0186166 -#define EPS 1e-6 -#define neighborhoodHalfWidth 4 // TUNABLE PARAMETER -- half-width of point-occlusion neighborhood -#define neighborhoodSize 9 -#define numSectors 8 - -#define trianglePeriod 1e-2 -#define useTriangle - -uniform float ONE; - -uniform sampler2D pointCloud_ECTexture; -uniform float occlusionAngle; -in vec2 v_textureCoordinates; - -layout(location = 0) out vec4 depthOut; - -// TODO: Include Uber copyright - -vec2 split(float a) { - const float SPLIT = 4097.0; - float t = a * SPLIT; - float a_hi = t * ONE - (t - a); - float a_lo = a * ONE - a_hi; - return vec2(a_hi, a_lo); -} - -vec2 twoSub(float a, float b) { - float s = (a - b); - float v = (s * ONE - a) * ONE; - float err = (a - (s - v) * ONE) * ONE * ONE * ONE - (b + v); - return vec2(s, err); -} - -vec2 twoSum(float a, float b) { - float s = (a + b); - float v = (s * ONE - a) * ONE; - float err = (a - (s - v) * ONE) * ONE * ONE * ONE + (b - v); - return vec2(s, err); -} - -vec2 twoSqr(float a) { - float prod = a * a; - vec2 a_fp64 = split(a); - float err = ((a_fp64.x * a_fp64.x - prod) * ONE + 2.0 * a_fp64.x * - a_fp64.y * ONE * ONE) + a_fp64.y * a_fp64.y * ONE * ONE * ONE; - return vec2(prod, err); -} - -vec2 twoProd(float a, float b) { - float prod = a * b; - vec2 a_fp64 = split(a); - vec2 b_fp64 = split(b); - float err = ((a_fp64.x * b_fp64.x - prod) + a_fp64.x * b_fp64.y + - a_fp64.y * b_fp64.x) + a_fp64.y * b_fp64.y; - return vec2(prod, err); -} - -vec2 quickTwoSum(float a, float b) { - float sum = (a + b) * ONE; - float err = b - (sum - a) * ONE; - return vec2(sum, err); -} - -vec2 sumFP64(vec2 a, vec2 b) { - vec2 s, t; - s = twoSum(a.x, b.x); - t = twoSum(a.y, b.y); - s.y += t.x; - s = quickTwoSum(s.x, s.y); - s.y += t.y; - s = quickTwoSum(s.x, s.y); - return s; -} - -vec2 subFP64(vec2 a, vec2 b) { - vec2 s, t; - s = twoSub(a.x, b.x); - t = twoSub(a.y, b.y); - s.y += t.x; - s = quickTwoSum(s.x, s.y); - s.y += t.y; - s = quickTwoSum(s.x, s.y); - return s; -} - -vec2 mulFP64(vec2 a, vec2 b) { - vec2 prod = twoProd(a.x, b.x); - // y component is for the error - prod.y += a.x * b.y; - prod.y += a.y * b.x; - prod = quickTwoSum(prod.x, prod.y); - return prod; -} - -vec2 divFP64(in vec2 a, in vec2 b) { - float xn = 1.0 / b.x; - vec2 yn = a * xn; - float diff = (subFP64(a, mulFP64(b, yn))).x; - vec2 prod = twoProd(xn, diff); - return sumFP64(yn, prod); -} - -vec2 sqrtFP64(in vec2 a) { - if (a.x == 0.0 && a.y == 0.0) return vec2(0.0, 0.0); - if (a.x < 0.0) return vec2(0.0 / 0.0, 0.0 / 0.0); - float x = 1.0 / sqrt(a.x); - float yn = a.x * x; - vec2 yn_sqr = twoSqr(yn) * ONE; - float diff = subFP64(a, yn_sqr).x; - vec2 prod = twoProd(x * 0.5, diff); - return sumFP64(vec2(yn, 0.0), prod); -} - -vec2 lengthFP64(in vec3 vec) { - vec2 highPrecisionX = split(vec.x); - vec2 highPrecisionY = split(vec.y); - vec2 highPrecisionZ = split(vec.z); - vec2 highPrecision = - sqrtFP64(sumFP64(sumFP64( - mulFP64(highPrecisionX, highPrecisionX), - mulFP64(highPrecisionY, highPrecisionY)), - mulFP64(highPrecisionZ, highPrecisionZ))); - return highPrecision; -} - -float triangle(in float x, in float period) { - return abs(mod(x, period) / period - 0.5) + EPS; -} - -float triangleFP64(in vec2 x, in float period) { - float lowPrecision = x.x + x.y; - vec2 floorTerm = split(floor(lowPrecision / period)); - vec2 periodHighPrecision = split(period); - vec2 term2 = mulFP64(periodHighPrecision, floorTerm); - vec2 moduloTerm = subFP64(x, term2); - vec2 normalized = divFP64(moduloTerm, periodHighPrecision); - normalized = subFP64(normalized, split(0.5)); - return abs(normalized.x + normalized.y) + EPS; -} - -float acosFast(in float inX) { - float x = abs(inX); - float res = ((C3 * x + C2) * x + C1) * x + C0; // p(x) - res *= sqrt(1.0 - x); - - return (inX >= 0.0) ? res : PI - res; -} - -float atanFast(in float x) { - return PI_4 * x - x * (abs(x) - 1.0) * (0.2447 + 0.0663 * abs(x)); -} - -float atan2(in float y, in float x) { - return x == 0.0 ? sign(y) * PI / 2.0 : atanFast(y, x); -} - -int getSector(in vec2 d) { - float angle = (atan2(float(d.y), float(d.x)) + PI) / TAU; - return int(angle * float(numSectors)); -} - -// Subsamples the neighbor pixel and stores the sector number -// in each component of the output -ivec4 getSectors(in vec2 vi) { - return ivec4(getSector(vi + vec2(-0.5, 0.5)), - getSector(vi + vec2(0.5, -0.5)), - getSector(vi + vec2(0.5, 0.5)), - getSector(vi + vec2(-0.5, -0.5))); -} - -ivec2 collapseSectors(in ivec4 sectors) { - int first = sectors[0]; - ivec2 collapsed = ivec2(first, first); - for (int i = 1; i < 4; i++) - if (sectors[i] != first) - collapsed.y = sectors[i]; - return collapsed; -} - -void main() { - float near = czm_entireFrustum.x; - float far = czm_entireFrustum.y; - ivec2 pos = ivec2(int(gl_FragCoord.x), int(gl_FragCoord.y)); - - // The position of this pixel in 3D (i.e the position of the point) - vec3 centerPosition = texture(pointCloud_ECTexture, v_textureCoordinates).xyz; - bool invalid = false; - - // If the EC of this pixel is zero, that means that it's not a valid - // pixel. We don't care about reprojecting it. - if (length(centerPosition) < EPS) - invalid = true; - - // We split our region of interest (the point of interest and its - // neighbors) - // into sectors. For the purposes of this shader, we have eight - // sectors. - // - // Each entry of sector_histogram contains the current best horizon - // pixel angle - ivec2 halfNeighborhood = ivec2(neighborhoodHalfWidth / 2, - neighborhoodHalfWidth / 2); - // Upper left corner of the neighborhood - ivec2 upperLeftCorner = pos - halfNeighborhood; - // Lower right corner of the neighborhood - ivec2 lowerRightCorner = pos + halfNeighborhood; - - // The widest the cone can be is 90 degrees - float maxAngle = PI / 2.0; - - // Our sector array defaults to an angle of "maxAngle" in each sector - // (i.e no horizon pixels!) - float sh[numSectors]; - for (int i = 0; i < numSectors; i++) { - sh[i] = maxAngle; - } - - // Right now this is obvious because everything happens in eye space, - // but this kind of statement is nice for a reference implementation - vec3 viewer = vec3(0.0); - - for (int i = -neighborhoodHalfWidth; i <= neighborhoodHalfWidth; i++) { - for (int j = -neighborhoodHalfWidth; j <= neighborhoodHalfWidth; j++) { - // d is the relative offset from the horizon pixel to the center pixel - // in 2D - ivec2 d = ivec2(i, j); - ivec2 pI = pos + d; - - // We now calculate the actual 3D position of the horizon pixel (the horizon point) - vec3 neighborPosition = texture(pointCloud_ECTexture, - vec2(pI) / czm_viewport.zw).xyz; - - // If our horizon pixel doesn't exist, ignore it and move on - if (length(neighborPosition) < EPS || pI == pos) { - continue; - } - - if (!invalid) { - // sectors contains both possible sectors that the - // neighbor pixel could be in - ivec2 sectors = collapseSectors(getSectors(vec2(d))); - - // This is the offset of the horizon point from the center in 3D - // (a 3D analog of d) - vec3 c = neighborPosition - centerPosition; - - // Now we calculate the dot product between the vector - // from the viewer to the center and the vector to the horizon pixel. - // We normalize both vectors first because we only care about their relative - // directions - // TODO: Redo the math and figure out whether the result should be negated or not - float dotProduct = dot(normalize(viewer - centerPosition), - normalize(c)); - - // We calculate the angle that this horizon pixel would make - // in the cone. The dot product is be equal to - // |vec_1| * |vec_2| * cos(angle_between), and in this case, - // the magnitude of both vectors is 1 because they are both - // normalized. - float angle = acosFast(dotProduct); - - // This horizon point is behind the current point. That means that it can't - // occlude the current point. So we ignore it and move on. - if (angle > maxAngle || angle <= 0.0) - continue; - // If we've found a horizon pixel, store it in the histogram - if (sh[sectors.x] > angle) { - sh[sectors.x] = angle; - } - if (sh[sectors.y] > angle) { - sh[sectors.y] = angle; - } - } - } - } - - if (!invalid) { - float accumulator = 0.0; - for (int i = 0; i < numSectors; i++) { - float angle = sh[i]; - // If the z component is less than zero, - // that means that there is no valid horizon pixel - if (angle <= 0.0 || angle > maxAngle) - angle = maxAngle; - accumulator += angle; - } - - // The solid angle is too small, so we occlude this point - if (accumulator < (2.0 * PI) * (1.0 - occlusionAngle)) { - depthOut = vec4(0); - } else { - // Write out the distance of the point - // - // We use the distance of the point rather than - // the linearized depth. This is because we want - // to encode as much information about position disparities - // between points as we can, and the z-values of - // neighboring points are usually very similar. - // On the other hand, the x-values and y-values are - // usually fairly different. -#ifdef useTriangle - // We can get even more accuracy by passing the 64-bit - // distance into a triangle wave function that - // uses 64-bit primitives internally. The region - // growing pass only cares about deltas between - // different pixels, so we just have to ensure that - // the period of triangle function is greater than that - // of the largest possible delta can arise between - // different points. - // - // The triangle function is C0 continuous, which avoids - // artifacts from discontinuities. That said, I have noticed - // some inexplicable artifacts occasionally, so please - // disable this optimization if that becomes an issue. - // - // It's important that the period of the triangle function - // is at least two orders of magnitude greater than - // the average depth delta that we are likely to come - // across. The triangle function works because we have - // some assumption of locality in the depth domain. - // Massive deltas break that locality -- but that's - // actually not an issue. Deltas that are larger than - // the period function will be "wrapped around", and deltas - // that are much larger than the period function may be - // "wrapped around" many times. A similar process occurs - // in many random number generators. The resulting delta - // is usually at least an order of magnitude greater than - // the average delta, so it won't even be considered in - // the region growing pass. - vec2 hpl = lengthFP64(centerPosition); - float triangleResult = triangleFP64(hpl, trianglePeriod); - depthOut = czm_packDepth(triangleResult); -#else - vec2 lengthOfFrustum = subFP64(split(czm_clampedFrustum.y), - split(czm_clampedFrustum.x)); - vec2 frustumStart = split(czm_clampedFrustum.x); - vec2 centerPositionLength = lengthFP64(centerPosition); - vec2 normalizedDepthFP64 = sumFP64(divFP64(centerPositionLength, - lengthOfFrustum), - frustumStart); - depthOut = czm_packDepth(normalizedDepthFP64.x + normalizedDepthFP64.y); -#endif - } - } -} diff --git a/Source/Shaders/PostProcessFilters/SectorHistogramPass.glsl b/Source/Shaders/PostProcessFilters/SectorHistogramPass.glsl index 714eea1540ca..2c0512ba383c 100644 --- a/Source/Shaders/PostProcessFilters/SectorHistogramPass.glsl +++ b/Source/Shaders/PostProcessFilters/SectorHistogramPass.glsl @@ -20,6 +20,14 @@ uniform sampler2D pointCloud_depthTexture; uniform sampler2D sectorLUT; uniform float neighborhoodSize; +float acosFast(in float inX) { + float x = abs(inX); + float res = ((C3 * x + C2) * x + C1) * x + C0; // p(x) + res *= sqrt(1.0 - x); + + return (inX >= 0.0) ? res : PI - res; +} + ivec2 readSectors(in ivec2 sectorPosition) { int halfSize = int(neighborhoodSize / 2.0); vec2 texCoordinate = vec2(sectorPosition + ivec2(halfSize)) / From 3e5cfaf9cbe754dc77b953ee3fc4834328515eb3 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Fri, 21 Jul 2017 12:52:06 -0400 Subject: [PATCH 131/240] Minor optimization with dot product --- Source/Shaders/PostProcessFilters/SectorGatheringPass.glsl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Shaders/PostProcessFilters/SectorGatheringPass.glsl b/Source/Shaders/PostProcessFilters/SectorGatheringPass.glsl index af1a23d7fb34..2e09f3522317 100644 --- a/Source/Shaders/PostProcessFilters/SectorGatheringPass.glsl +++ b/Source/Shaders/PostProcessFilters/SectorGatheringPass.glsl @@ -143,8 +143,8 @@ void main() { vec4 sh1 = texture2D(sectorFirst, v_textureCoordinates) * maxAngle; vec4 sh2 = texture2D(sectorSecond, v_textureCoordinates) * maxAngle; - float accumulator = sh1.x + sh1.y + sh1.z + sh1.w + - sh2.x + sh2.y + sh2.z + sh2.w; + vec4 ones = vec4(1.0); + float accumulator = dot(sh1, ones) + dot(sh2, ones); // The solid angle is too small, so we occlude this point if (accumulator < (2.0 * PI) * (1.0 - occlusionAngle)) { From 50761633ccbc41d874ed12b8c5e6138a04fda947 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Fri, 21 Jul 2017 13:45:56 -0400 Subject: [PATCH 132/240] Cleans up stencil commands --- Source/Scene/PointCloudPostProcessor.js | 109 ++++++++---------- .../DensityEstimationPass.glsl | 2 +- 2 files changed, 47 insertions(+), 64 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index e4860a9e7177..8cb941df6b05 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -125,6 +125,47 @@ define([ functionDestinationAlpha : BlendFunction.ZERO }; + this._testingFunc = StencilFunction.EQUAL; + this._testingOp = { + fail : StencilOperation.KEEP, + zFail : StencilOperation.KEEP, + zPass : StencilOperation.KEEP + }; + this._writeFunc = StencilFunction.ALWAYS; + this._writeOp = { + fail : StencilOperation.KEEP, + zFail : StencilOperation.KEEP, + zPass : StencilOperation.ZERO + }; + + this._positiveStencilTest = { + enabled : true, + reference : 0, + mask : 1, + frontFunction : this._testingFunc, + backFunction : this._testingFunc, + frontOperation : this._testingOp, + backOperation : this._testingOp + }; + this._negativeStencilTest = { + enabled : true, + reference : 1, + mask : 1, + frontFunction : this._testingFunc, + backFunction : this._testingFunc, + frontOperation : this._testingOp, + backOperation : this._testingOp + }; + this._stencilWrite = { + enabled : true, + reference : 1, + mask : 0, + frontFunction : this._writeFunc, + backFunction : this._writeFunc, + frontOperation : this._writeOp, + backOperation : this._writeOp + }; + this.rangeMin = 1e-6; this.rangeMax = 5e-2; } @@ -540,26 +581,11 @@ define([ processor.useTriangle ); - var func = StencilFunction.EQUAL; - var op = { - fail : StencilOperation.KEEP, - zFail : StencilOperation.KEEP, - zPass : StencilOperation.KEEP - }; - return context.createViewportQuadCommand(sectorGatheringStr, { uniformMap : uniformMap, framebuffer : processor._framebuffers.screenSpacePass, renderState : RenderState.fromCache({ - stencilTest : { - enabled : true, - reference : 0, - mask : 1, - frontFunction : func, - backFunction : func, - frontOperation : op, - backOperation : op - } + stencilTest : processor._positiveStencilTest }), pass : Pass.CESIUM_3D_TILE, owner : processor @@ -652,26 +678,11 @@ define([ processor.stencilViewEnabled ); - var func = StencilFunction.EQUAL; - var op = { - fail : StencilOperation.KEEP, - zFail : StencilOperation.KEEP, - zPass : StencilOperation.KEEP - }; - return context.createViewportQuadCommand(regionGrowingPassStr, { uniformMap : uniformMap, framebuffer : framebuffer, renderState : RenderState.fromCache({ - stencilTest : { - enabled : true, - reference : 0, - mask : 1, - frontFunction : func, - backFunction : func, - frontOperation : op, - backOperation : op - } + stencilTest : processor._positiveStencilTest }), pass : Pass.CESIUM_3D_TILE, owner : processor @@ -768,25 +779,11 @@ define([ var framebuffer = processor._framebuffers.stencilMask; - var func = StencilFunction.ALWAYS; - var op = { - fail : StencilOperation.KEEP, - zFail : StencilOperation.KEEP, - zPass : StencilOperation.ZERO - }; return context.createViewportQuadCommand(stencilMaskStageStr, { uniformMap : uniformMap, framebuffer : framebuffer, renderState : RenderState.fromCache({ - stencilTest : { - enabled : true, - reference : 1, - mask : 0, - frontFunction : func, - backFunction : func, - frontOperation : op, - backOperation : op - } + stencilTest : processor._stencilWrite }), pass : Pass.CESIUM_3D_TILE, owner : processor @@ -1076,22 +1073,8 @@ define([ derivedCommand.castShadows = false; derivedCommand.receiveShadows = false; - var func = StencilFunction.ALWAYS; - var op = { - fail: StencilOperation.KEEP, - zFail: StencilOperation.KEEP, - zPass: StencilOperation.ZERO - }; var derivedCommandRenderState = derivedCommand.renderState; - derivedCommandRenderState.stencilTest = { - enabled : true, - reference : 1, - mask : 0, - frontFunction : func, - backFunction : func, - frontOperation : op, - backOperation : op - }; + derivedCommandRenderState.stencilTest = this._stencilWrite; derivedCommand.renderState = RenderState.fromCache( derivedCommandRenderState ); @@ -1140,7 +1123,7 @@ define([ // Blend final result back into the main FBO commandList.push(this._blendCommand); - commandList.push(this._debugCommand); + //commandList.push(this._debugCommand); commandList.push(clearCommands['prior']); }; diff --git a/Source/Shaders/PostProcessFilters/DensityEstimationPass.glsl b/Source/Shaders/PostProcessFilters/DensityEstimationPass.glsl index e68d25295858..93493b16b778 100644 --- a/Source/Shaders/PostProcessFilters/DensityEstimationPass.glsl +++ b/Source/Shaders/PostProcessFilters/DensityEstimationPass.glsl @@ -27,5 +27,5 @@ void main() { } gl_FragData[0] = - vec4(vec3(float(densityValue) / densityScaleFactor), 1.0); + vec4(float(densityValue) / densityScaleFactor, 0.0, 0.0, 0.0); } From cb8ff59a02d4b3bf556d5498671cf3a147f31fd7 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Fri, 21 Jul 2017 13:56:24 -0400 Subject: [PATCH 133/240] Consistency fixes for region growing --- Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl | 5 +++-- Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl | 5 +---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl index 0fc51c57f348..ad9459d0902f 100644 --- a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl @@ -116,7 +116,8 @@ void loadIntoArray(inout float[neighborhoodSize] depthNeighbors, continue; } vec2 neighborCoords = vec2(vec2(d) + gl_FragCoord.xy) / czm_viewport.zw; - float neighbor = texture2D(pointCloud_depthTexture, neighborCoords).r; + float neighbor = czm_unpackDepth(texture2D(pointCloud_depthTexture, + neighborCoords)); vec4 colorNeighbor = texture2D(pointCloud_colorTexture, neighborCoords); if (pastCenter) { depthNeighbors[(j + 1) * neighborhoodFullWidth + i] = @@ -184,7 +185,7 @@ void main() { float weight = (1.0 - rI / 2.0) * - (1.0 - min(1.0, depthDelta / max(1e-5, rangeParameter))); + (1.0 - min(1.0, depthDelta / max(1e-38, rangeParameter))); depthAccum += neighbor * weight; colorAccum += colorNeighbor * weight; diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl index 4ad93efdd5be..140c005812d2 100644 --- a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl @@ -165,10 +165,7 @@ void main() { // If the area that we want to region grow is sufficently sparse if (float(iterationNumber - DELAY) <= density + EPS) { #if neighborhoodFullWidth == 3 - fastMedian3(depthNeighbors, - colorNeighbors, - finalDepth, - finalColor); + fastMedian3(depthNeighbors, colorNeighbors, finalDepth, finalColor); #else genericMedianFinder(depthNeighbors, colorNeighbors, finalDepth, finalColor); #endif From 04bfdd7f7b4b151a8f3d6f808e173837f5714299 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Fri, 21 Jul 2017 14:21:44 -0400 Subject: [PATCH 134/240] Switches the old floating point depth to packed depth --- Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl index ad9459d0902f..c69d18f390f2 100644 --- a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl @@ -136,7 +136,7 @@ void loadIntoArray(inout float[neighborhoodSize] depthNeighbors, void main() { vec4 color = texture2D(pointCloud_colorTexture, v_textureCoordinates); - float depth = texture2D(pointCloud_depthTexture, v_textureCoordinates).r; + float depth = czm_unpackDepth(texture2D(pointCloud_depthTexture, v_textureCoordinates)); vec4 finalColor = color; float finalDepth = depth; From 756419420c202858e9564bbcd749c7c29848a13d Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Fri, 21 Jul 2017 14:22:37 -0400 Subject: [PATCH 135/240] Now using a proper AO texture --- Source/Scene/PointCloudPostProcessor.js | 40 +++++++++++++------ .../SectorGatheringPass.glsl | 4 ++ 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 8cb941df6b05..b29157faafad 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -81,6 +81,7 @@ define([ this._sectorTextures = undefined; this._densityTexture = undefined; this._sectorLUTTexture = undefined; + this._aoTexture = undefined; this._dirty = undefined; this._clearStencil = undefined; this._densityEstimationCommand = undefined; @@ -185,6 +186,7 @@ define([ processor._sectorTextures[0].destroy(); processor._sectorTextures[1].destroy(); processor._sectorLUTTexture.destroy(); + processor._aoTexture.destroy(); processor._densityTexture.destroy(); processor._dirty.destroy(); processor._colorTextures[0].destroy(); @@ -260,6 +262,15 @@ define([ sampler : createSampler() }); + var aoTexture = new Texture({ + context : context, + width : screenWidth, + height : screenHeight, + pixelFormat : PixelFormat.RGBA, + pixelDatatype : PixelDatatype.UNSIGNED_BYTE, + sampler : createSampler() + }); + var densityMap = new Texture({ context : context, width : screenWidth, @@ -340,7 +351,7 @@ define([ }), screenSpacePass : new Framebuffer({ context : context, - colorTextures : [depthTextures[0]], + colorTextures : [depthTextures[0], aoTexture], depthStencilTexture: dirty, destroyAttachments : false }), @@ -379,6 +390,7 @@ define([ processor._sectorTextures = sectorTextures; processor._densityTexture = densityMap; processor._sectorLUTTexture = sectorLUTTexture; + processor._aoTexture = aoTexture; processor._colorTextures = colorTextures; processor._ecTexture = ecTexture; processor._dirty = dirty; @@ -639,6 +651,9 @@ define([ pointCloud_densityTexture : function() { return processor._densityTexture; }, + pointCloud_aoTexture : function() { + return processor._aoTexture; + }, rangeParameter : function() { if (processor.useTriangle) { return processor.rangeParameter; @@ -792,23 +807,24 @@ define([ function debugStage(processor, context) { var uniformMap = { - debugTexture : function() { - return processor._sectorTextures[0]; - }, - debugTexture1 : function() { - return processor._sectorTextures[1]; + aoTexture : function() { + return processor._aoTexture; } }; var debugStageStr = - 'uniform sampler2D debugTexture; \n' + - 'uniform sampler2D debugTexture1; \n' + + '#define EPS 1e-8 \n' + + 'uniform sampler2D aoTexture; \n' + 'varying vec2 v_textureCoordinates; \n' + 'void main() \n' + '{ \n' + - ' vec4 sh0 = texture2D(debugTexture, v_textureCoordinates); \n' + - ' vec4 sh1 = texture2D(debugTexture1, v_textureCoordinates); \n' + - ' gl_FragColor = 0.1 * vec4(sh0.x + sh0.y + sh0.z * sh0.w + sh1.x + sh1.y + sh1.z + sh1.w); \n' + + ' vec4 raw = texture2D(aoTexture, v_textureCoordinates); \n' + + ' float occlusion = czm_unpackDepth(raw); \n' + + ' if (occlusion > EPS) {\n ' + + ' gl_FragColor = vec4(occlusion); \n' + + ' } else { \n' + + ' gl_FragColor = vec4(1.0); \n' + + ' } \n' + '} \n'; return context.createViewportQuadCommand(debugStageStr, { @@ -1123,7 +1139,7 @@ define([ // Blend final result back into the main FBO commandList.push(this._blendCommand); - //commandList.push(this._debugCommand); + commandList.push(this._debugCommand); commandList.push(clearCommands['prior']); }; diff --git a/Source/Shaders/PostProcessFilters/SectorGatheringPass.glsl b/Source/Shaders/PostProcessFilters/SectorGatheringPass.glsl index 2e09f3522317..a119cb41464f 100644 --- a/Source/Shaders/PostProcessFilters/SectorGatheringPass.glsl +++ b/Source/Shaders/PostProcessFilters/SectorGatheringPass.glsl @@ -149,7 +149,11 @@ void main() { // The solid angle is too small, so we occlude this point if (accumulator < (2.0 * PI) * (1.0 - occlusionAngle)) { gl_FragData[0] = vec4(0.0); + gl_FragData[1] = vec4(0.0); } else { + float occlusion = accumulator / (4.0 * PI); + gl_FragData[1] = czm_packDepth(occlusion); + vec3 centerPosition = texture2D(pointCloud_ECTexture, v_textureCoordinates).xyz; // Write out the distance of the point // From 14f3b98e88132fabf29cdc371da087ecfd9d9c18 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Fri, 21 Jul 2017 14:30:58 -0400 Subject: [PATCH 136/240] Now clearing AO texture to 1.0 (no occlusion) --- Source/Scene/PointCloudPostProcessor.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index b29157faafad..9f544b6fab6e 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -83,7 +83,6 @@ define([ this._sectorLUTTexture = undefined; this._aoTexture = undefined; this._dirty = undefined; - this._clearStencil = undefined; this._densityEstimationCommand = undefined; this._sectorHistogramCommand = undefined; this._sectorGatheringCommand = undefined; @@ -355,6 +354,11 @@ define([ depthStencilTexture: dirty, destroyAttachments : false }), + aoBuffer : new Framebuffer({ + context : context, + colorTextures : [aoTexture], + destroyAttachments : false + }), sectorHistogramPass : new Framebuffer({ context : context, colorTextures : [sectorTextures[0], sectorTextures[1]], @@ -820,11 +824,7 @@ define([ '{ \n' + ' vec4 raw = texture2D(aoTexture, v_textureCoordinates); \n' + ' float occlusion = czm_unpackDepth(raw); \n' + - ' if (occlusion > EPS) {\n ' + - ' gl_FragColor = vec4(occlusion); \n' + - ' } else { \n' + - ' gl_FragColor = vec4(1.0); \n' + - ' } \n' + + ' gl_FragColor = vec4(occlusion); \n' + '} \n'; return context.createViewportQuadCommand(debugStageStr, { @@ -918,7 +918,8 @@ define([ owner : processor }); } else if (name === 'densityEstimationPass' || - name === 'sectorHistogramPass') { + name === 'sectorHistogramPass' || + name === 'aoBuffer') { clearCommands[name] = new ClearCommand({ framebuffer : framebuffers[name], color : new Color(1.0, 1.0, 1.0, 1.0), @@ -1121,6 +1122,7 @@ define([ commandList.push(clearCommands['screenSpacePass']); commandList.push(clearCommands['sectorHistogramPass']); commandList.push(sectorHistogramCommand); + commandList.push(clearCommands['aoBuffer']); commandList.push(sectorGatheringCommand); commandList.push(clearCommands['densityEstimationPass']); commandList.push(densityEstimationCommand); From 411363b40de89aa6fc2d8ca76e0738805984edc9 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Mon, 24 Jul 2017 11:26:54 -0400 Subject: [PATCH 137/240] Working AO --- .../3D Tiles Point Cloud Post Processing.html | 8 ++ Source/Scene/Cesium3DTileset.js | 4 +- Source/Scene/PointCloudPostProcessor.js | 115 +++++++++++++----- .../RegionGrowingPassGL1.glsl | 98 +++++++++++---- .../RegionGrowingPassGL2.glsl | 1 + .../SectorGatheringPass.glsl | 2 + 6 files changed, 171 insertions(+), 57 deletions(-) diff --git a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html index 01ec646a4207..e1b3c365eab9 100644 --- a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html +++ b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html @@ -140,6 +140,10 @@ tileset.pointCloudPostProcessorOptions.useTriangle = checked; }); +Sandcastle.addToggleButton('Enable AO', true, function(checked) { + tileset.pointCloudPostProcessorOptions.enableAO = checked; +}); + Sandcastle.addToggleButton('Density View', false, function(checked) { tileset.pointCloudPostProcessorOptions.densityViewEnabled = checked; }); @@ -148,6 +152,10 @@ tileset.pointCloudPostProcessorOptions.stencilViewEnabled = checked; }); +Sandcastle.addToggleButton('AO View', false, function(checked) { + tileset.pointCloudPostProcessorOptions.AOViewEnabled = checked; +}); + //Sandcastle_End Sandcastle.finishedLoading(); } diff --git a/Source/Scene/Cesium3DTileset.js b/Source/Scene/Cesium3DTileset.js index e96816df50e0..3545dadd09fc 100644 --- a/Source/Scene/Cesium3DTileset.js +++ b/Source/Scene/Cesium3DTileset.js @@ -637,7 +637,9 @@ define([ densityViewEnabled : false, stencilViewEnabled : false, pointAttenuationMultiplier : 2.0, - useTriangle : false + useTriangle : false, + enableAO : true, + AOViewEnabled : false }; this._pointCloudPostProcessor = new PointCloudPostProcessor(this.pointCloudPostProcessorOptions); diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 9f544b6fab6e..e08813ce600b 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -81,14 +81,14 @@ define([ this._sectorTextures = undefined; this._densityTexture = undefined; this._sectorLUTTexture = undefined; - this._aoTexture = undefined; + this._aoTextures = undefined; this._dirty = undefined; this._densityEstimationCommand = undefined; this._sectorHistogramCommand = undefined; this._sectorGatheringCommand = undefined; this._regionGrowingCommands = undefined; this._stencilCommands = undefined; - this._debugCommand = undefined; + this._aoCommand = undefined; this._copyCommands = undefined; this._blendCommand = undefined; this._clearCommands = undefined; @@ -104,6 +104,8 @@ define([ this.stencilViewEnabled = options.stencilViewEnabled; this.pointAttenuationMultiplier = options.pointAttenuationMultiplier; this.useTriangle = options.useTriangle; + this.enableAO = options.enableAO; + this.AOViewEnabled = options.AOViewEnabled; this._pointArray = undefined; @@ -185,7 +187,8 @@ define([ processor._sectorTextures[0].destroy(); processor._sectorTextures[1].destroy(); processor._sectorLUTTexture.destroy(); - processor._aoTexture.destroy(); + processor._aoTextures[0].destroy(); + processor._aoTextures[1].destroy(); processor._densityTexture.destroy(); processor._dirty.destroy(); processor._colorTextures[0].destroy(); @@ -251,6 +254,7 @@ define([ var colorTextures = new Array(2); var sectorTextures = new Array(2); var depthTextures = new Array(3); + var aoTextures = new Array(2); var ecTexture = new Texture({ context : context, @@ -261,15 +265,6 @@ define([ sampler : createSampler() }); - var aoTexture = new Texture({ - context : context, - width : screenWidth, - height : screenHeight, - pixelFormat : PixelFormat.RGBA, - pixelDatatype : PixelDatatype.UNSIGNED_BYTE, - sampler : createSampler() - }); - var densityMap = new Texture({ context : context, width : screenWidth, @@ -332,6 +327,15 @@ define([ pixelDatatype : PixelDatatype.UNSIGNED_BYTE, sampler : createSampler() }); + + aoTextures[i] = new Texture({ + context : context, + width : screenWidth, + height : screenHeight, + pixelFormat : PixelFormat.RGBA, + pixelDatatype : PixelDatatype.UNSIGNED_BYTE, + sampler : createSampler() + }); } // There used to be an explanation of how this worked here @@ -350,13 +354,18 @@ define([ }), screenSpacePass : new Framebuffer({ context : context, - colorTextures : [depthTextures[0], aoTexture], + colorTextures : [depthTextures[0], aoTextures[0]], depthStencilTexture: dirty, destroyAttachments : false }), - aoBuffer : new Framebuffer({ + aoBufferA : new Framebuffer({ context : context, - colorTextures : [aoTexture], + colorTextures : [aoTextures[1]], + destroyAttachments : false + }), + aoBufferB : new Framebuffer({ + context : context, + colorTextures : [aoTextures[0]], destroyAttachments : false }), sectorHistogramPass : new Framebuffer({ @@ -378,14 +387,16 @@ define([ regionGrowingPassA : new Framebuffer({ context : context, colorTextures : [colorTextures[1], - depthTextures[1]], + depthTextures[1], + aoTextures[1]], depthStencilTexture: dirty, destroyAttachments : false }), regionGrowingPassB : new Framebuffer({ context: context, colorTextures: [colorTextures[0], - depthTextures[0]], + depthTextures[0], + aoTextures[0]], depthStencilTexture: dirty, destroyAttachments: false }) @@ -394,7 +405,7 @@ define([ processor._sectorTextures = sectorTextures; processor._densityTexture = densityMap; processor._sectorLUTTexture = sectorLUTTexture; - processor._aoTexture = aoTexture; + processor._aoTextures = aoTextures; processor._colorTextures = colorTextures; processor._ecTexture = ecTexture; processor._dirty = dirty; @@ -656,7 +667,7 @@ define([ return processor._densityTexture; }, pointCloud_aoTexture : function() { - return processor._aoTexture; + return processor._aoTextures[i]; }, rangeParameter : function() { if (processor.useTriangle) { @@ -716,6 +727,9 @@ define([ pointCloud_depthTexture : function() { return processor._depthTextures[i]; }, + pointCloud_aoTexture : function() { + return processor._aoTextures[i]; + }, pointCloud_densityTexture : function() { return processor._densityTexture; }, @@ -736,11 +750,13 @@ define([ 'uniform int densityHalfWidth; \n' + 'uniform sampler2D pointCloud_colorTexture; \n' + 'uniform sampler2D pointCloud_depthTexture; \n' + + 'uniform sampler2D pointCloud_aoTexture; \n' + 'uniform sampler2D pointCloud_densityTexture; \n' + 'varying vec2 v_textureCoordinates; \n' + 'void main() \n' + '{ \n' + ' vec4 rawDepth = texture2D(pointCloud_depthTexture, v_textureCoordinates); \n' + + ' vec4 rawAO = texture2D(pointCloud_aoTexture, v_textureCoordinates); \n' + ' float depth = czm_unpackDepth(rawDepth); \n' + ' if (depth > EPS) { \n' + ' #ifdef densityView \n' + @@ -750,6 +766,7 @@ define([ ' gl_FragData[0] = texture2D(pointCloud_colorTexture, v_textureCoordinates); \n' + ' #endif \n' + ' gl_FragData[1] = rawDepth; \n' + + ' gl_FragData[2] = rawAO; \n' + ' } \n' + '} \n'; @@ -809,14 +826,14 @@ define([ }); } - function debugStage(processor, context) { + function aoStage(processor, context) { var uniformMap = { aoTexture : function() { - return processor._aoTexture; + return processor._aoTextures[0]; } }; - var debugStageStr = + var aoStageStr = '#define EPS 1e-8 \n' + 'uniform sampler2D aoTexture; \n' + 'varying vec2 v_textureCoordinates; \n' + @@ -827,7 +844,7 @@ define([ ' gl_FragColor = vec4(occlusion); \n' + '} \n'; - return context.createViewportQuadCommand(debugStageStr, { + return context.createViewportQuadCommand(aoStageStr, { uniformMap : uniformMap, renderState : RenderState.fromCache({ }), @@ -857,13 +874,31 @@ define([ var blendFS = '#define EPS 1e-8 \n' + + '#define enableAO' + '#extension GL_EXT_frag_depth : enable \n' + 'uniform sampler2D pointCloud_colorTexture; \n' + 'uniform sampler2D pointCloud_depthTexture; \n' + - 'varying vec2 v_textureCoordinates; \n' + + 'uniform sampler2D pointCloud_aoTexture; \n' + + 'varying vec2 v_textureCoordinates; \n\n' + + 'float sigmoid2(float x, float sharpness) { \n' + + ' if (x >= 1.0) return 1.0; \n' + + ' else if (x <= -1.0) return -1.0; \n' + + ' else { \n' + + ' if (sharpness < 0.0) sharpness -= 1.0; \n' + + ' \n' + + ' if (x > 0.0) return sharpness * x / (sharpness - x + 1.0); \n' + + ' else if (x < 0.0) return sharpness * x / (sharpness - abs(x) + 1.0); \n' + + ' else return 0.0; \n' + + ' } \n' + + '} \n\n' + 'void main() \n' + '{ \n' + ' vec4 color = texture2D(pointCloud_colorTexture, v_textureCoordinates); \n' + + ' #ifdef enableAO \n' + + ' float ao = czm_unpackDepth(texture2D(pointCloud_aoTexture, v_textureCoordinates)); \n' + + ' ao = clamp(sigmoid2(ao + 0.2, 0.2), 0.0, 1.0); \n' + + ' color.xyz = color.xyz * ao; \n' + + ' #endif // enableAO \n' + ' float rayDist = czm_unpackDepth(texture2D(pointCloud_depthTexture, v_textureCoordinates)); \n' + ' if (length(rayDist) < EPS) { \n' + ' discard;' + @@ -881,13 +916,22 @@ define([ blending : BlendingState.ALPHA_BLEND }); + blendFS = replaceConstants( + blendFS, + 'enableAO', + processor.enableAO + ); + var blendUniformMap = { pointCloud_colorTexture: function() { return processor._colorTextures[1 - numRegionGrowingPasses % 2]; }, pointCloud_depthTexture: function() { return processor._depthTextures[1 - numRegionGrowingPasses % 2]; - } + }, + pointCloud_aoTexture: function() { + return processor._aoTextures[1 - numRegionGrowingPasses % 2]; + }, }; var blendCommand = context.createViewportQuadCommand(blendFS, { @@ -897,7 +941,7 @@ define([ owner : processor }); - var debugCommand = debugStage(processor, context, processor._sectorTextures[0]); + var aoCommand = aoStage(processor, context, processor._sectorTextures[0]); var framebuffers = processor._framebuffers; var clearCommands = {}; @@ -919,7 +963,8 @@ define([ }); } else if (name === 'densityEstimationPass' || name === 'sectorHistogramPass' || - name === 'aoBuffer') { + name === 'aoBufferA' || + name === 'aoBufferB') { clearCommands[name] = new ClearCommand({ framebuffer : framebuffers[name], color : new Color(1.0, 1.0, 1.0, 1.0), @@ -947,7 +992,7 @@ define([ processor._blendCommand = blendCommand; processor._clearCommands = clearCommands; processor._copyCommands = copyCommands; - processor._debugCommand = debugCommand; + processor._aoCommand = aoCommand; } function createResources(processor, context, dirty) { @@ -1043,7 +1088,9 @@ define([ tileset.pointCloudPostProcessorOptions.densityViewEnabled !== this.densityViewEnabled || tileset.pointCloudPostProcessorOptions.stencilViewEnabled !== this.stencilViewEnabled || tileset.pointCloudPostProcessorOptions.pointAttenuationMultiplier !== this.pointAttenuationMultiplier || - tileset.pointCloudPostProcessorOptions.useTriangle !== this.useTriangle) { + tileset.pointCloudPostProcessorOptions.useTriangle !== this.useTriangle || + tileset.pointCloudPostProcessorOptions.enableAO !== this.enableAO || + tileset.pointCloudPostProcessorOptions.AOViewEnabled !== this.AOViewEnabled) { this.occlusionAngle = tileset.pointCloudPostProcessorOptions.occlusionAngle; this.rangeParameter = tileset.pointCloudPostProcessorOptions.rangeParameter; this.neighborhoodHalfWidth = tileset.pointCloudPostProcessorOptions.neighborhoodHalfWidth; @@ -1055,6 +1102,8 @@ define([ this.maxAbsRatio = tileset.pointCloudPostProcessorOptions.maxAbsRatio; this.pointAttenuationMultiplier = tileset.pointCloudPostProcessorOptions.pointAttenuationMultiplier; this.useTriangle = tileset.pointCloudPostProcessorOptions.useTriangle; + this.enableAO = tileset.pointCloudPostProcessorOptions.enableAO; + this.AOViewEnabled = tileset.pointCloudPostProcessorOptions.AOViewEnabled; dirty = true; } @@ -1122,7 +1171,7 @@ define([ commandList.push(clearCommands['screenSpacePass']); commandList.push(clearCommands['sectorHistogramPass']); commandList.push(sectorHistogramCommand); - commandList.push(clearCommands['aoBuffer']); + commandList.push(clearCommands['aoBufferB']); commandList.push(sectorGatheringCommand); commandList.push(clearCommands['densityEstimationPass']); commandList.push(densityEstimationCommand); @@ -1130,8 +1179,10 @@ define([ for (i = 0; i < numRegionGrowingCommands; i++) { if (i % 2 === 0) { commandList.push(clearCommands['regionGrowingPassA']); + //commandList.push(clearCommands['aoBufferA']); } else { commandList.push(clearCommands['regionGrowingPassB']); + //commandList.push(clearCommands['aoBufferB']); } commandList.push(copyCommands[i % 2]); @@ -1141,7 +1192,9 @@ define([ // Blend final result back into the main FBO commandList.push(this._blendCommand); - commandList.push(this._debugCommand); + if (this.AOViewEnabled && this.enableAO) { + commandList.push(this._aoCommand); + } commandList.push(clearCommands['prior']); }; diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl index c69d18f390f2..34b5783c4f7a 100644 --- a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl @@ -14,13 +14,14 @@ uniform sampler2D pointCloud_colorTexture; uniform sampler2D pointCloud_densityTexture; uniform sampler2D pointCloud_depthTexture; +uniform sampler2D pointCloud_aoTexture; uniform float rangeParameter; uniform int densityHalfWidth; uniform int iterationNumber; varying vec2 v_textureCoordinates; -#define otherswap(a, b, aC, bC) if (a > b) { temp = a; a = b; b = temp; tempColor = aC; aC = bC; bC = tempColor; } +#define otherswap(a, b, aO, bO, aC, bC) if (a > b) { temp = a; a = b; b = temp; tempAO = aO; aO = bO; bO = tempAO; tempColor = aC; aC = bC; bC = tempColor; } vec4 testColor(in int value) { if (value == 0) { @@ -48,64 +49,93 @@ vec4 testColor(in int value) { void comparisonNetwork8(inout float[neighborhoodSize] neighbors, + inout float[neighborhoodSize] aoNeighbors, inout vec4[neighborhoodSize] neighborsColor) { float temp; + float tempAO; vec4 tempColor; - otherswap(neighbors[0], neighbors[1], neighborsColor[0], neighborsColor[1]); - otherswap(neighbors[2], neighbors[3], neighborsColor[2], neighborsColor[3]); - otherswap(neighbors[0], neighbors[2], neighborsColor[0], neighborsColor[2]); - otherswap(neighbors[1], neighbors[3], neighborsColor[1], neighborsColor[3]); - otherswap(neighbors[1], neighbors[2], neighborsColor[1], neighborsColor[2]); - otherswap(neighbors[4], neighbors[5], neighborsColor[4], neighborsColor[5]); - otherswap(neighbors[6], neighbors[7], neighborsColor[6], neighborsColor[7]); - otherswap(neighbors[4], neighbors[6], neighborsColor[4], neighborsColor[6]); - otherswap(neighbors[5], neighbors[7], neighborsColor[5], neighborsColor[7]); - otherswap(neighbors[5], neighbors[6], neighborsColor[5], neighborsColor[6]); - otherswap(neighbors[0], neighbors[4], neighborsColor[0], neighborsColor[4]); - otherswap(neighbors[1], neighbors[5], neighborsColor[1], neighborsColor[5]); - otherswap(neighbors[1], neighbors[4], neighborsColor[1], neighborsColor[4]); - otherswap(neighbors[2], neighbors[6], neighborsColor[2], neighborsColor[6]); - otherswap(neighbors[3], neighbors[7], neighborsColor[3], neighborsColor[7]); - otherswap(neighbors[3], neighbors[6], neighborsColor[3], neighborsColor[6]); - otherswap(neighbors[2], neighbors[4], neighborsColor[2], neighborsColor[4]); - otherswap(neighbors[3], neighbors[5], neighborsColor[3], neighborsColor[5]); - otherswap(neighbors[3], neighbors[4], neighborsColor[3], neighborsColor[4]); + otherswap(neighbors[0], neighbors[1], aoNeighbors[0], aoNeighbors[1], + neighborsColor[0], neighborsColor[1]); + otherswap(neighbors[2], neighbors[3], aoNeighbors[2], aoNeighbors[3], + neighborsColor[2], neighborsColor[3]); + otherswap(neighbors[0], neighbors[2], aoNeighbors[0], aoNeighbors[2], + neighborsColor[0], neighborsColor[2]); + otherswap(neighbors[1], neighbors[3], aoNeighbors[1], aoNeighbors[3], + neighborsColor[1], neighborsColor[3]); + otherswap(neighbors[1], neighbors[2], aoNeighbors[1], aoNeighbors[2], + neighborsColor[1], neighborsColor[2]); + otherswap(neighbors[4], neighbors[5], aoNeighbors[4], aoNeighbors[5], + neighborsColor[4], neighborsColor[5]); + otherswap(neighbors[6], neighbors[7], aoNeighbors[6], aoNeighbors[7], + neighborsColor[6], neighborsColor[7]); + otherswap(neighbors[4], neighbors[6], aoNeighbors[4], aoNeighbors[6], + neighborsColor[4], neighborsColor[6]); + otherswap(neighbors[5], neighbors[7], aoNeighbors[5], aoNeighbors[7], + neighborsColor[5], neighborsColor[7]); + otherswap(neighbors[5], neighbors[6], aoNeighbors[5], aoNeighbors[6], + neighborsColor[5], neighborsColor[6]); + otherswap(neighbors[0], neighbors[4], aoNeighbors[0], aoNeighbors[4], + neighborsColor[0], neighborsColor[4]); + otherswap(neighbors[1], neighbors[5], aoNeighbors[1], aoNeighbors[5], + neighborsColor[1], neighborsColor[5]); + otherswap(neighbors[1], neighbors[4], aoNeighbors[1], aoNeighbors[4], + neighborsColor[1], neighborsColor[4]); + otherswap(neighbors[2], neighbors[6], aoNeighbors[2], aoNeighbors[6], + neighborsColor[2], neighborsColor[6]); + otherswap(neighbors[3], neighbors[7], aoNeighbors[3], aoNeighbors[7], + neighborsColor[3], neighborsColor[7]); + otherswap(neighbors[3], neighbors[6], aoNeighbors[3], aoNeighbors[6], + neighborsColor[3], neighborsColor[6]); + otherswap(neighbors[2], neighbors[4], aoNeighbors[2], aoNeighbors[4], + neighborsColor[2], neighborsColor[4]); + otherswap(neighbors[3], neighbors[5], aoNeighbors[3], aoNeighbors[5], + neighborsColor[3], neighborsColor[5]); + otherswap(neighbors[3], neighbors[4], aoNeighbors[3], aoNeighbors[4], + neighborsColor[3], neighborsColor[4]); } // NOTE: This can be sped up a lot by replacing the depth // primitive array with two vec4s and using swizzle operations! // (assuming that the neighborhood is exactly 3x3) void fastMedian3(in float[neighborhoodSize] neighbors, + in float[neighborhoodSize] aoNeighbors, in vec4[neighborhoodSize] colorNeighbors, out float outDepth, + out float outAO, out vec4 outColor) { - comparisonNetwork8(neighbors, colorNeighbors); + comparisonNetwork8(neighbors, aoNeighbors, colorNeighbors); for (int i = 0; i < neighborhoodSize; i++) { if (abs(neighbors[i]) > EPS) { outDepth = neighbors[i + (neighborhoodSize - 1 - i) / 2]; + outAO = aoNeighbors[i + (neighborhoodSize - 1 - i) / 2]; outColor = colorNeighbors[i + (neighborhoodSize - 1 - i) / 2]; return; } } outDepth = 0.0; + outAO = 1.0; outColor = vec4(0, 0, 0, 0); } void genericMedianFinder(in float[neighborhoodSize] neighbors, + in float[neighborhoodSize] aoNeighbors, in vec4[neighborhoodSize] colorNeighbors, out float outDepth, + out float outAO, out vec4 outColor) { // Perhaps we should have a valid way of handling the // difficult-to-optimize cases. // For now this does nothing. outDepth = 0.0; + outAO = 1.0; outColor = vec4(1, 0, 0, 1); } void loadIntoArray(inout float[neighborhoodSize] depthNeighbors, + inout float[neighborhoodSize] aoNeighbors, inout vec4[neighborhoodSize] colorNeighbors) { bool pastCenter = false; for (int j = -neighborhoodHalfWidth; j <= neighborhoodHalfWidth; j++) { @@ -118,15 +148,21 @@ void loadIntoArray(inout float[neighborhoodSize] depthNeighbors, vec2 neighborCoords = vec2(vec2(d) + gl_FragCoord.xy) / czm_viewport.zw; float neighbor = czm_unpackDepth(texture2D(pointCloud_depthTexture, neighborCoords)); + float aoNeighbor = czm_unpackDepth(texture2D(pointCloud_aoTexture, + neighborCoords)); vec4 colorNeighbor = texture2D(pointCloud_colorTexture, neighborCoords); if (pastCenter) { depthNeighbors[(j + 1) * neighborhoodFullWidth + i] = neighbor; + aoNeighbors[(j + 1) * neighborhoodFullWidth + i] = + aoNeighbor; colorNeighbors[(j + 1) * neighborhoodFullWidth + i] = colorNeighbor; } else { depthNeighbors[(j + 1) * neighborhoodFullWidth + i + 1] = neighbor; + aoNeighbors[(j + 1) * neighborhoodFullWidth + i + 1] = + aoNeighbor; colorNeighbors[(j + 1) * neighborhoodFullWidth + i + 1] = colorNeighbor; } @@ -136,12 +172,17 @@ void loadIntoArray(inout float[neighborhoodSize] depthNeighbors, void main() { vec4 color = texture2D(pointCloud_colorTexture, v_textureCoordinates); - float depth = czm_unpackDepth(texture2D(pointCloud_depthTexture, v_textureCoordinates)); + float depth = czm_unpackDepth(texture2D(pointCloud_depthTexture, + v_textureCoordinates)); + float ao = czm_unpackDepth(texture2D(pointCloud_aoTexture, + v_textureCoordinates)); vec4 finalColor = color; float finalDepth = depth; + float finalAO = ao; float depthNeighbors[neighborhoodSize]; + float aoNeighbors[neighborhoodSize]; vec4 colorNeighbors[neighborhoodSize]; float rIs[neighborhoodSize]; rIs[0] = SQRT2; @@ -153,7 +194,7 @@ void main() { rIs[6] = 1.0; rIs[7] = SQRT2; - loadIntoArray(depthNeighbors, colorNeighbors); + loadIntoArray(depthNeighbors, aoNeighbors, colorNeighbors); float density = ceil(densityScaleFactor * texture2D(pointCloud_densityTexture, v_textureCoordinates).r); @@ -163,20 +204,24 @@ void main() { // If the area that we want to region grow is sufficently sparse if (float(iterationNumber - DELAY) <= density + EPS) { #if neighborhoodFullWidth == 3 - fastMedian3(depthNeighbors, colorNeighbors, finalDepth, finalColor); + fastMedian3(depthNeighbors, aoNeighbors, colorNeighbors, + finalDepth, finalAO, finalColor); #else - genericMedianFinder(depthNeighbors, colorNeighbors, finalDepth, finalColor); + genericMedianFinder(depthNeighbors, aoNeighbors, colorNeighbors, + finalDepth, finalAO, finalColor); #endif } } // Otherwise if our depth value is valid else { float depthAccum = 0.0; + float aoAccum = 0.0; vec4 colorAccum = vec4(0); float normalization = 0.0; for (int i = 0; i < neighborhoodSize; i++) { float neighbor = depthNeighbors[i]; + float aoNeighbor = aoNeighbors[i]; vec4 colorNeighbor = colorNeighbors[i]; float rI = rIs[i]; @@ -188,6 +233,7 @@ void main() { (1.0 - min(1.0, depthDelta / max(1e-38, rangeParameter))); depthAccum += neighbor * weight; + aoAccum += aoNeighbor * weight; colorAccum += colorNeighbor * weight; normalization += weight; } @@ -196,6 +242,7 @@ void main() { if (abs(depthAccum) > EPS) { finalDepth = depthAccum / normalization; finalColor = colorAccum / normalization; + finalAO = aoAccum / normalization; } } @@ -209,4 +256,5 @@ void main() { #endif #endif gl_FragData[1] = czm_packDepth(finalDepth); + gl_FragData[2] = czm_packDepth(finalAO); } diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl index 140c005812d2..754097b88e90 100644 --- a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl @@ -13,6 +13,7 @@ uniform sampler2D pointCloud_colorTexture; uniform sampler2D pointCloud_densityTexture; uniform sampler2D pointCloud_depthTexture; +uniform sampler2D pointCloud_aoTexture; uniform float rangeParameter; uniform int densityHalfWidth; uniform int iterationNumber; diff --git a/Source/Shaders/PostProcessFilters/SectorGatheringPass.glsl b/Source/Shaders/PostProcessFilters/SectorGatheringPass.glsl index a119cb41464f..bec804c7adc5 100644 --- a/Source/Shaders/PostProcessFilters/SectorGatheringPass.glsl +++ b/Source/Shaders/PostProcessFilters/SectorGatheringPass.glsl @@ -1,3 +1,5 @@ +#extension GL_EXT_draw_buffers : enable + #define TAU 6.28318530718 #define PI 3.14159265359 #define EPS 1e-6 From 8aff6d650b318419e2adda96598787df39f0a1b3 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Mon, 24 Jul 2017 11:59:42 -0400 Subject: [PATCH 138/240] Adds more AO parameters --- .../3D Tiles Point Cloud Post Processing.html | 20 +++++++++++++++- Source/Scene/Cesium3DTileset.js | 4 +++- Source/Scene/PointCloudPostProcessor.js | 24 +++++++++++++++---- 3 files changed, 41 insertions(+), 7 deletions(-) diff --git a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html index e1b3c365eab9..49da9dd99ec3 100644 --- a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html +++ b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html @@ -74,6 +74,20 @@

AO Sigmoid Domain Offset + + +
AO Sigmoid Sharpness + + +
@@ -108,7 +122,9 @@ neighborhoodHalfWidth : tileset.pointCloudPostProcessorOptions.neighborhoodHalfWidth, neighborhoodVectorSize : tileset.pointCloudPostProcessorOptions.neighborhoodVectorSize, maxAbsRatio : tileset.pointCloudPostProcessorOptions.maxAbsRatio, - pointAttenuationMultiplier : tileset.pointCloudPostProcessorOptions.pointAttenuationMultiplier + pointAttenuationMultiplier : tileset.pointCloudPostProcessorOptions.pointAttenuationMultiplier, + sigmoidDomainOffset : tileset.pointCloudPostProcessorOptions.sigmoidDomainOffset, + sigmoidSharpness : tileset.pointCloudPostProcessorOptions.sigmoidSharpness }; Cesium.knockout.track(viewModel); @@ -131,6 +147,8 @@ subscribeParameter('neighborhoodVectorSize'); subscribeParameter('maxAbsRatio'); subscribeParameter('pointAttenuationMultiplier'); +subscribeParameter('sigmoidDomainOffset'); +subscribeParameter('sigmoidSharpness'); Sandcastle.addToggleButton('Enabled', true, function(checked) { tileset.pointCloudPostProcessorOptions.enabled = checked; diff --git a/Source/Scene/Cesium3DTileset.js b/Source/Scene/Cesium3DTileset.js index 3545dadd09fc..1ad87c4e4f1c 100644 --- a/Source/Scene/Cesium3DTileset.js +++ b/Source/Scene/Cesium3DTileset.js @@ -639,7 +639,9 @@ define([ pointAttenuationMultiplier : 2.0, useTriangle : false, enableAO : true, - AOViewEnabled : false + AOViewEnabled : false, + sigmoidSharpness : 0.2, + sigmoidDomainOffset : 0.2 }; this._pointCloudPostProcessor = new PointCloudPostProcessor(this.pointCloudPostProcessorOptions); diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index e08813ce600b..d05a72e52827 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -106,6 +106,8 @@ define([ this.useTriangle = options.useTriangle; this.enableAO = options.enableAO; this.AOViewEnabled = options.AOViewEnabled; + this.sigmoidDomainOffset = options.sigmoidDomainOffset; + this.sigmoidSharpness = options.sigmoidSharpness; this._pointArray = undefined; @@ -879,6 +881,8 @@ define([ 'uniform sampler2D pointCloud_colorTexture; \n' + 'uniform sampler2D pointCloud_depthTexture; \n' + 'uniform sampler2D pointCloud_aoTexture; \n' + + 'uniform float sigmoidDomainOffset; \n' + + 'uniform float sigmoidSharpness; \n' + 'varying vec2 v_textureCoordinates; \n\n' + 'float sigmoid2(float x, float sharpness) { \n' + ' if (x >= 1.0) return 1.0; \n' + @@ -896,7 +900,7 @@ define([ ' vec4 color = texture2D(pointCloud_colorTexture, v_textureCoordinates); \n' + ' #ifdef enableAO \n' + ' float ao = czm_unpackDepth(texture2D(pointCloud_aoTexture, v_textureCoordinates)); \n' + - ' ao = clamp(sigmoid2(ao + 0.2, 0.2), 0.0, 1.0); \n' + + ' ao = clamp(sigmoid2(ao + sigmoidDomainOffset, sigmoidSharpness), 0.0, 1.0); \n' + ' color.xyz = color.xyz * ao; \n' + ' #endif // enableAO \n' + ' float rayDist = czm_unpackDepth(texture2D(pointCloud_depthTexture, v_textureCoordinates)); \n' + @@ -923,15 +927,21 @@ define([ ); var blendUniformMap = { - pointCloud_colorTexture: function() { + pointCloud_colorTexture : function() { return processor._colorTextures[1 - numRegionGrowingPasses % 2]; }, - pointCloud_depthTexture: function() { + pointCloud_depthTexture : function() { return processor._depthTextures[1 - numRegionGrowingPasses % 2]; }, - pointCloud_aoTexture: function() { + pointCloud_aoTexture : function() { return processor._aoTextures[1 - numRegionGrowingPasses % 2]; }, + sigmoidDomainOffset : function() { + return processor.sigmoidDomainOffset; + }, + sigmoidSharpness : function() { + return processor.sigmoidSharpness; + } }; var blendCommand = context.createViewportQuadCommand(blendFS, { @@ -1090,7 +1100,9 @@ define([ tileset.pointCloudPostProcessorOptions.pointAttenuationMultiplier !== this.pointAttenuationMultiplier || tileset.pointCloudPostProcessorOptions.useTriangle !== this.useTriangle || tileset.pointCloudPostProcessorOptions.enableAO !== this.enableAO || - tileset.pointCloudPostProcessorOptions.AOViewEnabled !== this.AOViewEnabled) { + tileset.pointCloudPostProcessorOptions.AOViewEnabled !== this.AOViewEnabled || + tileset.pointCloudPostProcessorOptions.sigmoidDomainOffset !== this.sigmoidDomainOffset || + tileset.pointCloudPostProcessorOptions.sigmoidSharpness !== this.sigmoidSharpness) { this.occlusionAngle = tileset.pointCloudPostProcessorOptions.occlusionAngle; this.rangeParameter = tileset.pointCloudPostProcessorOptions.rangeParameter; this.neighborhoodHalfWidth = tileset.pointCloudPostProcessorOptions.neighborhoodHalfWidth; @@ -1104,6 +1116,8 @@ define([ this.useTriangle = tileset.pointCloudPostProcessorOptions.useTriangle; this.enableAO = tileset.pointCloudPostProcessorOptions.enableAO; this.AOViewEnabled = tileset.pointCloudPostProcessorOptions.AOViewEnabled; + this.sigmoidDomainOffset = tileset.pointCloudPostProcessorOptions.sigmoidDomainOffset; + this.sigmoidSharpness = tileset.pointCloudPostProcessorOptions.sigmoidSharpness; dirty = true; } From b97bb0d679ecf7d28202f30935cbc44bc91b98e5 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Mon, 24 Jul 2017 12:07:36 -0400 Subject: [PATCH 139/240] Adds the old clear commands back in --- Source/Scene/PointCloudPostProcessor.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index d05a72e52827..af5120501983 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -1193,10 +1193,10 @@ define([ for (i = 0; i < numRegionGrowingCommands; i++) { if (i % 2 === 0) { commandList.push(clearCommands['regionGrowingPassA']); - //commandList.push(clearCommands['aoBufferA']); + commandList.push(clearCommands['aoBufferA']); } else { commandList.push(clearCommands['regionGrowingPassB']); - //commandList.push(clearCommands['aoBufferB']); + commandList.push(clearCommands['aoBufferB']); } commandList.push(copyCommands[i % 2]); From 634d6ff3e9bb5898126cc1626e48816498e8abf9 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Mon, 24 Jul 2017 13:04:10 -0400 Subject: [PATCH 140/240] Adds WebGL 2 support --- .../RegionGrowingPassGL2.glsl | 95 ++++++++++++++----- 1 file changed, 71 insertions(+), 24 deletions(-) diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl index 754097b88e90..4f2ca2a1901e 100644 --- a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl @@ -21,8 +21,9 @@ uniform int iterationNumber; in vec2 v_textureCoordinates; layout(location = 0) out vec4 colorOut; layout(location = 1) out vec4 depthOut; +layout(location = 2) out vec4 aoOut; -#define otherswap(a, b, aC, bC) if (a > b) { temp = a; a = b; b = temp; tempColor = aC; aC = bC; bC = tempColor; } +#define otherswap(a, b, aO, bO, aC, bC) if (a > b) { temp = a; a = b; b = temp; tempAO = aO; aO = bO; bO = tempAO; tempColor = aC; aC = bC; bC = tempColor; } vec4 testColor(in int value) { switch (value) { @@ -50,64 +51,93 @@ vec4 testColor(in int value) { } void comparisonNetwork8(inout float[neighborhoodSize] neighbors, + inout float[neighborhoodSize] aoNeighbors, inout vec4[neighborhoodSize] neighborsColor) { float temp; + float tempAO; vec4 tempColor; - otherswap(neighbors[0], neighbors[1], neighborsColor[0], neighborsColor[1]); - otherswap(neighbors[2], neighbors[3], neighborsColor[2], neighborsColor[3]); - otherswap(neighbors[0], neighbors[2], neighborsColor[0], neighborsColor[2]); - otherswap(neighbors[1], neighbors[3], neighborsColor[1], neighborsColor[3]); - otherswap(neighbors[1], neighbors[2], neighborsColor[1], neighborsColor[2]); - otherswap(neighbors[4], neighbors[5], neighborsColor[4], neighborsColor[5]); - otherswap(neighbors[6], neighbors[7], neighborsColor[6], neighborsColor[7]); - otherswap(neighbors[4], neighbors[6], neighborsColor[4], neighborsColor[6]); - otherswap(neighbors[5], neighbors[7], neighborsColor[5], neighborsColor[7]); - otherswap(neighbors[5], neighbors[6], neighborsColor[5], neighborsColor[6]); - otherswap(neighbors[0], neighbors[4], neighborsColor[0], neighborsColor[4]); - otherswap(neighbors[1], neighbors[5], neighborsColor[1], neighborsColor[5]); - otherswap(neighbors[1], neighbors[4], neighborsColor[1], neighborsColor[4]); - otherswap(neighbors[2], neighbors[6], neighborsColor[2], neighborsColor[6]); - otherswap(neighbors[3], neighbors[7], neighborsColor[3], neighborsColor[7]); - otherswap(neighbors[3], neighbors[6], neighborsColor[3], neighborsColor[6]); - otherswap(neighbors[2], neighbors[4], neighborsColor[2], neighborsColor[4]); - otherswap(neighbors[3], neighbors[5], neighborsColor[3], neighborsColor[5]); - otherswap(neighbors[3], neighbors[4], neighborsColor[3], neighborsColor[4]); + otherswap(neighbors[0], neighbors[1], aoNeighbors[0], aoNeighbors[1], + neighborsColor[0], neighborsColor[1]); + otherswap(neighbors[2], neighbors[3], aoNeighbors[2], aoNeighbors[3], + neighborsColor[2], neighborsColor[3]); + otherswap(neighbors[0], neighbors[2], aoNeighbors[0], aoNeighbors[2], + neighborsColor[0], neighborsColor[2]); + otherswap(neighbors[1], neighbors[3], aoNeighbors[1], aoNeighbors[3], + neighborsColor[1], neighborsColor[3]); + otherswap(neighbors[1], neighbors[2], aoNeighbors[1], aoNeighbors[2], + neighborsColor[1], neighborsColor[2]); + otherswap(neighbors[4], neighbors[5], aoNeighbors[4], aoNeighbors[5], + neighborsColor[4], neighborsColor[5]); + otherswap(neighbors[6], neighbors[7], aoNeighbors[6], aoNeighbors[7], + neighborsColor[6], neighborsColor[7]); + otherswap(neighbors[4], neighbors[6], aoNeighbors[4], aoNeighbors[6], + neighborsColor[4], neighborsColor[6]); + otherswap(neighbors[5], neighbors[7], aoNeighbors[5], aoNeighbors[7], + neighborsColor[5], neighborsColor[7]); + otherswap(neighbors[5], neighbors[6], aoNeighbors[5], aoNeighbors[6], + neighborsColor[5], neighborsColor[6]); + otherswap(neighbors[0], neighbors[4], aoNeighbors[0], aoNeighbors[4], + neighborsColor[0], neighborsColor[4]); + otherswap(neighbors[1], neighbors[5], aoNeighbors[1], aoNeighbors[5], + neighborsColor[1], neighborsColor[5]); + otherswap(neighbors[1], neighbors[4], aoNeighbors[1], aoNeighbors[4], + neighborsColor[1], neighborsColor[4]); + otherswap(neighbors[2], neighbors[6], aoNeighbors[2], aoNeighbors[6], + neighborsColor[2], neighborsColor[6]); + otherswap(neighbors[3], neighbors[7], aoNeighbors[3], aoNeighbors[7], + neighborsColor[3], neighborsColor[7]); + otherswap(neighbors[3], neighbors[6], aoNeighbors[3], aoNeighbors[6], + neighborsColor[3], neighborsColor[6]); + otherswap(neighbors[2], neighbors[4], aoNeighbors[2], aoNeighbors[4], + neighborsColor[2], neighborsColor[4]); + otherswap(neighbors[3], neighbors[5], aoNeighbors[3], aoNeighbors[5], + neighborsColor[3], neighborsColor[5]); + otherswap(neighbors[3], neighbors[4], aoNeighbors[3], aoNeighbors[4], + neighborsColor[3], neighborsColor[4]); } // NOTE: This can be sped up a lot by replacing the depth // primitive array with two vec4s and using swizzle operations! // (assuming that the neighborhood is exactly 3x3) void fastMedian3(in float[neighborhoodSize] neighbors, + in float[neighborhoodSize] aoNeighbors, in vec4[neighborhoodSize] colorNeighbors, out float outDepth, + out float outAO, out vec4 outColor) { - comparisonNetwork8(neighbors, colorNeighbors); + comparisonNetwork8(neighbors, aoNeighbors, colorNeighbors); for (int i = 0; i < neighborhoodSize; i++) { if (abs(neighbors[i]) > EPS) { outDepth = neighbors[i + (neighborhoodSize - 1 - i) / 2]; + outAO = aoNeighbors[i + (neighborhoodSize - 1 - i) / 2]; outColor = colorNeighbors[i + (neighborhoodSize - 1 - i) / 2]; return; } } outDepth = 0.0; + outAO = 1.0; outColor = vec4(0, 0, 0, 0); } void genericMedianFinder(in float[neighborhoodSize] neighbors, + in float[neighborhoodSize] aoNeighbors, in vec4[neighborhoodSize] colorNeighbors, out float outDepth, + out float outAO, out vec4 outColor) { // Perhaps we should have a valid way of handling the // difficult-to-optimize cases. // For now this does nothing. outDepth = 0.0; + outAO = 1.0; outColor = vec4(1, 0, 0, 1); } void loadIntoArray(inout float[neighborhoodSize] depthNeighbors, + inout float[neighborhoodSize] aoNeighbors, inout vec4[neighborhoodSize] colorNeighbors) { bool pastCenter = false; for (int j = -neighborhoodHalfWidth; j <= neighborhoodHalfWidth; j++) { @@ -120,15 +150,21 @@ void loadIntoArray(inout float[neighborhoodSize] depthNeighbors, vec2 neighborCoords = vec2(vec2(d) + gl_FragCoord.xy) / czm_viewport.zw; float neighbor = czm_unpackDepth(texture(pointCloud_depthTexture, neighborCoords)); + float aoNeighbor = czm_unpackDepth(texture(pointCloud_aoTexture, + neighborCoords)); vec4 colorNeighbor = texture(pointCloud_colorTexture, neighborCoords); if (pastCenter) { depthNeighbors[(j + 1) * neighborhoodFullWidth + i] = neighbor; + aoNeighbors[(j + 1) * neighborhoodFullWidth + i] = + aoNeighbor; colorNeighbors[(j + 1) * neighborhoodFullWidth + i] = colorNeighbor; } else { depthNeighbors[(j + 1) * neighborhoodFullWidth + i + 1] = neighbor; + aoNeighbors[(j + 1) * neighborhoodFullWidth + i + 1] = + aoNeighbor; colorNeighbors[(j + 1) * neighborhoodFullWidth + i + 1] = colorNeighbor; } @@ -140,11 +176,15 @@ void main() { vec4 color = texture(pointCloud_colorTexture, v_textureCoordinates); float depth = czm_unpackDepth(texture(pointCloud_depthTexture, v_textureCoordinates)); + float ao = czm_unpackDepth(texture(pointCloud_aoTexture, + v_textureCoordinates)); vec4 finalColor = color; float finalDepth = depth; + float finalAO = ao; float depthNeighbors[neighborhoodSize]; + float aoNeighbors[neighborhoodSize]; vec4 colorNeighbors[neighborhoodSize]; float rIs[neighborhoodSize]; rIs[0] = SQRT2; @@ -156,7 +196,7 @@ void main() { rIs[6] = 1.0; rIs[7] = SQRT2; - loadIntoArray(depthNeighbors, colorNeighbors); + loadIntoArray(depthNeighbors, aoNeighbors, colorNeighbors); float density = ceil(densityScaleFactor * texture(pointCloud_densityTexture, v_textureCoordinates).r); @@ -166,20 +206,24 @@ void main() { // If the area that we want to region grow is sufficently sparse if (float(iterationNumber - DELAY) <= density + EPS) { #if neighborhoodFullWidth == 3 - fastMedian3(depthNeighbors, colorNeighbors, finalDepth, finalColor); + fastMedian3(depthNeighbors, aoNeighbors, colorNeighbors, + finalDepth, finalAO, finalColor); #else - genericMedianFinder(depthNeighbors, colorNeighbors, finalDepth, finalColor); + genericMedianFinder(depthNeighbors, aoNeighbors, colorNeighbors, + finalDepth, finalAO, finalColor); #endif } } // Otherwise if our depth value is valid else { float depthAccum = 0.0; + float aoAccum = 0.0; vec4 colorAccum = vec4(0); float normalization = 0.0; for (int i = 0; i < neighborhoodSize; i++) { float neighbor = depthNeighbors[i]; + float aoNeighbor = aoNeighbors[i]; vec4 colorNeighbor = colorNeighbors[i]; float rI = rIs[i]; @@ -191,6 +235,7 @@ void main() { (1.0 - min(1.0, depthDelta / max(1e-38, rangeParameter))); depthAccum += neighbor * weight; + aoAccum += aoNeighbor * weight; colorAccum += colorNeighbor * weight; normalization += weight; } @@ -199,6 +244,7 @@ void main() { if (abs(depthAccum) > EPS) { finalDepth = depthAccum / normalization; finalColor = colorAccum / normalization; + finalAO = aoAccum / normalization; } } @@ -212,4 +258,5 @@ void main() { #endif #endif depthOut = czm_packDepth(finalDepth); + aoOut = czm_packDepth(finalAO); } From 64ffd5e77f2467472e626be72c323436f3820344 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Mon, 24 Jul 2017 13:37:13 -0400 Subject: [PATCH 141/240] Dead code removal --- Source/Shaders/PostProcessFilters/SectorHistogramPass.glsl | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/Shaders/PostProcessFilters/SectorHistogramPass.glsl b/Source/Shaders/PostProcessFilters/SectorHistogramPass.glsl index 2c0512ba383c..aeab7f81598c 100644 --- a/Source/Shaders/PostProcessFilters/SectorHistogramPass.glsl +++ b/Source/Shaders/PostProcessFilters/SectorHistogramPass.glsl @@ -110,7 +110,6 @@ void main() { // sectors contains both possible sectors that the // neighbor pixel could be in - //ivec2 sectors = collapseSectors(getSectors(vec2(d))); ivec2 sectors = readSectors(d); // This is the offset of the horizon point from the center in 3D From 3fe107b218eb2869c063a4ab38fe6650dd4615e3 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Mon, 24 Jul 2017 13:46:13 -0400 Subject: [PATCH 142/240] AO no longer breaks density/stencil view --- Source/Scene/PointCloudPostProcessor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index af5120501983..ed6e7cc3ba84 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -923,7 +923,7 @@ define([ blendFS = replaceConstants( blendFS, 'enableAO', - processor.enableAO + processor.enableAO && !processor.densityViewEnabled && !processor.stencilViewEnabled ); var blendUniformMap = { From 525ae79ae0640f2eb6f601482bbedd321da3806b Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Mon, 24 Jul 2017 16:03:23 -0400 Subject: [PATCH 143/240] Fixes the AO artifacts; bug in czm_packDepth --- Source/Scene/PointCloudPostProcessor.js | 3 +++ .../PostProcessFilters/RegionGrowingPassGL1.glsl | 2 +- .../PostProcessFilters/SectorGatheringPass.glsl | 10 ++++++---- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index ed6e7cc3ba84..84fe0a1edee9 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -769,6 +769,9 @@ define([ ' #endif \n' + ' gl_FragData[1] = rawDepth; \n' + ' gl_FragData[2] = rawAO; \n' + + ' } else { \n' + + ' gl_FragData[1] = czm_packDepth(0.0); ' + + ' gl_FragData[2] = czm_packDepth(1.0 - EPS); ' + ' } \n' + '} \n'; diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl index 34b5783c4f7a..15b14fdac2da 100644 --- a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl @@ -256,5 +256,5 @@ void main() { #endif #endif gl_FragData[1] = czm_packDepth(finalDepth); - gl_FragData[2] = czm_packDepth(finalAO); + gl_FragData[2] = czm_packDepth(finalAO - 1e-7); } diff --git a/Source/Shaders/PostProcessFilters/SectorGatheringPass.glsl b/Source/Shaders/PostProcessFilters/SectorGatheringPass.glsl index bec804c7adc5..2d1a1f3be211 100644 --- a/Source/Shaders/PostProcessFilters/SectorGatheringPass.glsl +++ b/Source/Shaders/PostProcessFilters/SectorGatheringPass.glsl @@ -148,15 +148,17 @@ void main() { vec4 ones = vec4(1.0); float accumulator = dot(sh1, ones) + dot(sh2, ones); + vec3 centerPosition = texture2D(pointCloud_ECTexture, v_textureCoordinates).xyz; + // The solid angle is too small, so we occlude this point - if (accumulator < (2.0 * PI) * (1.0 - occlusionAngle)) { + if (accumulator < (2.0 * PI) * (1.0 - occlusionAngle) || + length(centerPosition) < EPS) { gl_FragData[0] = vec4(0.0); - gl_FragData[1] = vec4(0.0); + gl_FragData[1] = vec4(1.0 - EPS); } else { - float occlusion = accumulator / (4.0 * PI); + float occlusion = clamp(accumulator / (4.0 * PI), 0.0, 1.0); gl_FragData[1] = czm_packDepth(occlusion); - vec3 centerPosition = texture2D(pointCloud_ECTexture, v_textureCoordinates).xyz; // Write out the distance of the point // // We use the distance of the point rather than From 8132d44ad0346ebab150f44c30ef8ba21fb900bd Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Mon, 24 Jul 2017 16:14:41 -0400 Subject: [PATCH 144/240] Fixes the WebGL 2 version --- Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl index 4f2ca2a1901e..769c9aea357c 100644 --- a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl @@ -258,5 +258,5 @@ void main() { #endif #endif depthOut = czm_packDepth(finalDepth); - aoOut = czm_packDepth(finalAO); + aoOut = czm_packDepth(finalAO - 1e-7); } From ad7093109ac03cb8f17f4cce6b9746b81ce0eb0d Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Tue, 25 Jul 2017 10:46:19 -0400 Subject: [PATCH 145/240] Formatting fixes --- Source/Scene/PointCloudPostProcessor.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 84fe0a1edee9..df0db199ec23 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -675,12 +675,10 @@ define([ if (processor.useTriangle) { return processor.rangeParameter; } - if (processor.rangeParameter < rangeMin) { - return 0.0; - } - return processor.rangeParameter * (rangeMax - rangeMin) + rangeMin; - - + if (processor.rangeParameter < rangeMin) { + return 0.0; + } + return processor.rangeParameter * (rangeMax - rangeMin) + rangeMin; }, densityHalfWidth : function() { return processor.densityHalfWidth; From f50178cbb9eeca43dd8944a0b048ecefd3ae9faa Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Tue, 25 Jul 2017 13:28:51 -0400 Subject: [PATCH 146/240] Adds the edge culling filter back in --- Source/Scene/PointCloudPostProcessor.js | 86 ++++++++++++++----- .../DensityEstimationPass.glsl | 20 ++++- .../PostProcessFilters/EdgeCullingPass.glsl | 22 +++++ 3 files changed, 106 insertions(+), 22 deletions(-) create mode 100644 Source/Shaders/PostProcessFilters/EdgeCullingPass.glsl diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index df0db199ec23..9b3d9bcdb8ca 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -32,7 +32,8 @@ define([ '../Shaders/PostProcessFilters/RegionGrowingPassGL2', '../Shaders/PostProcessFilters/SectorHistogramPass', '../Shaders/PostProcessFilters/SectorGatheringPass', - '../Shaders/PostProcessFilters/DensityEstimationPass' + '../Shaders/PostProcessFilters/DensityEstimationPass', + '../Shaders/PostProcessFilters/EdgeCullingPass' ], function( Color, ComponentDatatype, @@ -66,7 +67,8 @@ define([ RegionGrowingPassGL2, SectorHistogramPass, SectorGatheringPass, - DensityEstimationPass + DensityEstimationPass, + EdgeCullingPass ) { 'use strict'; @@ -80,10 +82,12 @@ define([ this._depthTextures = undefined; this._sectorTextures = undefined; this._densityTexture = undefined; + this._edgeCullingTexture = undefined; this._sectorLUTTexture = undefined; this._aoTextures = undefined; this._dirty = undefined; this._densityEstimationCommand = undefined; + this._edgeCullingCommand = undefined; this._sectorHistogramCommand = undefined; this._sectorGatheringCommand = undefined; this._regionGrowingCommands = undefined; @@ -121,12 +125,13 @@ define([ functionDestinationAlpha : BlendFunction.ONE }; this._addBlend = { + enabled : true, equationRgb : BlendEquation.ADD, equationAlpha : BlendEquation.ADD, functionSourceRgb : BlendFunction.ONE, functionSourceAlpha : BlendFunction.ONE, functionDestinationRgb : BlendFunction.ONE, - functionDestinationAlpha : BlendFunction.ZERO + functionDestinationAlpha : BlendFunction.ONE }; this._testingFunc = StencilFunction.EQUAL; @@ -192,6 +197,7 @@ define([ processor._aoTextures[0].destroy(); processor._aoTextures[1].destroy(); processor._densityTexture.destroy(); + processor._edgeCullingTexture.destroy(); processor._dirty.destroy(); processor._colorTextures[0].destroy(); processor._colorTextures[1].destroy(); @@ -276,6 +282,15 @@ define([ sampler : createSampler() }); + var edgeCullingTexture = new Texture({ + context : context, + width : screenWidth, + height : screenHeight, + pixelFormat : PixelFormat.RGBA, + pixelDatatype : PixelDatatype.FLOAT, + sampler : createSampler() + }); + // Load the sector LUT that the point occlusion pass needs var lutSize = processor.neighborhoodHalfWidth * 2 + 1; var sectorLUTTexture = new Texture({ @@ -386,6 +401,11 @@ define([ colorTextures : [densityMap], destroyAttachments : false }), + edgeCullingPass : new Framebuffer({ + context : context, + colorTextures : [edgeCullingTexture], + destroyAttachments : false + }), regionGrowingPassA : new Framebuffer({ context : context, colorTextures : [colorTextures[1], @@ -406,6 +426,7 @@ define([ processor._depthTextures = depthTextures; processor._sectorTextures = sectorTextures; processor._densityTexture = densityMap; + processor._edgeCullingTexture = edgeCullingTexture; processor._sectorLUTTexture = sectorLUTTexture; processor._aoTextures = aoTextures; processor._colorTextures = colorTextures; @@ -499,21 +520,10 @@ define([ var renderState = overrides.renderState; if (!defined(overrides.renderState)) { - var func = StencilFunction.EQUAL; - var op = { - fail : StencilOperation.KEEP, - zFail : StencilOperation.KEEP, - zPass : StencilOperation.KEEP - }; - var stencilTest = { - enabled : true, - reference : 0, - mask : 1, - frontFunction : func, - backFunction : func, - frontOperation : op, - backOperation : op - }; + var stencilTest = processor._positiveStencilTest; + if (defined(overrides.stencilTest)) { + stencilTest = overrides.stencilTest; + } if (useStencil) { renderState = RenderState.fromCache({ stencilTest : stencilTest, @@ -628,6 +638,9 @@ define([ }, maxAbsRatio : function() { return processor.maxAbsRatio; + }, + pointCloud_edgeCullingTexture : function() { + return processor._edgeCullingTexture; } }; @@ -653,6 +666,33 @@ define([ ); } + function edgeCullingStage(processor, context) { + var uniformMap = { + }; + + var edgeCullingStr = replaceConstants( + EdgeCullingPass, + 'neighborhoodHalfWidth', + processor.densityHalfWidth + ); + + return createPointArrayCommand( + processor._depthTextures[0], + processor.densityHalfWidth * 2 + 1, + true, + processor._addBlend, + edgeCullingStr, + processor, + context, { + uniformMap : uniformMap, + framebuffer : processor._framebuffers.edgeCullingPass, + pass : Pass.CESIUM_3D_TILE, + owner : processor, + stencilTest : processor._negativeStencilTest + } + ); + } + function regionGrowingStage(processor, context, iteration) { var i = iteration % 2; var rangeMin = processor.rangeMin; @@ -863,6 +903,7 @@ define([ var copyCommands = new Array(2); var i; + processor._edgeCullingCommand = edgeCullingStage(processor, context); processor._densityEstimationCommand = densityEstimationStage(processor, context); processor._sectorHistogramCommand = sectorHistogramStage(processor, context); processor._sectorGatheringCommand = sectorGatheringStage(processor, context); @@ -960,10 +1001,12 @@ define([ if (framebuffers.hasOwnProperty(name)) { // The screen space pass should consider // the stencil value, so we don't clear it - // here. The density estimation pass uses + // here. Edge culling should only apply to invalid + // pixels. The density estimation pass uses // min blending, so we need to set the default // value to the maximum possible value - if (name === 'screenSpacePass') { + if (name === 'screenSpacePass' || + name === 'edgeCullingPass') { clearCommands[name] = new ClearCommand({ framebuffer : framebuffers[name], color : new Color(0.0, 0.0, 0.0, 0.0), @@ -1174,6 +1217,7 @@ define([ } // Apply processing commands + var edgeCullingCommand = this._edgeCullingCommand; var densityEstimationCommand = this._densityEstimationCommand; var sectorHistogramCommand = this._sectorHistogramCommand; var sectorGatheringCommand = this._sectorGatheringCommand; @@ -1188,6 +1232,8 @@ define([ commandList.push(sectorHistogramCommand); commandList.push(clearCommands['aoBufferB']); commandList.push(sectorGatheringCommand); + commandList.push(clearCommands['edgeCullingPass']); + commandList.push(edgeCullingCommand); commandList.push(clearCommands['densityEstimationPass']); commandList.push(densityEstimationCommand); diff --git a/Source/Shaders/PostProcessFilters/DensityEstimationPass.glsl b/Source/Shaders/PostProcessFilters/DensityEstimationPass.glsl index 93493b16b778..edbf26da2e0e 100644 --- a/Source/Shaders/PostProcessFilters/DensityEstimationPass.glsl +++ b/Source/Shaders/PostProcessFilters/DensityEstimationPass.glsl @@ -7,6 +7,8 @@ varying float centerPos; uniform sampler2D pointCloud_depthTexture; +uniform sampler2D pointCloud_edgeCullingTexture; + uniform float neighborhoodVectorSize; uniform float maxAbsRatio; @@ -14,6 +16,10 @@ void main() { vec2 v_textureCoordinates = gl_FragCoord.xy / czm_viewport.zw; float depth = czm_unpackDepth(texture2D(pointCloud_depthTexture, v_textureCoordinates)); + vec4 rawEdgeCull = texture2D(pointCloud_edgeCullingTexture, + v_textureCoordinates); + vec2 neighborhoodAccum = rawEdgeCull.xy; + vec2 absNeighborhoodAccum = rawEdgeCull.zw; ivec2 pos = ivec2(int(gl_FragCoord.x), int(gl_FragCoord.y)); int densityValue = 0; @@ -26,6 +32,16 @@ void main() { densityValue = 1; } - gl_FragData[0] = - vec4(float(densityValue) / densityScaleFactor, 0.0, 0.0, 0.0); + float absNeighborhoodAccumLength = length(absNeighborhoodAccum); + float absRatio = 0.0; + if (absNeighborhoodAccumLength > EPS) { + absRatio = length(neighborhoodAccum) / absNeighborhoodAccumLength; + } + if (!(length(neighborhoodAccum) > neighborhoodVectorSize && + absRatio > maxAbsRatio)) { + gl_FragData[0] = vec4(float(densityValue) / densityScaleFactor, + 0.0, 0.0, 0.0); + } else { + gl_FragData[0] = vec4(0.0); + } } diff --git a/Source/Shaders/PostProcessFilters/EdgeCullingPass.glsl b/Source/Shaders/PostProcessFilters/EdgeCullingPass.glsl new file mode 100644 index 000000000000..f0e7f8a4a695 --- /dev/null +++ b/Source/Shaders/PostProcessFilters/EdgeCullingPass.glsl @@ -0,0 +1,22 @@ +#extension GL_EXT_draw_buffers : enable + +#define EPS 1e-8 + +#define densityScaleFactor 10.0 + +varying float centerPos; + +uniform sampler2D pointCloud_depthTexture; + +void main() { + ivec2 pos = ivec2(int(gl_FragCoord.x), int(gl_FragCoord.y)); + ivec2 centerValue = ivec2(int(mod(centerPos, czm_viewport.z)), + int(centerPos) / int(czm_viewport.z)); + + vec2 diff = vec2(pos - centerValue); + + vec4 result; + result.xy = diff; + result.zw = abs(diff); + gl_FragData[0] = result; +} From 2fa6bcd86e5cca9f12a38b5569791e715c7a4c50 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Tue, 25 Jul 2017 15:15:56 -0400 Subject: [PATCH 147/240] Mostly fixes resizing crash --- Source/Scene/PointCloudPostProcessor.js | 33 +++++++++++++++++++++---- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 9b3d9bcdb8ca..d52fe298e6fb 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -191,6 +191,7 @@ define([ function destroyFramebuffers(processor) { processor._depthTextures[0].destroy(); processor._depthTextures[1].destroy(); + processor._ecTexture.destroy(); processor._sectorTextures[0].destroy(); processor._sectorTextures[1].destroy(); processor._sectorLUTTexture.destroy(); @@ -201,7 +202,6 @@ define([ processor._dirty.destroy(); processor._colorTextures[0].destroy(); processor._colorTextures[1].destroy(); - processor._ecTexture.destroy(); var framebuffers = processor._framebuffers; for (var name in framebuffers) { if (framebuffers.hasOwnProperty(name)) { @@ -209,9 +209,26 @@ define([ } } - processor._depthTextures = undefined; - processor._colorTextures = undefined; processor._framebuffers = undefined; + processor._colorTextures = undefined; + processor._ecTexture = undefined; + processor._depthTextures = undefined; + processor._sectorTextures = undefined; + processor._densityTexture = undefined; + processor._edgeCullingTexture = undefined; + processor._sectorLUTTexture = undefined; + processor._aoTextures = undefined; + processor._dirty = undefined; + processor._densityEstimationCommand = undefined; + processor._edgeCullingCommand = undefined; + processor._sectorHistogramCommand = undefined; + processor._sectorGatheringCommand = undefined; + processor._regionGrowingCommands = undefined; + processor._stencilCommands = undefined; + processor._aoCommand = undefined; + processor._copyCommands = undefined; + processor._blendCommand = undefined; + processor._clearCommands = undefined; } function generateSectorLUT(processor) { @@ -1055,6 +1072,7 @@ define([ var colorTextures = processor._colorTextures; var regionGrowingCommands = processor._regionGrowingCommands; var stencilCommands = processor._stencilCommands; + var nowDirty = false; var resized = defined(colorTextures) && ((colorTextures[0].width !== screenWidth) || (colorTextures[0].height !== screenHeight)); @@ -1062,6 +1080,7 @@ define([ if (!defined(colorTextures)) { createFramebuffers(processor, context); createPointArray(processor, context); + nowDirty = true; } if (!defined(regionGrowingCommands) || !defined(stencilCommands) || dirty) { @@ -1069,14 +1088,18 @@ define([ } if (resized) { + console.log('Resized!'); destroyFramebuffers(processor); createFramebuffers(processor, context); + createPointArray(processor, context); createCommands(processor, context); + nowDirty = true; } + return nowDirty; } function processingSupported(context) { - return context.depthTexture; + return context.depthTexture && context.blendMinmax; } function getECShaderProgram(context, shaderProgram) { @@ -1169,7 +1192,7 @@ define([ return; } - createResources(this, frameState.context, dirty); + dirty |= createResources(this, frameState.context, dirty); // Render point cloud commands into an offscreen FBO. var i; From e4bfc909c065aed215e4e1c029d9cd39ebe33c97 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Tue, 25 Jul 2017 15:36:04 -0400 Subject: [PATCH 148/240] Removes "resized" debug statement --- Source/Scene/PointCloudPostProcessor.js | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index d52fe298e6fb..7756bf13e961 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -1088,7 +1088,6 @@ define([ } if (resized) { - console.log('Resized!'); destroyFramebuffers(processor); createFramebuffers(processor, context); createPointArray(processor, context); From 3db07b2ce31ee3f83252157d3a6159bd155f6a0a Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Tue, 25 Jul 2017 15:40:45 -0400 Subject: [PATCH 149/240] Sets the region growing range parameter to 0.0 by default --- Source/Scene/Cesium3DTileset.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Scene/Cesium3DTileset.js b/Source/Scene/Cesium3DTileset.js index 1ad87c4e4f1c..6ca77f150388 100644 --- a/Source/Scene/Cesium3DTileset.js +++ b/Source/Scene/Cesium3DTileset.js @@ -628,9 +628,9 @@ define([ this.pointCloudPostProcessorOptions = { enabled : false, occlusionAngle : 0.1, - rangeParameter : 0.001, + rangeParameter : 0.0, neighborhoodHalfWidth : 4, - numRegionGrowingPasses : 4, + numRegionGrowingPasses : 5, densityHalfWidth : 4, neighborhoodVectorSize : 10.0, maxAbsRatio : 0.9, From 68e24d966566ce4dfef00a7b709871d3a4729c0e Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 26 Jul 2017 14:17:59 -0400 Subject: [PATCH 150/240] PointCloudPostProcessor now stores all the draw commands in a dictionary --- Source/Scene/PointCloudPostProcessor.js | 53 ++++++++++++++----------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 7756bf13e961..c502e94ca8df 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -86,7 +86,8 @@ define([ this._sectorLUTTexture = undefined; this._aoTextures = undefined; this._dirty = undefined; - this._densityEstimationCommand = undefined; + this._drawCommands = undefined; + /*this._densityEstimationCommand = undefined; this._edgeCullingCommand = undefined; this._sectorHistogramCommand = undefined; this._sectorGatheringCommand = undefined; @@ -94,7 +95,7 @@ define([ this._stencilCommands = undefined; this._aoCommand = undefined; this._copyCommands = undefined; - this._blendCommand = undefined; + this._blendCommand = undefined;*/ this._clearCommands = undefined; this.occlusionAngle = options.occlusionAngle; @@ -219,7 +220,8 @@ define([ processor._sectorLUTTexture = undefined; processor._aoTextures = undefined; processor._dirty = undefined; - processor._densityEstimationCommand = undefined; + processor._drawCommands = undefined; + /*processor._densityEstimationCommand = undefined; processor._edgeCullingCommand = undefined; processor._sectorHistogramCommand = undefined; processor._sectorGatheringCommand = undefined; @@ -228,7 +230,7 @@ define([ processor._aoCommand = undefined; processor._copyCommands = undefined; processor._blendCommand = undefined; - processor._clearCommands = undefined; + processor._clearCommands = undefined;*/ } function generateSectorLUT(processor) { @@ -914,16 +916,17 @@ define([ } function createCommands(processor, context) { + processor._drawCommands = {}; var numRegionGrowingPasses = processor.numRegionGrowingPasses; var regionGrowingCommands = new Array(numRegionGrowingPasses); var stencilCommands = new Array(numRegionGrowingPasses); var copyCommands = new Array(2); var i; - processor._edgeCullingCommand = edgeCullingStage(processor, context); - processor._densityEstimationCommand = densityEstimationStage(processor, context); - processor._sectorHistogramCommand = sectorHistogramStage(processor, context); - processor._sectorGatheringCommand = sectorGatheringStage(processor, context); + processor._drawCommands.edgeCullingCommand = edgeCullingStage(processor, context); + processor._drawCommands.densityEstimationCommand = densityEstimationStage(processor, context); + processor._drawCommands.sectorHistogramCommand = sectorHistogramStage(processor, context); + processor._drawCommands.sectorGatheringCommand = sectorGatheringStage(processor, context); for (i = 0; i < numRegionGrowingPasses; i++) { regionGrowingCommands[i] = regionGrowingStage(processor, context, i); @@ -1058,20 +1061,20 @@ define([ } } - processor._regionGrowingCommands = regionGrowingCommands; - processor._stencilCommands = stencilCommands; - processor._blendCommand = blendCommand; + processor._drawCommands.regionGrowingCommands = regionGrowingCommands; + processor._drawCommands.stencilCommands = stencilCommands; + processor._drawCommands.blendCommand = blendCommand; + processor._drawCommands.copyCommands = copyCommands; + processor._drawCommands.aoCommand = aoCommand; processor._clearCommands = clearCommands; - processor._copyCommands = copyCommands; - processor._aoCommand = aoCommand; } function createResources(processor, context, dirty) { var screenWidth = context.drawingBufferWidth; var screenHeight = context.drawingBufferHeight; var colorTextures = processor._colorTextures; - var regionGrowingCommands = processor._regionGrowingCommands; - var stencilCommands = processor._stencilCommands; + var regionGrowingCommands = (defined(processor._drawCommands)) ? processor._drawCommands.regionGrowingCommands : undefined; + var stencilCommands = (defined(processor._drawCommands)) ? processor._drawCommands.stencilCommands : undefined; var nowDirty = false; var resized = defined(colorTextures) && ((colorTextures[0].width !== screenWidth) || @@ -1239,14 +1242,16 @@ define([ } // Apply processing commands - var edgeCullingCommand = this._edgeCullingCommand; - var densityEstimationCommand = this._densityEstimationCommand; - var sectorHistogramCommand = this._sectorHistogramCommand; - var sectorGatheringCommand = this._sectorGatheringCommand; - var regionGrowingCommands = this._regionGrowingCommands; - var copyCommands = this._copyCommands; - var stencilCommands = this._stencilCommands; + var edgeCullingCommand = this._drawCommands.edgeCullingCommand; + var densityEstimationCommand = this._drawCommands.densityEstimationCommand; + var sectorHistogramCommand = this._drawCommands.sectorHistogramCommand; + var sectorGatheringCommand = this._drawCommands.sectorGatheringCommand; + var regionGrowingCommands = this._drawCommands.regionGrowingCommands; + var copyCommands = this._drawCommands.copyCommands; + var stencilCommands = this._drawCommands.stencilCommands; var clearCommands = this._clearCommands; + var blendCommand = this._drawCommands.blendCommand; + var aoCommand = this._drawCommands.aoCommand; var numRegionGrowingCommands = regionGrowingCommands.length; commandList.push(clearCommands['screenSpacePass']); @@ -1274,9 +1279,9 @@ define([ } // Blend final result back into the main FBO - commandList.push(this._blendCommand); + commandList.push(blendCommand); if (this.AOViewEnabled && this.enableAO) { - commandList.push(this._aoCommand); + commandList.push(aoCommand); } commandList.push(clearCommands['prior']); From bd3f598ffc06312b17c1457d187556635560e349 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 26 Jul 2017 14:47:15 -0400 Subject: [PATCH 151/240] Disables the filter by default for now --- .../gallery/3D Tiles Point Cloud Post Processing.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html index 49da9dd99ec3..2d3f73a7ea50 100644 --- a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html +++ b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html @@ -106,7 +106,7 @@ var tileset = scene.primitives.add(new Cesium.Cesium3DTileset({ url : url })); -tileset.pointCloudPostProcessorOptions.enabled = true; +tileset.pointCloudPostProcessorOptions.enabled = false; inspectorViewModel.tileset = tileset; tileset.readyPromise.then(function() { @@ -150,7 +150,7 @@ subscribeParameter('sigmoidDomainOffset'); subscribeParameter('sigmoidSharpness'); -Sandcastle.addToggleButton('Enabled', true, function(checked) { +Sandcastle.addToggleButton('Enabled', false, function(checked) { tileset.pointCloudPostProcessorOptions.enabled = checked; }); From 413947c01d9c88e0e1b38b789a614b41b14dbd67 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 26 Jul 2017 16:05:50 -0400 Subject: [PATCH 152/240] Removes old comments --- Source/Scene/PointCloudPostProcessor.js | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index c502e94ca8df..ce52e0367cd6 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -87,15 +87,6 @@ define([ this._aoTextures = undefined; this._dirty = undefined; this._drawCommands = undefined; - /*this._densityEstimationCommand = undefined; - this._edgeCullingCommand = undefined; - this._sectorHistogramCommand = undefined; - this._sectorGatheringCommand = undefined; - this._regionGrowingCommands = undefined; - this._stencilCommands = undefined; - this._aoCommand = undefined; - this._copyCommands = undefined; - this._blendCommand = undefined;*/ this._clearCommands = undefined; this.occlusionAngle = options.occlusionAngle; @@ -221,16 +212,6 @@ define([ processor._aoTextures = undefined; processor._dirty = undefined; processor._drawCommands = undefined; - /*processor._densityEstimationCommand = undefined; - processor._edgeCullingCommand = undefined; - processor._sectorHistogramCommand = undefined; - processor._sectorGatheringCommand = undefined; - processor._regionGrowingCommands = undefined; - processor._stencilCommands = undefined; - processor._aoCommand = undefined; - processor._copyCommands = undefined; - processor._blendCommand = undefined; - processor._clearCommands = undefined;*/ } function generateSectorLUT(processor) { From 485baae3ba8936b1e67b95a211e56d25859d2607 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Thu, 27 Jul 2017 10:11:51 -0400 Subject: [PATCH 153/240] Cleaner UI for sandcastle --- .../3D Tiles Point Cloud Post Processing.html | 43 +++++++++++++------ 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html index 2d3f73a7ea50..cdbb95a59bb4 100644 --- a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html +++ b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html @@ -25,7 +25,8 @@

Loading...

- + + + + + +
Occlusion Angle @@ -162,17 +163,35 @@ tileset.pointCloudPostProcessorOptions.enableAO = checked; }); -Sandcastle.addToggleButton('Density View', false, function(checked) { - tileset.pointCloudPostProcessorOptions.densityViewEnabled = checked; -}); - -Sandcastle.addToggleButton('Stencil View', false, function(checked) { - tileset.pointCloudPostProcessorOptions.stencilViewEnabled = checked; -}); - -Sandcastle.addToggleButton('AO View', false, function(checked) { - tileset.pointCloudPostProcessorOptions.AOViewEnabled = checked; -}); +Sandcastle.addToolbarMenu([{ + text : 'Color View', + onselect : function() { + tileset.pointCloudPostProcessorOptions.densityViewEnabled = false; + tileset.pointCloudPostProcessorOptions.stencilViewEnabled = false; + tileset.pointCloudPostProcessorOptions.aoViewEnabled = false; + } +}, { + text : 'Density View', + onselect : function() { + tileset.pointCloudPostProcessorOptions.densityViewEnabled = true; + tileset.pointCloudPostProcessorOptions.stencilViewEnabled = false; + tileset.pointCloudPostProcessorOptions.aoViewEnabled = false; + } +}, { + text : 'Stencil View', + onselect : function() { + tileset.pointCloudPostProcessorOptions.densityViewEnabled = false; + tileset.pointCloudPostProcessorOptions.stencilViewEnabled = true; + tileset.pointCloudPostProcessorOptions.aoViewEnabled = false; + } +}, { + text : 'AO View', + onselect : function() { + tileset.pointCloudPostProcessorOptions.densityViewEnabled = false; + tileset.pointCloudPostProcessorOptions.stencilViewEnabled = false; + tileset.pointCloudPostProcessorOptions.aoViewEnabled = true; + } +}]); //Sandcastle_End Sandcastle.finishedLoading(); From f63bd4068aeb01f62c2f72ff4515ac8cefcaafe4 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Thu, 27 Jul 2017 10:15:45 -0400 Subject: [PATCH 154/240] Fixes AO View option --- .../gallery/3D Tiles Point Cloud Post Processing.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html index cdbb95a59bb4..472d702af90d 100644 --- a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html +++ b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html @@ -189,7 +189,7 @@ onselect : function() { tileset.pointCloudPostProcessorOptions.densityViewEnabled = false; tileset.pointCloudPostProcessorOptions.stencilViewEnabled = false; - tileset.pointCloudPostProcessorOptions.aoViewEnabled = true; + tileset.pointCloudPostProcessorOptions.AOViewEnabled = true; } }]); From 467108fc1edf35a5d7296832bc19abc66392f672 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Thu, 27 Jul 2017 13:50:14 -0400 Subject: [PATCH 155/240] Moves PointArrayVS to its own file --- Source/Scene/PointCloudPostProcessor.js | 24 +++---------------- .../PostProcessFilters/PointArrayVS.glsl | 20 ++++++++++++++++ 2 files changed, 23 insertions(+), 21 deletions(-) create mode 100644 Source/Shaders/PostProcessFilters/PointArrayVS.glsl diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index ce52e0367cd6..895e10a4e48a 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -28,6 +28,7 @@ define([ '../Scene/BlendingState', '../Scene/StencilFunction', '../Scene/StencilOperation', + '../Shaders/PostProcessFilters/PointArrayVS', '../Shaders/PostProcessFilters/RegionGrowingPassGL1', '../Shaders/PostProcessFilters/RegionGrowingPassGL2', '../Shaders/PostProcessFilters/SectorHistogramPass', @@ -63,6 +64,7 @@ define([ BlendingState, StencilFunction, StencilOperation, + PointArrayVS, RegionGrowingPassGL1, RegionGrowingPassGL2, SectorHistogramPass, @@ -490,32 +492,12 @@ define([ createPointArray(processor, context); } - var vertexShaderSource = - '#define EPS 1e-6 \n' + - '#define kernelSize 9.0 \n\n' + - 'attribute vec4 position; \n' + - 'varying float centerPos; \n\n' + - 'uniform sampler2D pointCloud_depthTexture; \n\n' + - 'void main() \n' + - '{ \n' + - ' vec2 textureCoordinates = 0.5 * position.xy + vec2(0.5); \n' + - ' ivec2 screenSpaceCoordinates = ivec2(textureCoordinates * czm_viewport.zw); \n' + - ' if (length(texture2D(pointCloud_depthTexture, textureCoordinates)) > EPS) { \n' + - ' gl_Position = position; \n' + - ' gl_PointSize = kernelSize; \n' + - ' centerPos = float(screenSpaceCoordinates.x + screenSpaceCoordinates.y * int(czm_viewport.z)); \n' + - ' } else {\n' + - ' gl_Position = vec4(-10); \n' + - ' centerPos = 0.0; \n' + - ' } \n' + - '} \n'; - var uniformMap = (defined(overrides.uniformMap)) ? overrides.uniformMap : {}; uniformMap.pointCloud_depthTexture = function () { return depthTexture; }; - vertexShaderSource = replaceConstants(vertexShaderSource, 'kernelSize', kernelSize.toFixed(1)); + var vertexShaderSource = replaceConstants(PointArrayVS, 'kernelSize', kernelSize.toFixed(1)); var renderState = overrides.renderState; diff --git a/Source/Shaders/PostProcessFilters/PointArrayVS.glsl b/Source/Shaders/PostProcessFilters/PointArrayVS.glsl new file mode 100644 index 000000000000..1a154612688d --- /dev/null +++ b/Source/Shaders/PostProcessFilters/PointArrayVS.glsl @@ -0,0 +1,20 @@ +#define EPS 1e-6 +#define kernelSize 9.0 +attribute vec4 position; +varying float centerPos; + +uniform sampler2D pointCloud_depthTexture; + +void main() { + vec2 textureCoordinates = 0.5 * position.xy + vec2(0.5); + ivec2 screenSpaceCoordinates = ivec2(textureCoordinates * czm_viewport.zw); + if (length(texture2D(pointCloud_depthTexture, textureCoordinates)) > EPS) { + gl_Position = position; + gl_PointSize = kernelSize; + centerPos = float(screenSpaceCoordinates.x + screenSpaceCoordinates.y * int( + czm_viewport.z)); + } else { + gl_Position = vec4(-10); + centerPos = 0.0; + } +} From b93db5472b98494022f16d7c4eeaff9d6de27512 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Thu, 27 Jul 2017 14:16:55 -0400 Subject: [PATCH 156/240] Starting to implement random point reduction --- Source/Scene/PointCloudPostProcessor.js | 11 ++++++++++ .../PostProcessFilters/PointArrayVS.glsl | 20 +++++++++++++++++-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 895e10a4e48a..fb603ae93b6b 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -484,6 +484,7 @@ define([ kernelSize, useStencil, blendingState, + reductionFactor, fragmentShaderSource, processor, context, @@ -496,9 +497,16 @@ define([ uniformMap.pointCloud_depthTexture = function () { return depthTexture; }; + uniformMap.reductionFactor = function () { + return reductionFactor; + }; var vertexShaderSource = replaceConstants(PointArrayVS, 'kernelSize', kernelSize.toFixed(1)); + if (reductionFactor > 1.0 - 1e-6) { + vertexShaderSource = replaceConstants(vertexShaderSource, 'useReduction', false); + } + var renderState = overrides.renderState; if (!defined(overrides.renderState)) { @@ -566,6 +574,7 @@ define([ neighborhoodSize, true, processor._minBlend, + 1.0, SectorHistogramPass, processor, context, { @@ -637,6 +646,7 @@ define([ processor.densityHalfWidth * 2 + 1, false, processor._minBlend, + 1.0, densityEstimationStr, processor, context, { @@ -663,6 +673,7 @@ define([ processor.densityHalfWidth * 2 + 1, true, processor._addBlend, + 1.0, edgeCullingStr, processor, context, { diff --git a/Source/Shaders/PostProcessFilters/PointArrayVS.glsl b/Source/Shaders/PostProcessFilters/PointArrayVS.glsl index 1a154612688d..5d7f82b5746f 100644 --- a/Source/Shaders/PostProcessFilters/PointArrayVS.glsl +++ b/Source/Shaders/PostProcessFilters/PointArrayVS.glsl @@ -1,16 +1,32 @@ #define EPS 1e-6 #define kernelSize 9.0 +#define useReduction + attribute vec4 position; varying float centerPos; uniform sampler2D pointCloud_depthTexture; +uniform float reductionFactor; + +// Adapted from https://thebookofshaders.com/10/ +float random(in vec3 st) { + return fract(sin(dot(st.xyz, vec3(17.537, 78.233, 14.206))) * 43758.5453123); +} void main() { vec2 textureCoordinates = 0.5 * position.xy + vec2(0.5); ivec2 screenSpaceCoordinates = ivec2(textureCoordinates * czm_viewport.zw); - if (length(texture2D(pointCloud_depthTexture, textureCoordinates)) > EPS) { + vec4 pseudoDepth = texture2D(pointCloud_depthTexture, textureCoordinates); + if (length(pseudoDepth) > EPS) { gl_Position = position; - gl_PointSize = kernelSize; + float pointSize = kernelSize; +#ifdef useReduction + float reductionScalar = random(pseudoDepth.xyz); + if (reductionScalar > reductionFactor) { + pointSize *= reductionScalar; + } +#endif + gl_PointSize = pointSize; centerPos = float(screenSpaceCoordinates.x + screenSpaceCoordinates.y * int( czm_viewport.z)); } else { From 1f123252fefae077810d33a5c6cd3bbde6f9359c Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Thu, 27 Jul 2017 14:25:37 -0400 Subject: [PATCH 157/240] Parameters now attached to UI --- .../gallery/3D Tiles Point Cloud Post Processing.html | 11 ++++++++++- Source/Scene/Cesium3DTileset.js | 3 ++- Source/Scene/PointCloudPostProcessor.js | 7 +++++-- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html index 472d702af90d..78662ae69e51 100644 --- a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html +++ b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html @@ -89,6 +89,13 @@
Random Reduction Factor + + +
@@ -125,7 +132,8 @@ maxAbsRatio : tileset.pointCloudPostProcessorOptions.maxAbsRatio, pointAttenuationMultiplier : tileset.pointCloudPostProcessorOptions.pointAttenuationMultiplier, sigmoidDomainOffset : tileset.pointCloudPostProcessorOptions.sigmoidDomainOffset, - sigmoidSharpness : tileset.pointCloudPostProcessorOptions.sigmoidSharpness + sigmoidSharpness : tileset.pointCloudPostProcessorOptions.sigmoidSharpness, + randomReductionFactor : tileset.pointCloudPostProcessorOptions.randomReductionFactor }; Cesium.knockout.track(viewModel); @@ -150,6 +158,7 @@ subscribeParameter('pointAttenuationMultiplier'); subscribeParameter('sigmoidDomainOffset'); subscribeParameter('sigmoidSharpness'); +subscribeParameter('randomReductionFactor'); Sandcastle.addToggleButton('Enabled', false, function(checked) { tileset.pointCloudPostProcessorOptions.enabled = checked; diff --git a/Source/Scene/Cesium3DTileset.js b/Source/Scene/Cesium3DTileset.js index 6ca77f150388..6bf03c8bd78b 100644 --- a/Source/Scene/Cesium3DTileset.js +++ b/Source/Scene/Cesium3DTileset.js @@ -641,7 +641,8 @@ define([ enableAO : true, AOViewEnabled : false, sigmoidSharpness : 0.2, - sigmoidDomainOffset : 0.2 + sigmoidDomainOffset : 0.2, + randomReductionFactor : 1.0 }; this._pointCloudPostProcessor = new PointCloudPostProcessor(this.pointCloudPostProcessorOptions); diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index fb603ae93b6b..1cfacd179e0d 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -106,6 +106,7 @@ define([ this.AOViewEnabled = options.AOViewEnabled; this.sigmoidDomainOffset = options.sigmoidDomainOffset; this.sigmoidSharpness = options.sigmoidSharpness; + this.randomReductionFactor = options.randomReductionFactor; this._pointArray = undefined; @@ -574,7 +575,7 @@ define([ neighborhoodSize, true, processor._minBlend, - 1.0, + processor.randomReductionFactor, SectorHistogramPass, processor, context, { @@ -1145,7 +1146,8 @@ define([ tileset.pointCloudPostProcessorOptions.enableAO !== this.enableAO || tileset.pointCloudPostProcessorOptions.AOViewEnabled !== this.AOViewEnabled || tileset.pointCloudPostProcessorOptions.sigmoidDomainOffset !== this.sigmoidDomainOffset || - tileset.pointCloudPostProcessorOptions.sigmoidSharpness !== this.sigmoidSharpness) { + tileset.pointCloudPostProcessorOptions.sigmoidSharpness !== this.sigmoidSharpness || + tileset.pointCloudPostProcessorOptions.randomReductionFactor !== this.randomReductionFactor) { this.occlusionAngle = tileset.pointCloudPostProcessorOptions.occlusionAngle; this.rangeParameter = tileset.pointCloudPostProcessorOptions.rangeParameter; this.neighborhoodHalfWidth = tileset.pointCloudPostProcessorOptions.neighborhoodHalfWidth; @@ -1161,6 +1163,7 @@ define([ this.AOViewEnabled = tileset.pointCloudPostProcessorOptions.AOViewEnabled; this.sigmoidDomainOffset = tileset.pointCloudPostProcessorOptions.sigmoidDomainOffset; this.sigmoidSharpness = tileset.pointCloudPostProcessorOptions.sigmoidSharpness; + this.randomReductionFactor = tileset.pointCloudPostProcessorOptions.randomReductionFactor; dirty = true; } From a122a298a286d96f33822c10640c269f91562883 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Thu, 27 Jul 2017 15:07:06 -0400 Subject: [PATCH 158/240] Point arrays scale more aggressively now --- Source/Shaders/PostProcessFilters/PointArrayVS.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Shaders/PostProcessFilters/PointArrayVS.glsl b/Source/Shaders/PostProcessFilters/PointArrayVS.glsl index 5d7f82b5746f..1a518421521e 100644 --- a/Source/Shaders/PostProcessFilters/PointArrayVS.glsl +++ b/Source/Shaders/PostProcessFilters/PointArrayVS.glsl @@ -23,7 +23,7 @@ void main() { #ifdef useReduction float reductionScalar = random(pseudoDepth.xyz); if (reductionScalar > reductionFactor) { - pointSize *= reductionScalar; + pointSize *= reductionScalar * reductionFactor; } #endif gl_PointSize = pointSize; From 658a5b464341f3cb17c53f4034a596a8ce1d5bb8 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Thu, 27 Jul 2017 15:24:00 -0400 Subject: [PATCH 159/240] Adds random reduction for other point array commands --- Source/Scene/PointCloudPostProcessor.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 1cfacd179e0d..37f9153d8dca 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -647,7 +647,7 @@ define([ processor.densityHalfWidth * 2 + 1, false, processor._minBlend, - 1.0, + processor.randomReductionFactor, densityEstimationStr, processor, context, { @@ -674,7 +674,7 @@ define([ processor.densityHalfWidth * 2 + 1, true, processor._addBlend, - 1.0, + processor.randomReductionFactor, edgeCullingStr, processor, context, { From 295308707c5f842396d44aae89d519b0bea899d2 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Thu, 27 Jul 2017 17:23:54 -0400 Subject: [PATCH 160/240] Typo fix --- .../gallery/3D Tiles Point Cloud Post Processing.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html index 78662ae69e51..2c348579b094 100644 --- a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html +++ b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html @@ -177,21 +177,21 @@ onselect : function() { tileset.pointCloudPostProcessorOptions.densityViewEnabled = false; tileset.pointCloudPostProcessorOptions.stencilViewEnabled = false; - tileset.pointCloudPostProcessorOptions.aoViewEnabled = false; + tileset.pointCloudPostProcessorOptions.AOViewEnabled = false; } }, { text : 'Density View', onselect : function() { tileset.pointCloudPostProcessorOptions.densityViewEnabled = true; tileset.pointCloudPostProcessorOptions.stencilViewEnabled = false; - tileset.pointCloudPostProcessorOptions.aoViewEnabled = false; + tileset.pointCloudPostProcessorOptions.AOViewEnabled = false; } }, { text : 'Stencil View', onselect : function() { tileset.pointCloudPostProcessorOptions.densityViewEnabled = false; tileset.pointCloudPostProcessorOptions.stencilViewEnabled = true; - tileset.pointCloudPostProcessorOptions.aoViewEnabled = false; + tileset.pointCloudPostProcessorOptions.AOViewEnabled = false; } }, { text : 'AO View', From 2f7fab52c4b9bc5e961448fbdedc4d362d9d5d5b Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Fri, 28 Jul 2017 12:06:10 -0400 Subject: [PATCH 161/240] Now using the old point occlusion code --- Source/Scene/PointCloudPostProcessor.js | 67 ++- .../PointOcclusionPassGL1.glsl | 389 ++++++++++++++++++ .../PointOcclusionPassGL2.glsl | 354 ++++++++++++++++ 3 files changed, 807 insertions(+), 3 deletions(-) create mode 100644 Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl create mode 100644 Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 37f9153d8dca..5771a2a14762 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -29,6 +29,8 @@ define([ '../Scene/StencilFunction', '../Scene/StencilOperation', '../Shaders/PostProcessFilters/PointArrayVS', + '../Shaders/PostProcessFilters/PointOcclusionPassGL1', + '../Shaders/PostProcessFilters/PointOcclusionPassGL2', '../Shaders/PostProcessFilters/RegionGrowingPassGL1', '../Shaders/PostProcessFilters/RegionGrowingPassGL2', '../Shaders/PostProcessFilters/SectorHistogramPass', @@ -65,6 +67,8 @@ define([ StencilFunction, StencilOperation, PointArrayVS, + PointOcclusionPassGL1, + PointOcclusionPassGL2, RegionGrowingPassGL1, RegionGrowingPassGL2, SectorHistogramPass, @@ -559,6 +563,60 @@ define([ return sourceStr.replace(new RegExp(r, 'g'), '#define ' + constantName + ' ' + replacement); } + function pointOcclusionStage(processor, context) { + var uniformMap = { + sectorLUT : function() { + return processor._sectorLUTTexture; + }, + pointCloud_ECTexture : function() { + return processor._ecTexture; + }, + occlusionAngle : function() { + return processor.occlusionAngle; + }, + ONE : function() { + return 1.0; + } + }; + + var pointOcclusionStr = replaceConstants( + (context.webgl2) ? PointOcclusionPassGL2 : PointOcclusionPassGL1, + 'neighborhoodHalfWidth', + processor.neighborhoodHalfWidth + ); + + pointOcclusionStr = replaceConstants( + pointOcclusionStr, + 'useTriangle', + processor.useTriangle + ); + + var func = StencilFunction.EQUAL; + var op = { + fail : StencilOperation.KEEP, + zFail : StencilOperation.KEEP, + zPass : StencilOperation.KEEP + }; + + return context.createViewportQuadCommand(pointOcclusionStr, { + uniformMap : uniformMap, + framebuffer : processor._framebuffers.screenSpacePass, + renderState : RenderState.fromCache({ + stencilTest : { + enabled : true, + reference : 0, + mask : 1, + frontFunction : func, + backFunction : func, + frontOperation : op, + backOperation : op + } + }), + pass : Pass.CESIUM_3D_TILE, + owner : processor + }); + } + function sectorHistogramStage(processor, context) { var neighborhoodSize = processor.neighborhoodHalfWidth * 2 + 1; var uniformMap = { @@ -900,6 +958,7 @@ define([ var i; processor._drawCommands.edgeCullingCommand = edgeCullingStage(processor, context); processor._drawCommands.densityEstimationCommand = densityEstimationStage(processor, context); + processor._drawCommands.pointOcclusionCommand = pointOcclusionStage(processor, context); processor._drawCommands.sectorHistogramCommand = sectorHistogramStage(processor, context); processor._drawCommands.sectorGatheringCommand = sectorGatheringStage(processor, context); @@ -1221,6 +1280,7 @@ define([ // Apply processing commands var edgeCullingCommand = this._drawCommands.edgeCullingCommand; var densityEstimationCommand = this._drawCommands.densityEstimationCommand; + var pointOcclusionCommand = this._drawCommands.pointOcclusionCommand; var sectorHistogramCommand = this._drawCommands.sectorHistogramCommand; var sectorGatheringCommand = this._drawCommands.sectorGatheringCommand; var regionGrowingCommands = this._drawCommands.regionGrowingCommands; @@ -1232,10 +1292,11 @@ define([ var numRegionGrowingCommands = regionGrowingCommands.length; commandList.push(clearCommands['screenSpacePass']); - commandList.push(clearCommands['sectorHistogramPass']); - commandList.push(sectorHistogramCommand); + commandList.push(pointOcclusionCommand); + //commandList.push(clearCommands['sectorHistogramPass']); + //commandList.push(sectorHistogramCommand); commandList.push(clearCommands['aoBufferB']); - commandList.push(sectorGatheringCommand); + //commandList.push(sectorGatheringCommand); commandList.push(clearCommands['edgeCullingPass']); commandList.push(edgeCullingCommand); commandList.push(clearCommands['densityEstimationPass']); diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl new file mode 100644 index 000000000000..755a4009382b --- /dev/null +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl @@ -0,0 +1,389 @@ +#extension GL_EXT_frag_depth : enable + +#define TAU 6.28318530718 +#define PI 3.14159265359 +#define PI_4 0.785398163 +#define C0 1.57073 +#define C1 -0.212053 +#define C2 0.0740935 +#define C3 -0.0186166 +#define EPS 1e-6 +#define neighborhoodHalfWidth 4 // TUNABLE PARAMETER -- half-width of point-occlusion neighborhood +#define numSectors 8 + +#define trianglePeriod 1e-5 +#define useTriangle + +uniform float ONE; + +uniform sampler2D pointCloud_ECTexture; +uniform float occlusionAngle; +uniform sampler2D sectorLUT; +varying vec2 v_textureCoordinates; + +// TODO: Include Uber copyright + +vec2 split(float a) { + const float SPLIT = 4097.0; + float t = a * SPLIT; + float a_hi = t * ONE - (t - a); + float a_lo = a * ONE - a_hi; + return vec2(a_hi, a_lo); +} + +vec2 twoSub(float a, float b) { + float s = (a - b); + float v = (s * ONE - a) * ONE; + float err = (a - (s - v) * ONE) * ONE * ONE * ONE - (b + v); + return vec2(s, err); +} + +vec2 twoSum(float a, float b) { + float s = (a + b); + float v = (s * ONE - a) * ONE; + float err = (a - (s - v) * ONE) * ONE * ONE * ONE + (b - v); + return vec2(s, err); +} + +vec2 twoSqr(float a) { + float prod = a * a; + vec2 a_fp64 = split(a); + float err = ((a_fp64.x * a_fp64.x - prod) * ONE + 2.0 * a_fp64.x * + a_fp64.y * ONE * ONE) + a_fp64.y * a_fp64.y * ONE * ONE * ONE; + return vec2(prod, err); +} + +vec2 twoProd(float a, float b) { + float prod = a * b; + vec2 a_fp64 = split(a); + vec2 b_fp64 = split(b); + float err = ((a_fp64.x * b_fp64.x - prod) + a_fp64.x * b_fp64.y + + a_fp64.y * b_fp64.x) + a_fp64.y * b_fp64.y; + return vec2(prod, err); +} + +vec2 quickTwoSum(float a, float b) { + float sum = (a + b) * ONE; + float err = b - (sum - a) * ONE; + return vec2(sum, err); +} + +vec2 sumFP64(vec2 a, vec2 b) { + vec2 s, t; + s = twoSum(a.x, b.x); + t = twoSum(a.y, b.y); + s.y += t.x; + s = quickTwoSum(s.x, s.y); + s.y += t.y; + s = quickTwoSum(s.x, s.y); + return s; +} + +vec2 subFP64(vec2 a, vec2 b) { + vec2 s, t; + s = twoSub(a.x, b.x); + t = twoSub(a.y, b.y); + s.y += t.x; + s = quickTwoSum(s.x, s.y); + s.y += t.y; + s = quickTwoSum(s.x, s.y); + return s; +} + +vec2 mulFP64(vec2 a, vec2 b) { + vec2 prod = twoProd(a.x, b.x); + // y component is for the error + prod.y += a.x * b.y; + prod.y += a.y * b.x; + prod = quickTwoSum(prod.x, prod.y); + return prod; +} + +vec2 divFP64(in vec2 a, in vec2 b) { + float xn = 1.0 / b.x; + vec2 yn = a * xn; + float diff = (subFP64(a, mulFP64(b, yn))).x; + vec2 prod = twoProd(xn, diff); + return sumFP64(yn, prod); +} + +vec2 sqrtFP64(in vec2 a) { + if (a.x == 0.0 && a.y == 0.0) return vec2(0.0, 0.0); + if (a.x < 0.0) return vec2(0.0 / 0.0, 0.0 / 0.0); + float x = 1.0 / sqrt(a.x); + float yn = a.x * x; + vec2 yn_sqr = twoSqr(yn) * ONE; + float diff = subFP64(a, yn_sqr).x; + vec2 prod = twoProd(x * 0.5, diff); + return sumFP64(vec2(yn, 0.0), prod); +} + +vec2 lengthFP64(in vec3 vec) { + vec2 highPrecisionX = split(vec.x); + vec2 highPrecisionY = split(vec.y); + vec2 highPrecisionZ = split(vec.z); + vec2 highPrecision = + sqrtFP64(sumFP64(sumFP64( + mulFP64(highPrecisionX, highPrecisionX), + mulFP64(highPrecisionY, highPrecisionY)), + mulFP64(highPrecisionZ, highPrecisionZ))); + return highPrecision; +} + +float triangle(in float x, in float period) { + return abs(mod(x, period) / period - 0.5) + EPS; +} + +float triangleFP64(in vec2 x, in float period) { + float lowPrecision = x.x + x.y; + vec2 floorTerm = split(floor(lowPrecision / period)); + vec2 periodHighPrecision = split(period); + vec2 term2 = mulFP64(periodHighPrecision, floorTerm); + vec2 moduloTerm = subFP64(x, term2); + vec2 normalized = divFP64(moduloTerm, periodHighPrecision); + normalized = subFP64(normalized, split(0.5)); + return abs(normalized.x + normalized.y) + EPS; +} + +float acosFast(in float inX) { + float x = abs(inX); + float res = ((C3 * x + C2) * x + C1) * x + C0; // p(x) + res *= sqrt(1.0 - x); + + return (inX >= 0.0) ? res : PI - res; +} + +void modifySectorHistogram(in int index, + in float value, + inout vec4 shFirst, + inout vec4 shSecond) { + if (index < 4) { + if (index < 2) { + if (index == 0) { + shFirst.x = value; + } else { + shFirst.y = value; + } + } else { + if (index == 2) { + shFirst.z = value; + } else { + shFirst.w = value; + } + } + } else { + if (index < 6) { + if (index == 4) { + shSecond.x = value; + } else { + shSecond.y = value; + } + } else { + if (index == 6) { + shSecond.z = value; + } else { + shSecond.w = value; + } + } + } +} + +float readSectorHistogram(in int index, + in vec4 shFirst, + in vec4 shSecond) { + if (index < 4) { + if (index < 2) { + if (index == 0) { + return shFirst.x; + } else { + return shFirst.y; + } + } else { + if (index == 2) { + return shFirst.z; + } else { + return shFirst.w; + } + } + } else { + if (index < 6) { + if (index == 4) { + return shSecond.x; + } else { + return shSecond.y; + } + } else { + if (index == 6) { + return shSecond.z; + } else { + return shSecond.w; + } + } + } +} + +ivec2 readSectors(in ivec2 sectorPosition) { + vec2 texCoordinate = vec2(sectorPosition + ivec2(neighborhoodHalfWidth)) / + float(neighborhoodHalfWidth * 2); + vec2 unscaled = texture2D(sectorLUT, texCoordinate).rg; + return ivec2(unscaled * float(numSectors)); +} + +void main() { + float near = czm_currentFrustum.x; + float far = czm_currentFrustum.y; + ivec2 pos = ivec2(int(gl_FragCoord.x), int(gl_FragCoord.y)); + + // The position of this pixel in 3D (i.e the position of the point) + vec3 centerPosition = texture2D(pointCloud_ECTexture, v_textureCoordinates).xyz; + + // If the EC of this pixel is zero, that means that it's not a valid + // pixel. We don't care about reprojecting it. + if (length(centerPosition) == 0.) + discard; + + // We split our region of interest (the point of interest and its + // neighbors) + // into sectors. For the purposes of this shader, we have eight + // sectors. + // + // Each entry of sector_histogram contains the current best horizon + // pixel angle + ivec2 halfNeighborhood = ivec2(neighborhoodHalfWidth / 2, + neighborhoodHalfWidth / 2); + // Upper left corner of the neighborhood + ivec2 upperLeftCorner = pos - halfNeighborhood; + // Lower right corner of the neighborhood + ivec2 lowerRightCorner = pos + halfNeighborhood; + + // The widest the cone can be is 90 degrees + float maxAngle = PI / 2.0; + + vec4 shFirst = vec4(maxAngle); + vec4 shSecond = vec4(maxAngle); + + // Right now this is obvious because everything happens in eye space, + // but this kind of statement is nice for a reference implementation + vec3 viewer = vec3(0.0); + + for (int i = -neighborhoodHalfWidth; i <= neighborhoodHalfWidth; i++) { + for (int j = -neighborhoodHalfWidth; j <= neighborhoodHalfWidth; j++) { + // d is the relative offset from the horizon pixel to the center pixel + // in 2D + ivec2 d = ivec2(i, j); + ivec2 pI = pos + d; + + // We now calculate the actual 3D position of the horizon pixel (the horizon point) + vec3 neighborPosition = texture2D(pointCloud_ECTexture, + vec2(pI) / czm_viewport.zw).xyz; + + // If our horizon pixel doesn't exist, ignore it and move on + if (length(neighborPosition) < EPS || pI == pos) { + continue; + } + + // sectors contains both possible sectors that the + // neighbor pixel could be in + //ivec2 sectors = collapseSectors(getSectors(vec2(d))); + ivec2 sectors = readSectors(d); + + // This is the offset of the horizon point from the center in 3D + // (a 3D analog of d) + vec3 c = neighborPosition - centerPosition; + + // Now we calculate the dot product between the vector + // from the viewer to the center and the vector to the horizon pixel. + // We normalize both vectors first because we only care about their relative + // directions + // TODO: Redo the math and figure out whether the result should be negated or not + float dotProduct = dot(normalize(viewer - centerPosition), + normalize(c)); + + // We calculate the angle that this horizon pixel would make + // in the cone. The dot product is be equal to + // |vec_1| * |vec_2| * cos(angle_between), and in this case, + // the magnitude of both vectors is 1 because they are both + // normalized. + float angle = acosFast(dotProduct); + + // This horizon point is behind the current point. That means that it can't + // occlude the current point. So we ignore it and move on. + if (angle > maxAngle || angle <= 0.0) + continue; + // If we've found a horizon pixel, store it in the histogram + if (readSectorHistogram(sectors.x, shFirst, shSecond) > angle) { + modifySectorHistogram(sectors.x, angle, shFirst, shSecond); + } + if (readSectorHistogram(sectors.y, shFirst, shSecond) > angle) { + modifySectorHistogram(sectors.y, angle, shFirst, shSecond); + } + } + } + + float accumulator = 0.0; + for (int i = 0; i < numSectors; i++) { + float angle = readSectorHistogram(i, shFirst, shSecond); + // If the z component is less than zero, + // that means that there is no valid horizon pixel + if (angle <= 0.0 || angle > maxAngle) + angle = maxAngle; + accumulator += angle; + } + + // The solid angle is too small, so we occlude this point + if (accumulator < (2.0 * PI) * (1.0 - occlusionAngle)) { + gl_FragData[0] = vec4(0.0); + } else { + // Write out the distance of the point + // + // We use the distance of the point rather than + // the linearized depth. This is because we want + // to encode as much information about position disparities + // between points as we can, and the z-values of + // neighboring points are usually very similar. + // On the other hand, the x-values and y-values are + // usually fairly different. +#ifdef useTriangle + // We can get even more accuracy by passing the 64-bit + // distance into a triangle wave function that + // uses 64-bit primitives internally. The region + // growing pass only cares about deltas between + // different pixels, so we just have to ensure that + // the period of triangle function is greater than that + // of the largest possible delta can arise between + // different points. + // + // The triangle function is C0 continuous, which avoids + // artifacts from discontinuities. That said, I have noticed + // some inexplicable artifacts occasionally, so please + // disable this optimization if that becomes an issue. + // + // It's important that the period of the triangle function + // is at least two orders of magnitude greater than + // the average depth delta that we are likely to come + // across. The triangle function works because we have + // some assumption of locality in the depth domain. + // Massive deltas break that locality -- but that's + // actually not an issue. Deltas that are larger than + // the period function will be "wrapped around", and deltas + // that are much larger than the period function may be + // "wrapped around" many times. A similar process occurs + // in many random number generators. The resulting delta + // is usually at least an order of magnitude greater than + // the average delta, so it won't even be considered in + // the region growing pass. + vec2 hpl = lengthFP64(centerPosition); + float triangleResult = triangleFP64(hpl, trianglePeriod); + gl_FragData[0] = czm_packDepth(triangleResult); +#else + vec2 lengthOfFrustum = subFP64(split(czm_clampedFrustum.y), + split(czm_clampedFrustum.x)); + vec2 frustumStart = split(czm_clampedFrustum.x); + vec2 centerPositionLength = lengthFP64(centerPosition); + vec2 normalizedDepthFP64 = sumFP64(divFP64(centerPositionLength, + lengthOfFrustum), + frustumStart); + gl_FragData[0] = czm_packDepth(normalizedDepthFP64.x + normalizedDepthFP64.y); +#endif + } +} diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl new file mode 100644 index 000000000000..2067d8e40695 --- /dev/null +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl @@ -0,0 +1,354 @@ +#version 300 es + +#define TAU 6.28318530718 +#define PI 3.14159265359 +#define PI_4 0.785398163 +#define C0 1.57073 +#define C1 -0.212053 +#define C2 0.0740935 +#define C3 -0.0186166 +#define EPS 1e-6 +#define neighborhoodHalfWidth 4 // TUNABLE PARAMETER -- half-width of point-occlusion neighborhood +#define neighborhoodSize 9 +#define numSectors 8 + +#define trianglePeriod 1e-2 +#define useTriangle + +uniform float ONE; + +uniform sampler2D pointCloud_ECTexture; +uniform float occlusionAngle; +in vec2 v_textureCoordinates; + +layout(location = 0) out vec4 depthOut; + +// TODO: Include Uber copyright + +vec2 split(float a) { + const float SPLIT = 4097.0; + float t = a * SPLIT; + float a_hi = t * ONE - (t - a); + float a_lo = a * ONE - a_hi; + return vec2(a_hi, a_lo); +} + +vec2 twoSub(float a, float b) { + float s = (a - b); + float v = (s * ONE - a) * ONE; + float err = (a - (s - v) * ONE) * ONE * ONE * ONE - (b + v); + return vec2(s, err); +} + +vec2 twoSum(float a, float b) { + float s = (a + b); + float v = (s * ONE - a) * ONE; + float err = (a - (s - v) * ONE) * ONE * ONE * ONE + (b - v); + return vec2(s, err); +} + +vec2 twoSqr(float a) { + float prod = a * a; + vec2 a_fp64 = split(a); + float err = ((a_fp64.x * a_fp64.x - prod) * ONE + 2.0 * a_fp64.x * + a_fp64.y * ONE * ONE) + a_fp64.y * a_fp64.y * ONE * ONE * ONE; + return vec2(prod, err); +} + +vec2 twoProd(float a, float b) { + float prod = a * b; + vec2 a_fp64 = split(a); + vec2 b_fp64 = split(b); + float err = ((a_fp64.x * b_fp64.x - prod) + a_fp64.x * b_fp64.y + + a_fp64.y * b_fp64.x) + a_fp64.y * b_fp64.y; + return vec2(prod, err); +} + +vec2 quickTwoSum(float a, float b) { + float sum = (a + b) * ONE; + float err = b - (sum - a) * ONE; + return vec2(sum, err); +} + +vec2 sumFP64(vec2 a, vec2 b) { + vec2 s, t; + s = twoSum(a.x, b.x); + t = twoSum(a.y, b.y); + s.y += t.x; + s = quickTwoSum(s.x, s.y); + s.y += t.y; + s = quickTwoSum(s.x, s.y); + return s; +} + +vec2 subFP64(vec2 a, vec2 b) { + vec2 s, t; + s = twoSub(a.x, b.x); + t = twoSub(a.y, b.y); + s.y += t.x; + s = quickTwoSum(s.x, s.y); + s.y += t.y; + s = quickTwoSum(s.x, s.y); + return s; +} + +vec2 mulFP64(vec2 a, vec2 b) { + vec2 prod = twoProd(a.x, b.x); + // y component is for the error + prod.y += a.x * b.y; + prod.y += a.y * b.x; + prod = quickTwoSum(prod.x, prod.y); + return prod; +} + +vec2 divFP64(in vec2 a, in vec2 b) { + float xn = 1.0 / b.x; + vec2 yn = a * xn; + float diff = (subFP64(a, mulFP64(b, yn))).x; + vec2 prod = twoProd(xn, diff); + return sumFP64(yn, prod); +} + +vec2 sqrtFP64(in vec2 a) { + if (a.x == 0.0 && a.y == 0.0) return vec2(0.0, 0.0); + if (a.x < 0.0) return vec2(0.0 / 0.0, 0.0 / 0.0); + float x = 1.0 / sqrt(a.x); + float yn = a.x * x; + vec2 yn_sqr = twoSqr(yn) * ONE; + float diff = subFP64(a, yn_sqr).x; + vec2 prod = twoProd(x * 0.5, diff); + return sumFP64(vec2(yn, 0.0), prod); +} + +vec2 lengthFP64(in vec3 vec) { + vec2 highPrecisionX = split(vec.x); + vec2 highPrecisionY = split(vec.y); + vec2 highPrecisionZ = split(vec.z); + vec2 highPrecision = + sqrtFP64(sumFP64(sumFP64( + mulFP64(highPrecisionX, highPrecisionX), + mulFP64(highPrecisionY, highPrecisionY)), + mulFP64(highPrecisionZ, highPrecisionZ))); + return highPrecision; +} + +float triangle(in float x, in float period) { + return abs(mod(x, period) / period - 0.5) + EPS; +} + +float triangleFP64(in vec2 x, in float period) { + float lowPrecision = x.x + x.y; + vec2 floorTerm = split(floor(lowPrecision / period)); + vec2 periodHighPrecision = split(period); + vec2 term2 = mulFP64(periodHighPrecision, floorTerm); + vec2 moduloTerm = subFP64(x, term2); + vec2 normalized = divFP64(moduloTerm, periodHighPrecision); + normalized = subFP64(normalized, split(0.5)); + return abs(normalized.x + normalized.y) + EPS; +} + +float acosFast(in float inX) { + float x = abs(inX); + float res = ((C3 * x + C2) * x + C1) * x + C0; // p(x) + res *= sqrt(1.0 - x); + + return (inX >= 0.0) ? res : PI - res; +} + +float atanFast(in float x) { + return PI_4 * x - x * (abs(x) - 1.0) * (0.2447 + 0.0663 * abs(x)); +} + +float atan2(in float y, in float x) { + return x == 0.0 ? sign(y) * PI / 2.0 : atanFast(y, x); +} + +int getSector(in vec2 d) { + float angle = (atan2(float(d.y), float(d.x)) + PI) / TAU; + return int(angle * float(numSectors)); +} + +// Subsamples the neighbor pixel and stores the sector number +// in each component of the output +ivec4 getSectors(in vec2 vi) { + return ivec4(getSector(vi + vec2(-0.5, 0.5)), + getSector(vi + vec2(0.5, -0.5)), + getSector(vi + vec2(0.5, 0.5)), + getSector(vi + vec2(-0.5, -0.5))); +} + +ivec2 collapseSectors(in ivec4 sectors) { + int first = sectors[0]; + ivec2 collapsed = ivec2(first, first); + for (int i = 1; i < 4; i++) + if (sectors[i] != first) + collapsed.y = sectors[i]; + return collapsed; +} + +void main() { + float near = czm_entireFrustum.x; + float far = czm_entireFrustum.y; + ivec2 pos = ivec2(int(gl_FragCoord.x), int(gl_FragCoord.y)); + + // The position of this pixel in 3D (i.e the position of the point) + vec3 centerPosition = texture(pointCloud_ECTexture, v_textureCoordinates).xyz; + bool invalid = false; + + // If the EC of this pixel is zero, that means that it's not a valid + // pixel. We don't care about reprojecting it. + if (length(centerPosition) < EPS) + invalid = true; + + // We split our region of interest (the point of interest and its + // neighbors) + // into sectors. For the purposes of this shader, we have eight + // sectors. + // + // Each entry of sector_histogram contains the current best horizon + // pixel angle + ivec2 halfNeighborhood = ivec2(neighborhoodHalfWidth / 2, + neighborhoodHalfWidth / 2); + // Upper left corner of the neighborhood + ivec2 upperLeftCorner = pos - halfNeighborhood; + // Lower right corner of the neighborhood + ivec2 lowerRightCorner = pos + halfNeighborhood; + + // The widest the cone can be is 90 degrees + float maxAngle = PI / 2.0; + + // Our sector array defaults to an angle of "maxAngle" in each sector + // (i.e no horizon pixels!) + float sh[numSectors]; + for (int i = 0; i < numSectors; i++) { + sh[i] = maxAngle; + } + + // Right now this is obvious because everything happens in eye space, + // but this kind of statement is nice for a reference implementation + vec3 viewer = vec3(0.0); + + for (int i = -neighborhoodHalfWidth; i <= neighborhoodHalfWidth; i++) { + for (int j = -neighborhoodHalfWidth; j <= neighborhoodHalfWidth; j++) { + // d is the relative offset from the horizon pixel to the center pixel + // in 2D + ivec2 d = ivec2(i, j); + ivec2 pI = pos + d; + + // We now calculate the actual 3D position of the horizon pixel (the horizon point) + vec3 neighborPosition = texture(pointCloud_ECTexture, + vec2(pI) / czm_viewport.zw).xyz; + + // If our horizon pixel doesn't exist, ignore it and move on + if (length(neighborPosition) < EPS || pI == pos) { + continue; + } + + if (!invalid) { + // sectors contains both possible sectors that the + // neighbor pixel could be in + ivec2 sectors = collapseSectors(getSectors(vec2(d))); + + // This is the offset of the horizon point from the center in 3D + // (a 3D analog of d) + vec3 c = neighborPosition - centerPosition; + + // Now we calculate the dot product between the vector + // from the viewer to the center and the vector to the horizon pixel. + // We normalize both vectors first because we only care about their relative + // directions + // TODO: Redo the math and figure out whether the result should be negated or not + float dotProduct = dot(normalize(viewer - centerPosition), + normalize(c)); + + // We calculate the angle that this horizon pixel would make + // in the cone. The dot product is be equal to + // |vec_1| * |vec_2| * cos(angle_between), and in this case, + // the magnitude of both vectors is 1 because they are both + // normalized. + float angle = acosFast(dotProduct); + + // This horizon point is behind the current point. That means that it can't + // occlude the current point. So we ignore it and move on. + if (angle > maxAngle || angle <= 0.0) + continue; + // If we've found a horizon pixel, store it in the histogram + if (sh[sectors.x] > angle) { + sh[sectors.x] = angle; + } + if (sh[sectors.y] > angle) { + sh[sectors.y] = angle; + } + } + } + } + + if (!invalid) { + float accumulator = 0.0; + for (int i = 0; i < numSectors; i++) { + float angle = sh[i]; + // If the z component is less than zero, + // that means that there is no valid horizon pixel + if (angle <= 0.0 || angle > maxAngle) + angle = maxAngle; + accumulator += angle; + } + + // The solid angle is too small, so we occlude this point + if (accumulator < (2.0 * PI) * (1.0 - occlusionAngle)) { + depthOut = vec4(0); + } else { + // Write out the distance of the point + // + // We use the distance of the point rather than + // the linearized depth. This is because we want + // to encode as much information about position disparities + // between points as we can, and the z-values of + // neighboring points are usually very similar. + // On the other hand, the x-values and y-values are + // usually fairly different. +#ifdef useTriangle + // We can get even more accuracy by passing the 64-bit + // distance into a triangle wave function that + // uses 64-bit primitives internally. The region + // growing pass only cares about deltas between + // different pixels, so we just have to ensure that + // the period of triangle function is greater than that + // of the largest possible delta can arise between + // different points. + // + // The triangle function is C0 continuous, which avoids + // artifacts from discontinuities. That said, I have noticed + // some inexplicable artifacts occasionally, so please + // disable this optimization if that becomes an issue. + // + // It's important that the period of the triangle function + // is at least two orders of magnitude greater than + // the average depth delta that we are likely to come + // across. The triangle function works because we have + // some assumption of locality in the depth domain. + // Massive deltas break that locality -- but that's + // actually not an issue. Deltas that are larger than + // the period function will be "wrapped around", and deltas + // that are much larger than the period function may be + // "wrapped around" many times. A similar process occurs + // in many random number generators. The resulting delta + // is usually at least an order of magnitude greater than + // the average delta, so it won't even be considered in + // the region growing pass. + vec2 hpl = lengthFP64(centerPosition); + float triangleResult = triangleFP64(hpl, trianglePeriod); + depthOut = czm_packDepth(triangleResult); +#else + vec2 lengthOfFrustum = subFP64(split(czm_clampedFrustum.y), + split(czm_clampedFrustum.x)); + vec2 frustumStart = split(czm_clampedFrustum.x); + vec2 centerPositionLength = lengthFP64(centerPosition); + vec2 normalizedDepthFP64 = sumFP64(divFP64(centerPositionLength, + lengthOfFrustum), + frustumStart); + depthOut = czm_packDepth(normalizedDepthFP64.x + normalizedDepthFP64.y); +#endif + } + } +} From 06b988324ebc4dfe45f13cb19c7de48262a6b284 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Fri, 28 Jul 2017 14:02:49 -0400 Subject: [PATCH 162/240] AO works with the new setup now --- Source/Scene/PointCloudPostProcessor.js | 2 +- .../PointOcclusionPassGL1.glsl | 13 +- .../PointOcclusionPassGL2.glsl | 233 ++++++++---------- 3 files changed, 115 insertions(+), 133 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 5771a2a14762..af21b8153815 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -1292,11 +1292,11 @@ define([ var numRegionGrowingCommands = regionGrowingCommands.length; commandList.push(clearCommands['screenSpacePass']); - commandList.push(pointOcclusionCommand); //commandList.push(clearCommands['sectorHistogramPass']); //commandList.push(sectorHistogramCommand); commandList.push(clearCommands['aoBufferB']); //commandList.push(sectorGatheringCommand); + commandList.push(pointOcclusionCommand); commandList.push(clearCommands['edgeCullingPass']); commandList.push(edgeCullingCommand); commandList.push(clearCommands['densityEstimationPass']); diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl index 755a4009382b..9a527759982c 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl @@ -1,3 +1,4 @@ +#extension GL_EXT_draw_buffers : enable #extension GL_EXT_frag_depth : enable #define TAU 6.28318530718 @@ -236,11 +237,14 @@ void main() { // The position of this pixel in 3D (i.e the position of the point) vec3 centerPosition = texture2D(pointCloud_ECTexture, v_textureCoordinates).xyz; + bool invalid = false; // If the EC of this pixel is zero, that means that it's not a valid // pixel. We don't care about reprojecting it. - if (length(centerPosition) == 0.) - discard; + if (length(centerPosition) < EPS) { + gl_FragData[0] = vec4(0.0); + gl_FragData[1] = vec4(1.0 - EPS); + } // We split our region of interest (the point of interest and its // neighbors) @@ -284,7 +288,6 @@ void main() { // sectors contains both possible sectors that the // neighbor pixel could be in - //ivec2 sectors = collapseSectors(getSectors(vec2(d))); ivec2 sectors = readSectors(d); // This is the offset of the horizon point from the center in 3D @@ -333,7 +336,11 @@ void main() { // The solid angle is too small, so we occlude this point if (accumulator < (2.0 * PI) * (1.0 - occlusionAngle)) { gl_FragData[0] = vec4(0.0); + gl_FragData[1] = vec4(1.0 - EPS); } else { + float occlusion = clamp(accumulator / (4.0 * PI), 0.0, 1.0); + gl_FragData[1] = czm_packDepth(occlusion); + // Write out the distance of the point // // We use the distance of the point rather than diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl index 2067d8e40695..54798d527e9a 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl @@ -19,6 +19,7 @@ uniform float ONE; uniform sampler2D pointCloud_ECTexture; uniform float occlusionAngle; +uniform sampler2D sectorLUT; in vec2 v_textureCoordinates; layout(location = 0) out vec4 depthOut; @@ -155,35 +156,11 @@ float acosFast(in float inX) { return (inX >= 0.0) ? res : PI - res; } -float atanFast(in float x) { - return PI_4 * x - x * (abs(x) - 1.0) * (0.2447 + 0.0663 * abs(x)); -} - -float atan2(in float y, in float x) { - return x == 0.0 ? sign(y) * PI / 2.0 : atanFast(y, x); -} - -int getSector(in vec2 d) { - float angle = (atan2(float(d.y), float(d.x)) + PI) / TAU; - return int(angle * float(numSectors)); -} - -// Subsamples the neighbor pixel and stores the sector number -// in each component of the output -ivec4 getSectors(in vec2 vi) { - return ivec4(getSector(vi + vec2(-0.5, 0.5)), - getSector(vi + vec2(0.5, -0.5)), - getSector(vi + vec2(0.5, 0.5)), - getSector(vi + vec2(-0.5, -0.5))); -} - -ivec2 collapseSectors(in ivec4 sectors) { - int first = sectors[0]; - ivec2 collapsed = ivec2(first, first); - for (int i = 1; i < 4; i++) - if (sectors[i] != first) - collapsed.y = sectors[i]; - return collapsed; +ivec2 readSectors(in ivec2 sectorPosition) { + vec2 texCoordinate = vec2(sectorPosition + ivec2(neighborhoodHalfWidth)) / + float(neighborhoodHalfWidth * 2); + vec2 unscaled = texture2D(sectorLUT, texCoordinate).rg; + return ivec2(unscaled * float(numSectors)); } void main() { @@ -197,8 +174,10 @@ void main() { // If the EC of this pixel is zero, that means that it's not a valid // pixel. We don't care about reprojecting it. - if (length(centerPosition) < EPS) - invalid = true; + if (length(centerPosition) < EPS) { + gl_FragData[0] = vec4(0.0); + gl_FragData[1] = vec4(1.0 - EPS); + } // We split our region of interest (the point of interest and its // neighbors) @@ -244,111 +223,107 @@ void main() { continue; } - if (!invalid) { - // sectors contains both possible sectors that the - // neighbor pixel could be in - ivec2 sectors = collapseSectors(getSectors(vec2(d))); - - // This is the offset of the horizon point from the center in 3D - // (a 3D analog of d) - vec3 c = neighborPosition - centerPosition; - - // Now we calculate the dot product between the vector - // from the viewer to the center and the vector to the horizon pixel. - // We normalize both vectors first because we only care about their relative - // directions - // TODO: Redo the math and figure out whether the result should be negated or not - float dotProduct = dot(normalize(viewer - centerPosition), - normalize(c)); - - // We calculate the angle that this horizon pixel would make - // in the cone. The dot product is be equal to - // |vec_1| * |vec_2| * cos(angle_between), and in this case, - // the magnitude of both vectors is 1 because they are both - // normalized. - float angle = acosFast(dotProduct); - - // This horizon point is behind the current point. That means that it can't - // occlude the current point. So we ignore it and move on. - if (angle > maxAngle || angle <= 0.0) - continue; - // If we've found a horizon pixel, store it in the histogram - if (sh[sectors.x] > angle) { - sh[sectors.x] = angle; - } - if (sh[sectors.y] > angle) { - sh[sectors.y] = angle; - } + // sectors contains both possible sectors that the + // neighbor pixel could be in + ivec2 sectors = readSectors(d); + + // This is the offset of the horizon point from the center in 3D + // (a 3D analog of d) + vec3 c = neighborPosition - centerPosition; + + // Now we calculate the dot product between the vector + // from the viewer to the center and the vector to the horizon pixel. + // We normalize both vectors first because we only care about their relative + // directions + // TODO: Redo the math and figure out whether the result should be negated or not + float dotProduct = dot(normalize(viewer - centerPosition), + normalize(c)); + + // We calculate the angle that this horizon pixel would make + // in the cone. The dot product is be equal to + // |vec_1| * |vec_2| * cos(angle_between), and in this case, + // the magnitude of both vectors is 1 because they are both + // normalized. + float angle = acosFast(dotProduct); + + // This horizon point is behind the current point. That means that it can't + // occlude the current point. So we ignore it and move on. + if (angle > maxAngle || angle <= 0.0) + continue; + // If we've found a horizon pixel, store it in the histogram + if (sh[sectors.x] > angle) { + sh[sectors.x] = angle; + } + if (sh[sectors.y] > angle) { + sh[sectors.y] = angle; } } } - if (!invalid) { - float accumulator = 0.0; - for (int i = 0; i < numSectors; i++) { - float angle = sh[i]; - // If the z component is less than zero, - // that means that there is no valid horizon pixel - if (angle <= 0.0 || angle > maxAngle) - angle = maxAngle; - accumulator += angle; - } + float accumulator = 0.0; + for (int i = 0; i < numSectors; i++) { + float angle = sh[i]; + // If the z component is less than zero, + // that means that there is no valid horizon pixel + if (angle <= 0.0 || angle > maxAngle) + angle = maxAngle; + accumulator += angle; + } - // The solid angle is too small, so we occlude this point - if (accumulator < (2.0 * PI) * (1.0 - occlusionAngle)) { - depthOut = vec4(0); - } else { - // Write out the distance of the point - // - // We use the distance of the point rather than - // the linearized depth. This is because we want - // to encode as much information about position disparities - // between points as we can, and the z-values of - // neighboring points are usually very similar. - // On the other hand, the x-values and y-values are - // usually fairly different. + // The solid angle is too small, so we occlude this point + if (accumulator < (2.0 * PI) * (1.0 - occlusionAngle)) { + depthOut = vec4(0); + } else { + // Write out the distance of the point + // + // We use the distance of the point rather than + // the linearized depth. This is because we want + // to encode as much information about position disparities + // between points as we can, and the z-values of + // neighboring points are usually very similar. + // On the other hand, the x-values and y-values are + // usually fairly different. #ifdef useTriangle - // We can get even more accuracy by passing the 64-bit - // distance into a triangle wave function that - // uses 64-bit primitives internally. The region - // growing pass only cares about deltas between - // different pixels, so we just have to ensure that - // the period of triangle function is greater than that - // of the largest possible delta can arise between - // different points. - // - // The triangle function is C0 continuous, which avoids - // artifacts from discontinuities. That said, I have noticed - // some inexplicable artifacts occasionally, so please - // disable this optimization if that becomes an issue. - // - // It's important that the period of the triangle function - // is at least two orders of magnitude greater than - // the average depth delta that we are likely to come - // across. The triangle function works because we have - // some assumption of locality in the depth domain. - // Massive deltas break that locality -- but that's - // actually not an issue. Deltas that are larger than - // the period function will be "wrapped around", and deltas - // that are much larger than the period function may be - // "wrapped around" many times. A similar process occurs - // in many random number generators. The resulting delta - // is usually at least an order of magnitude greater than - // the average delta, so it won't even be considered in - // the region growing pass. - vec2 hpl = lengthFP64(centerPosition); - float triangleResult = triangleFP64(hpl, trianglePeriod); - depthOut = czm_packDepth(triangleResult); + // We can get even more accuracy by passing the 64-bit + // distance into a triangle wave function that + // uses 64-bit primitives internally. The region + // growing pass only cares about deltas between + // different pixels, so we just have to ensure that + // the period of triangle function is greater than that + // of the largest possible delta can arise between + // different points. + // + // The triangle function is C0 continuous, which avoids + // artifacts from discontinuities. That said, I have noticed + // some inexplicable artifacts occasionally, so please + // disable this optimization if that becomes an issue. + // + // It's important that the period of the triangle function + // is at least two orders of magnitude greater than + // the average depth delta that we are likely to come + // across. The triangle function works because we have + // some assumption of locality in the depth domain. + // Massive deltas break that locality -- but that's + // actually not an issue. Deltas that are larger than + // the period function will be "wrapped around", and deltas + // that are much larger than the period function may be + // "wrapped around" many times. A similar process occurs + // in many random number generators. The resulting delta + // is usually at least an order of magnitude greater than + // the average delta, so it won't even be considered in + // the region growing pass. + vec2 hpl = lengthFP64(centerPosition); + float triangleResult = triangleFP64(hpl, trianglePeriod); + depthOut = czm_packDepth(triangleResult); #else - vec2 lengthOfFrustum = subFP64(split(czm_clampedFrustum.y), - split(czm_clampedFrustum.x)); - vec2 frustumStart = split(czm_clampedFrustum.x); - vec2 centerPositionLength = lengthFP64(centerPosition); - vec2 normalizedDepthFP64 = sumFP64(divFP64(centerPositionLength, - lengthOfFrustum), - frustumStart); - depthOut = czm_packDepth(normalizedDepthFP64.x + normalizedDepthFP64.y); + vec2 lengthOfFrustum = subFP64(split(czm_clampedFrustum.y), + split(czm_clampedFrustum.x)); + vec2 frustumStart = split(czm_clampedFrustum.x); + vec2 centerPositionLength = lengthFP64(centerPosition); + vec2 normalizedDepthFP64 = sumFP64(divFP64(centerPositionLength, + lengthOfFrustum), + frustumStart); + depthOut = czm_packDepth(normalizedDepthFP64.x + normalizedDepthFP64.y); #endif - } } } From d05acb34964bc0c51c29354cbc2babd9d0dc46c4 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Fri, 28 Jul 2017 14:45:54 -0400 Subject: [PATCH 163/240] Resets everything to the old "check the whole neighborhood" technique --- .../3D Tiles Point Cloud Post Processing.html | 11 +- Source/Scene/Cesium3DTileset.js | 3 +- Source/Scene/PointCloudPostProcessor.js | 285 ++---------------- .../DensityEdgeCullPass.glsl | 54 ++++ .../DensityEstimationPass.glsl | 47 --- .../PostProcessFilters/PointArrayVS.glsl | 36 --- .../PointOcclusionPassGL2.glsl | 11 +- .../SectorGatheringPass.glsl | 214 ------------- .../SectorHistogramPass.glsl | 153 ---------- 9 files changed, 89 insertions(+), 725 deletions(-) create mode 100644 Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl delete mode 100644 Source/Shaders/PostProcessFilters/DensityEstimationPass.glsl delete mode 100644 Source/Shaders/PostProcessFilters/PointArrayVS.glsl delete mode 100644 Source/Shaders/PostProcessFilters/SectorGatheringPass.glsl delete mode 100644 Source/Shaders/PostProcessFilters/SectorHistogramPass.glsl diff --git a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html index 2c348579b094..7390c940fce1 100644 --- a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html +++ b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html @@ -89,13 +89,6 @@ - - Random Reduction Factor - - - - - @@ -132,8 +125,7 @@ maxAbsRatio : tileset.pointCloudPostProcessorOptions.maxAbsRatio, pointAttenuationMultiplier : tileset.pointCloudPostProcessorOptions.pointAttenuationMultiplier, sigmoidDomainOffset : tileset.pointCloudPostProcessorOptions.sigmoidDomainOffset, - sigmoidSharpness : tileset.pointCloudPostProcessorOptions.sigmoidSharpness, - randomReductionFactor : tileset.pointCloudPostProcessorOptions.randomReductionFactor + sigmoidSharpness : tileset.pointCloudPostProcessorOptions.sigmoidSharpness }; Cesium.knockout.track(viewModel); @@ -158,7 +150,6 @@ subscribeParameter('pointAttenuationMultiplier'); subscribeParameter('sigmoidDomainOffset'); subscribeParameter('sigmoidSharpness'); -subscribeParameter('randomReductionFactor'); Sandcastle.addToggleButton('Enabled', false, function(checked) { tileset.pointCloudPostProcessorOptions.enabled = checked; diff --git a/Source/Scene/Cesium3DTileset.js b/Source/Scene/Cesium3DTileset.js index 6bf03c8bd78b..6ca77f150388 100644 --- a/Source/Scene/Cesium3DTileset.js +++ b/Source/Scene/Cesium3DTileset.js @@ -641,8 +641,7 @@ define([ enableAO : true, AOViewEnabled : false, sigmoidSharpness : 0.2, - sigmoidDomainOffset : 0.2, - randomReductionFactor : 1.0 + sigmoidDomainOffset : 0.2 }; this._pointCloudPostProcessor = new PointCloudPostProcessor(this.pointCloudPostProcessorOptions); diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index af21b8153815..e31c33484cfd 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -28,15 +28,11 @@ define([ '../Scene/BlendingState', '../Scene/StencilFunction', '../Scene/StencilOperation', - '../Shaders/PostProcessFilters/PointArrayVS', '../Shaders/PostProcessFilters/PointOcclusionPassGL1', '../Shaders/PostProcessFilters/PointOcclusionPassGL2', '../Shaders/PostProcessFilters/RegionGrowingPassGL1', '../Shaders/PostProcessFilters/RegionGrowingPassGL2', - '../Shaders/PostProcessFilters/SectorHistogramPass', - '../Shaders/PostProcessFilters/SectorGatheringPass', - '../Shaders/PostProcessFilters/DensityEstimationPass', - '../Shaders/PostProcessFilters/EdgeCullingPass' + '../Shaders/PostProcessFilters/DensityEdgeCullPass', ], function( Color, ComponentDatatype, @@ -66,15 +62,11 @@ define([ BlendingState, StencilFunction, StencilOperation, - PointArrayVS, PointOcclusionPassGL1, PointOcclusionPassGL2, RegionGrowingPassGL1, RegionGrowingPassGL2, - SectorHistogramPass, - SectorGatheringPass, - DensityEstimationPass, - EdgeCullingPass + DensityEdgeCullPass ) { 'use strict'; @@ -110,7 +102,6 @@ define([ this.AOViewEnabled = options.AOViewEnabled; this.sigmoidDomainOffset = options.sigmoidDomainOffset; this.sigmoidSharpness = options.sigmoidSharpness; - this.randomReductionFactor = options.randomReductionFactor; this._pointArray = undefined; @@ -441,115 +432,6 @@ define([ processor._dirty = dirty; } - function createPointArray(processor, context) { - var screenWidth = context.drawingBufferWidth; - var screenHeight = context.drawingBufferHeight; - - var vertexArr = new Float32Array(screenWidth * screenHeight * 2); - - var xIncrement = 2.0 / screenWidth; - var yIncrement = 2.0 / screenHeight; - - var baryOffsetX = xIncrement / 2.0; - var baryOffsetY = yIncrement / 2.0; - - var k = 0; - for (var i = -1.0; i < 1.0; i += xIncrement) { - for (var j = -1.0; j < 1.0; j += yIncrement) { - vertexArr[k++] = i + baryOffsetX; - vertexArr[k++] = j + baryOffsetY; - } - } - - var geometry = new Geometry({ - attributes: { - position : new GeometryAttribute({ - componentDatatype : ComponentDatatype.FLOAT, - componentsPerAttribute : 2, - values : vertexArr - }) - }, - primitiveType : PrimitiveType.POINTS - }); - - var pointArray = VertexArray.fromGeometry({ - context : context, - geometry : geometry, - attributeLocations : { - position : 0 - }, - bufferUsage : BufferUsage.STATIC_DRAW, - interleave : true - }); - - processor._pointArray = pointArray; - } - - function createPointArrayCommand(depthTexture, - kernelSize, - useStencil, - blendingState, - reductionFactor, - fragmentShaderSource, - processor, - context, - overrides) { - if (!defined(processor._pointArray)) { - createPointArray(processor, context); - } - - var uniformMap = (defined(overrides.uniformMap)) ? overrides.uniformMap : {}; - uniformMap.pointCloud_depthTexture = function () { - return depthTexture; - }; - uniformMap.reductionFactor = function () { - return reductionFactor; - }; - - var vertexShaderSource = replaceConstants(PointArrayVS, 'kernelSize', kernelSize.toFixed(1)); - - if (reductionFactor > 1.0 - 1e-6) { - vertexShaderSource = replaceConstants(vertexShaderSource, 'useReduction', false); - } - - var renderState = overrides.renderState; - - if (!defined(overrides.renderState)) { - var stencilTest = processor._positiveStencilTest; - if (defined(overrides.stencilTest)) { - stencilTest = overrides.stencilTest; - } - if (useStencil) { - renderState = RenderState.fromCache({ - stencilTest : stencilTest, - blending : blendingState - }); - } else { - renderState = RenderState.fromCache({ - blending : blendingState - }); - } - } - - return new DrawCommand({ - vertexArray : processor._pointArray, - primitiveType : PrimitiveType.POINTS, - renderState : renderState, - shaderProgram : ShaderProgram.fromCache({ - context : context, - vertexShaderSource : vertexShaderSource, - fragmentShaderSource : fragmentShaderSource, - attributeLocations : { - position : 0 - } - }), - uniformMap : uniformMap, - owner : overrides.owner, - framebuffer : overrides.framebuffer, - pass : overrides.pass - }); - } - function replaceConstants(sourceStr, constantName, replacement) { var r; if (typeof(replacement) === 'boolean') { @@ -617,132 +499,33 @@ define([ }); } - function sectorHistogramStage(processor, context) { - var neighborhoodSize = processor.neighborhoodHalfWidth * 2 + 1; - var uniformMap = { - sectorLUT : function() { - return processor._sectorLUTTexture; - }, - neighborhoodSize : function() { - return neighborhoodSize; - } - }; - - return createPointArrayCommand( - processor._ecTexture, - neighborhoodSize, - true, - processor._minBlend, - processor.randomReductionFactor, - SectorHistogramPass, - processor, - context, { - uniformMap : uniformMap, - framebuffer : processor._framebuffers.sectorHistogramPass, - pass : Pass.CESIUM_3D_TILE, - owner : processor - } - ); - } - - function sectorGatheringStage(processor, context) { + function densityEdgeCullStage(processor, context) { var uniformMap = { - pointCloud_ECTexture : function() { - return processor._ecTexture; - }, - sectorFirst : function() { - return processor._sectorTextures[0]; - }, - sectorSecond : function() { - return processor._sectorTextures[1]; - }, - occlusionAngle : function() { - return processor.occlusionAngle; + pointCloud_depthTexture : function() { + return processor._depthTextures[0]; }, - ONE : function() { - return 1.0; - } - }; - - var sectorGatheringStr = replaceConstants( - SectorGatheringPass, - 'useTriangle', - processor.useTriangle - ); - - return context.createViewportQuadCommand(sectorGatheringStr, { - uniformMap : uniformMap, - framebuffer : processor._framebuffers.screenSpacePass, - renderState : RenderState.fromCache({ - stencilTest : processor._positiveStencilTest - }), - pass : Pass.CESIUM_3D_TILE, - owner : processor - }); - } - - function densityEstimationStage(processor, context) { - var uniformMap = { neighborhoodVectorSize : function() { return processor.neighborhoodVectorSize; }, maxAbsRatio : function() { return processor.maxAbsRatio; - }, - pointCloud_edgeCullingTexture : function() { - return processor._edgeCullingTexture; - } - }; - - var densityEstimationStr = replaceConstants( - DensityEstimationPass, - 'neighborhoodHalfWidth', - processor.densityHalfWidth - ); - - return createPointArrayCommand( - processor._depthTextures[0], - processor.densityHalfWidth * 2 + 1, - false, - processor._minBlend, - processor.randomReductionFactor, - densityEstimationStr, - processor, - context, { - uniformMap : uniformMap, - framebuffer : processor._framebuffers.densityEstimationPass, - pass : Pass.CESIUM_3D_TILE, - owner : processor } - ); - } - - function edgeCullingStage(processor, context) { - var uniformMap = { }; - var edgeCullingStr = replaceConstants( - EdgeCullingPass, + var densityEdgeCullStr = replaceConstants( + DensityEdgeCullPass, 'neighborhoodHalfWidth', processor.densityHalfWidth ); - return createPointArrayCommand( - processor._depthTextures[0], - processor.densityHalfWidth * 2 + 1, - true, - processor._addBlend, - processor.randomReductionFactor, - edgeCullingStr, - processor, - context, { - uniformMap : uniformMap, - framebuffer : processor._framebuffers.edgeCullingPass, - pass : Pass.CESIUM_3D_TILE, - owner : processor, - stencilTest : processor._negativeStencilTest - } - ); + return context.createViewportQuadCommand(densityEdgeCullStr, { + uniformMap : uniformMap, + framebuffer : processor._framebuffers.densityEstimationPass, + renderState : RenderState.fromCache({ + }), + pass : Pass.CESIUM_3D_TILE, + owner : processor + }); } function regionGrowingStage(processor, context, iteration) { @@ -956,11 +739,8 @@ define([ var copyCommands = new Array(2); var i; - processor._drawCommands.edgeCullingCommand = edgeCullingStage(processor, context); - processor._drawCommands.densityEstimationCommand = densityEstimationStage(processor, context); + processor._drawCommands.densityEdgeCullCommand = densityEdgeCullStage(processor, context); processor._drawCommands.pointOcclusionCommand = pointOcclusionStage(processor, context); - processor._drawCommands.sectorHistogramCommand = sectorHistogramStage(processor, context); - processor._drawCommands.sectorGatheringCommand = sectorGatheringStage(processor, context); for (i = 0; i < numRegionGrowingPasses; i++) { regionGrowingCommands[i] = regionGrowingStage(processor, context, i); @@ -1055,12 +835,11 @@ define([ if (framebuffers.hasOwnProperty(name)) { // The screen space pass should consider // the stencil value, so we don't clear it - // here. Edge culling should only apply to invalid - // pixels. The density estimation pass uses - // min blending, so we need to set the default - // value to the maximum possible value - if (name === 'screenSpacePass' || - name === 'edgeCullingPass') { + // here. + // Also we want to clear the AO buffer to white + // so that the pixels that never get region-grown + // do not appear black + if (name === 'screenSpacePass') { clearCommands[name] = new ClearCommand({ framebuffer : framebuffers[name], color : new Color(0.0, 0.0, 0.0, 0.0), @@ -1069,9 +848,7 @@ define([ pass : Pass.CESIUM_3D_TILE, owner : processor }); - } else if (name === 'densityEstimationPass' || - name === 'sectorHistogramPass' || - name === 'aoBufferA' || + } else if (name === 'aoBufferA' || name === 'aoBufferB') { clearCommands[name] = new ClearCommand({ framebuffer : framebuffers[name], @@ -1116,7 +893,6 @@ define([ if (!defined(colorTextures)) { createFramebuffers(processor, context); - createPointArray(processor, context); nowDirty = true; } @@ -1127,7 +903,6 @@ define([ if (resized) { destroyFramebuffers(processor); createFramebuffers(processor, context); - createPointArray(processor, context); createCommands(processor, context); nowDirty = true; } @@ -1205,8 +980,7 @@ define([ tileset.pointCloudPostProcessorOptions.enableAO !== this.enableAO || tileset.pointCloudPostProcessorOptions.AOViewEnabled !== this.AOViewEnabled || tileset.pointCloudPostProcessorOptions.sigmoidDomainOffset !== this.sigmoidDomainOffset || - tileset.pointCloudPostProcessorOptions.sigmoidSharpness !== this.sigmoidSharpness || - tileset.pointCloudPostProcessorOptions.randomReductionFactor !== this.randomReductionFactor) { + tileset.pointCloudPostProcessorOptions.sigmoidSharpness !== this.sigmoidSharpness) { this.occlusionAngle = tileset.pointCloudPostProcessorOptions.occlusionAngle; this.rangeParameter = tileset.pointCloudPostProcessorOptions.rangeParameter; this.neighborhoodHalfWidth = tileset.pointCloudPostProcessorOptions.neighborhoodHalfWidth; @@ -1222,7 +996,6 @@ define([ this.AOViewEnabled = tileset.pointCloudPostProcessorOptions.AOViewEnabled; this.sigmoidDomainOffset = tileset.pointCloudPostProcessorOptions.sigmoidDomainOffset; this.sigmoidSharpness = tileset.pointCloudPostProcessorOptions.sigmoidSharpness; - this.randomReductionFactor = tileset.pointCloudPostProcessorOptions.randomReductionFactor; dirty = true; } @@ -1278,11 +1051,8 @@ define([ } // Apply processing commands - var edgeCullingCommand = this._drawCommands.edgeCullingCommand; - var densityEstimationCommand = this._drawCommands.densityEstimationCommand; + var densityEdgeCullCommand = this._drawCommands.densityEdgeCullCommand; var pointOcclusionCommand = this._drawCommands.pointOcclusionCommand; - var sectorHistogramCommand = this._drawCommands.sectorHistogramCommand; - var sectorGatheringCommand = this._drawCommands.sectorGatheringCommand; var regionGrowingCommands = this._drawCommands.regionGrowingCommands; var copyCommands = this._drawCommands.copyCommands; var stencilCommands = this._drawCommands.stencilCommands; @@ -1292,15 +1062,10 @@ define([ var numRegionGrowingCommands = regionGrowingCommands.length; commandList.push(clearCommands['screenSpacePass']); - //commandList.push(clearCommands['sectorHistogramPass']); - //commandList.push(sectorHistogramCommand); commandList.push(clearCommands['aoBufferB']); - //commandList.push(sectorGatheringCommand); commandList.push(pointOcclusionCommand); - commandList.push(clearCommands['edgeCullingPass']); - commandList.push(edgeCullingCommand); commandList.push(clearCommands['densityEstimationPass']); - commandList.push(densityEstimationCommand); + commandList.push(densityEdgeCullCommand); for (i = 0; i < numRegionGrowingCommands; i++) { if (i % 2 === 0) { diff --git a/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl b/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl new file mode 100644 index 000000000000..b225fd2c747b --- /dev/null +++ b/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl @@ -0,0 +1,54 @@ +#define neighborhoodHalfWidth 4 // TUNABLE PARAMETER -- half-width of region-growing kernel + +#define EPS 1e-8 + +#define densityScaleFactor 10.0 + +uniform sampler2D pointCloud_depthTexture; +uniform float neighborhoodVectorSize; +uniform float maxAbsRatio; +varying vec2 v_textureCoordinates; + +void main() { + float center = czm_unpackDepth(texture2D(pointCloud_depthTexture, + v_textureCoordinates)); + ivec2 pos = ivec2(int(gl_FragCoord.x), int(gl_FragCoord.y)); + + float closestNeighbor = float(neighborhoodHalfWidth) + 1.0; + vec2 neighborhoodAccum = vec2(0.0); + vec2 absNeighborhoodAccum = vec2(0.0); + + if (center < EPS) { + for (int i = -neighborhoodHalfWidth; i <= neighborhoodHalfWidth; i++) { + for (int j = -neighborhoodHalfWidth; j <= neighborhoodHalfWidth; j++) { + ivec2 d = ivec2(i, j); + ivec2 pI = pos + d; + + float neighbor = czm_unpackDepth(texture2D(pointCloud_depthTexture, + vec2(pI) / czm_viewport.zw)); + if (neighbor < EPS || pI == pos) { + continue; + } + + neighborhoodAccum += vec2(d); + absNeighborhoodAccum += abs(vec2(d)); + closestNeighbor = min(closestNeighbor, + max(abs(float(i)), + abs(float(j)))); + } + } + + float absRatio = length(neighborhoodAccum) / + length(absNeighborhoodAccum); + if (int(closestNeighbor) <= neighborhoodHalfWidth && + !(absRatio > maxAbsRatio && + length(neighborhoodAccum) > neighborhoodVectorSize)) { + gl_FragData[0] = vec4(vec3(closestNeighbor / + densityScaleFactor), 1.0); + } else { + gl_FragData[0] = vec4(vec3(0.0), 1.0); + } + } else { + gl_FragData[0] = vec4(vec3(1.0 / densityScaleFactor), 1.0); + } +} diff --git a/Source/Shaders/PostProcessFilters/DensityEstimationPass.glsl b/Source/Shaders/PostProcessFilters/DensityEstimationPass.glsl deleted file mode 100644 index edbf26da2e0e..000000000000 --- a/Source/Shaders/PostProcessFilters/DensityEstimationPass.glsl +++ /dev/null @@ -1,47 +0,0 @@ -#extension GL_EXT_draw_buffers : enable - -#define EPS 1e-8 - -#define densityScaleFactor 10.0 - -varying float centerPos; - -uniform sampler2D pointCloud_depthTexture; -uniform sampler2D pointCloud_edgeCullingTexture; - -uniform float neighborhoodVectorSize; -uniform float maxAbsRatio; - -void main() { - vec2 v_textureCoordinates = gl_FragCoord.xy / czm_viewport.zw; - float depth = czm_unpackDepth(texture2D(pointCloud_depthTexture, - v_textureCoordinates)); - vec4 rawEdgeCull = texture2D(pointCloud_edgeCullingTexture, - v_textureCoordinates); - vec2 neighborhoodAccum = rawEdgeCull.xy; - vec2 absNeighborhoodAccum = rawEdgeCull.zw; - ivec2 pos = ivec2(int(gl_FragCoord.x), int(gl_FragCoord.y)); - int densityValue = 0; - - if (depth < EPS) { - ivec2 centerValue = ivec2(int(mod(centerPos, czm_viewport.z)), - int(centerPos) / int(czm_viewport.z)); - vec2 diff = vec2(pos - centerValue); - densityValue = int(max(abs(diff.x), abs(diff.y))); - } else { - densityValue = 1; - } - - float absNeighborhoodAccumLength = length(absNeighborhoodAccum); - float absRatio = 0.0; - if (absNeighborhoodAccumLength > EPS) { - absRatio = length(neighborhoodAccum) / absNeighborhoodAccumLength; - } - if (!(length(neighborhoodAccum) > neighborhoodVectorSize && - absRatio > maxAbsRatio)) { - gl_FragData[0] = vec4(float(densityValue) / densityScaleFactor, - 0.0, 0.0, 0.0); - } else { - gl_FragData[0] = vec4(0.0); - } -} diff --git a/Source/Shaders/PostProcessFilters/PointArrayVS.glsl b/Source/Shaders/PostProcessFilters/PointArrayVS.glsl deleted file mode 100644 index 1a518421521e..000000000000 --- a/Source/Shaders/PostProcessFilters/PointArrayVS.glsl +++ /dev/null @@ -1,36 +0,0 @@ -#define EPS 1e-6 -#define kernelSize 9.0 -#define useReduction - -attribute vec4 position; -varying float centerPos; - -uniform sampler2D pointCloud_depthTexture; -uniform float reductionFactor; - -// Adapted from https://thebookofshaders.com/10/ -float random(in vec3 st) { - return fract(sin(dot(st.xyz, vec3(17.537, 78.233, 14.206))) * 43758.5453123); -} - -void main() { - vec2 textureCoordinates = 0.5 * position.xy + vec2(0.5); - ivec2 screenSpaceCoordinates = ivec2(textureCoordinates * czm_viewport.zw); - vec4 pseudoDepth = texture2D(pointCloud_depthTexture, textureCoordinates); - if (length(pseudoDepth) > EPS) { - gl_Position = position; - float pointSize = kernelSize; -#ifdef useReduction - float reductionScalar = random(pseudoDepth.xyz); - if (reductionScalar > reductionFactor) { - pointSize *= reductionScalar * reductionFactor; - } -#endif - gl_PointSize = pointSize; - centerPos = float(screenSpaceCoordinates.x + screenSpaceCoordinates.y * int( - czm_viewport.z)); - } else { - gl_Position = vec4(-10); - centerPos = 0.0; - } -} diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl index 54798d527e9a..4a722614bd60 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl @@ -23,6 +23,7 @@ uniform sampler2D sectorLUT; in vec2 v_textureCoordinates; layout(location = 0) out vec4 depthOut; +layout(location = 1) out vec4 aoOut; // TODO: Include Uber copyright @@ -159,7 +160,7 @@ float acosFast(in float inX) { ivec2 readSectors(in ivec2 sectorPosition) { vec2 texCoordinate = vec2(sectorPosition + ivec2(neighborhoodHalfWidth)) / float(neighborhoodHalfWidth * 2); - vec2 unscaled = texture2D(sectorLUT, texCoordinate).rg; + vec2 unscaled = texture(sectorLUT, texCoordinate).rg; return ivec2(unscaled * float(numSectors)); } @@ -175,8 +176,8 @@ void main() { // If the EC of this pixel is zero, that means that it's not a valid // pixel. We don't care about reprojecting it. if (length(centerPosition) < EPS) { - gl_FragData[0] = vec4(0.0); - gl_FragData[1] = vec4(1.0 - EPS); + depthOut = vec4(0.0); + aoOut = vec4(1.0 - EPS); } // We split our region of interest (the point of interest and its @@ -273,7 +274,11 @@ void main() { // The solid angle is too small, so we occlude this point if (accumulator < (2.0 * PI) * (1.0 - occlusionAngle)) { depthOut = vec4(0); + aoOut = vec4(1.0 - EPS); } else { + float occlusion = clamp(accumulator / (4.0 * PI), 0.0, 1.0); + aoOut = czm_packDepth(occlusion); + // Write out the distance of the point // // We use the distance of the point rather than diff --git a/Source/Shaders/PostProcessFilters/SectorGatheringPass.glsl b/Source/Shaders/PostProcessFilters/SectorGatheringPass.glsl deleted file mode 100644 index 2d1a1f3be211..000000000000 --- a/Source/Shaders/PostProcessFilters/SectorGatheringPass.glsl +++ /dev/null @@ -1,214 +0,0 @@ -#extension GL_EXT_draw_buffers : enable - -#define TAU 6.28318530718 -#define PI 3.14159265359 -#define EPS 1e-6 -#define numSectors 8 -#define maxAngle 1.57079632679 // The maximum sector angle is PI / 2 - -#define trianglePeriod 1e-5 -#define useTriangle - -uniform sampler2D sectorFirst; -uniform sampler2D sectorSecond; -uniform sampler2D pointCloud_ECTexture; -uniform float occlusionAngle; -uniform float ONE; - -varying vec2 v_textureCoordinates; - -// TODO: Include Uber copyright - -vec2 split(float a) { - const float SPLIT = 4097.0; - float t = a * SPLIT; - float a_hi = t * ONE - (t - a); - float a_lo = a * ONE - a_hi; - return vec2(a_hi, a_lo); -} - -vec2 twoSub(float a, float b) { - float s = (a - b); - float v = (s * ONE - a) * ONE; - float err = (a - (s - v) * ONE) * ONE * ONE * ONE - (b + v); - return vec2(s, err); -} - -vec2 twoSum(float a, float b) { - float s = (a + b); - float v = (s * ONE - a) * ONE; - float err = (a - (s - v) * ONE) * ONE * ONE * ONE + (b - v); - return vec2(s, err); -} - -vec2 twoSqr(float a) { - float prod = a * a; - vec2 a_fp64 = split(a); - float err = ((a_fp64.x * a_fp64.x - prod) * ONE + 2.0 * a_fp64.x * - a_fp64.y * ONE * ONE) + a_fp64.y * a_fp64.y * ONE * ONE * ONE; - return vec2(prod, err); -} - -vec2 twoProd(float a, float b) { - float prod = a * b; - vec2 a_fp64 = split(a); - vec2 b_fp64 = split(b); - float err = ((a_fp64.x * b_fp64.x - prod) + a_fp64.x * b_fp64.y + - a_fp64.y * b_fp64.x) + a_fp64.y * b_fp64.y; - return vec2(prod, err); -} - -vec2 quickTwoSum(float a, float b) { - float sum = (a + b) * ONE; - float err = b - (sum - a) * ONE; - return vec2(sum, err); -} - -vec2 sumFP64(vec2 a, vec2 b) { - vec2 s, t; - s = twoSum(a.x, b.x); - t = twoSum(a.y, b.y); - s.y += t.x; - s = quickTwoSum(s.x, s.y); - s.y += t.y; - s = quickTwoSum(s.x, s.y); - return s; -} - -vec2 subFP64(vec2 a, vec2 b) { - vec2 s, t; - s = twoSub(a.x, b.x); - t = twoSub(a.y, b.y); - s.y += t.x; - s = quickTwoSum(s.x, s.y); - s.y += t.y; - s = quickTwoSum(s.x, s.y); - return s; -} - -vec2 mulFP64(vec2 a, vec2 b) { - vec2 prod = twoProd(a.x, b.x); - // y component is for the error - prod.y += a.x * b.y; - prod.y += a.y * b.x; - prod = quickTwoSum(prod.x, prod.y); - return prod; -} - -vec2 divFP64(in vec2 a, in vec2 b) { - float xn = 1.0 / b.x; - vec2 yn = a * xn; - float diff = (subFP64(a, mulFP64(b, yn))).x; - vec2 prod = twoProd(xn, diff); - return sumFP64(yn, prod); -} - -vec2 sqrtFP64(in vec2 a) { - if (a.x == 0.0 && a.y == 0.0) return vec2(0.0, 0.0); - if (a.x < 0.0) return vec2(0.0 / 0.0, 0.0 / 0.0); - float x = 1.0 / sqrt(a.x); - float yn = a.x * x; - vec2 yn_sqr = twoSqr(yn) * ONE; - float diff = subFP64(a, yn_sqr).x; - vec2 prod = twoProd(x * 0.5, diff); - return sumFP64(vec2(yn, 0.0), prod); -} - -vec2 lengthFP64(in vec3 vec) { - vec2 highPrecisionX = split(vec.x); - vec2 highPrecisionY = split(vec.y); - vec2 highPrecisionZ = split(vec.z); - vec2 highPrecision = - sqrtFP64(sumFP64(sumFP64( - mulFP64(highPrecisionX, highPrecisionX), - mulFP64(highPrecisionY, highPrecisionY)), - mulFP64(highPrecisionZ, highPrecisionZ))); - return highPrecision; -} - -float triangle(in float x, in float period) { - return abs(mod(x, period) / period - 0.5) + EPS; -} - -float triangleFP64(in vec2 x, in float period) { - float lowPrecision = x.x + x.y; - vec2 floorTerm = split(floor(lowPrecision / period)); - vec2 periodHighPrecision = split(period); - vec2 term2 = mulFP64(periodHighPrecision, floorTerm); - vec2 moduloTerm = subFP64(x, term2); - vec2 normalized = divFP64(moduloTerm, periodHighPrecision); - normalized = subFP64(normalized, split(0.5)); - return abs(normalized.x + normalized.y) + EPS; -} - -void main() { - vec4 sh1 = texture2D(sectorFirst, v_textureCoordinates) * maxAngle; - vec4 sh2 = texture2D(sectorSecond, v_textureCoordinates) * maxAngle; - - vec4 ones = vec4(1.0); - float accumulator = dot(sh1, ones) + dot(sh2, ones); - - vec3 centerPosition = texture2D(pointCloud_ECTexture, v_textureCoordinates).xyz; - - // The solid angle is too small, so we occlude this point - if (accumulator < (2.0 * PI) * (1.0 - occlusionAngle) || - length(centerPosition) < EPS) { - gl_FragData[0] = vec4(0.0); - gl_FragData[1] = vec4(1.0 - EPS); - } else { - float occlusion = clamp(accumulator / (4.0 * PI), 0.0, 1.0); - gl_FragData[1] = czm_packDepth(occlusion); - - // Write out the distance of the point - // - // We use the distance of the point rather than - // the linearized depth. This is because we want - // to encode as much information about position disparities - // between points as we can, and the z-values of - // neighboring points are usually very similar. - // On the other hand, the x-values and y-values are - // usually fairly different. -#ifdef useTriangle - // We can get even more accuracy by passing the 64-bit - // distance into a triangle wave function that - // uses 64-bit primitives internally. The region - // growing pass only cares about deltas between - // different pixels, so we just have to ensure that - // the period of triangle function is greater than that - // of the largest possible delta can arise between - // different points. - // - // The triangle function is C0 continuous, which avoids - // artifacts from discontinuities. That said, I have noticed - // some inexplicable artifacts occasionally, so please - // disable this optimization if that becomes an issue. - // - // It's important that the period of the triangle function - // is at least two orders of magnitude greater than - // the average depth delta that we are likely to come - // across. The triangle function works because we have - // some assumption of locality in the depth domain. - // Massive deltas break that locality -- but that's - // actually not an issue. Deltas that are larger than - // the period function will be "wrapped around", and deltas - // that are much larger than the period function may be - // "wrapped around" many times. A similar process occurs - // in many random number generators. The resulting delta - // is usually at least an order of magnitude greater than - // the average delta, so it won't even be considered in - // the region growing pass. - vec2 hpl = lengthFP64(centerPosition); - float triangleResult = triangleFP64(hpl, trianglePeriod); - gl_FragData[0] = czm_packDepth(triangleResult); -#else - vec2 lengthOfFrustum = subFP64(split(czm_clampedFrustum.y), - split(czm_clampedFrustum.x)); - vec2 frustumStart = split(czm_clampedFrustum.x); - vec2 centerPositionLength = lengthFP64(centerPosition); - vec2 normalizedDepthFP64 = sumFP64(divFP64(centerPositionLength, - lengthOfFrustum), - frustumStart); - gl_FragData[0] = czm_packDepth(normalizedDepthFP64.x + normalizedDepthFP64.y); -#endif - } -} diff --git a/Source/Shaders/PostProcessFilters/SectorHistogramPass.glsl b/Source/Shaders/PostProcessFilters/SectorHistogramPass.glsl deleted file mode 100644 index aeab7f81598c..000000000000 --- a/Source/Shaders/PostProcessFilters/SectorHistogramPass.glsl +++ /dev/null @@ -1,153 +0,0 @@ -#extension GL_EXT_frag_depth : enable -#extension GL_EXT_draw_buffers : enable - -#define TAU 6.28318530718 -#define PI 3.14159265359 -#define PI_4 0.785398163 -#define C0 1.57073 -#define C1 -0.212053 -#define C2 0.0740935 -#define C3 -0.0186166 -#define EPS 1e-6 -#define maxAngle 1.57079632679 // The maximum sector angle is PI / 2 -#define numSectors 8 - -varying float centerPos; - -// This texture actually contains eye-space coordinates, -// it just has to be called `pointCloud_depthTexture` -uniform sampler2D pointCloud_depthTexture; -uniform sampler2D sectorLUT; -uniform float neighborhoodSize; - -float acosFast(in float inX) { - float x = abs(inX); - float res = ((C3 * x + C2) * x + C1) * x + C0; // p(x) - res *= sqrt(1.0 - x); - - return (inX >= 0.0) ? res : PI - res; -} - -ivec2 readSectors(in ivec2 sectorPosition) { - int halfSize = int(neighborhoodSize / 2.0); - vec2 texCoordinate = vec2(sectorPosition + ivec2(halfSize)) / - float(halfSize * 2); - vec2 unscaled = texture2D(sectorLUT, texCoordinate).rg; - return ivec2(unscaled * float(numSectors)); -} - -void updateOutput(in int index, - in float value, - inout vec4 sh0, - inout vec4 sh1) { - // We could conditionally write out to gl_FragData here, - // however on hardware that doesn't support dynamic branching - // that would perform 8 writes instead of 1! So we write out - // to a dummy variable and then copy that over - if (index < 4) { - if (index < 2) { - if (index == 0) { - sh0.x = value; - } else { - sh0.y = value; - } - } else { - if (index == 2) { - sh0.z = value; - } else { - sh0.w = value; - } - } - } else { - if (index < 6) { - if (index == 4) { - sh1.x = value; - } else { - sh1.y = value; - } - } else { - if (index == 6) { - sh1.z = value; - } else { - sh1.w = value; - } - } - } -} - -void main() { - vec2 v_textureCoordinates = gl_FragCoord.xy / czm_viewport.zw; - - ivec2 centerScreenSpace = ivec2(gl_FragCoord.xy); - - // The position of the neighbor in 3D (eye space) - vec3 centerPosition = texture2D(pointCloud_depthTexture, - v_textureCoordinates).xyz; - - ivec2 neighborScreenSpace = ivec2(int(mod(centerPos, czm_viewport.z)), - int(centerPos) / int(czm_viewport.z)); - vec2 neighborTextureSpace = vec2(neighborScreenSpace) / czm_viewport.zw; - - // The position of this neighborhood center in 3D (eye space) - vec3 neighborPosition = texture2D(pointCloud_depthTexture, - neighborTextureSpace).xyz; - - // If our horizon pixel doesn't exist, ignore it and move on - if (length(neighborPosition) < EPS || - neighborScreenSpace == centerScreenSpace) { - gl_FragData[0] = vec4(1.0); - gl_FragData[1] = vec4(1.0); - return; - } - - // Right now this is obvious because everything happens in eye space, - // but this kind of statement is nice for a reference implementation - vec3 viewer = vec3(0.0); - - // d is the relative offset from the horizon pixel to the center pixel - // in 2D - ivec2 d = neighborScreenSpace - centerScreenSpace; - - // sectors contains both possible sectors that the - // neighbor pixel could be in - ivec2 sectors = readSectors(d); - - // This is the offset of the horizon point from the center in 3D - // (a 3D analog of d) - vec3 c = neighborPosition - centerPosition; - - // Now we calculate the dot product between the vector - // from the viewer to the center and the vector to the horizon pixel. - // We normalize both vectors first because we only care about their relative - // directions - // TODO: Redo the math and figure out whether the result should be negated or not - float dotProduct = dot(normalize(viewer - centerPosition), - normalize(c)); - - // We calculate the angle that this horizon pixel would make - // in the cone. The dot product is be equal to - // |vec_1| * |vec_2| * cos(angle_between), and in this case, - // the magnitude of both vectors is 1 because they are both - // normalized. - float angle = acosFast(dotProduct); - - // This horizon point is behind the current point. That means that it can't - // occlude the current point. So we ignore it and move on. - if (angle > maxAngle || angle < 0.0) { - gl_FragData[0] = vec4(1.0); - gl_FragData[1] = vec4(1.0); - return; - } - - // Normalize to [0, 1] - angle /= maxAngle; - - vec4 sh0 = vec4(1.0); - vec4 sh1 = vec4(1.0); - - updateOutput(sectors.x, angle, sh0, sh1); - updateOutput(sectors.y, angle, sh0, sh1); - - gl_FragData[0] = vec4(sh0); - gl_FragData[1] = vec4(sh1); -} From bd10aa899b750e9f24454e39b3494df1f6d3fb98 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Fri, 28 Jul 2017 15:43:22 -0400 Subject: [PATCH 164/240] Now using texelFetch rather than texture for the WebGL 2 point occlusion pass --- Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl index 4a722614bd60..0c9649666dc5 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl @@ -216,8 +216,7 @@ void main() { ivec2 pI = pos + d; // We now calculate the actual 3D position of the horizon pixel (the horizon point) - vec3 neighborPosition = texture(pointCloud_ECTexture, - vec2(pI) / czm_viewport.zw).xyz; + vec3 neighborPosition = texelFetch(pointCloud_ECTexture, ivec2(pI), 0).xyz; // If our horizon pixel doesn't exist, ignore it and move on if (length(neighborPosition) < EPS || pI == pos) { From cc26265027e8da7137f7d42c7c899c50aa720753 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Fri, 28 Jul 2017 15:49:59 -0400 Subject: [PATCH 165/240] Now using texelFetch(es) in the region growing pass, if we are on WebGL 2 hardware --- .../PostProcessFilters/RegionGrowingPassGL2.glsl | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl index 769c9aea357c..bd60206b3c12 100644 --- a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl @@ -147,12 +147,16 @@ void loadIntoArray(inout float[neighborhoodSize] depthNeighbors, pastCenter = true; continue; } - vec2 neighborCoords = vec2(vec2(d) + gl_FragCoord.xy) / czm_viewport.zw; - float neighbor = czm_unpackDepth(texture(pointCloud_depthTexture, - neighborCoords)); - float aoNeighbor = czm_unpackDepth(texture(pointCloud_aoTexture, - neighborCoords)); - vec4 colorNeighbor = texture(pointCloud_colorTexture, neighborCoords); + ivec2 neighborCoords = d + ivec2(gl_FragCoord.xy); + float neighbor = czm_unpackDepth(texelFetch(pointCloud_depthTexture, + neighborCoords, + 0)); + float aoNeighbor = czm_unpackDepth(texelFetch(pointCloud_aoTexture, + neighborCoords, + 0)); + vec4 colorNeighbor = texelFetch(pointCloud_colorTexture, + neighborCoords, + 0); if (pastCenter) { depthNeighbors[(j + 1) * neighborhoodFullWidth + i] = neighbor; From e9cc868d6aa7b454e191c0ac63368dc1e6b27043 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Fri, 28 Jul 2017 19:18:50 -0400 Subject: [PATCH 166/240] Removes more old, unused code --- Source/Scene/PointCloudPostProcessor.js | 28 +------------------------ 1 file changed, 1 insertion(+), 27 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index e31c33484cfd..8596188a165d 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -78,7 +78,6 @@ define([ this._colorTextures = undefined; this._ecTexture = undefined; this._depthTextures = undefined; - this._sectorTextures = undefined; this._densityTexture = undefined; this._edgeCullingTexture = undefined; this._sectorLUTTexture = undefined; @@ -182,8 +181,6 @@ define([ processor._depthTextures[0].destroy(); processor._depthTextures[1].destroy(); processor._ecTexture.destroy(); - processor._sectorTextures[0].destroy(); - processor._sectorTextures[1].destroy(); processor._sectorLUTTexture.destroy(); processor._aoTextures[0].destroy(); processor._aoTextures[1].destroy(); @@ -203,7 +200,6 @@ define([ processor._colorTextures = undefined; processor._ecTexture = undefined; processor._depthTextures = undefined; - processor._sectorTextures = undefined; processor._densityTexture = undefined; processor._edgeCullingTexture = undefined; processor._sectorLUTTexture = undefined; @@ -258,7 +254,6 @@ define([ var screenHeight = context.drawingBufferHeight; var colorTextures = new Array(2); - var sectorTextures = new Array(2); var depthTextures = new Array(3); var aoTextures = new Array(2); @@ -325,15 +320,6 @@ define([ sampler : createSampler() }); - sectorTextures[i] = new Texture({ - context : context, - width : screenWidth, - height : screenHeight, - pixelFormat : PixelFormat.RGBA, - pixelDatatype : PixelDatatype.FLOAT, - sampler : createSampler() - }); - depthTextures[i] = new Texture({ context : context, width : screenWidth, @@ -383,12 +369,6 @@ define([ colorTextures : [aoTextures[0]], destroyAttachments : false }), - sectorHistogramPass : new Framebuffer({ - context : context, - colorTextures : [sectorTextures[0], sectorTextures[1]], - depthStencilTexture: dirty, - destroyAttachments : false - }), stencilMask : new Framebuffer({ context : context, depthStencilTexture: dirty, @@ -399,11 +379,6 @@ define([ colorTextures : [densityMap], destroyAttachments : false }), - edgeCullingPass : new Framebuffer({ - context : context, - colorTextures : [edgeCullingTexture], - destroyAttachments : false - }), regionGrowingPassA : new Framebuffer({ context : context, colorTextures : [colorTextures[1], @@ -422,7 +397,6 @@ define([ }) }; processor._depthTextures = depthTextures; - processor._sectorTextures = sectorTextures; processor._densityTexture = densityMap; processor._edgeCullingTexture = edgeCullingTexture; processor._sectorLUTTexture = sectorLUTTexture; @@ -827,7 +801,7 @@ define([ owner : processor }); - var aoCommand = aoStage(processor, context, processor._sectorTextures[0]); + var aoCommand = aoStage(processor, context); var framebuffers = processor._framebuffers; var clearCommands = {}; From fe5b55fc0f72be9cf0e8677be3177abb14d310bb Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Mon, 31 Jul 2017 11:01:26 -0400 Subject: [PATCH 167/240] Once again, density estimation only applies to invalid pixels --- Source/Scene/PointCloudPostProcessor.js | 32 +++++++++---------- .../DensityEdgeCullPass.glsl | 6 ++-- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 8596188a165d..a078fb67ce4a 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -86,6 +86,7 @@ define([ this._drawCommands = undefined; this._clearCommands = undefined; + this.densityScaleFactor = 10.0; this.occlusionAngle = options.occlusionAngle; this.rangeParameter = options.rangeParameter; this.neighborhoodHalfWidth = options.neighborhoodHalfWidth; @@ -377,6 +378,7 @@ define([ densityEstimationPass : new Framebuffer({ context : context, colorTextures : [densityMap], + depthStencilTexture: dirty, destroyAttachments : false }), regionGrowingPassA : new Framebuffer({ @@ -447,26 +449,11 @@ define([ processor.useTriangle ); - var func = StencilFunction.EQUAL; - var op = { - fail : StencilOperation.KEEP, - zFail : StencilOperation.KEEP, - zPass : StencilOperation.KEEP - }; - return context.createViewportQuadCommand(pointOcclusionStr, { uniformMap : uniformMap, framebuffer : processor._framebuffers.screenSpacePass, renderState : RenderState.fromCache({ - stencilTest : { - enabled : true, - reference : 0, - mask : 1, - frontFunction : func, - backFunction : func, - frontOperation : op, - backOperation : op - } + stencilTest : processor._positiveStencilTest }), pass : Pass.CESIUM_3D_TILE, owner : processor @@ -496,6 +483,7 @@ define([ uniformMap : uniformMap, framebuffer : processor._framebuffers.densityEstimationPass, renderState : RenderState.fromCache({ + stencilTest : processor._negativeStencilTest }), pass : Pass.CESIUM_3D_TILE, owner : processor @@ -809,7 +797,8 @@ define([ if (framebuffers.hasOwnProperty(name)) { // The screen space pass should consider // the stencil value, so we don't clear it - // here. + // here. 1.0 / densityScale is the base density + // for invalid pixels, so we clear to that. // Also we want to clear the AO buffer to white // so that the pixels that never get region-grown // do not appear black @@ -822,6 +811,15 @@ define([ pass : Pass.CESIUM_3D_TILE, owner : processor }); + } else if (name === 'densityEstimationPass') { + clearCommands[name] = new ClearCommand({ + framebuffer : framebuffers[name], + color : new Color(1.0 / processor.densityScaleFactor, 0.0, 0.0, 0.0), + depth : 1.0, + renderState : RenderState.fromCache(), + pass : Pass.CESIUM_3D_TILE, + owner : processor + }); } else if (name === 'aoBufferA' || name === 'aoBufferB') { clearCommands[name] = new ClearCommand({ diff --git a/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl b/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl index b225fd2c747b..ef99954c91b1 100644 --- a/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl +++ b/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl @@ -44,11 +44,11 @@ void main() { !(absRatio > maxAbsRatio && length(neighborhoodAccum) > neighborhoodVectorSize)) { gl_FragData[0] = vec4(vec3(closestNeighbor / - densityScaleFactor), 1.0); + densityScaleFactor), 0.0); } else { - gl_FragData[0] = vec4(vec3(0.0), 1.0); + gl_FragData[0] = vec4(vec4(0.0)); } } else { - gl_FragData[0] = vec4(vec3(1.0 / densityScaleFactor), 1.0); + gl_FragData[0] = vec4(1.0 / densityScaleFactor, 0.0, 0.0, 0.0); } } From 366cf55ee7a9db4f3ac2f5d0283679c6129efc07 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Mon, 31 Jul 2017 11:54:41 -0400 Subject: [PATCH 168/240] Adds random dropout factor for point occlusion --- .../3D Tiles Point Cloud Post Processing.html | 11 ++++++++++- Source/Scene/Cesium3DTileset.js | 3 ++- Source/Scene/PointCloudPostProcessor.js | 8 +++++++- .../PostProcessFilters/PointOcclusionPassGL2.glsl | 14 ++++++++++++++ 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html index 7390c940fce1..81ba03dc81ea 100644 --- a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html +++ b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html @@ -89,6 +89,13 @@ + + Dropout Factor + + + + + @@ -125,7 +132,8 @@ maxAbsRatio : tileset.pointCloudPostProcessorOptions.maxAbsRatio, pointAttenuationMultiplier : tileset.pointCloudPostProcessorOptions.pointAttenuationMultiplier, sigmoidDomainOffset : tileset.pointCloudPostProcessorOptions.sigmoidDomainOffset, - sigmoidSharpness : tileset.pointCloudPostProcessorOptions.sigmoidSharpness + sigmoidSharpness : tileset.pointCloudPostProcessorOptions.sigmoidSharpness, + dropoutFactor : tileset.pointCloudPostProcessorOptions.dropoutFactor }; Cesium.knockout.track(viewModel); @@ -150,6 +158,7 @@ subscribeParameter('pointAttenuationMultiplier'); subscribeParameter('sigmoidDomainOffset'); subscribeParameter('sigmoidSharpness'); +subscribeParameter('dropoutFactor'); Sandcastle.addToggleButton('Enabled', false, function(checked) { tileset.pointCloudPostProcessorOptions.enabled = checked; diff --git a/Source/Scene/Cesium3DTileset.js b/Source/Scene/Cesium3DTileset.js index ac7ea95938a4..f152ac175dd2 100644 --- a/Source/Scene/Cesium3DTileset.js +++ b/Source/Scene/Cesium3DTileset.js @@ -662,7 +662,8 @@ define([ enableAO : true, AOViewEnabled : false, sigmoidSharpness : 0.2, - sigmoidDomainOffset : 0.2 + sigmoidDomainOffset : 0.2, + dropoutFactor : 0.0 }; this._pointCloudPostProcessor = new PointCloudPostProcessor(this.pointCloudPostProcessorOptions); diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index a078fb67ce4a..6c5bf75a7381 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -102,6 +102,7 @@ define([ this.AOViewEnabled = options.AOViewEnabled; this.sigmoidDomainOffset = options.sigmoidDomainOffset; this.sigmoidSharpness = options.sigmoidSharpness; + this.dropoutFactor = options.dropoutFactor; this._pointArray = undefined; @@ -432,6 +433,9 @@ define([ occlusionAngle : function() { return processor.occlusionAngle; }, + dropoutFactor : function() { + return processor.dropoutFactor; + }, ONE : function() { return 1.0; } @@ -952,7 +956,8 @@ define([ tileset.pointCloudPostProcessorOptions.enableAO !== this.enableAO || tileset.pointCloudPostProcessorOptions.AOViewEnabled !== this.AOViewEnabled || tileset.pointCloudPostProcessorOptions.sigmoidDomainOffset !== this.sigmoidDomainOffset || - tileset.pointCloudPostProcessorOptions.sigmoidSharpness !== this.sigmoidSharpness) { + tileset.pointCloudPostProcessorOptions.sigmoidSharpness !== this.sigmoidSharpness || + tileset.pointCloudPostProcessorOptions.dropoutFactor !== this.dropoutFactor) { this.occlusionAngle = tileset.pointCloudPostProcessorOptions.occlusionAngle; this.rangeParameter = tileset.pointCloudPostProcessorOptions.rangeParameter; this.neighborhoodHalfWidth = tileset.pointCloudPostProcessorOptions.neighborhoodHalfWidth; @@ -968,6 +973,7 @@ define([ this.AOViewEnabled = tileset.pointCloudPostProcessorOptions.AOViewEnabled; this.sigmoidDomainOffset = tileset.pointCloudPostProcessorOptions.sigmoidDomainOffset; this.sigmoidSharpness = tileset.pointCloudPostProcessorOptions.sigmoidSharpness; + this.dropoutFactor = tileset.pointCloudPostProcessorOptions.dropoutFactor; dirty = true; } diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl index 0c9649666dc5..1ee2a3493692 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl @@ -19,6 +19,7 @@ uniform float ONE; uniform sampler2D pointCloud_ECTexture; uniform float occlusionAngle; +uniform float dropoutFactor; uniform sampler2D sectorLUT; in vec2 v_textureCoordinates; @@ -164,6 +165,10 @@ ivec2 readSectors(in ivec2 sectorPosition) { return ivec2(unscaled * float(numSectors)); } +float random(vec2 st) { + return fract(sin(dot(st.xy, vec2(12.9898, 78.233))) * 43758.5453123); +} + void main() { float near = czm_entireFrustum.x; float far = czm_entireFrustum.y; @@ -208,12 +213,21 @@ void main() { // but this kind of statement is nice for a reference implementation vec3 viewer = vec3(0.0); + float seed = random(v_textureCoordinates); for (int i = -neighborhoodHalfWidth; i <= neighborhoodHalfWidth; i++) { for (int j = -neighborhoodHalfWidth; j <= neighborhoodHalfWidth; j++) { // d is the relative offset from the horizon pixel to the center pixel // in 2D ivec2 d = ivec2(i, j); ivec2 pI = pos + d; + vec2 normPI = vec2(pI) / czm_viewport.zw; + + // A cheap approximation of randomness -- local neighborhoods are not + // sufficiently random, but small changes in the seed yield different + // neighborhoods + if (fract(seed * dot(normPI, vec2(902433.23341, 303403.963351))) < dropoutFactor) { + continue; + } // We now calculate the actual 3D position of the horizon pixel (the horizon point) vec3 neighborPosition = texelFetch(pointCloud_ECTexture, ivec2(pI), 0).xyz; From faa7271b4dae6e8b95d0a34e5de03d9c2746824a Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Mon, 31 Jul 2017 12:13:59 -0400 Subject: [PATCH 169/240] Density estimation now uses the new dropout factor --- Source/Scene/PointCloudPostProcessor.js | 17 ++++++++++++++++ .../DensityEdgeCullPass.glsl | 20 ++++++++++++++++++- .../PointOcclusionPassGL2.glsl | 6 +++++- 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 6c5bf75a7381..926a6583e072 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -453,6 +453,13 @@ define([ processor.useTriangle ); + if (processor.dropoutFactor < 1e-6) { + pointOcclusionStr = replaceConstants( + pointOcclusionStr, + 'dropoutEnabled', + false); + } + return context.createViewportQuadCommand(pointOcclusionStr, { uniformMap : uniformMap, framebuffer : processor._framebuffers.screenSpacePass, @@ -474,6 +481,9 @@ define([ }, maxAbsRatio : function() { return processor.maxAbsRatio; + }, + dropoutFactor : function() { + return processor.dropoutFactor; } }; @@ -483,6 +493,13 @@ define([ processor.densityHalfWidth ); + if (processor.dropoutFactor < 1e-6 || !context.webgl2) { + densityEdgeCullStr = replaceConstants( + densityEdgeCullStr, + 'dropoutEnabled', + false); + } + return context.createViewportQuadCommand(densityEdgeCullStr, { uniformMap : uniformMap, framebuffer : processor._framebuffers.densityEstimationPass, diff --git a/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl b/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl index ef99954c91b1..b04ef1fab6f4 100644 --- a/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl +++ b/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl @@ -3,12 +3,18 @@ #define EPS 1e-8 #define densityScaleFactor 10.0 +#define dropoutEnabled uniform sampler2D pointCloud_depthTexture; uniform float neighborhoodVectorSize; uniform float maxAbsRatio; +uniform float dropoutFactor; varying vec2 v_textureCoordinates; +float random(vec2 st) { + return fract(sin(dot(st.xy, vec2(12.9898, 78.233))) * 43758.5453123); +} + void main() { float center = czm_unpackDepth(texture2D(pointCloud_depthTexture, v_textureCoordinates)); @@ -19,13 +25,25 @@ void main() { vec2 absNeighborhoodAccum = vec2(0.0); if (center < EPS) { + float seed = random(v_textureCoordinates); for (int i = -neighborhoodHalfWidth; i <= neighborhoodHalfWidth; i++) { for (int j = -neighborhoodHalfWidth; j <= neighborhoodHalfWidth; j++) { ivec2 d = ivec2(i, j); ivec2 pI = pos + d; + vec2 normPI = vec2(pI) / czm_viewport.zw; + +#ifdef dropoutEnabled + // A cheap approximation of randomness -- local neighborhoods are not + // sufficiently random, but small changes in the seed yield different + // neighborhoods + if (fract(seed * dot(normPI, vec2(902433.23341, 303403.963351))) + < dropoutFactor) { + continue; + } +#endif // dropoutEnabled float neighbor = czm_unpackDepth(texture2D(pointCloud_depthTexture, - vec2(pI) / czm_viewport.zw)); + normPI)); if (neighbor < EPS || pI == pos) { continue; } diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl index 1ee2a3493692..4ae7429372d5 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl @@ -14,6 +14,7 @@ #define trianglePeriod 1e-2 #define useTriangle +#define dropoutEnabled uniform float ONE; @@ -222,12 +223,15 @@ void main() { ivec2 pI = pos + d; vec2 normPI = vec2(pI) / czm_viewport.zw; +#ifdef dropoutEnabled // A cheap approximation of randomness -- local neighborhoods are not // sufficiently random, but small changes in the seed yield different // neighborhoods - if (fract(seed * dot(normPI, vec2(902433.23341, 303403.963351))) < dropoutFactor) { + if (fract(seed * dot(normPI, vec2(902433.23341, 303403.963351))) + < dropoutFactor) { continue; } +#endif //dropoutEnabled // We now calculate the actual 3D position of the horizon pixel (the horizon point) vec3 neighborPosition = texelFetch(pointCloud_ECTexture, ivec2(pI), 0).xyz; From cf20cc4df2218a361b013b4f5771a6d0a7053209 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Mon, 31 Jul 2017 13:44:49 -0400 Subject: [PATCH 170/240] Changes dropout so that it works a lot more like the old reduction factor --- .../DensityEdgeCullPass.glsl | 23 +++++++++++-------- .../PointOcclusionPassGL2.glsl | 23 ++++++++----------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl b/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl index b04ef1fab6f4..52c27cd68528 100644 --- a/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl +++ b/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl @@ -25,23 +25,26 @@ void main() { vec2 absNeighborhoodAccum = vec2(0.0); if (center < EPS) { + int width = neighborhoodHalfWidth; + +#ifdef dropoutEnabled float seed = random(v_textureCoordinates); + if (seed < dropoutFactor) { + width = int(float(width) * (1.0 - dropoutFactor)); + } +#endif //dropoutEnabled + +#ifdef dropoutEnabled + for (int i = -width; i <= width; i++) { + for (int j = -width; j <= width; j++) { +#else for (int i = -neighborhoodHalfWidth; i <= neighborhoodHalfWidth; i++) { for (int j = -neighborhoodHalfWidth; j <= neighborhoodHalfWidth; j++) { +#endif // dropoutEnabled ivec2 d = ivec2(i, j); ivec2 pI = pos + d; vec2 normPI = vec2(pI) / czm_viewport.zw; -#ifdef dropoutEnabled - // A cheap approximation of randomness -- local neighborhoods are not - // sufficiently random, but small changes in the seed yield different - // neighborhoods - if (fract(seed * dot(normPI, vec2(902433.23341, 303403.963351))) - < dropoutFactor) { - continue; - } -#endif // dropoutEnabled - float neighbor = czm_unpackDepth(texture2D(pointCloud_depthTexture, normPI)); if (neighbor < EPS || pI == pos) { diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl index 4ae7429372d5..fa88c30440e2 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl @@ -214,24 +214,21 @@ void main() { // but this kind of statement is nice for a reference implementation vec3 viewer = vec3(0.0); + int width = neighborhoodHalfWidth; + +#ifdef dropoutEnabled float seed = random(v_textureCoordinates); - for (int i = -neighborhoodHalfWidth; i <= neighborhoodHalfWidth; i++) { - for (int j = -neighborhoodHalfWidth; j <= neighborhoodHalfWidth; j++) { + if (seed < dropoutFactor) { + width = int(float(width) * (1.0 - dropoutFactor)); + } +#endif //dropoutEnabled + + for (int i = -width; i <= width; i++) { + for (int j = -width; j <= width; j++) { // d is the relative offset from the horizon pixel to the center pixel // in 2D ivec2 d = ivec2(i, j); ivec2 pI = pos + d; - vec2 normPI = vec2(pI) / czm_viewport.zw; - -#ifdef dropoutEnabled - // A cheap approximation of randomness -- local neighborhoods are not - // sufficiently random, but small changes in the seed yield different - // neighborhoods - if (fract(seed * dot(normPI, vec2(902433.23341, 303403.963351))) - < dropoutFactor) { - continue; - } -#endif //dropoutEnabled // We now calculate the actual 3D position of the horizon pixel (the horizon point) vec3 neighborPosition = texelFetch(pointCloud_ECTexture, ivec2(pI), 0).xyz; From 297fb9f01d8de0beda7ab16fd521c83a8f06f99b Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Tue, 1 Aug 2017 10:18:52 -0400 Subject: [PATCH 171/240] Delay parameter is now configurable --- .../3D Tiles Point Cloud Post Processing.html | 11 ++++++++++- Source/Scene/Cesium3DTileset.js | 3 ++- Source/Scene/PointCloudPostProcessor.js | 19 +++++++++++++++++-- 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html index 81ba03dc81ea..3b2b82a94589 100644 --- a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html +++ b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html @@ -96,6 +96,13 @@ + + Delay + + + + + @@ -133,7 +140,8 @@ pointAttenuationMultiplier : tileset.pointCloudPostProcessorOptions.pointAttenuationMultiplier, sigmoidDomainOffset : tileset.pointCloudPostProcessorOptions.sigmoidDomainOffset, sigmoidSharpness : tileset.pointCloudPostProcessorOptions.sigmoidSharpness, - dropoutFactor : tileset.pointCloudPostProcessorOptions.dropoutFactor + dropoutFactor : tileset.pointCloudPostProcessorOptions.dropoutFactor, + delay : tileset.pointCloudPostProcessorOptions.delay }; Cesium.knockout.track(viewModel); @@ -159,6 +167,7 @@ subscribeParameter('sigmoidDomainOffset'); subscribeParameter('sigmoidSharpness'); subscribeParameter('dropoutFactor'); +subscribeParameter('delay'); Sandcastle.addToggleButton('Enabled', false, function(checked) { tileset.pointCloudPostProcessorOptions.enabled = checked; diff --git a/Source/Scene/Cesium3DTileset.js b/Source/Scene/Cesium3DTileset.js index f152ac175dd2..7be25959882f 100644 --- a/Source/Scene/Cesium3DTileset.js +++ b/Source/Scene/Cesium3DTileset.js @@ -663,7 +663,8 @@ define([ AOViewEnabled : false, sigmoidSharpness : 0.2, sigmoidDomainOffset : 0.2, - dropoutFactor : 0.0 + dropoutFactor : 0.0, + delay : 0 }; this._pointCloudPostProcessor = new PointCloudPostProcessor(this.pointCloudPostProcessorOptions); diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 926a6583e072..f43cb96482ae 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -103,6 +103,7 @@ define([ this.sigmoidDomainOffset = options.sigmoidDomainOffset; this.sigmoidSharpness = options.sigmoidSharpness; this.dropoutFactor = options.dropoutFactor; + this.delay = options.delay; this._pointArray = undefined; @@ -566,6 +567,12 @@ define([ processor.stencilViewEnabled ); + regionGrowingPassStr = replaceConstants( + regionGrowingPassStr, + 'DELAY', + processor.delay + ); + return context.createViewportQuadCommand(regionGrowingPassStr, { uniformMap : uniformMap, framebuffer : framebuffer, @@ -657,7 +664,7 @@ define([ var stencilMaskStageStr = '#define EPS 1e-8 \n' + '#define cutoff 0 \n' + - '#define DELAY 0 \n' + + '#define DELAY 1 \n' + '#define densityScaleFactor 10.0 \n' + 'uniform sampler2D pointCloud_densityTexture; \n' + 'varying vec2 v_textureCoordinates; \n' + @@ -674,6 +681,12 @@ define([ iteration ); + stencilMaskStageStr = replaceConstants( + stencilMaskStageStr, + 'DELAY', + processor.delay + ); + var framebuffer = processor._framebuffers.stencilMask; return context.createViewportQuadCommand(stencilMaskStageStr, { @@ -974,7 +987,8 @@ define([ tileset.pointCloudPostProcessorOptions.AOViewEnabled !== this.AOViewEnabled || tileset.pointCloudPostProcessorOptions.sigmoidDomainOffset !== this.sigmoidDomainOffset || tileset.pointCloudPostProcessorOptions.sigmoidSharpness !== this.sigmoidSharpness || - tileset.pointCloudPostProcessorOptions.dropoutFactor !== this.dropoutFactor) { + tileset.pointCloudPostProcessorOptions.dropoutFactor !== this.dropoutFactor || + tileset.pointCloudPostProcessorOptions.delay !== this.delay) { this.occlusionAngle = tileset.pointCloudPostProcessorOptions.occlusionAngle; this.rangeParameter = tileset.pointCloudPostProcessorOptions.rangeParameter; this.neighborhoodHalfWidth = tileset.pointCloudPostProcessorOptions.neighborhoodHalfWidth; @@ -991,6 +1005,7 @@ define([ this.sigmoidDomainOffset = tileset.pointCloudPostProcessorOptions.sigmoidDomainOffset; this.sigmoidSharpness = tileset.pointCloudPostProcessorOptions.sigmoidSharpness; this.dropoutFactor = tileset.pointCloudPostProcessorOptions.dropoutFactor; + this.delay = tileset.pointCloudPostProcessorOptions.delay; dirty = true; } From b00501f61e2377b23491395712850f71cf2cefda Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 2 Aug 2017 13:53:33 -0400 Subject: [PATCH 172/240] Sigmoid function is now much simpler --- Source/Scene/PointCloudPostProcessor.js | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index f43cb96482ae..198e9206aaa8 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -757,22 +757,14 @@ define([ 'uniform float sigmoidSharpness; \n' + 'varying vec2 v_textureCoordinates; \n\n' + 'float sigmoid2(float x, float sharpness) { \n' + - ' if (x >= 1.0) return 1.0; \n' + - ' else if (x <= -1.0) return -1.0; \n' + - ' else { \n' + - ' if (sharpness < 0.0) sharpness -= 1.0; \n' + - ' \n' + - ' if (x > 0.0) return sharpness * x / (sharpness - x + 1.0); \n' + - ' else if (x < 0.0) return sharpness * x / (sharpness - abs(x) + 1.0); \n' + - ' else return 0.0; \n' + - ' } \n' + + ' return sharpness * x / (sharpness - x + 1.0);' + '} \n\n' + 'void main() \n' + '{ \n' + ' vec4 color = texture2D(pointCloud_colorTexture, v_textureCoordinates); \n' + ' #ifdef enableAO \n' + ' float ao = czm_unpackDepth(texture2D(pointCloud_aoTexture, v_textureCoordinates)); \n' + - ' ao = clamp(sigmoid2(ao + sigmoidDomainOffset, sigmoidSharpness), 0.0, 1.0); \n' + + ' ao = clamp(sigmoid2(clamp(ao + sigmoidDomainOffset, 0.0, 1.0), sigmoidSharpness), 0.0, 1.0); \n' + ' color.xyz = color.xyz * ao; \n' + ' #endif // enableAO \n' + ' float rayDist = czm_unpackDepth(texture2D(pointCloud_depthTexture, v_textureCoordinates)); \n' + From 371aaea8553a177b7ef3e8971289fd1e9df344f1 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 2 Aug 2017 14:01:50 -0400 Subject: [PATCH 173/240] Sigmoid function rename --- Source/Scene/PointCloudPostProcessor.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 198e9206aaa8..1920ba8bcad7 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -756,7 +756,7 @@ define([ 'uniform float sigmoidDomainOffset; \n' + 'uniform float sigmoidSharpness; \n' + 'varying vec2 v_textureCoordinates; \n\n' + - 'float sigmoid2(float x, float sharpness) { \n' + + 'float sigmoid(float x, float sharpness) { \n' + ' return sharpness * x / (sharpness - x + 1.0);' + '} \n\n' + 'void main() \n' + @@ -764,7 +764,7 @@ define([ ' vec4 color = texture2D(pointCloud_colorTexture, v_textureCoordinates); \n' + ' #ifdef enableAO \n' + ' float ao = czm_unpackDepth(texture2D(pointCloud_aoTexture, v_textureCoordinates)); \n' + - ' ao = clamp(sigmoid2(clamp(ao + sigmoidDomainOffset, 0.0, 1.0), sigmoidSharpness), 0.0, 1.0); \n' + + ' ao = clamp(sigmoid(clamp(ao + sigmoidDomainOffset, 0.0, 1.0), sigmoidSharpness), 0.0, 1.0); \n' + ' color.xyz = color.xyz * ao; \n' + ' #endif // enableAO \n' + ' float rayDist = czm_unpackDepth(texture2D(pointCloud_depthTexture, v_textureCoordinates)); \n' + From f47da9e20c6e63a610b90715861885c4041838a3 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 2 Aug 2017 15:39:56 -0400 Subject: [PATCH 174/240] Updates the doc comment on the point cloud post processor --- Source/Scene/Cesium3DTileset.js | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/Source/Scene/Cesium3DTileset.js b/Source/Scene/Cesium3DTileset.js index 7be25959882f..b25368ce5ee0 100644 --- a/Source/Scene/Cesium3DTileset.js +++ b/Source/Scene/Cesium3DTileset.js @@ -638,13 +638,31 @@ define([ /** * This property handles options for the point cloud post processor *

- * TODO: Write documentation for these properties + * @param {Boolean} enabled Whether or not point cloud post processing will occur + * @param {Number} occlusionAngle The occlusion angle -- [0, 4 * pi] is represented by [-1, 1] + * @param {Number} rangeParameter The equivalent of the range sigma on a bilateral filter; range [0, 1] + * @param {Number} neighborhoodHalfWidth Half of the width of the point occlusion operator's kernel size minus 1 + * @param {Number} densityHalfWidth Half of the width of the density estimation operator's kernel size minus 1 + * @param {Number} neighborhoodVectorSize Parameter for the edge culling algorithm; decrease to make edge culling more aggressive + * @param {Number} maxAbsRatio Parameter for the edge culling algorithm; decrease to make edge culling more aggressive + * @param {Boolean} densityViewEnabled Whether or not the density view is enabled + * @param {Boolean} stencilViewEnabled Whether or not the stencil view is enabled + * @param {Boolean} pointAttenuationMultiplier The factor by which points at the near plane are larger than points at the far plane + * @param {Boolean} useTriangle Whether or not to use the triangle wave optimization + * @param {Boolean} enableAO Whether or not to blend with ambient occlusion + * @param {Boolean} AOViewEnabled Whether or not the ambient occlusion view is enabled + * @param {Number} sigmoidSharpness The "sharpness" of the sigmoid function used for AO; closer to 0 is sharper + * @param {Number} sigmoidDomainOffset The offset into the domain of the sigmoid function -- used for brightness control + * @param {Number} dropoutFactor Used to probabilistically tune the neighbor search; closer to 1.0 means smaller neighborhoods + * @param {Number} delay The number of iterations of blurring that valid pixels receive *

* * @type {Object} * @default {enabled : true, occlusionAngle : 0.1, rangeParameter : 1.0, neighborhoodHalfWidth : 4 * numRegionGrowingPasses : 4, densityHalfWidth : 4, neighborhoodVectorSize : 10.0, maxAbsRatio : 0.9 - * densityViewEnabled : false, stencilViewEnabled : false, pointAttenuationMultiplier : 2.0} + * densityViewEnabled : false, stencilViewEnabled : false, pointAttenuationMultiplier : 2.0, + * useTriangle : false, enableAO : true, AOViewEnabled : true, sigmoidSharpness : 0.2, + * sigmoidDomainOffset : 0.2, dropoutFactor : 0.0, delay : 0} */ this.pointCloudPostProcessorOptions = { enabled : false, From c78b3a39ee66aa5aaf9eb44d0f55e49229d50fbd Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 2 Aug 2017 15:43:42 -0400 Subject: [PATCH 175/240] Renames the aoStage to debugViewStage --- Source/Scene/PointCloudPostProcessor.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 1920ba8bcad7..7aa59a6e70be 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -700,14 +700,14 @@ define([ }); } - function aoStage(processor, context) { + function debugViewStage(processor, context) { var uniformMap = { aoTexture : function() { return processor._aoTextures[0]; } }; - var aoStageStr = + var debugViewStageStr = '#define EPS 1e-8 \n' + 'uniform sampler2D aoTexture; \n' + 'varying vec2 v_textureCoordinates; \n' + @@ -718,7 +718,7 @@ define([ ' gl_FragColor = vec4(occlusion); \n' + '} \n'; - return context.createViewportQuadCommand(aoStageStr, { + return context.createViewportQuadCommand(debugViewStageStr, { uniformMap : uniformMap, renderState : RenderState.fromCache({ }), @@ -815,7 +815,7 @@ define([ owner : processor }); - var aoCommand = aoStage(processor, context); + var debugViewCommand = debugViewStage(processor, context); var framebuffers = processor._framebuffers; var clearCommands = {}; @@ -874,7 +874,7 @@ define([ processor._drawCommands.stencilCommands = stencilCommands; processor._drawCommands.blendCommand = blendCommand; processor._drawCommands.copyCommands = copyCommands; - processor._drawCommands.aoCommand = aoCommand; + processor._drawCommands.debugViewCommand = debugViewCommand; processor._clearCommands = clearCommands; } @@ -1060,7 +1060,7 @@ define([ var stencilCommands = this._drawCommands.stencilCommands; var clearCommands = this._clearCommands; var blendCommand = this._drawCommands.blendCommand; - var aoCommand = this._drawCommands.aoCommand; + var debugViewCommand = this._drawCommands.debugViewCommand; var numRegionGrowingCommands = regionGrowingCommands.length; commandList.push(clearCommands['screenSpacePass']); @@ -1086,7 +1086,7 @@ define([ // Blend final result back into the main FBO commandList.push(blendCommand); if (this.AOViewEnabled && this.enableAO) { - commandList.push(aoCommand); + commandList.push(debugViewCommand); } commandList.push(clearCommands['prior']); From 411c08fd648edaab3f15c55194380592f295c6e4 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 2 Aug 2017 15:55:37 -0400 Subject: [PATCH 176/240] Adds in depth view --- .../3D Tiles Point Cloud Post Processing.html | 12 +++++++++ Source/Scene/Cesium3DTileset.js | 1 + Source/Scene/PointCloudPostProcessor.js | 26 ++++++++++++------- 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html index 3b2b82a94589..d0fdcaddc623 100644 --- a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html +++ b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html @@ -184,6 +184,15 @@ Sandcastle.addToolbarMenu([{ text : 'Color View', onselect : function() { + tileset.pointCloudPostProcessorOptions.depthViewEnabled = false; + tileset.pointCloudPostProcessorOptions.densityViewEnabled = false; + tileset.pointCloudPostProcessorOptions.stencilViewEnabled = false; + tileset.pointCloudPostProcessorOptions.AOViewEnabled = false; + } +}, { + text : 'Depth View', + onselect : function() { + tileset.pointCloudPostProcessorOptions.depthViewEnabled = true; tileset.pointCloudPostProcessorOptions.densityViewEnabled = false; tileset.pointCloudPostProcessorOptions.stencilViewEnabled = false; tileset.pointCloudPostProcessorOptions.AOViewEnabled = false; @@ -191,6 +200,7 @@ }, { text : 'Density View', onselect : function() { + tileset.pointCloudPostProcessorOptions.depthViewEnabled = false; tileset.pointCloudPostProcessorOptions.densityViewEnabled = true; tileset.pointCloudPostProcessorOptions.stencilViewEnabled = false; tileset.pointCloudPostProcessorOptions.AOViewEnabled = false; @@ -198,6 +208,7 @@ }, { text : 'Stencil View', onselect : function() { + tileset.pointCloudPostProcessorOptions.depthViewEnabled = false; tileset.pointCloudPostProcessorOptions.densityViewEnabled = false; tileset.pointCloudPostProcessorOptions.stencilViewEnabled = true; tileset.pointCloudPostProcessorOptions.AOViewEnabled = false; @@ -205,6 +216,7 @@ }, { text : 'AO View', onselect : function() { + tileset.pointCloudPostProcessorOptions.depthViewEnabled = false; tileset.pointCloudPostProcessorOptions.densityViewEnabled = false; tileset.pointCloudPostProcessorOptions.stencilViewEnabled = false; tileset.pointCloudPostProcessorOptions.AOViewEnabled = true; diff --git a/Source/Scene/Cesium3DTileset.js b/Source/Scene/Cesium3DTileset.js index b25368ce5ee0..7ec73f76a432 100644 --- a/Source/Scene/Cesium3DTileset.js +++ b/Source/Scene/Cesium3DTileset.js @@ -678,6 +678,7 @@ define([ pointAttenuationMultiplier : 2.0, useTriangle : false, enableAO : true, + depthViewEnabled : false, AOViewEnabled : false, sigmoidSharpness : 0.2, sigmoidDomainOffset : 0.2, diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 7aa59a6e70be..8dad2a1d2544 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -100,6 +100,7 @@ define([ this.useTriangle = options.useTriangle; this.enableAO = options.enableAO; this.AOViewEnabled = options.AOViewEnabled; + this.depthViewEnabled = options.depthViewEnabled; this.sigmoidDomainOffset = options.sigmoidDomainOffset; this.sigmoidSharpness = options.sigmoidSharpness; this.dropoutFactor = options.dropoutFactor; @@ -700,22 +701,22 @@ define([ }); } - function debugViewStage(processor, context) { + function debugViewStage(processor, context, texture) { var uniformMap = { - aoTexture : function() { - return processor._aoTextures[0]; + debugTexture : function() { + return texture; } }; var debugViewStageStr = '#define EPS 1e-8 \n' + - 'uniform sampler2D aoTexture; \n' + + 'uniform sampler2D debugTexture; \n' + 'varying vec2 v_textureCoordinates; \n' + 'void main() \n' + '{ \n' + - ' vec4 raw = texture2D(aoTexture, v_textureCoordinates); \n' + - ' float occlusion = czm_unpackDepth(raw); \n' + - ' gl_FragColor = vec4(occlusion); \n' + + ' vec4 raw = texture2D(debugTexture, v_textureCoordinates); \n' + + ' float value = czm_unpackDepth(raw); \n' + + ' gl_FragColor = vec4(value); \n' + '} \n'; return context.createViewportQuadCommand(debugViewStageStr, { @@ -815,7 +816,12 @@ define([ owner : processor }); - var debugViewCommand = debugViewStage(processor, context); + var debugViewCommand; + if (processor.AOViewEnabled) { + debugViewCommand = debugViewStage(processor, context, processor._aoTextures[0]); + } else if (processor.depthViewEnabled) { + debugViewCommand = debugViewStage(processor, context, processor._depthTextures[0]); + } var framebuffers = processor._framebuffers; var clearCommands = {}; @@ -972,6 +978,7 @@ define([ tileset.pointCloudPostProcessorOptions.neighborhoodVectorSize !== this.neighborhoodVectorSize || tileset.pointCloudPostProcessorOptions.maxAbsRatio !== this.maxAbsRatio || tileset.pointCloudPostProcessorOptions.densityViewEnabled !== this.densityViewEnabled || + tileset.pointCloudPostProcessorOptions.depthViewEnabled !== this.depthViewEnabled || tileset.pointCloudPostProcessorOptions.stencilViewEnabled !== this.stencilViewEnabled || tileset.pointCloudPostProcessorOptions.pointAttenuationMultiplier !== this.pointAttenuationMultiplier || tileset.pointCloudPostProcessorOptions.useTriangle !== this.useTriangle || @@ -988,6 +995,7 @@ define([ this.densityHalfWidth = tileset.pointCloudPostProcessorOptions.densityHalfWidth; this.neighborhoodVectorSize = tileset.pointCloudPostProcessorOptions.neighborhoodVectorSize; this.densityViewEnabled = tileset.pointCloudPostProcessorOptions.densityViewEnabled; + this.depthViewEnabled = tileset.pointCloudPostProcessorOptions.depthViewEnabled; this.stencilViewEnabled = tileset.pointCloudPostProcessorOptions.stencilViewEnabled; this.maxAbsRatio = tileset.pointCloudPostProcessorOptions.maxAbsRatio; this.pointAttenuationMultiplier = tileset.pointCloudPostProcessorOptions.pointAttenuationMultiplier; @@ -1085,7 +1093,7 @@ define([ // Blend final result back into the main FBO commandList.push(blendCommand); - if (this.AOViewEnabled && this.enableAO) { + if ((this.AOViewEnabled && this.enableAO) || this.depthViewEnabled) { commandList.push(debugViewCommand); } From cdc5ecc49970e7d17d6f912a7825cb5ecf5b9ae4 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Thu, 3 Aug 2017 11:26:50 -0400 Subject: [PATCH 177/240] Changes the triangle wave period to a more reasonable value --- Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl | 2 +- Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl index 9a527759982c..84cb3e410d6a 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl @@ -12,7 +12,7 @@ #define neighborhoodHalfWidth 4 // TUNABLE PARAMETER -- half-width of point-occlusion neighborhood #define numSectors 8 -#define trianglePeriod 1e-5 +#define trianglePeriod 1.0 #define useTriangle uniform float ONE; diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl index fa88c30440e2..24fbf967915c 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl @@ -12,7 +12,7 @@ #define neighborhoodSize 9 #define numSectors 8 -#define trianglePeriod 1e-2 +#define trianglePeriod 1.0 #define useTriangle #define dropoutEnabled From 02998efa4bf95f6f6f3063e7a106e0190f986d3c Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Fri, 4 Aug 2017 09:49:59 -0400 Subject: [PATCH 178/240] Adds documentation for the depth view --- Source/Scene/Cesium3DTileset.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/Scene/Cesium3DTileset.js b/Source/Scene/Cesium3DTileset.js index 7ec73f76a432..824ea10221e0 100644 --- a/Source/Scene/Cesium3DTileset.js +++ b/Source/Scene/Cesium3DTileset.js @@ -650,6 +650,7 @@ define([ * @param {Boolean} pointAttenuationMultiplier The factor by which points at the near plane are larger than points at the far plane * @param {Boolean} useTriangle Whether or not to use the triangle wave optimization * @param {Boolean} enableAO Whether or not to blend with ambient occlusion + * @param {Boolean} depthViewEnabled Whether or not the depth view is enabled * @param {Boolean} AOViewEnabled Whether or not the ambient occlusion view is enabled * @param {Number} sigmoidSharpness The "sharpness" of the sigmoid function used for AO; closer to 0 is sharper * @param {Number} sigmoidDomainOffset The offset into the domain of the sigmoid function -- used for brightness control @@ -661,7 +662,7 @@ define([ * @default {enabled : true, occlusionAngle : 0.1, rangeParameter : 1.0, neighborhoodHalfWidth : 4 * numRegionGrowingPasses : 4, densityHalfWidth : 4, neighborhoodVectorSize : 10.0, maxAbsRatio : 0.9 * densityViewEnabled : false, stencilViewEnabled : false, pointAttenuationMultiplier : 2.0, - * useTriangle : false, enableAO : true, AOViewEnabled : true, sigmoidSharpness : 0.2, + * useTriangle : false, enableAO : true, depthViewEnabled : false, AOViewEnabled : true, sigmoidSharpness : 0.2, * sigmoidDomainOffset : 0.2, dropoutFactor : 0.0, delay : 0} */ this.pointCloudPostProcessorOptions = { From d96632da1dab207b587940712fb59c9604b2b319 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Fri, 4 Aug 2017 10:57:31 -0400 Subject: [PATCH 179/240] Fixes a bug with rescaled ray depth --- Source/Scene/PointCloudPostProcessor.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 8dad2a1d2544..aa703415d57f 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -774,15 +774,19 @@ define([ ' } else { \n' + ' float frustumLength = czm_clampedFrustum.y - czm_clampedFrustum.x; \n' + ' float scaledRayDist = rayDist * frustumLength + czm_clampedFrustum.x; \n' + - ' vec4 ray = normalize(czm_windowToEyeCoordinates(vec4(gl_FragCoord))); \n' + - ' float depth = czm_eyeToWindowCoordinates(ray * scaledRayDist).z; \n' + + ' vec3 ray = normalize(czm_windowToEyeCoordinates(vec4(gl_FragCoord)).xyz); \n' + + ' float depth = czm_eyeToWindowCoordinates(vec4(ray * scaledRayDist, 0)).z; \n' + ' gl_FragColor = color; \n' + ' gl_FragDepthEXT = depth; \n' + ' }' + '} \n'; var blendRenderState = RenderState.fromCache({ - blending : BlendingState.ALPHA_BLEND + blending : BlendingState.ALPHA_BLEND/*, + depthMask : true, + depthTest : { + enabled : true + }*/ }); blendFS = replaceConstants( From 74dcc292efa057f7d022a2847e41f6e8ff6b4b63 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Fri, 4 Aug 2017 14:04:42 -0400 Subject: [PATCH 180/240] Fixes bug where eye-space coordinates weren't homogeneous --- Source/Scene/PointCloudPostProcessor.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index aa703415d57f..03ebf1633328 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -775,18 +775,18 @@ define([ ' float frustumLength = czm_clampedFrustum.y - czm_clampedFrustum.x; \n' + ' float scaledRayDist = rayDist * frustumLength + czm_clampedFrustum.x; \n' + ' vec3 ray = normalize(czm_windowToEyeCoordinates(vec4(gl_FragCoord)).xyz); \n' + - ' float depth = czm_eyeToWindowCoordinates(vec4(ray * scaledRayDist, 0)).z; \n' + + ' float depth = czm_eyeToWindowCoordinates(vec4(ray * scaledRayDist, 1.0)).z; \n' + ' gl_FragColor = color; \n' + ' gl_FragDepthEXT = depth; \n' + ' }' + '} \n'; var blendRenderState = RenderState.fromCache({ - blending : BlendingState.ALPHA_BLEND/*, + blending : BlendingState.ALPHA_BLEND, depthMask : true, depthTest : { enabled : true - }*/ + } }); blendFS = replaceConstants( From 48119a540d81645a65374ad156a593e7d56d0f8c Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Fri, 4 Aug 2017 14:07:14 -0400 Subject: [PATCH 181/240] Moves blending to its own file --- Source/Scene/PointCloudPostProcessor.js | 42 +++---------------- .../PointCloudPostProcessorBlendPass.glsl | 35 ++++++++++++++++ 2 files changed, 40 insertions(+), 37 deletions(-) create mode 100644 Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 03ebf1633328..8f63af26967b 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -33,6 +33,7 @@ define([ '../Shaders/PostProcessFilters/RegionGrowingPassGL1', '../Shaders/PostProcessFilters/RegionGrowingPassGL2', '../Shaders/PostProcessFilters/DensityEdgeCullPass', + '../Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass' ], function( Color, ComponentDatatype, @@ -66,7 +67,8 @@ define([ PointOcclusionPassGL2, RegionGrowingPassGL1, RegionGrowingPassGL2, - DensityEdgeCullPass + DensityEdgeCullPass, + PointCloudPostProcessorBlendPass ) { 'use strict'; @@ -747,40 +749,6 @@ define([ copyCommands[0] = copyRegionGrowingColorStage(processor, context, 0); copyCommands[1] = copyRegionGrowingColorStage(processor, context, 1); - var blendFS = - '#define EPS 1e-8 \n' + - '#define enableAO' + - '#extension GL_EXT_frag_depth : enable \n' + - 'uniform sampler2D pointCloud_colorTexture; \n' + - 'uniform sampler2D pointCloud_depthTexture; \n' + - 'uniform sampler2D pointCloud_aoTexture; \n' + - 'uniform float sigmoidDomainOffset; \n' + - 'uniform float sigmoidSharpness; \n' + - 'varying vec2 v_textureCoordinates; \n\n' + - 'float sigmoid(float x, float sharpness) { \n' + - ' return sharpness * x / (sharpness - x + 1.0);' + - '} \n\n' + - 'void main() \n' + - '{ \n' + - ' vec4 color = texture2D(pointCloud_colorTexture, v_textureCoordinates); \n' + - ' #ifdef enableAO \n' + - ' float ao = czm_unpackDepth(texture2D(pointCloud_aoTexture, v_textureCoordinates)); \n' + - ' ao = clamp(sigmoid(clamp(ao + sigmoidDomainOffset, 0.0, 1.0), sigmoidSharpness), 0.0, 1.0); \n' + - ' color.xyz = color.xyz * ao; \n' + - ' #endif // enableAO \n' + - ' float rayDist = czm_unpackDepth(texture2D(pointCloud_depthTexture, v_textureCoordinates)); \n' + - ' if (length(rayDist) < EPS) { \n' + - ' discard;' + - ' } else { \n' + - ' float frustumLength = czm_clampedFrustum.y - czm_clampedFrustum.x; \n' + - ' float scaledRayDist = rayDist * frustumLength + czm_clampedFrustum.x; \n' + - ' vec3 ray = normalize(czm_windowToEyeCoordinates(vec4(gl_FragCoord)).xyz); \n' + - ' float depth = czm_eyeToWindowCoordinates(vec4(ray * scaledRayDist, 1.0)).z; \n' + - ' gl_FragColor = color; \n' + - ' gl_FragDepthEXT = depth; \n' + - ' }' + - '} \n'; - var blendRenderState = RenderState.fromCache({ blending : BlendingState.ALPHA_BLEND, depthMask : true, @@ -789,8 +757,8 @@ define([ } }); - blendFS = replaceConstants( - blendFS, + var blendFS = replaceConstants( + PointCloudPostProcessorBlendPass, 'enableAO', processor.enableAO && !processor.densityViewEnabled && !processor.stencilViewEnabled ); diff --git a/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl b/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl new file mode 100644 index 000000000000..e3b9c21f8c96 --- /dev/null +++ b/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl @@ -0,0 +1,35 @@ +#define EPS 1e-8 +#define enableAO +#extension GL_EXT_frag_depth : enable + +uniform sampler2D pointCloud_colorTexture; +uniform sampler2D pointCloud_depthTexture; +uniform sampler2D pointCloud_aoTexture; +uniform float sigmoidDomainOffset; +uniform float sigmoidSharpness; +varying vec2 v_textureCoordinates; +float sigmoid(float x, float sharpness) { + return sharpness * x / (sharpness - x + 1.0); +} +void main() { + vec4 color = texture2D(pointCloud_colorTexture, v_textureCoordinates); +#ifdef enableAO + float ao = czm_unpackDepth(texture2D(pointCloud_aoTexture, + v_textureCoordinates)); + ao = clamp(sigmoid(clamp(ao + sigmoidDomainOffset, 0.0, 1.0), sigmoidSharpness), + 0.0, 1.0); + color.xyz = color.xyz * ao; +#endif // enableAO + float rayDist = czm_unpackDepth(texture2D(pointCloud_depthTexture, + v_textureCoordinates)); + if (length(rayDist) < EPS) { + discard; + } else { + float frustumLength = czm_clampedFrustum.y - czm_clampedFrustum.x; + float scaledRayDist = rayDist * frustumLength + czm_clampedFrustum.x; + vec3 ray = normalize(czm_windowToEyeCoordinates(vec4(gl_FragCoord)).xyz); + float depth = czm_eyeToWindowCoordinates(vec4(ray * scaledRayDist, 1.0)).z; + gl_FragColor = color; + gl_FragDepthEXT = depth; + } +} From 21f3e23af58e2d5f4ecc078132d25dcc9a341f9f Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Fri, 4 Aug 2017 14:39:01 -0400 Subject: [PATCH 182/240] Now using Uber's FP64 primitives for depth in the blending shader --- Source/Scene/PointCloudPostProcessor.js | 3 + .../PointCloudPostProcessorBlendPass.glsl | 90 ++++++++++++++++++- 2 files changed, 90 insertions(+), 3 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 8f63af26967b..9b014ad957e0 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -778,6 +778,9 @@ define([ }, sigmoidSharpness : function() { return processor.sigmoidSharpness; + }, + ONE : function() { + return 1.0; } }; diff --git a/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl b/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl index e3b9c21f8c96..6740a3e519ce 100644 --- a/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl +++ b/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl @@ -7,10 +7,91 @@ uniform sampler2D pointCloud_depthTexture; uniform sampler2D pointCloud_aoTexture; uniform float sigmoidDomainOffset; uniform float sigmoidSharpness; +uniform float ONE; varying vec2 v_textureCoordinates; + +// TODO: Include Uber copyright + +vec2 split(float a) { + const float SPLIT = 4097.0; + float t = a * SPLIT; + float a_hi = t * ONE - (t - a); + float a_lo = a * ONE - a_hi; + return vec2(a_hi, a_lo); +} + +vec2 twoSub(float a, float b) { + float s = (a - b); + float v = (s * ONE - a) * ONE; + float err = (a - (s - v) * ONE) * ONE * ONE * ONE - (b + v); + return vec2(s, err); +} + +vec2 twoSum(float a, float b) { + float s = (a + b); + float v = (s * ONE - a) * ONE; + float err = (a - (s - v) * ONE) * ONE * ONE * ONE + (b - v); + return vec2(s, err); +} + +vec2 twoSqr(float a) { + float prod = a * a; + vec2 a_fp64 = split(a); + float err = ((a_fp64.x * a_fp64.x - prod) * ONE + 2.0 * a_fp64.x * + a_fp64.y * ONE * ONE) + a_fp64.y * a_fp64.y * ONE * ONE * ONE; + return vec2(prod, err); +} + +vec2 twoProd(float a, float b) { + float prod = a * b; + vec2 a_fp64 = split(a); + vec2 b_fp64 = split(b); + float err = ((a_fp64.x * b_fp64.x - prod) + a_fp64.x * b_fp64.y + + a_fp64.y * b_fp64.x) + a_fp64.y * b_fp64.y; + return vec2(prod, err); +} + +vec2 quickTwoSum(float a, float b) { + float sum = (a + b) * ONE; + float err = b - (sum - a) * ONE; + return vec2(sum, err); +} + +vec2 sumFP64(vec2 a, vec2 b) { + vec2 s, t; + s = twoSum(a.x, b.x); + t = twoSum(a.y, b.y); + s.y += t.x; + s = quickTwoSum(s.x, s.y); + s.y += t.y; + s = quickTwoSum(s.x, s.y); + return s; +} + +vec2 subFP64(vec2 a, vec2 b) { + vec2 s, t; + s = twoSub(a.x, b.x); + t = twoSub(a.y, b.y); + s.y += t.x; + s = quickTwoSum(s.x, s.y); + s.y += t.y; + s = quickTwoSum(s.x, s.y); + return s; +} + +vec2 mulFP64(vec2 a, vec2 b) { + vec2 prod = twoProd(a.x, b.x); + // y component is for the error + prod.y += a.x * b.y; + prod.y += a.y * b.x; + prod = quickTwoSum(prod.x, prod.y); + return prod; +} + float sigmoid(float x, float sharpness) { return sharpness * x / (sharpness - x + 1.0); } + void main() { vec4 color = texture2D(pointCloud_colorTexture, v_textureCoordinates); #ifdef enableAO @@ -25,11 +106,14 @@ void main() { if (length(rayDist) < EPS) { discard; } else { - float frustumLength = czm_clampedFrustum.y - czm_clampedFrustum.x; - float scaledRayDist = rayDist * frustumLength + czm_clampedFrustum.x; + vec2 frustumLengthFP64 = twoSub(czm_clampedFrustum.y, czm_clampedFrustum.x); + vec2 scaledRayDistFP64 = mulFP64(split(rayDist), frustumLengthFP64); + scaledRayDistFP64 = sumFP64(scaledRayDistFP64, split(czm_clampedFrustum.x)); + float scaledRayDist = scaledRayDistFP64.x + scaledRayDistFP64.y; + vec3 ray = normalize(czm_windowToEyeCoordinates(vec4(gl_FragCoord)).xyz); float depth = czm_eyeToWindowCoordinates(vec4(ray * scaledRayDist, 1.0)).z; - gl_FragColor = color; + gl_FragColor = vec4(vec3(depth), 1.0); gl_FragDepthEXT = depth; } } From ca0870be6a19640bd6fa2742125622fda96ddc1b Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Fri, 4 Aug 2017 14:41:30 -0400 Subject: [PATCH 183/240] Fixes the triangle wave mode --- Source/Scene/PointCloudPostProcessor.js | 21 ++++++++++++------- .../PointCloudPostProcessorBlendPass.glsl | 2 +- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 9b014ad957e0..8bc9b1a65642 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -749,13 +749,20 @@ define([ copyCommands[0] = copyRegionGrowingColorStage(processor, context, 0); copyCommands[1] = copyRegionGrowingColorStage(processor, context, 1); - var blendRenderState = RenderState.fromCache({ - blending : BlendingState.ALPHA_BLEND, - depthMask : true, - depthTest : { - enabled : true - } - }); + var blendRenderState; + if (processor.useTriangle) { + blendRenderState = RenderState.fromCache({ + blending : BlendingState.ALPHA_BLEND + }); + } else { + blendRenderState = RenderState.fromCache({ + blending : BlendingState.ALPHA_BLEND, + depthMask : true, + depthTest : { + enabled : true + } + }); + } var blendFS = replaceConstants( PointCloudPostProcessorBlendPass, diff --git a/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl b/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl index 6740a3e519ce..aa591942afcb 100644 --- a/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl +++ b/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl @@ -113,7 +113,7 @@ void main() { vec3 ray = normalize(czm_windowToEyeCoordinates(vec4(gl_FragCoord)).xyz); float depth = czm_eyeToWindowCoordinates(vec4(ray * scaledRayDist, 1.0)).z; - gl_FragColor = vec4(vec3(depth), 1.0); + gl_FragColor = color; gl_FragDepthEXT = depth; } } From 9fa77dd0e4dde5da69e7041e90851d95cef70176 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Fri, 4 Aug 2017 23:07:32 -0400 Subject: [PATCH 184/240] Temporarily disables blending --- Source/Scene/PointCloudPostProcessor.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 8bc9b1a65642..82fb87b60094 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -756,11 +756,11 @@ define([ }); } else { blendRenderState = RenderState.fromCache({ - blending : BlendingState.ALPHA_BLEND, + blending : BlendingState.ALPHA_BLEND/*, depthMask : true, depthTest : { enabled : true - } + }*/ }); } From 30d99c31a79288981139058885533791950ff282 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Mon, 7 Aug 2017 17:18:21 -0400 Subject: [PATCH 185/240] No longer using ray distances; eye-space coordinates used everywhere --- Source/Scene/PointCloudPostProcessor.js | 15 +++-- .../DensityEdgeCullPass.glsl | 8 +-- .../PointCloudPostProcessorBlendPass.glsl | 13 +---- .../PointOcclusionPassGL1.glsl | 53 +----------------- .../PointOcclusionPassGL2.glsl | 9 +-- .../RegionGrowingPassGL1.glsl | 51 +++++++++-------- .../RegionGrowingPassGL2.glsl | 55 +++++++++---------- 7 files changed, 72 insertions(+), 132 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 82fb87b60094..d94905af1e0e 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -331,7 +331,7 @@ define([ width : screenWidth, height : screenHeight, pixelFormat : PixelFormat.RGBA, - pixelDatatype : PixelDatatype.UNSIGNED_BYTE, + pixelDatatype : PixelDatatype.FLOAT, sampler : createSampler() }); @@ -623,20 +623,19 @@ define([ 'varying vec2 v_textureCoordinates; \n' + 'void main() \n' + '{ \n' + - ' vec4 rawDepth = texture2D(pointCloud_depthTexture, v_textureCoordinates); \n' + + ' vec4 depth = texture2D(pointCloud_depthTexture, v_textureCoordinates); \n' + ' vec4 rawAO = texture2D(pointCloud_aoTexture, v_textureCoordinates); \n' + - ' float depth = czm_unpackDepth(rawDepth); \n' + - ' if (depth > EPS) { \n' + + ' if (length(depth) > EPS) { \n' + ' #ifdef densityView \n' + ' float density = ceil(densityScaleFactor * texture2D(pointCloud_densityTexture, v_textureCoordinates).r); \n' + ' gl_FragData[0] = vec4(vec3(density / float(densityHalfWidth)), 1.0); \n' + ' #else \n' + ' gl_FragData[0] = texture2D(pointCloud_colorTexture, v_textureCoordinates); \n' + ' #endif \n' + - ' gl_FragData[1] = rawDepth; \n' + + ' gl_FragData[1] = depth; \n' + ' gl_FragData[2] = rawAO; \n' + ' } else { \n' + - ' gl_FragData[1] = czm_packDepth(0.0); ' + + ' gl_FragData[1] = vec4(0.0); ' + ' gl_FragData[2] = czm_packDepth(1.0 - EPS); ' + ' } \n' + '} \n'; @@ -756,11 +755,11 @@ define([ }); } else { blendRenderState = RenderState.fromCache({ - blending : BlendingState.ALPHA_BLEND/*, + blending : BlendingState.ALPHA_BLEND, depthMask : true, depthTest : { enabled : true - }*/ + } }); } diff --git a/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl b/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl index 52c27cd68528..012fea3ba89b 100644 --- a/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl +++ b/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl @@ -16,8 +16,8 @@ float random(vec2 st) { } void main() { - float center = czm_unpackDepth(texture2D(pointCloud_depthTexture, - v_textureCoordinates)); + float center = length(texture2D(pointCloud_depthTexture, + v_textureCoordinates)); ivec2 pos = ivec2(int(gl_FragCoord.x), int(gl_FragCoord.y)); float closestNeighbor = float(neighborhoodHalfWidth) + 1.0; @@ -45,8 +45,8 @@ void main() { ivec2 pI = pos + d; vec2 normPI = vec2(pI) / czm_viewport.zw; - float neighbor = czm_unpackDepth(texture2D(pointCloud_depthTexture, - normPI)); + float neighbor = length(texture2D(pointCloud_depthTexture, + normPI)); if (neighbor < EPS || pI == pos) { continue; } diff --git a/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl b/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl index aa591942afcb..c480314b0be0 100644 --- a/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl +++ b/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl @@ -101,18 +101,11 @@ void main() { 0.0, 1.0); color.xyz = color.xyz * ao; #endif // enableAO - float rayDist = czm_unpackDepth(texture2D(pointCloud_depthTexture, - v_textureCoordinates)); - if (length(rayDist) < EPS) { + vec4 ec = texture2D(pointCloud_depthTexture, v_textureCoordinates); + if (length(ec) < EPS) { discard; } else { - vec2 frustumLengthFP64 = twoSub(czm_clampedFrustum.y, czm_clampedFrustum.x); - vec2 scaledRayDistFP64 = mulFP64(split(rayDist), frustumLengthFP64); - scaledRayDistFP64 = sumFP64(scaledRayDistFP64, split(czm_clampedFrustum.x)); - float scaledRayDist = scaledRayDistFP64.x + scaledRayDistFP64.y; - - vec3 ray = normalize(czm_windowToEyeCoordinates(vec4(gl_FragCoord)).xyz); - float depth = czm_eyeToWindowCoordinates(vec4(ray * scaledRayDist, 1.0)).z; + float depth = czm_eyeToWindowCoordinates(vec4(ec.xyz, 1.0)).z; gl_FragColor = color; gl_FragDepthEXT = depth; } diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl index 84cb3e410d6a..c1bfe048b35f 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl @@ -340,57 +340,6 @@ void main() { } else { float occlusion = clamp(accumulator / (4.0 * PI), 0.0, 1.0); gl_FragData[1] = czm_packDepth(occlusion); - - // Write out the distance of the point - // - // We use the distance of the point rather than - // the linearized depth. This is because we want - // to encode as much information about position disparities - // between points as we can, and the z-values of - // neighboring points are usually very similar. - // On the other hand, the x-values and y-values are - // usually fairly different. -#ifdef useTriangle - // We can get even more accuracy by passing the 64-bit - // distance into a triangle wave function that - // uses 64-bit primitives internally. The region - // growing pass only cares about deltas between - // different pixels, so we just have to ensure that - // the period of triangle function is greater than that - // of the largest possible delta can arise between - // different points. - // - // The triangle function is C0 continuous, which avoids - // artifacts from discontinuities. That said, I have noticed - // some inexplicable artifacts occasionally, so please - // disable this optimization if that becomes an issue. - // - // It's important that the period of the triangle function - // is at least two orders of magnitude greater than - // the average depth delta that we are likely to come - // across. The triangle function works because we have - // some assumption of locality in the depth domain. - // Massive deltas break that locality -- but that's - // actually not an issue. Deltas that are larger than - // the period function will be "wrapped around", and deltas - // that are much larger than the period function may be - // "wrapped around" many times. A similar process occurs - // in many random number generators. The resulting delta - // is usually at least an order of magnitude greater than - // the average delta, so it won't even be considered in - // the region growing pass. - vec2 hpl = lengthFP64(centerPosition); - float triangleResult = triangleFP64(hpl, trianglePeriod); - gl_FragData[0] = czm_packDepth(triangleResult); -#else - vec2 lengthOfFrustum = subFP64(split(czm_clampedFrustum.y), - split(czm_clampedFrustum.x)); - vec2 frustumStart = split(czm_clampedFrustum.x); - vec2 centerPositionLength = lengthFP64(centerPosition); - vec2 normalizedDepthFP64 = sumFP64(divFP64(centerPositionLength, - lengthOfFrustum), - frustumStart); - gl_FragData[0] = czm_packDepth(normalizedDepthFP64.x + normalizedDepthFP64.y); -#endif + gl_FragData[0] = vec4(centerPosition, 0.0); } } diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl index 24fbf967915c..73e8a4358356 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl @@ -292,8 +292,9 @@ void main() { } else { float occlusion = clamp(accumulator / (4.0 * PI), 0.0, 1.0); aoOut = czm_packDepth(occlusion); + depthOut = vec4(centerPosition, 0.0); - // Write out the distance of the point + /*// Write out the distance of the point // // We use the distance of the point rather than // the linearized depth. This is because we want @@ -302,7 +303,7 @@ void main() { // neighboring points are usually very similar. // On the other hand, the x-values and y-values are // usually fairly different. -#ifdef useTriangle + #ifdef useTriangle // We can get even more accuracy by passing the 64-bit // distance into a triangle wave function that // uses 64-bit primitives internally. The region @@ -334,7 +335,7 @@ void main() { vec2 hpl = lengthFP64(centerPosition); float triangleResult = triangleFP64(hpl, trianglePeriod); depthOut = czm_packDepth(triangleResult); -#else + #else vec2 lengthOfFrustum = subFP64(split(czm_clampedFrustum.y), split(czm_clampedFrustum.x)); vec2 frustumStart = split(czm_clampedFrustum.x); @@ -343,6 +344,6 @@ void main() { lengthOfFrustum), frustumStart); depthOut = czm_packDepth(normalizedDepthFP64.x + normalizedDepthFP64.y); -#endif + #endif*/ } } diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl index 15b14fdac2da..44215d69c9d3 100644 --- a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl @@ -21,7 +21,7 @@ uniform int iterationNumber; varying vec2 v_textureCoordinates; -#define otherswap(a, b, aO, bO, aC, bC) if (a > b) { temp = a; a = b; b = temp; tempAO = aO; aO = bO; bO = tempAO; tempColor = aC; aC = bC; bC = tempColor; } +#define otherswap(a, b, aO, bO, aC, bC) if (length(a) > length(b)) { temp = a; a = b; b = temp; tempAO = aO; aO = bO; bO = tempAO; tempColor = aC; aC = bC; bC = tempColor; } vec4 testColor(in int value) { if (value == 0) { @@ -48,10 +48,10 @@ vec4 testColor(in int value) { } -void comparisonNetwork8(inout float[neighborhoodSize] neighbors, +void comparisonNetwork8(inout vec4[neighborhoodSize] neighbors, inout float[neighborhoodSize] aoNeighbors, inout vec4[neighborhoodSize] neighborsColor) { - float temp; + vec4 temp; float tempAO; vec4 tempColor; @@ -98,16 +98,16 @@ void comparisonNetwork8(inout float[neighborhoodSize] neighbors, // NOTE: This can be sped up a lot by replacing the depth // primitive array with two vec4s and using swizzle operations! // (assuming that the neighborhood is exactly 3x3) -void fastMedian3(in float[neighborhoodSize] neighbors, +void fastMedian3(in vec4[neighborhoodSize] neighbors, in float[neighborhoodSize] aoNeighbors, in vec4[neighborhoodSize] colorNeighbors, - out float outDepth, + out vec4 outDepth, out float outAO, out vec4 outColor) { comparisonNetwork8(neighbors, aoNeighbors, colorNeighbors); for (int i = 0; i < neighborhoodSize; i++) { - if (abs(neighbors[i]) > EPS) { + if (length(neighbors[i]) > EPS) { outDepth = neighbors[i + (neighborhoodSize - 1 - i) / 2]; outAO = aoNeighbors[i + (neighborhoodSize - 1 - i) / 2]; outColor = colorNeighbors[i + (neighborhoodSize - 1 - i) / 2]; @@ -115,26 +115,26 @@ void fastMedian3(in float[neighborhoodSize] neighbors, } } - outDepth = 0.0; + outDepth = vec4(0.0); outAO = 1.0; - outColor = vec4(0, 0, 0, 0); + outColor = vec4(0.0); } -void genericMedianFinder(in float[neighborhoodSize] neighbors, +void genericMedianFinder(in vec4[neighborhoodSize] neighbors, in float[neighborhoodSize] aoNeighbors, in vec4[neighborhoodSize] colorNeighbors, - out float outDepth, + out vec4 outDepth, out float outAO, out vec4 outColor) { // Perhaps we should have a valid way of handling the // difficult-to-optimize cases. // For now this does nothing. - outDepth = 0.0; + outDepth = vec4(0.0); outAO = 1.0; - outColor = vec4(1, 0, 0, 1); + outColor = vec4(0.0); } -void loadIntoArray(inout float[neighborhoodSize] depthNeighbors, +void loadIntoArray(inout vec4[neighborhoodSize] depthNeighbors, inout float[neighborhoodSize] aoNeighbors, inout vec4[neighborhoodSize] colorNeighbors) { bool pastCenter = false; @@ -146,8 +146,8 @@ void loadIntoArray(inout float[neighborhoodSize] depthNeighbors, continue; } vec2 neighborCoords = vec2(vec2(d) + gl_FragCoord.xy) / czm_viewport.zw; - float neighbor = czm_unpackDepth(texture2D(pointCloud_depthTexture, - neighborCoords)); + vec4 neighbor = texture2D(pointCloud_depthTexture, + neighborCoords); float aoNeighbor = czm_unpackDepth(texture2D(pointCloud_aoTexture, neighborCoords)); vec4 colorNeighbor = texture2D(pointCloud_colorTexture, neighborCoords); @@ -172,16 +172,15 @@ void loadIntoArray(inout float[neighborhoodSize] depthNeighbors, void main() { vec4 color = texture2D(pointCloud_colorTexture, v_textureCoordinates); - float depth = czm_unpackDepth(texture2D(pointCloud_depthTexture, - v_textureCoordinates)); + vec4 depth = texture2D(pointCloud_depthTexture, v_textureCoordinates); float ao = czm_unpackDepth(texture2D(pointCloud_aoTexture, v_textureCoordinates)); vec4 finalColor = color; - float finalDepth = depth; + vec4 finalDepth = depth; float finalAO = ao; - float depthNeighbors[neighborhoodSize]; + vec4 depthNeighbors[neighborhoodSize]; float aoNeighbors[neighborhoodSize]; vec4 colorNeighbors[neighborhoodSize]; float rIs[neighborhoodSize]; @@ -200,7 +199,7 @@ void main() { texture2D(pointCloud_densityTexture, v_textureCoordinates).r); // If our depth value is invalid - if (abs(depth) < EPS) { + if (length(depth) < EPS) { // If the area that we want to region grow is sufficently sparse if (float(iterationNumber - DELAY) <= density + EPS) { #if neighborhoodFullWidth == 3 @@ -214,19 +213,19 @@ void main() { } // Otherwise if our depth value is valid else { - float depthAccum = 0.0; + vec4 depthAccum = vec4(0.0); float aoAccum = 0.0; vec4 colorAccum = vec4(0); float normalization = 0.0; for (int i = 0; i < neighborhoodSize; i++) { - float neighbor = depthNeighbors[i]; + vec4 neighbor = depthNeighbors[i]; float aoNeighbor = aoNeighbors[i]; vec4 colorNeighbor = colorNeighbors[i]; float rI = rIs[i]; - if (abs(neighbor) > EPS) { - float depthDelta = abs(neighbor - depth); + if (length(neighbor) > EPS) { + float depthDelta = length(neighbor - depth); float weight = (1.0 - rI / 2.0) * @@ -239,7 +238,7 @@ void main() { } } - if (abs(depthAccum) > EPS) { + if (length(depthAccum) > EPS) { finalDepth = depthAccum / normalization; finalColor = colorAccum / normalization; finalAO = aoAccum / normalization; @@ -255,6 +254,6 @@ void main() { gl_FragData[0] = finalColor; #endif #endif - gl_FragData[1] = czm_packDepth(finalDepth); + gl_FragData[1] = finalDepth; gl_FragData[2] = czm_packDepth(finalAO - 1e-7); } diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl index bd60206b3c12..190c38027667 100644 --- a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl @@ -23,7 +23,7 @@ layout(location = 0) out vec4 colorOut; layout(location = 1) out vec4 depthOut; layout(location = 2) out vec4 aoOut; -#define otherswap(a, b, aO, bO, aC, bC) if (a > b) { temp = a; a = b; b = temp; tempAO = aO; aO = bO; bO = tempAO; tempColor = aC; aC = bC; bC = tempColor; } +#define otherswap(a, b, aO, bO, aC, bC) if (length(a) > length(b)) { temp = a; a = b; b = temp; tempAO = aO; aO = bO; bO = tempAO; tempColor = aC; aC = bC; bC = tempColor; } vec4 testColor(in int value) { switch (value) { @@ -50,10 +50,10 @@ vec4 testColor(in int value) { } } -void comparisonNetwork8(inout float[neighborhoodSize] neighbors, +void comparisonNetwork8(inout vec4[neighborhoodSize] neighbors, inout float[neighborhoodSize] aoNeighbors, inout vec4[neighborhoodSize] neighborsColor) { - float temp; + vec4 temp; float tempAO; vec4 tempColor; @@ -100,16 +100,16 @@ void comparisonNetwork8(inout float[neighborhoodSize] neighbors, // NOTE: This can be sped up a lot by replacing the depth // primitive array with two vec4s and using swizzle operations! // (assuming that the neighborhood is exactly 3x3) -void fastMedian3(in float[neighborhoodSize] neighbors, +void fastMedian3(in vec4[neighborhoodSize] neighbors, in float[neighborhoodSize] aoNeighbors, in vec4[neighborhoodSize] colorNeighbors, - out float outDepth, + out vec4 outDepth, out float outAO, out vec4 outColor) { comparisonNetwork8(neighbors, aoNeighbors, colorNeighbors); for (int i = 0; i < neighborhoodSize; i++) { - if (abs(neighbors[i]) > EPS) { + if (length(neighbors[i]) > EPS) { outDepth = neighbors[i + (neighborhoodSize - 1 - i) / 2]; outAO = aoNeighbors[i + (neighborhoodSize - 1 - i) / 2]; outColor = colorNeighbors[i + (neighborhoodSize - 1 - i) / 2]; @@ -117,26 +117,26 @@ void fastMedian3(in float[neighborhoodSize] neighbors, } } - outDepth = 0.0; + outDepth = vec4(0.0); outAO = 1.0; - outColor = vec4(0, 0, 0, 0); + outColor = vec4(0.0); } -void genericMedianFinder(in float[neighborhoodSize] neighbors, +void genericMedianFinder(in vec4[neighborhoodSize] neighbors, in float[neighborhoodSize] aoNeighbors, in vec4[neighborhoodSize] colorNeighbors, - out float outDepth, + out vec4 outDepth, out float outAO, out vec4 outColor) { // Perhaps we should have a valid way of handling the // difficult-to-optimize cases. // For now this does nothing. - outDepth = 0.0; + outDepth = vec4(0.0); outAO = 1.0; - outColor = vec4(1, 0, 0, 1); + outColor = vec4(0.0); } -void loadIntoArray(inout float[neighborhoodSize] depthNeighbors, +void loadIntoArray(inout vec4[neighborhoodSize] depthNeighbors, inout float[neighborhoodSize] aoNeighbors, inout vec4[neighborhoodSize] colorNeighbors) { bool pastCenter = false; @@ -148,9 +148,9 @@ void loadIntoArray(inout float[neighborhoodSize] depthNeighbors, continue; } ivec2 neighborCoords = d + ivec2(gl_FragCoord.xy); - float neighbor = czm_unpackDepth(texelFetch(pointCloud_depthTexture, - neighborCoords, - 0)); + vec4 neighbor = texelFetch(pointCloud_depthTexture, + neighborCoords, + 0); float aoNeighbor = czm_unpackDepth(texelFetch(pointCloud_aoTexture, neighborCoords, 0)); @@ -178,16 +178,15 @@ void loadIntoArray(inout float[neighborhoodSize] depthNeighbors, void main() { vec4 color = texture(pointCloud_colorTexture, v_textureCoordinates); - float depth = czm_unpackDepth(texture(pointCloud_depthTexture, - v_textureCoordinates)); + vec4 depth = texture(pointCloud_depthTexture, v_textureCoordinates); float ao = czm_unpackDepth(texture(pointCloud_aoTexture, v_textureCoordinates)); vec4 finalColor = color; - float finalDepth = depth; + vec4 finalDepth = depth; float finalAO = ao; - float depthNeighbors[neighborhoodSize]; + vec4 depthNeighbors[neighborhoodSize]; float aoNeighbors[neighborhoodSize]; vec4 colorNeighbors[neighborhoodSize]; float rIs[neighborhoodSize]; @@ -206,7 +205,7 @@ void main() { texture(pointCloud_densityTexture, v_textureCoordinates).r); // If our depth value is invalid - if (abs(depth) < EPS) { + if (length(depth) < EPS) { // If the area that we want to region grow is sufficently sparse if (float(iterationNumber - DELAY) <= density + EPS) { #if neighborhoodFullWidth == 3 @@ -220,19 +219,19 @@ void main() { } // Otherwise if our depth value is valid else { - float depthAccum = 0.0; + vec4 depthAccum = vec4(0.0); float aoAccum = 0.0; - vec4 colorAccum = vec4(0); + vec4 colorAccum = vec4(0.0); float normalization = 0.0; for (int i = 0; i < neighborhoodSize; i++) { - float neighbor = depthNeighbors[i]; + vec4 neighbor = depthNeighbors[i]; float aoNeighbor = aoNeighbors[i]; vec4 colorNeighbor = colorNeighbors[i]; float rI = rIs[i]; - if (abs(neighbor) > EPS) { - float depthDelta = abs(neighbor - depth); + if (length(neighbor) > EPS) { + float depthDelta = length(neighbor - depth); float weight = (1.0 - rI / 2.0) * @@ -245,7 +244,7 @@ void main() { } } - if (abs(depthAccum) > EPS) { + if (length(depthAccum) > EPS) { finalDepth = depthAccum / normalization; finalColor = colorAccum / normalization; finalAO = aoAccum / normalization; @@ -261,6 +260,6 @@ void main() { colorOut = finalColor; #endif #endif - depthOut = czm_packDepth(finalDepth); + depthOut = finalDepth; aoOut = czm_packDepth(finalAO - 1e-7); } From a7c93aeb7897ef6b3d031b349c305a43987c9307 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Mon, 7 Aug 2017 17:28:57 -0400 Subject: [PATCH 186/240] Fixes packed/unpacked modes for debug view --- Source/Scene/PointCloudPostProcessor.js | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index d94905af1e0e..0e1c174e6ac4 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -702,7 +702,7 @@ define([ }); } - function debugViewStage(processor, context, texture) { + function debugViewStage(processor, context, texture, unpack) { var uniformMap = { debugTexture : function() { return texture; @@ -715,11 +715,19 @@ define([ 'varying vec2 v_textureCoordinates; \n' + 'void main() \n' + '{ \n' + - ' vec4 raw = texture2D(debugTexture, v_textureCoordinates); \n' + - ' float value = czm_unpackDepth(raw); \n' + + ' vec4 value = texture2D(debugTexture, v_textureCoordinates); \n' + + '#ifdef unpack \n' + + ' value = vec4(czm_unpackDepth(value)); \n' + + '#endif // unpack \n' + ' gl_FragColor = vec4(value); \n' + '} \n'; + debugViewStageStr = replaceConstants( + debugViewStageStr, + 'unpack', + unpack + ); + return context.createViewportQuadCommand(debugViewStageStr, { uniformMap : uniformMap, renderState : RenderState.fromCache({ @@ -799,9 +807,9 @@ define([ var debugViewCommand; if (processor.AOViewEnabled) { - debugViewCommand = debugViewStage(processor, context, processor._aoTextures[0]); + debugViewCommand = debugViewStage(processor, context, processor._aoTextures[0], true); } else if (processor.depthViewEnabled) { - debugViewCommand = debugViewStage(processor, context, processor._depthTextures[0]); + debugViewCommand = debugViewStage(processor, context, processor._depthTextures[0], false); } var framebuffers = processor._framebuffers; From 1820dc2a3d5079f38eb53eb9cc74550249a7e0e9 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Tue, 8 Aug 2017 09:52:01 -0400 Subject: [PATCH 187/240] Performance improvements for the WebGL 1 shader --- .../RegionGrowingPassGL1.glsl | 74 +++++++++++-------- 1 file changed, 44 insertions(+), 30 deletions(-) diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl index 44215d69c9d3..47a7a97761e0 100644 --- a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl @@ -21,7 +21,7 @@ uniform int iterationNumber; varying vec2 v_textureCoordinates; -#define otherswap(a, b, aO, bO, aC, bC) if (length(a) > length(b)) { temp = a; a = b; b = temp; tempAO = aO; aO = bO; bO = tempAO; tempColor = aC; aC = bC; bC = tempColor; } +#define otherswap(a, b, aO, bO, aC, bC) if (a > b) { temp = a; a = b; b = temp; tempAO = aO; aO = bO; bO = tempAO; tempColor = aC; aC = bC; bC = tempColor; } vec4 testColor(in int value) { if (value == 0) { @@ -48,10 +48,10 @@ vec4 testColor(in int value) { } -void comparisonNetwork8(inout vec4[neighborhoodSize] neighbors, +void comparisonNetwork8(inout float[neighborhoodSize] neighbors, inout float[neighborhoodSize] aoNeighbors, inout vec4[neighborhoodSize] neighborsColor) { - vec4 temp; + float temp; float tempAO; vec4 tempColor; @@ -98,16 +98,16 @@ void comparisonNetwork8(inout vec4[neighborhoodSize] neighbors, // NOTE: This can be sped up a lot by replacing the depth // primitive array with two vec4s and using swizzle operations! // (assuming that the neighborhood is exactly 3x3) -void fastMedian3(in vec4[neighborhoodSize] neighbors, +void fastMedian3(in float[neighborhoodSize] neighbors, in float[neighborhoodSize] aoNeighbors, in vec4[neighborhoodSize] colorNeighbors, - out vec4 outDepth, + out float outDepth, out float outAO, out vec4 outColor) { comparisonNetwork8(neighbors, aoNeighbors, colorNeighbors); for (int i = 0; i < neighborhoodSize; i++) { - if (length(neighbors[i]) > EPS) { + if (abs(neighbors[i]) > EPS) { outDepth = neighbors[i + (neighborhoodSize - 1 - i) / 2]; outAO = aoNeighbors[i + (neighborhoodSize - 1 - i) / 2]; outColor = colorNeighbors[i + (neighborhoodSize - 1 - i) / 2]; @@ -115,26 +115,27 @@ void fastMedian3(in vec4[neighborhoodSize] neighbors, } } - outDepth = vec4(0.0); + outDepth = 0.0; outAO = 1.0; - outColor = vec4(0.0); + outColor = vec4(0, 0, 0, 0); } -void genericMedianFinder(in vec4[neighborhoodSize] neighbors, +void genericMedianFinder(in float[neighborhoodSize] neighbors, in float[neighborhoodSize] aoNeighbors, in vec4[neighborhoodSize] colorNeighbors, - out vec4 outDepth, + out float outDepth, out float outAO, out vec4 outColor) { // Perhaps we should have a valid way of handling the // difficult-to-optimize cases. // For now this does nothing. - outDepth = vec4(0.0); + outDepth = 0.0; outAO = 1.0; - outColor = vec4(0.0); + outColor = vec4(1, 0, 0, 1); } -void loadIntoArray(inout vec4[neighborhoodSize] depthNeighbors, +void loadIntoArray(inout vec4[neighborhoodSize] ecNeighbors, + inout float[neighborhoodSize] depthNeighbors, inout float[neighborhoodSize] aoNeighbors, inout vec4[neighborhoodSize] colorNeighbors) { bool pastCenter = false; @@ -146,12 +147,15 @@ void loadIntoArray(inout vec4[neighborhoodSize] depthNeighbors, continue; } vec2 neighborCoords = vec2(vec2(d) + gl_FragCoord.xy) / czm_viewport.zw; - vec4 neighbor = texture2D(pointCloud_depthTexture, - neighborCoords); + vec4 neighborEC = texture2D(pointCloud_depthTexture, + neighborCoords); + float neighbor = length(neighborEC); float aoNeighbor = czm_unpackDepth(texture2D(pointCloud_aoTexture, neighborCoords)); vec4 colorNeighbor = texture2D(pointCloud_colorTexture, neighborCoords); if (pastCenter) { + ecNeighbors[(j + 1) * neighborhoodFullWidth + i] = + neighborEC; depthNeighbors[(j + 1) * neighborhoodFullWidth + i] = neighbor; aoNeighbors[(j + 1) * neighborhoodFullWidth + i] = @@ -159,6 +163,8 @@ void loadIntoArray(inout vec4[neighborhoodSize] depthNeighbors, colorNeighbors[(j + 1) * neighborhoodFullWidth + i] = colorNeighbor; } else { + ecNeighbors[(j + 1) * neighborhoodFullWidth + i + 1] = + neighborEC; depthNeighbors[(j + 1) * neighborhoodFullWidth + i + 1] = neighbor; aoNeighbors[(j + 1) * neighborhoodFullWidth + i + 1] = @@ -172,15 +178,17 @@ void loadIntoArray(inout vec4[neighborhoodSize] depthNeighbors, void main() { vec4 color = texture2D(pointCloud_colorTexture, v_textureCoordinates); - vec4 depth = texture2D(pointCloud_depthTexture, v_textureCoordinates); + vec4 ec = texture2D(pointCloud_depthTexture, v_textureCoordinates); + float depth = length(ec); float ao = czm_unpackDepth(texture2D(pointCloud_aoTexture, v_textureCoordinates)); vec4 finalColor = color; - vec4 finalDepth = depth; float finalAO = ao; + vec4 finalEC = ec; - vec4 depthNeighbors[neighborhoodSize]; + vec4 ecNeighbors[neighborhoodSize]; + float depthNeighbors[neighborhoodSize]; float aoNeighbors[neighborhoodSize]; vec4 colorNeighbors[neighborhoodSize]; float rIs[neighborhoodSize]; @@ -193,15 +201,16 @@ void main() { rIs[6] = 1.0; rIs[7] = SQRT2; - loadIntoArray(depthNeighbors, aoNeighbors, colorNeighbors); + loadIntoArray(ecNeighbors, depthNeighbors, aoNeighbors, colorNeighbors); float density = ceil(densityScaleFactor * texture2D(pointCloud_densityTexture, v_textureCoordinates).r); // If our depth value is invalid - if (length(depth) < EPS) { + if (abs(depth) < EPS) { // If the area that we want to region grow is sufficently sparse if (float(iterationNumber - DELAY) <= density + EPS) { + float finalDepth = depth; #if neighborhoodFullWidth == 3 fastMedian3(depthNeighbors, aoNeighbors, colorNeighbors, finalDepth, finalAO, finalColor); @@ -209,40 +218,45 @@ void main() { genericMedianFinder(depthNeighbors, aoNeighbors, colorNeighbors, finalDepth, finalAO, finalColor); #endif + for (int i = 0; i < neighborhoodSize; i++) { + if (abs(depthNeighbors[i] - finalDepth) < EPS) { + finalEC = ecNeighbors[i]; + } + } } } // Otherwise if our depth value is valid else { - vec4 depthAccum = vec4(0.0); + vec4 ecAccum = vec4(0.0); float aoAccum = 0.0; vec4 colorAccum = vec4(0); float normalization = 0.0; for (int i = 0; i < neighborhoodSize; i++) { - vec4 neighbor = depthNeighbors[i]; + vec4 ecNeighbor = ecNeighbors[i]; float aoNeighbor = aoNeighbors[i]; vec4 colorNeighbor = colorNeighbors[i]; float rI = rIs[i]; - if (length(neighbor) > EPS) { - float depthDelta = length(neighbor - depth); + if (length(ecNeighbor) > EPS) { + float ecDelta = length(ecNeighbor - ec); float weight = (1.0 - rI / 2.0) * - (1.0 - min(1.0, depthDelta / max(1e-38, rangeParameter))); + (1.0 - min(1.0, ecDelta / max(1e-38, rangeParameter))); - depthAccum += neighbor * weight; + ecAccum += ecNeighbor * weight; aoAccum += aoNeighbor * weight; colorAccum += colorNeighbor * weight; normalization += weight; } } - if (length(depthAccum) > EPS) { - finalDepth = depthAccum / normalization; + if (length(ecAccum) > EPS) { + finalEC = ecAccum / normalization; finalColor = colorAccum / normalization; finalAO = aoAccum / normalization; - } + } } #ifdef densityView @@ -254,6 +268,6 @@ void main() { gl_FragData[0] = finalColor; #endif #endif - gl_FragData[1] = finalDepth; + gl_FragData[1] = finalEC; gl_FragData[2] = czm_packDepth(finalAO - 1e-7); } From f7ff5bd27706001bd8aae4c7c2370d86f5bec542 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Tue, 8 Aug 2017 11:18:11 -0400 Subject: [PATCH 188/240] Performance fixes for the WebGL 2 shader too --- .../RegionGrowingPassGL1.glsl | 2 +- .../RegionGrowingPassGL2.glsl | 78 +++++++++++-------- 2 files changed, 47 insertions(+), 33 deletions(-) diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl index 47a7a97761e0..0464763902b3 100644 --- a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl @@ -256,7 +256,7 @@ void main() { finalEC = ecAccum / normalization; finalColor = colorAccum / normalization; finalAO = aoAccum / normalization; - } + } } #ifdef densityView diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl index 190c38027667..aa6efa38bbc6 100644 --- a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl @@ -20,10 +20,10 @@ uniform int iterationNumber; in vec2 v_textureCoordinates; layout(location = 0) out vec4 colorOut; -layout(location = 1) out vec4 depthOut; +layout(location = 1) out vec4 ecOut; layout(location = 2) out vec4 aoOut; -#define otherswap(a, b, aO, bO, aC, bC) if (length(a) > length(b)) { temp = a; a = b; b = temp; tempAO = aO; aO = bO; bO = tempAO; tempColor = aC; aC = bC; bC = tempColor; } +#define otherswap(a, b, aO, bO, aC, bC) if (a > b) { temp = a; a = b; b = temp; tempAO = aO; aO = bO; bO = tempAO; tempColor = aC; aC = bC; bC = tempColor; } vec4 testColor(in int value) { switch (value) { @@ -50,10 +50,10 @@ vec4 testColor(in int value) { } } -void comparisonNetwork8(inout vec4[neighborhoodSize] neighbors, +void comparisonNetwork8(inout float[neighborhoodSize] neighbors, inout float[neighborhoodSize] aoNeighbors, inout vec4[neighborhoodSize] neighborsColor) { - vec4 temp; + float temp; float tempAO; vec4 tempColor; @@ -100,16 +100,16 @@ void comparisonNetwork8(inout vec4[neighborhoodSize] neighbors, // NOTE: This can be sped up a lot by replacing the depth // primitive array with two vec4s and using swizzle operations! // (assuming that the neighborhood is exactly 3x3) -void fastMedian3(in vec4[neighborhoodSize] neighbors, +void fastMedian3(in float[neighborhoodSize] neighbors, in float[neighborhoodSize] aoNeighbors, in vec4[neighborhoodSize] colorNeighbors, - out vec4 outDepth, + out float outDepth, out float outAO, out vec4 outColor) { comparisonNetwork8(neighbors, aoNeighbors, colorNeighbors); for (int i = 0; i < neighborhoodSize; i++) { - if (length(neighbors[i]) > EPS) { + if (abs(neighbors[i]) > EPS) { outDepth = neighbors[i + (neighborhoodSize - 1 - i) / 2]; outAO = aoNeighbors[i + (neighborhoodSize - 1 - i) / 2]; outColor = colorNeighbors[i + (neighborhoodSize - 1 - i) / 2]; @@ -117,26 +117,27 @@ void fastMedian3(in vec4[neighborhoodSize] neighbors, } } - outDepth = vec4(0.0); + outDepth = 0.0; outAO = 1.0; - outColor = vec4(0.0); + outColor = vec4(0, 0, 0, 0); } -void genericMedianFinder(in vec4[neighborhoodSize] neighbors, +void genericMedianFinder(in float[neighborhoodSize] neighbors, in float[neighborhoodSize] aoNeighbors, in vec4[neighborhoodSize] colorNeighbors, - out vec4 outDepth, + out float outDepth, out float outAO, out vec4 outColor) { // Perhaps we should have a valid way of handling the // difficult-to-optimize cases. // For now this does nothing. - outDepth = vec4(0.0); + outDepth = 0.0; outAO = 1.0; - outColor = vec4(0.0); + outColor = vec4(1, 0, 0, 1); } -void loadIntoArray(inout vec4[neighborhoodSize] depthNeighbors, +void loadIntoArray(inout vec4[neighborhoodSize] ecNeighbors, + inout float[neighborhoodSize] depthNeighbors, inout float[neighborhoodSize] aoNeighbors, inout vec4[neighborhoodSize] colorNeighbors) { bool pastCenter = false; @@ -148,9 +149,10 @@ void loadIntoArray(inout vec4[neighborhoodSize] depthNeighbors, continue; } ivec2 neighborCoords = d + ivec2(gl_FragCoord.xy); - vec4 neighbor = texelFetch(pointCloud_depthTexture, - neighborCoords, - 0); + vec4 neighborEC = texelFetch(pointCloud_depthTexture, + neighborCoords, + 0); + float neighbor = length(neighborEC); float aoNeighbor = czm_unpackDepth(texelFetch(pointCloud_aoTexture, neighborCoords, 0)); @@ -158,6 +160,8 @@ void loadIntoArray(inout vec4[neighborhoodSize] depthNeighbors, neighborCoords, 0); if (pastCenter) { + ecNeighbors[(j + 1) * neighborhoodFullWidth + i] = + neighborEC; depthNeighbors[(j + 1) * neighborhoodFullWidth + i] = neighbor; aoNeighbors[(j + 1) * neighborhoodFullWidth + i] = @@ -165,6 +169,8 @@ void loadIntoArray(inout vec4[neighborhoodSize] depthNeighbors, colorNeighbors[(j + 1) * neighborhoodFullWidth + i] = colorNeighbor; } else { + ecNeighbors[(j + 1) * neighborhoodFullWidth + i + 1] = + neighborEC; depthNeighbors[(j + 1) * neighborhoodFullWidth + i + 1] = neighbor; aoNeighbors[(j + 1) * neighborhoodFullWidth + i + 1] = @@ -178,15 +184,17 @@ void loadIntoArray(inout vec4[neighborhoodSize] depthNeighbors, void main() { vec4 color = texture(pointCloud_colorTexture, v_textureCoordinates); - vec4 depth = texture(pointCloud_depthTexture, v_textureCoordinates); + vec4 ec = texture(pointCloud_depthTexture, v_textureCoordinates); + float depth = length(ec); float ao = czm_unpackDepth(texture(pointCloud_aoTexture, v_textureCoordinates)); vec4 finalColor = color; - vec4 finalDepth = depth; float finalAO = ao; + vec4 finalEC = ec; - vec4 depthNeighbors[neighborhoodSize]; + vec4 ecNeighbors[neighborhoodSize]; + float depthNeighbors[neighborhoodSize]; float aoNeighbors[neighborhoodSize]; vec4 colorNeighbors[neighborhoodSize]; float rIs[neighborhoodSize]; @@ -199,15 +207,16 @@ void main() { rIs[6] = 1.0; rIs[7] = SQRT2; - loadIntoArray(depthNeighbors, aoNeighbors, colorNeighbors); + loadIntoArray(ecNeighbors, depthNeighbors, aoNeighbors, colorNeighbors); float density = ceil(densityScaleFactor * texture(pointCloud_densityTexture, v_textureCoordinates).r); // If our depth value is invalid - if (length(depth) < EPS) { + if (abs(depth) < EPS) { // If the area that we want to region grow is sufficently sparse if (float(iterationNumber - DELAY) <= density + EPS) { + float finalDepth = depth; #if neighborhoodFullWidth == 3 fastMedian3(depthNeighbors, aoNeighbors, colorNeighbors, finalDepth, finalAO, finalColor); @@ -215,37 +224,42 @@ void main() { genericMedianFinder(depthNeighbors, aoNeighbors, colorNeighbors, finalDepth, finalAO, finalColor); #endif + for (int i = 0; i < neighborhoodSize; i++) { + if (abs(depthNeighbors[i] - finalDepth) < EPS) { + finalEC = ecNeighbors[i]; + } + } } } // Otherwise if our depth value is valid else { - vec4 depthAccum = vec4(0.0); + vec4 ecAccum = vec4(0.0); float aoAccum = 0.0; - vec4 colorAccum = vec4(0.0); + vec4 colorAccum = vec4(0); float normalization = 0.0; for (int i = 0; i < neighborhoodSize; i++) { - vec4 neighbor = depthNeighbors[i]; + vec4 ecNeighbor = ecNeighbors[i]; float aoNeighbor = aoNeighbors[i]; vec4 colorNeighbor = colorNeighbors[i]; float rI = rIs[i]; - if (length(neighbor) > EPS) { - float depthDelta = length(neighbor - depth); + if (length(ecNeighbor) > EPS) { + float ecDelta = length(ecNeighbor - ec); float weight = (1.0 - rI / 2.0) * - (1.0 - min(1.0, depthDelta / max(1e-38, rangeParameter))); + (1.0 - min(1.0, ecDelta / max(1e-38, rangeParameter))); - depthAccum += neighbor * weight; + ecAccum += ecNeighbor * weight; aoAccum += aoNeighbor * weight; colorAccum += colorNeighbor * weight; normalization += weight; } } - if (length(depthAccum) > EPS) { - finalDepth = depthAccum / normalization; + if (length(ecAccum) > EPS) { + finalEC = ecAccum / normalization; finalColor = colorAccum / normalization; finalAO = aoAccum / normalization; } @@ -260,6 +274,6 @@ void main() { colorOut = finalColor; #endif #endif - depthOut = finalDepth; + ecOut = finalEC; aoOut = czm_packDepth(finalAO - 1e-7); } From 84e0bf70fedeaa5ff5b316d4d9a43722428a4b9b Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 9 Aug 2017 12:10:19 -0400 Subject: [PATCH 189/240] Fixes AO view --- Source/Scene/PointCloudPostProcessor.js | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 0e1c174e6ac4..c14a33261618 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -711,6 +711,7 @@ define([ var debugViewStageStr = '#define EPS 1e-8 \n' + + '#define unpack \n' + 'uniform sampler2D debugTexture; \n' + 'varying vec2 v_textureCoordinates; \n' + 'void main() \n' + From f690632cf935751f9b1b9ea71d0075640ad0a4a6 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 9 Aug 2017 15:51:00 -0400 Subject: [PATCH 190/240] Removes Uber's FP64 code --- Source/Scene/PointCloudPostProcessor.js | 6 - .../PointCloudPostProcessorBlendPass.glsl | 80 +------- .../PointOcclusionPassGL1.glsl | 126 ------------- .../PointOcclusionPassGL2.glsl | 178 ------------------ 4 files changed, 1 insertion(+), 389 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index c14a33261618..fd6b36ab8b0c 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -439,9 +439,6 @@ define([ }, dropoutFactor : function() { return processor.dropoutFactor; - }, - ONE : function() { - return 1.0; } }; @@ -793,9 +790,6 @@ define([ }, sigmoidSharpness : function() { return processor.sigmoidSharpness; - }, - ONE : function() { - return 1.0; } }; diff --git a/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl b/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl index c480314b0be0..8401e7863312 100644 --- a/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl +++ b/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl @@ -7,87 +7,9 @@ uniform sampler2D pointCloud_depthTexture; uniform sampler2D pointCloud_aoTexture; uniform float sigmoidDomainOffset; uniform float sigmoidSharpness; -uniform float ONE; +uniform float splitScreenX; varying vec2 v_textureCoordinates; -// TODO: Include Uber copyright - -vec2 split(float a) { - const float SPLIT = 4097.0; - float t = a * SPLIT; - float a_hi = t * ONE - (t - a); - float a_lo = a * ONE - a_hi; - return vec2(a_hi, a_lo); -} - -vec2 twoSub(float a, float b) { - float s = (a - b); - float v = (s * ONE - a) * ONE; - float err = (a - (s - v) * ONE) * ONE * ONE * ONE - (b + v); - return vec2(s, err); -} - -vec2 twoSum(float a, float b) { - float s = (a + b); - float v = (s * ONE - a) * ONE; - float err = (a - (s - v) * ONE) * ONE * ONE * ONE + (b - v); - return vec2(s, err); -} - -vec2 twoSqr(float a) { - float prod = a * a; - vec2 a_fp64 = split(a); - float err = ((a_fp64.x * a_fp64.x - prod) * ONE + 2.0 * a_fp64.x * - a_fp64.y * ONE * ONE) + a_fp64.y * a_fp64.y * ONE * ONE * ONE; - return vec2(prod, err); -} - -vec2 twoProd(float a, float b) { - float prod = a * b; - vec2 a_fp64 = split(a); - vec2 b_fp64 = split(b); - float err = ((a_fp64.x * b_fp64.x - prod) + a_fp64.x * b_fp64.y + - a_fp64.y * b_fp64.x) + a_fp64.y * b_fp64.y; - return vec2(prod, err); -} - -vec2 quickTwoSum(float a, float b) { - float sum = (a + b) * ONE; - float err = b - (sum - a) * ONE; - return vec2(sum, err); -} - -vec2 sumFP64(vec2 a, vec2 b) { - vec2 s, t; - s = twoSum(a.x, b.x); - t = twoSum(a.y, b.y); - s.y += t.x; - s = quickTwoSum(s.x, s.y); - s.y += t.y; - s = quickTwoSum(s.x, s.y); - return s; -} - -vec2 subFP64(vec2 a, vec2 b) { - vec2 s, t; - s = twoSub(a.x, b.x); - t = twoSub(a.y, b.y); - s.y += t.x; - s = quickTwoSum(s.x, s.y); - s.y += t.y; - s = quickTwoSum(s.x, s.y); - return s; -} - -vec2 mulFP64(vec2 a, vec2 b) { - vec2 prod = twoProd(a.x, b.x); - // y component is for the error - prod.y += a.x * b.y; - prod.y += a.y * b.x; - prod = quickTwoSum(prod.x, prod.y); - return prod; -} - float sigmoid(float x, float sharpness) { return sharpness * x / (sharpness - x + 1.0); } diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl index c1bfe048b35f..c6c0a7e1e2a1 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl @@ -15,137 +15,11 @@ #define trianglePeriod 1.0 #define useTriangle -uniform float ONE; - uniform sampler2D pointCloud_ECTexture; uniform float occlusionAngle; uniform sampler2D sectorLUT; varying vec2 v_textureCoordinates; -// TODO: Include Uber copyright - -vec2 split(float a) { - const float SPLIT = 4097.0; - float t = a * SPLIT; - float a_hi = t * ONE - (t - a); - float a_lo = a * ONE - a_hi; - return vec2(a_hi, a_lo); -} - -vec2 twoSub(float a, float b) { - float s = (a - b); - float v = (s * ONE - a) * ONE; - float err = (a - (s - v) * ONE) * ONE * ONE * ONE - (b + v); - return vec2(s, err); -} - -vec2 twoSum(float a, float b) { - float s = (a + b); - float v = (s * ONE - a) * ONE; - float err = (a - (s - v) * ONE) * ONE * ONE * ONE + (b - v); - return vec2(s, err); -} - -vec2 twoSqr(float a) { - float prod = a * a; - vec2 a_fp64 = split(a); - float err = ((a_fp64.x * a_fp64.x - prod) * ONE + 2.0 * a_fp64.x * - a_fp64.y * ONE * ONE) + a_fp64.y * a_fp64.y * ONE * ONE * ONE; - return vec2(prod, err); -} - -vec2 twoProd(float a, float b) { - float prod = a * b; - vec2 a_fp64 = split(a); - vec2 b_fp64 = split(b); - float err = ((a_fp64.x * b_fp64.x - prod) + a_fp64.x * b_fp64.y + - a_fp64.y * b_fp64.x) + a_fp64.y * b_fp64.y; - return vec2(prod, err); -} - -vec2 quickTwoSum(float a, float b) { - float sum = (a + b) * ONE; - float err = b - (sum - a) * ONE; - return vec2(sum, err); -} - -vec2 sumFP64(vec2 a, vec2 b) { - vec2 s, t; - s = twoSum(a.x, b.x); - t = twoSum(a.y, b.y); - s.y += t.x; - s = quickTwoSum(s.x, s.y); - s.y += t.y; - s = quickTwoSum(s.x, s.y); - return s; -} - -vec2 subFP64(vec2 a, vec2 b) { - vec2 s, t; - s = twoSub(a.x, b.x); - t = twoSub(a.y, b.y); - s.y += t.x; - s = quickTwoSum(s.x, s.y); - s.y += t.y; - s = quickTwoSum(s.x, s.y); - return s; -} - -vec2 mulFP64(vec2 a, vec2 b) { - vec2 prod = twoProd(a.x, b.x); - // y component is for the error - prod.y += a.x * b.y; - prod.y += a.y * b.x; - prod = quickTwoSum(prod.x, prod.y); - return prod; -} - -vec2 divFP64(in vec2 a, in vec2 b) { - float xn = 1.0 / b.x; - vec2 yn = a * xn; - float diff = (subFP64(a, mulFP64(b, yn))).x; - vec2 prod = twoProd(xn, diff); - return sumFP64(yn, prod); -} - -vec2 sqrtFP64(in vec2 a) { - if (a.x == 0.0 && a.y == 0.0) return vec2(0.0, 0.0); - if (a.x < 0.0) return vec2(0.0 / 0.0, 0.0 / 0.0); - float x = 1.0 / sqrt(a.x); - float yn = a.x * x; - vec2 yn_sqr = twoSqr(yn) * ONE; - float diff = subFP64(a, yn_sqr).x; - vec2 prod = twoProd(x * 0.5, diff); - return sumFP64(vec2(yn, 0.0), prod); -} - -vec2 lengthFP64(in vec3 vec) { - vec2 highPrecisionX = split(vec.x); - vec2 highPrecisionY = split(vec.y); - vec2 highPrecisionZ = split(vec.z); - vec2 highPrecision = - sqrtFP64(sumFP64(sumFP64( - mulFP64(highPrecisionX, highPrecisionX), - mulFP64(highPrecisionY, highPrecisionY)), - mulFP64(highPrecisionZ, highPrecisionZ))); - return highPrecision; -} - -float triangle(in float x, in float period) { - return abs(mod(x, period) / period - 0.5) + EPS; -} - -float triangleFP64(in vec2 x, in float period) { - float lowPrecision = x.x + x.y; - vec2 floorTerm = split(floor(lowPrecision / period)); - vec2 periodHighPrecision = split(period); - vec2 term2 = mulFP64(periodHighPrecision, floorTerm); - vec2 moduloTerm = subFP64(x, term2); - vec2 normalized = divFP64(moduloTerm, periodHighPrecision); - normalized = subFP64(normalized, split(0.5)); - return abs(normalized.x + normalized.y) + EPS; -} - float acosFast(in float inX) { float x = abs(inX); float res = ((C3 * x + C2) * x + C1) * x + C0; // p(x) diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl index 73e8a4358356..868d2eeca890 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl @@ -16,8 +16,6 @@ #define useTriangle #define dropoutEnabled -uniform float ONE; - uniform sampler2D pointCloud_ECTexture; uniform float occlusionAngle; uniform float dropoutFactor; @@ -27,130 +25,6 @@ in vec2 v_textureCoordinates; layout(location = 0) out vec4 depthOut; layout(location = 1) out vec4 aoOut; -// TODO: Include Uber copyright - -vec2 split(float a) { - const float SPLIT = 4097.0; - float t = a * SPLIT; - float a_hi = t * ONE - (t - a); - float a_lo = a * ONE - a_hi; - return vec2(a_hi, a_lo); -} - -vec2 twoSub(float a, float b) { - float s = (a - b); - float v = (s * ONE - a) * ONE; - float err = (a - (s - v) * ONE) * ONE * ONE * ONE - (b + v); - return vec2(s, err); -} - -vec2 twoSum(float a, float b) { - float s = (a + b); - float v = (s * ONE - a) * ONE; - float err = (a - (s - v) * ONE) * ONE * ONE * ONE + (b - v); - return vec2(s, err); -} - -vec2 twoSqr(float a) { - float prod = a * a; - vec2 a_fp64 = split(a); - float err = ((a_fp64.x * a_fp64.x - prod) * ONE + 2.0 * a_fp64.x * - a_fp64.y * ONE * ONE) + a_fp64.y * a_fp64.y * ONE * ONE * ONE; - return vec2(prod, err); -} - -vec2 twoProd(float a, float b) { - float prod = a * b; - vec2 a_fp64 = split(a); - vec2 b_fp64 = split(b); - float err = ((a_fp64.x * b_fp64.x - prod) + a_fp64.x * b_fp64.y + - a_fp64.y * b_fp64.x) + a_fp64.y * b_fp64.y; - return vec2(prod, err); -} - -vec2 quickTwoSum(float a, float b) { - float sum = (a + b) * ONE; - float err = b - (sum - a) * ONE; - return vec2(sum, err); -} - -vec2 sumFP64(vec2 a, vec2 b) { - vec2 s, t; - s = twoSum(a.x, b.x); - t = twoSum(a.y, b.y); - s.y += t.x; - s = quickTwoSum(s.x, s.y); - s.y += t.y; - s = quickTwoSum(s.x, s.y); - return s; -} - -vec2 subFP64(vec2 a, vec2 b) { - vec2 s, t; - s = twoSub(a.x, b.x); - t = twoSub(a.y, b.y); - s.y += t.x; - s = quickTwoSum(s.x, s.y); - s.y += t.y; - s = quickTwoSum(s.x, s.y); - return s; -} - -vec2 mulFP64(vec2 a, vec2 b) { - vec2 prod = twoProd(a.x, b.x); - // y component is for the error - prod.y += a.x * b.y; - prod.y += a.y * b.x; - prod = quickTwoSum(prod.x, prod.y); - return prod; -} - -vec2 divFP64(in vec2 a, in vec2 b) { - float xn = 1.0 / b.x; - vec2 yn = a * xn; - float diff = (subFP64(a, mulFP64(b, yn))).x; - vec2 prod = twoProd(xn, diff); - return sumFP64(yn, prod); -} - -vec2 sqrtFP64(in vec2 a) { - if (a.x == 0.0 && a.y == 0.0) return vec2(0.0, 0.0); - if (a.x < 0.0) return vec2(0.0 / 0.0, 0.0 / 0.0); - float x = 1.0 / sqrt(a.x); - float yn = a.x * x; - vec2 yn_sqr = twoSqr(yn) * ONE; - float diff = subFP64(a, yn_sqr).x; - vec2 prod = twoProd(x * 0.5, diff); - return sumFP64(vec2(yn, 0.0), prod); -} - -vec2 lengthFP64(in vec3 vec) { - vec2 highPrecisionX = split(vec.x); - vec2 highPrecisionY = split(vec.y); - vec2 highPrecisionZ = split(vec.z); - vec2 highPrecision = - sqrtFP64(sumFP64(sumFP64( - mulFP64(highPrecisionX, highPrecisionX), - mulFP64(highPrecisionY, highPrecisionY)), - mulFP64(highPrecisionZ, highPrecisionZ))); - return highPrecision; -} - -float triangle(in float x, in float period) { - return abs(mod(x, period) / period - 0.5) + EPS; -} - -float triangleFP64(in vec2 x, in float period) { - float lowPrecision = x.x + x.y; - vec2 floorTerm = split(floor(lowPrecision / period)); - vec2 periodHighPrecision = split(period); - vec2 term2 = mulFP64(periodHighPrecision, floorTerm); - vec2 moduloTerm = subFP64(x, term2); - vec2 normalized = divFP64(moduloTerm, periodHighPrecision); - normalized = subFP64(normalized, split(0.5)); - return abs(normalized.x + normalized.y) + EPS; -} - float acosFast(in float inX) { float x = abs(inX); float res = ((C3 * x + C2) * x + C1) * x + C0; // p(x) @@ -293,57 +167,5 @@ void main() { float occlusion = clamp(accumulator / (4.0 * PI), 0.0, 1.0); aoOut = czm_packDepth(occlusion); depthOut = vec4(centerPosition, 0.0); - - /*// Write out the distance of the point - // - // We use the distance of the point rather than - // the linearized depth. This is because we want - // to encode as much information about position disparities - // between points as we can, and the z-values of - // neighboring points are usually very similar. - // On the other hand, the x-values and y-values are - // usually fairly different. - #ifdef useTriangle - // We can get even more accuracy by passing the 64-bit - // distance into a triangle wave function that - // uses 64-bit primitives internally. The region - // growing pass only cares about deltas between - // different pixels, so we just have to ensure that - // the period of triangle function is greater than that - // of the largest possible delta can arise between - // different points. - // - // The triangle function is C0 continuous, which avoids - // artifacts from discontinuities. That said, I have noticed - // some inexplicable artifacts occasionally, so please - // disable this optimization if that becomes an issue. - // - // It's important that the period of the triangle function - // is at least two orders of magnitude greater than - // the average depth delta that we are likely to come - // across. The triangle function works because we have - // some assumption of locality in the depth domain. - // Massive deltas break that locality -- but that's - // actually not an issue. Deltas that are larger than - // the period function will be "wrapped around", and deltas - // that are much larger than the period function may be - // "wrapped around" many times. A similar process occurs - // in many random number generators. The resulting delta - // is usually at least an order of magnitude greater than - // the average delta, so it won't even be considered in - // the region growing pass. - vec2 hpl = lengthFP64(centerPosition); - float triangleResult = triangleFP64(hpl, trianglePeriod); - depthOut = czm_packDepth(triangleResult); - #else - vec2 lengthOfFrustum = subFP64(split(czm_clampedFrustum.y), - split(czm_clampedFrustum.x)); - vec2 frustumStart = split(czm_clampedFrustum.x); - vec2 centerPositionLength = lengthFP64(centerPosition); - vec2 normalizedDepthFP64 = sumFP64(divFP64(centerPositionLength, - lengthOfFrustum), - frustumStart); - depthOut = czm_packDepth(normalizedDepthFP64.x + normalizedDepthFP64.y); - #endif*/ } } From a58a50c1e25e8bb086b5209b36b8b32321e7872b Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 9 Aug 2017 15:52:12 -0400 Subject: [PATCH 191/240] Removes deck.gl from LICENSE.md --- LICENSE.md | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/LICENSE.md b/LICENSE.md index cb85f788dd5d..61b0e64e78f5 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -672,28 +672,6 @@ https://github.com/KhronosGroup/glTF-WebGL-PBR >CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE >OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -### deck.gl - -Copyright (c) 2015 - 2017 Uber Technologies, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - Tests ===== From fa162307bfe8efdfdcc4db62aeaeef502bc451f2 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Thu, 10 Aug 2017 10:54:13 -0400 Subject: [PATCH 192/240] Removes EdgeCullingPass.glsl --- .../PostProcessFilters/EdgeCullingPass.glsl | 22 ------------------- 1 file changed, 22 deletions(-) delete mode 100644 Source/Shaders/PostProcessFilters/EdgeCullingPass.glsl diff --git a/Source/Shaders/PostProcessFilters/EdgeCullingPass.glsl b/Source/Shaders/PostProcessFilters/EdgeCullingPass.glsl deleted file mode 100644 index f0e7f8a4a695..000000000000 --- a/Source/Shaders/PostProcessFilters/EdgeCullingPass.glsl +++ /dev/null @@ -1,22 +0,0 @@ -#extension GL_EXT_draw_buffers : enable - -#define EPS 1e-8 - -#define densityScaleFactor 10.0 - -varying float centerPos; - -uniform sampler2D pointCloud_depthTexture; - -void main() { - ivec2 pos = ivec2(int(gl_FragCoord.x), int(gl_FragCoord.y)); - ivec2 centerValue = ivec2(int(mod(centerPos, czm_viewport.z)), - int(centerPos) / int(czm_viewport.z)); - - vec2 diff = vec2(pos - centerValue); - - vec4 result; - result.xy = diff; - result.zw = abs(diff); - gl_FragData[0] = result; -} From 8f8f851bb5c92f8858ad650cc0c4e7c629181ecd Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Thu, 10 Aug 2017 11:01:52 -0400 Subject: [PATCH 193/240] Moves enabled check out of PointCloudPostProcessor --- Source/Scene/Cesium3DTileset.js | 3 +-- Source/Scene/PointCloudPostProcessor.js | 4 ---- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/Source/Scene/Cesium3DTileset.js b/Source/Scene/Cesium3DTileset.js index 824ea10221e0..22ecf1829ba9 100644 --- a/Source/Scene/Cesium3DTileset.js +++ b/Source/Scene/Cesium3DTileset.js @@ -1557,8 +1557,7 @@ define([ // Number of commands added by each update above statistics.numberOfCommands = (commandList.length - numberOfInitialCommands); - if (addedCommandsLength > 0) { - // TODO : only do this if the tileset is purely point clouds. + if (tileset.pointCloudPostProcessorOptions.enabled && (addedCommandsLength > 0)) { tileset._pointCloudPostProcessor.update(frameState, numberOfInitialCommands, tileset); } diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index fd6b36ab8b0c..5eb2448cdb8d 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -993,10 +993,6 @@ define([ dirty = true; } - if (!tileset.pointCloudPostProcessorOptions.enabled) { - return; - } - dirty |= createResources(this, frameState.context, dirty); // Render point cloud commands into an offscreen FBO. From c430bd95076bb55ed534d337c516948a6a35effc Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Thu, 10 Aug 2017 11:07:33 -0400 Subject: [PATCH 194/240] Style fixes for point cloud attenuation options and position_absolute --- Source/Scene/PointCloud3DTileContent.js | 29 ++++++++----------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/Source/Scene/PointCloud3DTileContent.js b/Source/Scene/PointCloud3DTileContent.js index 845ef01da8e5..26c44e1b6e01 100644 --- a/Source/Scene/PointCloud3DTileContent.js +++ b/Source/Scene/PointCloud3DTileContent.js @@ -113,9 +113,6 @@ define([ this._hasNormals = false; this._hasBatchIds = false; - // Used to determine how to attenuate points - this._pointAttenuationMaxSize = 1.0; - // Use per-point normals to hide back-facing points. this.backFaceCulling = false; this._backFaceCulling = false; @@ -125,6 +122,7 @@ define([ this._highlightColor = Color.clone(Color.WHITE); this._pointSize = 1.0; + this._pointAttenuationMaxSize = 1.0; this._quantizedVolumeScale = undefined; this._quantizedVolumeOffset = undefined; @@ -259,15 +257,6 @@ define([ return this._batchTable; } }, - - /** - * @private - */ - pointAttenuationMaxSize : { - get : function() { - return this._pointAttenuationMaxSize; - } - } }); var sizeOfUint32 = Uint32Array.BYTES_PER_ELEMENT; @@ -781,7 +770,7 @@ define([ } // Edit the function header to accept the point position, color, and normal - return source.replace('()', '(vec3 position, vec3 position_absolute, vec4 color, vec3 normal)'); + return source.replace('()', '(vec3 position, vec3 positionWC, vec4 color, vec3 normal)'); } function createShaders(content, frameState, style) { @@ -994,7 +983,7 @@ define([ } else { vs += ' vec3 position = a_position; \n'; } - vs += ' vec3 position_absolute = vec3(czm_model * vec4(position, 1.0)); \n'; + vs += ' vec3 positionWC = vec3(czm_model * vec4(position, 1.0)); \n'; if (hasNormals) { if (isOctEncoded16P) { @@ -1007,23 +996,23 @@ define([ } if (hasColorStyle) { - vs += ' color = getColorFromStyle(position, position_absolute, color, normal); \n'; + vs += ' color = getColorFromStyle(position, positionWC, color, normal); \n'; } if (hasShowStyle) { - vs += ' float show = float(getShowFromStyle(position, position_absolute, color, normal)); \n'; + vs += ' float show = float(getShowFromStyle(position, positionWC, color, normal)); \n'; } if (hasPointSizeStyle) { - vs += ' gl_PointSize = getPointSizeFromStyle(position, position_absolute, color, normal); \n'; + vs += ' gl_PointSize = getPointSizeFromStyle(position, positionWC, color, normal); \n'; } else { vs += ' gl_PointSize = u_pointSize; \n'; } - vs += ' vec4 position_EC = czm_view * vec4(position_absolute, 1.0); \n' + - ' position_EC.z *= -1.0; \n\n' + + vs += ' vec4 positionEC = czm_view * vec4(positionWC, 1.0); \n' + + ' positionEC.z *= -1.0; \n\n' + ' float attenuationFactor = \n' + - ' ((position_EC.z - czm_clampedFrustum.x) /\n' + + ' ((positionEC.z - czm_clampedFrustum.x) /\n' + ' (czm_clampedFrustum.y - czm_clampedFrustum.x)); \n' + ' gl_PointSize *= mix(u_pointAttenuationMaxSize, 1.0, attenuationFactor); \n\n' + ' color = color * u_highlightColor; \n'; From 25c8c7e50716a2493418e019882218a60b719f5f Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 23 Aug 2017 15:28:47 -0400 Subject: [PATCH 195/240] Now destroying the PointCloudPostProcessor when necessary --- Source/Scene/Cesium3DTileset.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Source/Scene/Cesium3DTileset.js b/Source/Scene/Cesium3DTileset.js index 22ecf1829ba9..5ff11e668978 100644 --- a/Source/Scene/Cesium3DTileset.js +++ b/Source/Scene/Cesium3DTileset.js @@ -1787,6 +1787,8 @@ define([ } } + this._pointCloudPostProcessor.destroy(); + this._root = undefined; return destroyObject(this); }; From 24ecf218dcc661706381bc1f03e5e566847ac280 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 23 Aug 2017 15:36:07 -0400 Subject: [PATCH 196/240] Removes old, unused code --- Source/Scene/PointCloudPostProcessor.js | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 5eb2448cdb8d..ddb8b4656f1a 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -108,27 +108,6 @@ define([ this.dropoutFactor = options.dropoutFactor; this.delay = options.delay; - this._pointArray = undefined; - - this._minBlend = { - enabled : true, - equationRgb : BlendEquation.MIN, - equationAlpha : BlendEquation.MIN, - functionSourceRgb : BlendFunction.ONE, - functionSourceAlpha : BlendFunction.ONE, - functionDestinationRgb : BlendFunction.ONE, - functionDestinationAlpha : BlendFunction.ONE - }; - this._addBlend = { - enabled : true, - equationRgb : BlendEquation.ADD, - equationAlpha : BlendEquation.ADD, - functionSourceRgb : BlendFunction.ONE, - functionSourceAlpha : BlendFunction.ONE, - functionDestinationRgb : BlendFunction.ONE, - functionDestinationAlpha : BlendFunction.ONE - }; - this._testingFunc = StencilFunction.EQUAL; this._testingOp = { fail : StencilOperation.KEEP, From 560272708b5f6ca34177125fb56f9c094d7d0407 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 23 Aug 2017 15:39:44 -0400 Subject: [PATCH 197/240] Moves inner functions out --- Source/Scene/PointCloudPostProcessor.js | 42 ++++++++++++------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index ddb8b4656f1a..f73bb8131b84 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -193,29 +193,29 @@ define([ processor._drawCommands = undefined; } - function generateSectorLUT(processor) { - function getSector(dx, dy, numSectors) { - var angle = (Math.atan2(dy, dx) + Math.PI) / (2.0 * Math.PI) - 1e-6; - return Math.trunc(angle * numSectors); - } + function getSector(dx, dy, numSectors) { + var angle = (Math.atan2(dy, dx) + Math.PI) / (2.0 * Math.PI) - 1e-6; + return Math.trunc(angle * numSectors); + } - function collapseSectors(dx, dy, numSectors) { - var sectors = new Uint8Array(4); - sectors[0] = getSector(dx - 0.5, dy + 0.5, numSectors); - sectors[1] = getSector(dx + 0.5, dy - 0.5, numSectors); - sectors[2] = getSector(dx + 0.5, dy + 0.5, numSectors); - sectors[3] = getSector(dx - 0.5, dy - 0.5, numSectors); - - var first = sectors[0]; - var second = sectors[0]; - sectors.forEach(function(element) { - if (element !== first) { - second = element; - } - }); - return new Array(first, second); - } + function collapseSectors(dx, dy, numSectors) { + var sectors = new Uint8Array(4); + sectors[0] = getSector(dx - 0.5, dy + 0.5, numSectors); + sectors[1] = getSector(dx + 0.5, dy - 0.5, numSectors); + sectors[2] = getSector(dx + 0.5, dy + 0.5, numSectors); + sectors[3] = getSector(dx - 0.5, dy - 0.5, numSectors); + + var first = sectors[0]; + var second = sectors[0]; + sectors.forEach(function(element) { + if (element !== first) { + second = element; + } + }); + return [first, second]; + } + function generateSectorLUT(processor) { var numSectors = 8; var lutSize = processor.neighborhoodHalfWidth * 2 + 1; var lut = new Uint8Array(lutSize * lutSize * 4); From 527b703aa1c4d6bd1dd6bdf80068331ecf612c62 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 23 Aug 2017 15:40:36 -0400 Subject: [PATCH 198/240] Depth texture array now the right length --- Source/Scene/PointCloudPostProcessor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index f73bb8131b84..427505f7aa12 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -239,7 +239,7 @@ define([ var screenHeight = context.drawingBufferHeight; var colorTextures = new Array(2); - var depthTextures = new Array(3); + var depthTextures = new Array(2); var aoTextures = new Array(2); var ecTexture = new Texture({ From 0f11323ce38577494efafd89d35c61075de9ca26 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 23 Aug 2017 15:44:43 -0400 Subject: [PATCH 199/240] Now creates sector LUT without copying --- Source/Scene/PointCloudPostProcessor.js | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 427505f7aa12..8c9e91ec6a2b 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -271,20 +271,18 @@ define([ // Load the sector LUT that the point occlusion pass needs var lutSize = processor.neighborhoodHalfWidth * 2 + 1; + var lutData = generateSectorLUT(processor); var sectorLUTTexture = new Texture({ context : context, - width : lutSize, - height : lutSize, + source : { + width : lutSize, + height : lutSize, + arrayBufferView : lutData + }, pixelFormat : PixelFormat.RGBA, pixelDatatype : PixelDatatype.UNSIGNED_BYTE, sampler : createSampler() }); - var lutData = generateSectorLUT(processor); - sectorLUTTexture.copyFrom({ - width : lutSize, - height : lutSize, - arrayBufferView : lutData - }); var dirty = new Texture({ context: context, From 42369710a1bf9d05f930c945910734e5138e9cf1 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 23 Aug 2017 15:50:15 -0400 Subject: [PATCH 200/240] Renames dirty texture --- Source/Scene/PointCloudPostProcessor.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 8c9e91ec6a2b..6933aa3219dc 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -84,7 +84,7 @@ define([ this._edgeCullingTexture = undefined; this._sectorLUTTexture = undefined; this._aoTextures = undefined; - this._dirty = undefined; + this._stencilMaskTexture = undefined; this._drawCommands = undefined; this._clearCommands = undefined; @@ -171,7 +171,7 @@ define([ processor._aoTextures[1].destroy(); processor._densityTexture.destroy(); processor._edgeCullingTexture.destroy(); - processor._dirty.destroy(); + processor._stencilMaskTexture.destroy(); processor._colorTextures[0].destroy(); processor._colorTextures[1].destroy(); var framebuffers = processor._framebuffers; @@ -284,7 +284,7 @@ define([ sampler : createSampler() }); - var dirty = new Texture({ + var stencilMaskTexture = new Texture({ context: context, width: screenWidth, height: screenHeight, @@ -333,13 +333,13 @@ define([ colorTextures[0], ecTexture ], - depthStencilTexture : dirty, + depthStencilTexture : stencilMaskTexture, destroyAttachments : false }), screenSpacePass : new Framebuffer({ context : context, colorTextures : [depthTextures[0], aoTextures[0]], - depthStencilTexture: dirty, + depthStencilTexture: stencilMaskTexture, destroyAttachments : false }), aoBufferA : new Framebuffer({ @@ -354,13 +354,13 @@ define([ }), stencilMask : new Framebuffer({ context : context, - depthStencilTexture: dirty, + depthStencilTexture: stencilMaskTexture, destroyAttachments : false }), densityEstimationPass : new Framebuffer({ context : context, colorTextures : [densityMap], - depthStencilTexture: dirty, + depthStencilTexture: stencilMaskTexture, destroyAttachments : false }), regionGrowingPassA : new Framebuffer({ @@ -368,7 +368,7 @@ define([ colorTextures : [colorTextures[1], depthTextures[1], aoTextures[1]], - depthStencilTexture: dirty, + depthStencilTexture: stencilMaskTexture, destroyAttachments : false }), regionGrowingPassB : new Framebuffer({ @@ -376,7 +376,7 @@ define([ colorTextures: [colorTextures[0], depthTextures[0], aoTextures[0]], - depthStencilTexture: dirty, + depthStencilTexture: stencilMaskTexture, destroyAttachments: false }) }; @@ -387,7 +387,7 @@ define([ processor._aoTextures = aoTextures; processor._colorTextures = colorTextures; processor._ecTexture = ecTexture; - processor._dirty = dirty; + processor._stencilMaskTexture = stencilMaskTexture; } function replaceConstants(sourceStr, constantName, replacement) { From c365313cb5d3bac270793a081598afefd4626351 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 23 Aug 2017 15:52:39 -0400 Subject: [PATCH 201/240] Colon consistency --- Source/Scene/PointCloudPostProcessor.js | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 6933aa3219dc..54d54c5aaa03 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -285,12 +285,12 @@ define([ }); var stencilMaskTexture = new Texture({ - context: context, - width: screenWidth, - height: screenHeight, - pixelFormat: PixelFormat.DEPTH_STENCIL, - pixelDatatype: PixelDatatype.UNSIGNED_INT_24_8, - sampler: createSampler() + context : context, + width : screenWidth, + height : screenHeight, + pixelFormat : PixelFormat.DEPTH_STENCIL, + pixelDatatype : PixelDatatype.UNSIGNED_INT_24_8, + sampler : createSampler() }); for (i = 0; i < 2; ++i) { @@ -372,12 +372,12 @@ define([ destroyAttachments : false }), regionGrowingPassB : new Framebuffer({ - context: context, - colorTextures: [colorTextures[0], - depthTextures[0], - aoTextures[0]], - depthStencilTexture: stencilMaskTexture, - destroyAttachments: false + context : context, + colorTextures : [colorTextures[0], + depthTextures[0], + aoTextures[0]], + depthStencilTexture : stencilMaskTexture, + destroyAttachments : false }) }; processor._depthTextures = depthTextures; From aeeb27fe10b63c8c395a4e1f63b82a11d20cb16c Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Sun, 27 Aug 2017 10:00:32 -0400 Subject: [PATCH 202/240] Renames ecTexture and depthTexture --- Source/Scene/PointCloudPostProcessor.js | 47 +++++++++---------------- 1 file changed, 17 insertions(+), 30 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 54d54c5aaa03..f66129434743 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -78,8 +78,7 @@ define([ function PointCloudPostProcessor(options) { this._framebuffers = undefined; this._colorTextures = undefined; - this._ecTexture = undefined; - this._depthTextures = undefined; + this._ecTextures = undefined; this._densityTexture = undefined; this._edgeCullingTexture = undefined; this._sectorLUTTexture = undefined; @@ -163,9 +162,8 @@ define([ } function destroyFramebuffers(processor) { - processor._depthTextures[0].destroy(); - processor._depthTextures[1].destroy(); - processor._ecTexture.destroy(); + processor._ecTextures[0].destroy(); + processor._ecTextures[1].destroy(); processor._sectorLUTTexture.destroy(); processor._aoTextures[0].destroy(); processor._aoTextures[1].destroy(); @@ -183,8 +181,7 @@ define([ processor._framebuffers = undefined; processor._colorTextures = undefined; - processor._ecTexture = undefined; - processor._depthTextures = undefined; + processor._ecTextures = undefined; processor._densityTexture = undefined; processor._edgeCullingTexture = undefined; processor._sectorLUTTexture = undefined; @@ -239,18 +236,9 @@ define([ var screenHeight = context.drawingBufferHeight; var colorTextures = new Array(2); - var depthTextures = new Array(2); + var ecTextures = new Array(2); var aoTextures = new Array(2); - var ecTexture = new Texture({ - context : context, - width : screenWidth, - height : screenHeight, - pixelFormat : PixelFormat.RGBA, - pixelDatatype : PixelDatatype.FLOAT, - sampler : createSampler() - }); - var densityMap = new Texture({ context : context, width : screenWidth, @@ -303,7 +291,7 @@ define([ sampler : createSampler() }); - depthTextures[i] = new Texture({ + ecTextures[i] = new Texture({ context : context, width : screenWidth, height : screenHeight, @@ -331,14 +319,14 @@ define([ context : context, colorTextures : [ colorTextures[0], - ecTexture + ecTextures[1] ], depthStencilTexture : stencilMaskTexture, destroyAttachments : false }), screenSpacePass : new Framebuffer({ context : context, - colorTextures : [depthTextures[0], aoTextures[0]], + colorTextures : [ecTextures[0], aoTextures[0]], depthStencilTexture: stencilMaskTexture, destroyAttachments : false }), @@ -366,7 +354,7 @@ define([ regionGrowingPassA : new Framebuffer({ context : context, colorTextures : [colorTextures[1], - depthTextures[1], + ecTextures[1], aoTextures[1]], depthStencilTexture: stencilMaskTexture, destroyAttachments : false @@ -374,19 +362,18 @@ define([ regionGrowingPassB : new Framebuffer({ context : context, colorTextures : [colorTextures[0], - depthTextures[0], + ecTextures[0], aoTextures[0]], depthStencilTexture : stencilMaskTexture, destroyAttachments : false }) }; - processor._depthTextures = depthTextures; + processor._ecTextures = ecTextures; processor._densityTexture = densityMap; processor._edgeCullingTexture = edgeCullingTexture; processor._sectorLUTTexture = sectorLUTTexture; processor._aoTextures = aoTextures; processor._colorTextures = colorTextures; - processor._ecTexture = ecTexture; processor._stencilMaskTexture = stencilMaskTexture; } @@ -409,7 +396,7 @@ define([ return processor._sectorLUTTexture; }, pointCloud_ECTexture : function() { - return processor._ecTexture; + return processor._ecTextures[1]; }, occlusionAngle : function() { return processor.occlusionAngle; @@ -452,7 +439,7 @@ define([ function densityEdgeCullStage(processor, context) { var uniformMap = { pointCloud_depthTexture : function() { - return processor._depthTextures[0]; + return processor._ecTextures[0]; }, neighborhoodVectorSize : function() { return processor.neighborhoodVectorSize; @@ -499,7 +486,7 @@ define([ return processor._colorTextures[i]; }, pointCloud_depthTexture : function() { - return processor._depthTextures[i]; + return processor._ecTextures[i]; }, pointCloud_densityTexture : function() { return processor._densityTexture; @@ -567,7 +554,7 @@ define([ return processor._colorTextures[i]; }, pointCloud_depthTexture : function() { - return processor._depthTextures[i]; + return processor._ecTextures[i]; }, pointCloud_aoTexture : function() { return processor._aoTextures[i]; @@ -757,7 +744,7 @@ define([ return processor._colorTextures[1 - numRegionGrowingPasses % 2]; }, pointCloud_depthTexture : function() { - return processor._depthTextures[1 - numRegionGrowingPasses % 2]; + return processor._ecTextures[1 - numRegionGrowingPasses % 2]; }, pointCloud_aoTexture : function() { return processor._aoTextures[1 - numRegionGrowingPasses % 2]; @@ -781,7 +768,7 @@ define([ if (processor.AOViewEnabled) { debugViewCommand = debugViewStage(processor, context, processor._aoTextures[0], true); } else if (processor.depthViewEnabled) { - debugViewCommand = debugViewStage(processor, context, processor._depthTextures[0], false); + debugViewCommand = debugViewStage(processor, context, processor._ecTextures[0], false); } var framebuffers = processor._framebuffers; From 2c35e2e95bb769929657326ad11b91bbaf66d657 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Sun, 27 Aug 2017 10:08:07 -0400 Subject: [PATCH 203/240] Renames most of the variables in the shaders to EC rather than depth --- Source/Scene/PointCloudPostProcessor.js | 18 +++++++++--------- .../DensityEdgeCullPass.glsl | 6 +++--- .../PointCloudPostProcessorBlendPass.glsl | 4 ++-- .../PointOcclusionPassGL1.glsl | 6 +++--- .../PointOcclusionPassGL2.glsl | 6 +++--- .../RegionGrowingPassGL1.glsl | 6 +++--- 6 files changed, 23 insertions(+), 23 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index f66129434743..581b8cbe2d02 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -395,7 +395,7 @@ define([ sectorLUT : function() { return processor._sectorLUTTexture; }, - pointCloud_ECTexture : function() { + pointCloud_ecTexture : function() { return processor._ecTextures[1]; }, occlusionAngle : function() { @@ -438,7 +438,7 @@ define([ function densityEdgeCullStage(processor, context) { var uniformMap = { - pointCloud_depthTexture : function() { + pointCloud_ecTexture : function() { return processor._ecTextures[0]; }, neighborhoodVectorSize : function() { @@ -485,7 +485,7 @@ define([ pointCloud_colorTexture : function() { return processor._colorTextures[i]; }, - pointCloud_depthTexture : function() { + pointCloud_ecTexture : function() { return processor._ecTextures[i]; }, pointCloud_densityTexture : function() { @@ -553,7 +553,7 @@ define([ pointCloud_colorTexture : function() { return processor._colorTextures[i]; }, - pointCloud_depthTexture : function() { + pointCloud_ecTexture : function() { return processor._ecTextures[i]; }, pointCloud_aoTexture : function() { @@ -578,22 +578,22 @@ define([ '#define EPS 1e-6 \n' + 'uniform int densityHalfWidth; \n' + 'uniform sampler2D pointCloud_colorTexture; \n' + - 'uniform sampler2D pointCloud_depthTexture; \n' + + 'uniform sampler2D pointCloud_ecTexture; \n' + 'uniform sampler2D pointCloud_aoTexture; \n' + 'uniform sampler2D pointCloud_densityTexture; \n' + 'varying vec2 v_textureCoordinates; \n' + 'void main() \n' + '{ \n' + - ' vec4 depth = texture2D(pointCloud_depthTexture, v_textureCoordinates); \n' + + ' vec4 ec = texture2D(pointCloud_ecTexture, v_textureCoordinates); \n' + ' vec4 rawAO = texture2D(pointCloud_aoTexture, v_textureCoordinates); \n' + - ' if (length(depth) > EPS) { \n' + + ' if (length(ec) > EPS) { \n' + ' #ifdef densityView \n' + ' float density = ceil(densityScaleFactor * texture2D(pointCloud_densityTexture, v_textureCoordinates).r); \n' + ' gl_FragData[0] = vec4(vec3(density / float(densityHalfWidth)), 1.0); \n' + ' #else \n' + ' gl_FragData[0] = texture2D(pointCloud_colorTexture, v_textureCoordinates); \n' + ' #endif \n' + - ' gl_FragData[1] = depth; \n' + + ' gl_FragData[1] = ec; \n' + ' gl_FragData[2] = rawAO; \n' + ' } else { \n' + ' gl_FragData[1] = vec4(0.0); ' + @@ -743,7 +743,7 @@ define([ pointCloud_colorTexture : function() { return processor._colorTextures[1 - numRegionGrowingPasses % 2]; }, - pointCloud_depthTexture : function() { + pointCloud_ecTexture : function() { return processor._ecTextures[1 - numRegionGrowingPasses % 2]; }, pointCloud_aoTexture : function() { diff --git a/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl b/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl index 012fea3ba89b..9346187aa1aa 100644 --- a/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl +++ b/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl @@ -5,7 +5,7 @@ #define densityScaleFactor 10.0 #define dropoutEnabled -uniform sampler2D pointCloud_depthTexture; +uniform sampler2D pointCloud_ecTexture; uniform float neighborhoodVectorSize; uniform float maxAbsRatio; uniform float dropoutFactor; @@ -16,7 +16,7 @@ float random(vec2 st) { } void main() { - float center = length(texture2D(pointCloud_depthTexture, + float center = length(texture2D(pointCloud_ecTexture, v_textureCoordinates)); ivec2 pos = ivec2(int(gl_FragCoord.x), int(gl_FragCoord.y)); @@ -45,7 +45,7 @@ void main() { ivec2 pI = pos + d; vec2 normPI = vec2(pI) / czm_viewport.zw; - float neighbor = length(texture2D(pointCloud_depthTexture, + float neighbor = length(texture2D(pointCloud_ecTexture, normPI)); if (neighbor < EPS || pI == pos) { continue; diff --git a/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl b/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl index 8401e7863312..47486470ab28 100644 --- a/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl +++ b/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl @@ -3,7 +3,7 @@ #extension GL_EXT_frag_depth : enable uniform sampler2D pointCloud_colorTexture; -uniform sampler2D pointCloud_depthTexture; +uniform sampler2D pointCloud_ecTexture; uniform sampler2D pointCloud_aoTexture; uniform float sigmoidDomainOffset; uniform float sigmoidSharpness; @@ -23,7 +23,7 @@ void main() { 0.0, 1.0); color.xyz = color.xyz * ao; #endif // enableAO - vec4 ec = texture2D(pointCloud_depthTexture, v_textureCoordinates); + vec4 ec = texture2D(pointCloud_ecTexture, v_textureCoordinates); if (length(ec) < EPS) { discard; } else { diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl index c6c0a7e1e2a1..e378fa3cb487 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl @@ -15,7 +15,7 @@ #define trianglePeriod 1.0 #define useTriangle -uniform sampler2D pointCloud_ECTexture; +uniform sampler2D pointCloud_ecTexture; uniform float occlusionAngle; uniform sampler2D sectorLUT; varying vec2 v_textureCoordinates; @@ -110,7 +110,7 @@ void main() { ivec2 pos = ivec2(int(gl_FragCoord.x), int(gl_FragCoord.y)); // The position of this pixel in 3D (i.e the position of the point) - vec3 centerPosition = texture2D(pointCloud_ECTexture, v_textureCoordinates).xyz; + vec3 centerPosition = texture2D(pointCloud_ecTexture, v_textureCoordinates).xyz; bool invalid = false; // If the EC of this pixel is zero, that means that it's not a valid @@ -152,7 +152,7 @@ void main() { ivec2 pI = pos + d; // We now calculate the actual 3D position of the horizon pixel (the horizon point) - vec3 neighborPosition = texture2D(pointCloud_ECTexture, + vec3 neighborPosition = texture2D(pointCloud_ecTexture, vec2(pI) / czm_viewport.zw).xyz; // If our horizon pixel doesn't exist, ignore it and move on diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl index 868d2eeca890..817e6758a54a 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl @@ -16,7 +16,7 @@ #define useTriangle #define dropoutEnabled -uniform sampler2D pointCloud_ECTexture; +uniform sampler2D pointCloud_ecTexture; uniform float occlusionAngle; uniform float dropoutFactor; uniform sampler2D sectorLUT; @@ -50,7 +50,7 @@ void main() { ivec2 pos = ivec2(int(gl_FragCoord.x), int(gl_FragCoord.y)); // The position of this pixel in 3D (i.e the position of the point) - vec3 centerPosition = texture(pointCloud_ECTexture, v_textureCoordinates).xyz; + vec3 centerPosition = texture(pointCloud_ecTexture, v_textureCoordinates).xyz; bool invalid = false; // If the EC of this pixel is zero, that means that it's not a valid @@ -105,7 +105,7 @@ void main() { ivec2 pI = pos + d; // We now calculate the actual 3D position of the horizon pixel (the horizon point) - vec3 neighborPosition = texelFetch(pointCloud_ECTexture, ivec2(pI), 0).xyz; + vec3 neighborPosition = texelFetch(pointCloud_ecTexture, ivec2(pI), 0).xyz; // If our horizon pixel doesn't exist, ignore it and move on if (length(neighborPosition) < EPS || pI == pos) { diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl index 0464763902b3..63235603aca7 100644 --- a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl @@ -13,7 +13,7 @@ uniform sampler2D pointCloud_colorTexture; uniform sampler2D pointCloud_densityTexture; -uniform sampler2D pointCloud_depthTexture; +uniform sampler2D pointCloud_ecTexture; uniform sampler2D pointCloud_aoTexture; uniform float rangeParameter; uniform int densityHalfWidth; @@ -147,7 +147,7 @@ void loadIntoArray(inout vec4[neighborhoodSize] ecNeighbors, continue; } vec2 neighborCoords = vec2(vec2(d) + gl_FragCoord.xy) / czm_viewport.zw; - vec4 neighborEC = texture2D(pointCloud_depthTexture, + vec4 neighborEC = texture2D(pointCloud_ecTexture, neighborCoords); float neighbor = length(neighborEC); float aoNeighbor = czm_unpackDepth(texture2D(pointCloud_aoTexture, @@ -178,7 +178,7 @@ void loadIntoArray(inout vec4[neighborhoodSize] ecNeighbors, void main() { vec4 color = texture2D(pointCloud_colorTexture, v_textureCoordinates); - vec4 ec = texture2D(pointCloud_depthTexture, v_textureCoordinates); + vec4 ec = texture2D(pointCloud_ecTexture, v_textureCoordinates); float depth = length(ec); float ao = czm_unpackDepth(texture2D(pointCloud_aoTexture, v_textureCoordinates)); From 92f9c639e58a25609373172023ab9d3eb1300ef3 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Sun, 27 Aug 2017 10:14:36 -0400 Subject: [PATCH 204/240] Fixes the WebGL2 region growing pass --- Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl index aa6efa38bbc6..724e7d39eafa 100644 --- a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl @@ -12,7 +12,7 @@ uniform sampler2D pointCloud_colorTexture; uniform sampler2D pointCloud_densityTexture; -uniform sampler2D pointCloud_depthTexture; +uniform sampler2D pointCloud_ecTexture; uniform sampler2D pointCloud_aoTexture; uniform float rangeParameter; uniform int densityHalfWidth; @@ -149,7 +149,7 @@ void loadIntoArray(inout vec4[neighborhoodSize] ecNeighbors, continue; } ivec2 neighborCoords = d + ivec2(gl_FragCoord.xy); - vec4 neighborEC = texelFetch(pointCloud_depthTexture, + vec4 neighborEC = texelFetch(pointCloud_ecTexture, neighborCoords, 0); float neighbor = length(neighborEC); @@ -184,7 +184,7 @@ void loadIntoArray(inout vec4[neighborhoodSize] ecNeighbors, void main() { vec4 color = texture(pointCloud_colorTexture, v_textureCoordinates); - vec4 ec = texture(pointCloud_depthTexture, v_textureCoordinates); + vec4 ec = texture(pointCloud_ecTexture, v_textureCoordinates); float depth = length(ec); float ao = czm_unpackDepth(texture(pointCloud_aoTexture, v_textureCoordinates)); From ab114aedb6250e3815c71a1237ed2048e763ea0e Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Sun, 27 Aug 2017 10:18:08 -0400 Subject: [PATCH 205/240] Removes old TODO --- Source/Scene/PointCloudPostProcessor.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 581b8cbe2d02..0f76c6ae9671 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -310,10 +310,6 @@ define([ }); } - // There used to be an explanation of how this worked here - // but it got too long. - // TODO: Find a better place to put an explanation of what all - // the framebuffers are meant for. processor._framebuffers = { prior : new Framebuffer({ context : context, From 091af74f962936562779b92ef603f6e216a1d8e4 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Sun, 27 Aug 2017 10:29:55 -0400 Subject: [PATCH 206/240] Prefixes all the uniforms with a u_ --- Source/Scene/PointCloudPostProcessor.js | 26 +++++++++---------- .../DensityEdgeCullPass.glsl | 14 +++++----- .../PointCloudPostProcessorBlendPass.glsl | 6 ++--- .../PointOcclusionPassGL1.glsl | 4 +-- .../PointOcclusionPassGL2.glsl | 10 +++---- .../RegionGrowingPassGL1.glsl | 14 +++++----- .../RegionGrowingPassGL2.glsl | 14 +++++----- 7 files changed, 44 insertions(+), 44 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 0f76c6ae9671..f669e9b29869 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -394,10 +394,10 @@ define([ pointCloud_ecTexture : function() { return processor._ecTextures[1]; }, - occlusionAngle : function() { + u_occlusionAngle : function() { return processor.occlusionAngle; }, - dropoutFactor : function() { + u_dropoutFactor : function() { return processor.dropoutFactor; } }; @@ -437,13 +437,13 @@ define([ pointCloud_ecTexture : function() { return processor._ecTextures[0]; }, - neighborhoodVectorSize : function() { + u_neighborhoodVectorSize : function() { return processor.neighborhoodVectorSize; }, - maxAbsRatio : function() { + u_maxAbsRatio : function() { return processor.maxAbsRatio; }, - dropoutFactor : function() { + u_dropoutFactor : function() { return processor.dropoutFactor; } }; @@ -490,7 +490,7 @@ define([ pointCloud_aoTexture : function() { return processor._aoTextures[i]; }, - rangeParameter : function() { + u_rangeParameter : function() { if (processor.useTriangle) { return processor.rangeParameter; } @@ -499,10 +499,10 @@ define([ } return processor.rangeParameter * (rangeMax - rangeMin) + rangeMin; }, - densityHalfWidth : function() { + u_densityHalfWidth : function() { return processor.densityHalfWidth; }, - iterationNumber : function() { + u_iterationNumber : function() { return iteration; } }; @@ -558,7 +558,7 @@ define([ pointCloud_densityTexture : function() { return processor._densityTexture; }, - densityHalfWidth : function() { + u_densityHalfWidth : function() { return processor.densityHalfWidth; } }; @@ -572,7 +572,7 @@ define([ '#define densityView \n' + '#define densityScaleFactor 10.0 \n' + '#define EPS 1e-6 \n' + - 'uniform int densityHalfWidth; \n' + + 'uniform int u_densityHalfWidth; \n' + 'uniform sampler2D pointCloud_colorTexture; \n' + 'uniform sampler2D pointCloud_ecTexture; \n' + 'uniform sampler2D pointCloud_aoTexture; \n' + @@ -585,7 +585,7 @@ define([ ' if (length(ec) > EPS) { \n' + ' #ifdef densityView \n' + ' float density = ceil(densityScaleFactor * texture2D(pointCloud_densityTexture, v_textureCoordinates).r); \n' + - ' gl_FragData[0] = vec4(vec3(density / float(densityHalfWidth)), 1.0); \n' + + ' gl_FragData[0] = vec4(vec3(density / float(u_densityHalfWidth)), 1.0); \n' + ' #else \n' + ' gl_FragData[0] = texture2D(pointCloud_colorTexture, v_textureCoordinates); \n' + ' #endif \n' + @@ -745,10 +745,10 @@ define([ pointCloud_aoTexture : function() { return processor._aoTextures[1 - numRegionGrowingPasses % 2]; }, - sigmoidDomainOffset : function() { + u_sigmoidDomainOffset : function() { return processor.sigmoidDomainOffset; }, - sigmoidSharpness : function() { + u_sigmoidSharpness : function() { return processor.sigmoidSharpness; } }; diff --git a/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl b/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl index 9346187aa1aa..0e089ae2f9a8 100644 --- a/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl +++ b/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl @@ -6,9 +6,9 @@ #define dropoutEnabled uniform sampler2D pointCloud_ecTexture; -uniform float neighborhoodVectorSize; -uniform float maxAbsRatio; -uniform float dropoutFactor; +uniform float u_neighborhoodVectorSize; +uniform float u_maxAbsRatio; +uniform float u_dropoutFactor; varying vec2 v_textureCoordinates; float random(vec2 st) { @@ -29,8 +29,8 @@ void main() { #ifdef dropoutEnabled float seed = random(v_textureCoordinates); - if (seed < dropoutFactor) { - width = int(float(width) * (1.0 - dropoutFactor)); + if (seed < u_dropoutFactor) { + width = int(float(width) * (1.0 - u_dropoutFactor)); } #endif //dropoutEnabled @@ -62,8 +62,8 @@ void main() { float absRatio = length(neighborhoodAccum) / length(absNeighborhoodAccum); if (int(closestNeighbor) <= neighborhoodHalfWidth && - !(absRatio > maxAbsRatio && - length(neighborhoodAccum) > neighborhoodVectorSize)) { + !(absRatio > u_maxAbsRatio && + length(neighborhoodAccum) > u_neighborhoodVectorSize)) { gl_FragData[0] = vec4(vec3(closestNeighbor / densityScaleFactor), 0.0); } else { diff --git a/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl b/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl index 47486470ab28..995157f02c71 100644 --- a/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl +++ b/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl @@ -5,8 +5,8 @@ uniform sampler2D pointCloud_colorTexture; uniform sampler2D pointCloud_ecTexture; uniform sampler2D pointCloud_aoTexture; -uniform float sigmoidDomainOffset; -uniform float sigmoidSharpness; +uniform float u_sigmoidDomainOffset; +uniform float u_sigmoidSharpness; uniform float splitScreenX; varying vec2 v_textureCoordinates; @@ -19,7 +19,7 @@ void main() { #ifdef enableAO float ao = czm_unpackDepth(texture2D(pointCloud_aoTexture, v_textureCoordinates)); - ao = clamp(sigmoid(clamp(ao + sigmoidDomainOffset, 0.0, 1.0), sigmoidSharpness), + ao = clamp(sigmoid(clamp(ao + u_sigmoidDomainOffset, 0.0, 1.0), u_sigmoidSharpness), 0.0, 1.0); color.xyz = color.xyz * ao; #endif // enableAO diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl index e378fa3cb487..be0adc4de3dc 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl @@ -16,7 +16,7 @@ #define useTriangle uniform sampler2D pointCloud_ecTexture; -uniform float occlusionAngle; +uniform float u_occlusionAngle; uniform sampler2D sectorLUT; varying vec2 v_textureCoordinates; @@ -208,7 +208,7 @@ void main() { } // The solid angle is too small, so we occlude this point - if (accumulator < (2.0 * PI) * (1.0 - occlusionAngle)) { + if (accumulator < (2.0 * PI) * (1.0 - u_occlusionAngle)) { gl_FragData[0] = vec4(0.0); gl_FragData[1] = vec4(1.0 - EPS); } else { diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl index 817e6758a54a..7bf84ee28be3 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl @@ -17,8 +17,8 @@ #define dropoutEnabled uniform sampler2D pointCloud_ecTexture; -uniform float occlusionAngle; -uniform float dropoutFactor; +uniform float u_occlusionAngle; +uniform float u_dropoutFactor; uniform sampler2D sectorLUT; in vec2 v_textureCoordinates; @@ -92,8 +92,8 @@ void main() { #ifdef dropoutEnabled float seed = random(v_textureCoordinates); - if (seed < dropoutFactor) { - width = int(float(width) * (1.0 - dropoutFactor)); + if (seed < u_dropoutFactor) { + width = int(float(width) * (1.0 - u_dropoutFactor)); } #endif //dropoutEnabled @@ -160,7 +160,7 @@ void main() { } // The solid angle is too small, so we occlude this point - if (accumulator < (2.0 * PI) * (1.0 - occlusionAngle)) { + if (accumulator < (2.0 * PI) * (1.0 - u_occlusionAngle)) { depthOut = vec4(0); aoOut = vec4(1.0 - EPS); } else { diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl index 63235603aca7..92821421005d 100644 --- a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl @@ -15,9 +15,9 @@ uniform sampler2D pointCloud_colorTexture; uniform sampler2D pointCloud_densityTexture; uniform sampler2D pointCloud_ecTexture; uniform sampler2D pointCloud_aoTexture; -uniform float rangeParameter; -uniform int densityHalfWidth; -uniform int iterationNumber; +uniform float u_rangeParameter; +uniform int u_densityHalfWidth; +uniform int u_iterationNumber; varying vec2 v_textureCoordinates; @@ -209,7 +209,7 @@ void main() { // If our depth value is invalid if (abs(depth) < EPS) { // If the area that we want to region grow is sufficently sparse - if (float(iterationNumber - DELAY) <= density + EPS) { + if (float(u_iterationNumber - DELAY) <= density + EPS) { float finalDepth = depth; #if neighborhoodFullWidth == 3 fastMedian3(depthNeighbors, aoNeighbors, colorNeighbors, @@ -243,7 +243,7 @@ void main() { float weight = (1.0 - rI / 2.0) * - (1.0 - min(1.0, ecDelta / max(1e-38, rangeParameter))); + (1.0 - min(1.0, ecDelta / max(1e-38, u_rangeParameter))); ecAccum += ecNeighbor * weight; aoAccum += aoNeighbor * weight; @@ -260,10 +260,10 @@ void main() { } #ifdef densityView - gl_FragData[0] = vec4(vec3(density / float(densityHalfWidth)), 1.0); + gl_FragData[0] = vec4(vec3(density / float(u_densityHalfWidth)), 1.0); #else #ifdef stencilView - gl_FragData[0] = testColor(iterationNumber); + gl_FragData[0] = testColor(u_iterationNumber); #else gl_FragData[0] = finalColor; #endif diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl index 724e7d39eafa..276e21aaa372 100644 --- a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl @@ -14,9 +14,9 @@ uniform sampler2D pointCloud_colorTexture; uniform sampler2D pointCloud_densityTexture; uniform sampler2D pointCloud_ecTexture; uniform sampler2D pointCloud_aoTexture; -uniform float rangeParameter; -uniform int densityHalfWidth; -uniform int iterationNumber; +uniform float u_rangeParameter; +uniform int u_densityHalfWidth; +uniform int u_iterationNumber; in vec2 v_textureCoordinates; layout(location = 0) out vec4 colorOut; @@ -215,7 +215,7 @@ void main() { // If our depth value is invalid if (abs(depth) < EPS) { // If the area that we want to region grow is sufficently sparse - if (float(iterationNumber - DELAY) <= density + EPS) { + if (float(u_iterationNumber - DELAY) <= density + EPS) { float finalDepth = depth; #if neighborhoodFullWidth == 3 fastMedian3(depthNeighbors, aoNeighbors, colorNeighbors, @@ -249,7 +249,7 @@ void main() { float weight = (1.0 - rI / 2.0) * - (1.0 - min(1.0, ecDelta / max(1e-38, rangeParameter))); + (1.0 - min(1.0, ecDelta / max(1e-38, u_rangeParameter))); ecAccum += ecNeighbor * weight; aoAccum += aoNeighbor * weight; @@ -266,10 +266,10 @@ void main() { } #ifdef densityView - colorOut = vec4(vec3(density / float(densityHalfWidth)), 1.0); + colorOut = vec4(vec3(density / float(u_densityHalfWidth)), 1.0); #else #ifdef stencilView - colorOut = testColor(iterationNumber); + colorOut = testColor(u_iterationNumber); #else colorOut = finalColor; #endif From 81baa5056592e8fa947b5b2e123dfc04737fb136 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Sun, 27 Aug 2017 10:30:36 -0400 Subject: [PATCH 207/240] Removes uniform from other branch --- .../PostProcessFilters/PointCloudPostProcessorBlendPass.glsl | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl b/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl index 995157f02c71..d53294797996 100644 --- a/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl +++ b/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl @@ -7,7 +7,6 @@ uniform sampler2D pointCloud_ecTexture; uniform sampler2D pointCloud_aoTexture; uniform float u_sigmoidDomainOffset; uniform float u_sigmoidSharpness; -uniform float splitScreenX; varying vec2 v_textureCoordinates; float sigmoid(float x, float sharpness) { From f4bef2406f0b623cbc4bb7d5e298b00286bd00f4 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Sun, 27 Aug 2017 10:41:01 -0400 Subject: [PATCH 208/240] Replaces Str with FS --- Source/Scene/PointCloudPostProcessor.js | 72 ++++++++++++------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index f669e9b29869..9fc452951ab7 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -373,17 +373,17 @@ define([ processor._stencilMaskTexture = stencilMaskTexture; } - function replaceConstants(sourceStr, constantName, replacement) { + function replaceConstants(sourceFS, constantName, replacement) { var r; if (typeof(replacement) === 'boolean') { if (replacement === false) { r = '#define\\s' + constantName; - return sourceStr.replace(new RegExp(r, 'g'), '/*#define ' + constantName + '*/'); + return sourceFS.replace(new RegExp(r, 'g'), '/*#define ' + constantName + '*/'); } - return sourceStr; + return sourceFS; } r = '#define\\s' + constantName + '\\s([0-9.]+)'; - return sourceStr.replace(new RegExp(r, 'g'), '#define ' + constantName + ' ' + replacement); + return sourceFS.replace(new RegExp(r, 'g'), '#define ' + constantName + ' ' + replacement); } function pointOcclusionStage(processor, context) { @@ -402,26 +402,26 @@ define([ } }; - var pointOcclusionStr = replaceConstants( + var pointOcclusionFS = replaceConstants( (context.webgl2) ? PointOcclusionPassGL2 : PointOcclusionPassGL1, 'neighborhoodHalfWidth', processor.neighborhoodHalfWidth ); - pointOcclusionStr = replaceConstants( - pointOcclusionStr, + pointOcclusionFS = replaceConstants( + pointOcclusionFS, 'useTriangle', processor.useTriangle ); if (processor.dropoutFactor < 1e-6) { - pointOcclusionStr = replaceConstants( - pointOcclusionStr, + pointOcclusionFS = replaceConstants( + pointOcclusionFS, 'dropoutEnabled', false); } - return context.createViewportQuadCommand(pointOcclusionStr, { + return context.createViewportQuadCommand(pointOcclusionFS, { uniformMap : uniformMap, framebuffer : processor._framebuffers.screenSpacePass, renderState : RenderState.fromCache({ @@ -448,20 +448,20 @@ define([ } }; - var densityEdgeCullStr = replaceConstants( + var densityEdgeCullFS = replaceConstants( DensityEdgeCullPass, 'neighborhoodHalfWidth', processor.densityHalfWidth ); if (processor.dropoutFactor < 1e-6 || !context.webgl2) { - densityEdgeCullStr = replaceConstants( - densityEdgeCullStr, + densityEdgeCullFS = replaceConstants( + densityEdgeCullFS, 'dropoutEnabled', false); } - return context.createViewportQuadCommand(densityEdgeCullStr, { + return context.createViewportQuadCommand(densityEdgeCullFS, { uniformMap : uniformMap, framebuffer : processor._framebuffers.densityEstimationPass, renderState : RenderState.fromCache({ @@ -511,29 +511,29 @@ define([ processor._framebuffers.regionGrowingPassA : processor._framebuffers.regionGrowingPassB; - var regionGrowingPassStr = (context.webgl2) ? + var regionGrowingPassFS = (context.webgl2) ? RegionGrowingPassGL2 : RegionGrowingPassGL1; - regionGrowingPassStr = replaceConstants( - regionGrowingPassStr, + regionGrowingPassFS = replaceConstants( + regionGrowingPassFS, 'densityView', processor.densityViewEnabled ); - regionGrowingPassStr = replaceConstants( - regionGrowingPassStr, + regionGrowingPassFS = replaceConstants( + regionGrowingPassFS, 'stencilView', processor.stencilViewEnabled ); - regionGrowingPassStr = replaceConstants( - regionGrowingPassStr, + regionGrowingPassFS = replaceConstants( + regionGrowingPassFS, 'DELAY', processor.delay ); - return context.createViewportQuadCommand(regionGrowingPassStr, { + return context.createViewportQuadCommand(regionGrowingPassFS, { uniformMap : uniformMap, framebuffer : framebuffer, renderState : RenderState.fromCache({ @@ -567,7 +567,7 @@ define([ processor._framebuffers.regionGrowingPassA : processor._framebuffers.regionGrowingPassB; - var copyStageStr = + var copyStageFS = '#extension GL_EXT_draw_buffers : enable \n' + '#define densityView \n' + '#define densityScaleFactor 10.0 \n' + @@ -597,13 +597,13 @@ define([ ' } \n' + '} \n'; - copyStageStr = replaceConstants( - copyStageStr, + copyStageFS = replaceConstants( + copyStageFS, 'densityView', processor.densityViewEnabled ); - return context.createViewportQuadCommand(copyStageStr, { + return context.createViewportQuadCommand(copyStageFS, { uniformMap : uniformMap, framebuffer : framebuffer, renderState : RenderState.fromCache({ @@ -620,7 +620,7 @@ define([ } }; - var stencilMaskStageStr = + var stencilMaskStageFS = '#define EPS 1e-8 \n' + '#define cutoff 0 \n' + '#define DELAY 1 \n' + @@ -634,21 +634,21 @@ define([ ' discard; \n' + '} \n'; - stencilMaskStageStr = replaceConstants( - stencilMaskStageStr, + stencilMaskStageFS = replaceConstants( + stencilMaskStageFS, 'cutoff', iteration ); - stencilMaskStageStr = replaceConstants( - stencilMaskStageStr, + stencilMaskStageFS = replaceConstants( + stencilMaskStageFS, 'DELAY', processor.delay ); var framebuffer = processor._framebuffers.stencilMask; - return context.createViewportQuadCommand(stencilMaskStageStr, { + return context.createViewportQuadCommand(stencilMaskStageFS, { uniformMap : uniformMap, framebuffer : framebuffer, renderState : RenderState.fromCache({ @@ -666,7 +666,7 @@ define([ } }; - var debugViewStageStr = + var debugViewStageFS = '#define EPS 1e-8 \n' + '#define unpack \n' + 'uniform sampler2D debugTexture; \n' + @@ -680,13 +680,13 @@ define([ ' gl_FragColor = vec4(value); \n' + '} \n'; - debugViewStageStr = replaceConstants( - debugViewStageStr, + debugViewStageFS = replaceConstants( + debugViewStageFS, 'unpack', unpack ); - return context.createViewportQuadCommand(debugViewStageStr, { + return context.createViewportQuadCommand(debugViewStageFS, { uniformMap : uniformMap, renderState : RenderState.fromCache({ }), From cecc9d0a5f1b186f2d551c5ec72c26a3b4cb8056 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Sun, 27 Aug 2017 10:48:10 -0400 Subject: [PATCH 209/240] Removes most of the epsilon(s) in the code --- Source/Scene/PointCloudPostProcessor.js | 10 ++++------ .../PostProcessFilters/DensityEdgeCullPass.glsl | 6 +++--- .../PointCloudPostProcessorBlendPass.glsl | 4 ++-- .../PostProcessFilters/PointOcclusionPassGL1.glsl | 9 ++++----- .../PostProcessFilters/PointOcclusionPassGL2.glsl | 9 ++++----- .../PostProcessFilters/RegionGrowingPassGL1.glsl | 14 +++++++------- .../PostProcessFilters/RegionGrowingPassGL2.glsl | 14 +++++++------- 7 files changed, 31 insertions(+), 35 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 9fc452951ab7..0466f1a85aa3 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -571,7 +571,6 @@ define([ '#extension GL_EXT_draw_buffers : enable \n' + '#define densityView \n' + '#define densityScaleFactor 10.0 \n' + - '#define EPS 1e-6 \n' + 'uniform int u_densityHalfWidth; \n' + 'uniform sampler2D pointCloud_colorTexture; \n' + 'uniform sampler2D pointCloud_ecTexture; \n' + @@ -582,7 +581,7 @@ define([ '{ \n' + ' vec4 ec = texture2D(pointCloud_ecTexture, v_textureCoordinates); \n' + ' vec4 rawAO = texture2D(pointCloud_aoTexture, v_textureCoordinates); \n' + - ' if (length(ec) > EPS) { \n' + + ' if (length(ec) > czm_epsilon6) { \n' + ' #ifdef densityView \n' + ' float density = ceil(densityScaleFactor * texture2D(pointCloud_densityTexture, v_textureCoordinates).r); \n' + ' gl_FragData[0] = vec4(vec3(density / float(u_densityHalfWidth)), 1.0); \n' + @@ -593,7 +592,7 @@ define([ ' gl_FragData[2] = rawAO; \n' + ' } else { \n' + ' gl_FragData[1] = vec4(0.0); ' + - ' gl_FragData[2] = czm_packDepth(1.0 - EPS); ' + + ' gl_FragData[2] = czm_packDepth(1.0 - czm_epsilon6); ' + ' } \n' + '} \n'; @@ -621,7 +620,7 @@ define([ }; var stencilMaskStageFS = - '#define EPS 1e-8 \n' + + '#define epsilon8 1e-8 \n' + '#define cutoff 0 \n' + '#define DELAY 1 \n' + '#define densityScaleFactor 10.0 \n' + @@ -630,7 +629,7 @@ define([ 'void main() \n' + '{ \n' + ' float density = ceil(densityScaleFactor * texture2D(pointCloud_densityTexture, v_textureCoordinates).r); \n' + - ' if (float(cutoff - DELAY) + EPS > density) \n' + + ' if (float(cutoff - DELAY) + epsilon8 > density) \n' + ' discard; \n' + '} \n'; @@ -667,7 +666,6 @@ define([ }; var debugViewStageFS = - '#define EPS 1e-8 \n' + '#define unpack \n' + 'uniform sampler2D debugTexture; \n' + 'varying vec2 v_textureCoordinates; \n' + diff --git a/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl b/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl index 0e089ae2f9a8..a35d0bf2b7ec 100644 --- a/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl +++ b/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl @@ -1,6 +1,6 @@ #define neighborhoodHalfWidth 4 // TUNABLE PARAMETER -- half-width of region-growing kernel -#define EPS 1e-8 +#define epsilon8 1e-8 #define densityScaleFactor 10.0 #define dropoutEnabled @@ -24,7 +24,7 @@ void main() { vec2 neighborhoodAccum = vec2(0.0); vec2 absNeighborhoodAccum = vec2(0.0); - if (center < EPS) { + if (center < epsilon8) { int width = neighborhoodHalfWidth; #ifdef dropoutEnabled @@ -47,7 +47,7 @@ void main() { float neighbor = length(texture2D(pointCloud_ecTexture, normPI)); - if (neighbor < EPS || pI == pos) { + if (neighbor < epsilon8 || pI == pos) { continue; } diff --git a/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl b/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl index d53294797996..140453bbbca5 100644 --- a/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl +++ b/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl @@ -1,4 +1,4 @@ -#define EPS 1e-8 +#define epsilon8 1e-8 #define enableAO #extension GL_EXT_frag_depth : enable @@ -23,7 +23,7 @@ void main() { color.xyz = color.xyz * ao; #endif // enableAO vec4 ec = texture2D(pointCloud_ecTexture, v_textureCoordinates); - if (length(ec) < EPS) { + if (length(ec) < epsilon8) { discard; } else { float depth = czm_eyeToWindowCoordinates(vec4(ec.xyz, 1.0)).z; diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl index be0adc4de3dc..0bc6169a1555 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl @@ -8,7 +8,6 @@ #define C1 -0.212053 #define C2 0.0740935 #define C3 -0.0186166 -#define EPS 1e-6 #define neighborhoodHalfWidth 4 // TUNABLE PARAMETER -- half-width of point-occlusion neighborhood #define numSectors 8 @@ -115,9 +114,9 @@ void main() { // If the EC of this pixel is zero, that means that it's not a valid // pixel. We don't care about reprojecting it. - if (length(centerPosition) < EPS) { + if (length(centerPosition) < czm_epsilon6) { gl_FragData[0] = vec4(0.0); - gl_FragData[1] = vec4(1.0 - EPS); + gl_FragData[1] = vec4(1.0 - czm_epsilon6); } // We split our region of interest (the point of interest and its @@ -156,7 +155,7 @@ void main() { vec2(pI) / czm_viewport.zw).xyz; // If our horizon pixel doesn't exist, ignore it and move on - if (length(neighborPosition) < EPS || pI == pos) { + if (length(neighborPosition) < czm_epsilon6 || pI == pos) { continue; } @@ -210,7 +209,7 @@ void main() { // The solid angle is too small, so we occlude this point if (accumulator < (2.0 * PI) * (1.0 - u_occlusionAngle)) { gl_FragData[0] = vec4(0.0); - gl_FragData[1] = vec4(1.0 - EPS); + gl_FragData[1] = vec4(1.0 - czm_epsilon6); } else { float occlusion = clamp(accumulator / (4.0 * PI), 0.0, 1.0); gl_FragData[1] = czm_packDepth(occlusion); diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl index 7bf84ee28be3..b8392e2a4d0d 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl @@ -7,7 +7,6 @@ #define C1 -0.212053 #define C2 0.0740935 #define C3 -0.0186166 -#define EPS 1e-6 #define neighborhoodHalfWidth 4 // TUNABLE PARAMETER -- half-width of point-occlusion neighborhood #define neighborhoodSize 9 #define numSectors 8 @@ -55,9 +54,9 @@ void main() { // If the EC of this pixel is zero, that means that it's not a valid // pixel. We don't care about reprojecting it. - if (length(centerPosition) < EPS) { + if (length(centerPosition) < czm_epsilon6) { depthOut = vec4(0.0); - aoOut = vec4(1.0 - EPS); + aoOut = vec4(1.0 - czm_epsilon6); } // We split our region of interest (the point of interest and its @@ -108,7 +107,7 @@ void main() { vec3 neighborPosition = texelFetch(pointCloud_ecTexture, ivec2(pI), 0).xyz; // If our horizon pixel doesn't exist, ignore it and move on - if (length(neighborPosition) < EPS || pI == pos) { + if (length(neighborPosition) < czm_epsilon6 || pI == pos) { continue; } @@ -162,7 +161,7 @@ void main() { // The solid angle is too small, so we occlude this point if (accumulator < (2.0 * PI) * (1.0 - u_occlusionAngle)) { depthOut = vec4(0); - aoOut = vec4(1.0 - EPS); + aoOut = vec4(1.0 - czm_epsilon6); } else { float occlusion = clamp(accumulator / (4.0 * PI), 0.0, 1.0); aoOut = czm_packDepth(occlusion); diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl index 92821421005d..0cb1e187b383 100644 --- a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl @@ -4,7 +4,7 @@ #define neighborhoodHalfWidth 1 // TUNABLE PARAMETER -- half-width of region-growing kernel #define neighborhoodFullWidth 3 #define neighborhoodSize 8 -#define EPS 1e-8 +#define epsilon8 1e-8 #define SQRT2 1.414213562 #define densityScaleFactor 10.0 #define densityView @@ -107,7 +107,7 @@ void fastMedian3(in float[neighborhoodSize] neighbors, comparisonNetwork8(neighbors, aoNeighbors, colorNeighbors); for (int i = 0; i < neighborhoodSize; i++) { - if (abs(neighbors[i]) > EPS) { + if (abs(neighbors[i]) > epsilon8) { outDepth = neighbors[i + (neighborhoodSize - 1 - i) / 2]; outAO = aoNeighbors[i + (neighborhoodSize - 1 - i) / 2]; outColor = colorNeighbors[i + (neighborhoodSize - 1 - i) / 2]; @@ -207,9 +207,9 @@ void main() { texture2D(pointCloud_densityTexture, v_textureCoordinates).r); // If our depth value is invalid - if (abs(depth) < EPS) { + if (abs(depth) < epsilon8) { // If the area that we want to region grow is sufficently sparse - if (float(u_iterationNumber - DELAY) <= density + EPS) { + if (float(u_iterationNumber - DELAY) <= density + epsilon8) { float finalDepth = depth; #if neighborhoodFullWidth == 3 fastMedian3(depthNeighbors, aoNeighbors, colorNeighbors, @@ -219,7 +219,7 @@ void main() { finalDepth, finalAO, finalColor); #endif for (int i = 0; i < neighborhoodSize; i++) { - if (abs(depthNeighbors[i] - finalDepth) < EPS) { + if (abs(depthNeighbors[i] - finalDepth) < epsilon8) { finalEC = ecNeighbors[i]; } } @@ -238,7 +238,7 @@ void main() { vec4 colorNeighbor = colorNeighbors[i]; float rI = rIs[i]; - if (length(ecNeighbor) > EPS) { + if (length(ecNeighbor) > epsilon8) { float ecDelta = length(ecNeighbor - ec); float weight = @@ -252,7 +252,7 @@ void main() { } } - if (length(ecAccum) > EPS) { + if (length(ecAccum) > epsilon8) { finalEC = ecAccum / normalization; finalColor = colorAccum / normalization; finalAO = aoAccum / normalization; diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl index 276e21aaa372..7b44a5e001c8 100644 --- a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl @@ -3,7 +3,7 @@ #define neighborhoodHalfWidth 1 // TUNABLE PARAMETER -- half-width of region-growing kernel #define neighborhoodFullWidth 3 #define neighborhoodSize 8 -#define EPS 1e-8 +#define epsilon8 1e-8 #define SQRT2 1.414213562 #define densityScaleFactor 10.0 #define densityView @@ -109,7 +109,7 @@ void fastMedian3(in float[neighborhoodSize] neighbors, comparisonNetwork8(neighbors, aoNeighbors, colorNeighbors); for (int i = 0; i < neighborhoodSize; i++) { - if (abs(neighbors[i]) > EPS) { + if (abs(neighbors[i]) > epsilon8) { outDepth = neighbors[i + (neighborhoodSize - 1 - i) / 2]; outAO = aoNeighbors[i + (neighborhoodSize - 1 - i) / 2]; outColor = colorNeighbors[i + (neighborhoodSize - 1 - i) / 2]; @@ -213,9 +213,9 @@ void main() { texture(pointCloud_densityTexture, v_textureCoordinates).r); // If our depth value is invalid - if (abs(depth) < EPS) { + if (abs(depth) < epsilon8) { // If the area that we want to region grow is sufficently sparse - if (float(u_iterationNumber - DELAY) <= density + EPS) { + if (float(u_iterationNumber - DELAY) <= density + epsilon8) { float finalDepth = depth; #if neighborhoodFullWidth == 3 fastMedian3(depthNeighbors, aoNeighbors, colorNeighbors, @@ -225,7 +225,7 @@ void main() { finalDepth, finalAO, finalColor); #endif for (int i = 0; i < neighborhoodSize; i++) { - if (abs(depthNeighbors[i] - finalDepth) < EPS) { + if (abs(depthNeighbors[i] - finalDepth) < epsilon8) { finalEC = ecNeighbors[i]; } } @@ -244,7 +244,7 @@ void main() { vec4 colorNeighbor = colorNeighbors[i]; float rI = rIs[i]; - if (length(ecNeighbor) > EPS) { + if (length(ecNeighbor) > epsilon8) { float ecDelta = length(ecNeighbor - ec); float weight = @@ -258,7 +258,7 @@ void main() { } } - if (length(ecAccum) > EPS) { + if (length(ecAccum) > epsilon8) { finalEC = ecAccum / normalization; finalColor = colorAccum / normalization; finalAO = aoAccum / normalization; From bcba5f3b7f88d5b1781cee2963333b808b743f67 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Sun, 27 Aug 2017 10:54:05 -0400 Subject: [PATCH 210/240] Simplifies createResources logic --- Source/Scene/PointCloudPostProcessor.js | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 0466f1a85aa3..649c3075136a 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -162,6 +162,11 @@ define([ } function destroyFramebuffers(processor) { + var framebuffers = processor._framebuffers; + if (!defined(framebuffers)) { + return; + } + processor._ecTextures[0].destroy(); processor._ecTextures[1].destroy(); processor._sectorLUTTexture.destroy(); @@ -172,7 +177,6 @@ define([ processor._stencilMaskTexture.destroy(); processor._colorTextures[0].destroy(); processor._colorTextures[1].destroy(); - var framebuffers = processor._framebuffers; for (var name in framebuffers) { if (framebuffers.hasOwnProperty(name)) { framebuffers[name].destroy(); @@ -830,23 +834,12 @@ define([ var screenWidth = context.drawingBufferWidth; var screenHeight = context.drawingBufferHeight; var colorTextures = processor._colorTextures; - var regionGrowingCommands = (defined(processor._drawCommands)) ? processor._drawCommands.regionGrowingCommands : undefined; - var stencilCommands = (defined(processor._drawCommands)) ? processor._drawCommands.stencilCommands : undefined; var nowDirty = false; var resized = defined(colorTextures) && ((colorTextures[0].width !== screenWidth) || (colorTextures[0].height !== screenHeight)); - if (!defined(colorTextures)) { - createFramebuffers(processor, context); - nowDirty = true; - } - - if (!defined(regionGrowingCommands) || !defined(stencilCommands) || dirty) { - createCommands(processor, context); - } - - if (resized) { + if (!defined(colorTextures) || resized || dirty) { destroyFramebuffers(processor); createFramebuffers(processor, context); createCommands(processor, context); From 2980ba6a75b0d7e8e57e2fa9064c85e8b59d1fc6 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Sun, 27 Aug 2017 10:56:03 -0400 Subject: [PATCH 211/240] More accurate processingSupported function --- Source/Scene/PointCloudPostProcessor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 649c3075136a..27723e0c0f05 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -849,7 +849,7 @@ define([ } function processingSupported(context) { - return context.depthTexture && context.blendMinmax; + return context.floatingPointTexture && context.drawBuffers && context.fragmentDepth; } function getECShaderProgram(context, shaderProgram) { From b60d6b39c04b79c14f5a0a6c8986d34cfd340433 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Thu, 31 Aug 2017 05:57:38 -0400 Subject: [PATCH 212/240] Using dot notation for the clearCommands now --- Source/Scene/PointCloudPostProcessor.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 27723e0c0f05..193cc7804c17 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -1002,19 +1002,19 @@ define([ var debugViewCommand = this._drawCommands.debugViewCommand; var numRegionGrowingCommands = regionGrowingCommands.length; - commandList.push(clearCommands['screenSpacePass']); - commandList.push(clearCommands['aoBufferB']); + commandList.push(clearCommands.screenSpacePass); + commandList.push(clearCommands.aoBufferB); commandList.push(pointOcclusionCommand); - commandList.push(clearCommands['densityEstimationPass']); + commandList.push(clearCommands.densityEstimationPass); commandList.push(densityEdgeCullCommand); for (i = 0; i < numRegionGrowingCommands; i++) { if (i % 2 === 0) { - commandList.push(clearCommands['regionGrowingPassA']); - commandList.push(clearCommands['aoBufferA']); + commandList.push(clearCommands.regionGrowingPassA); + commandList.push(clearCommands.aoBufferA); } else { - commandList.push(clearCommands['regionGrowingPassB']); - commandList.push(clearCommands['aoBufferB']); + commandList.push(clearCommands.regionGrowingPassB); + commandList.push(clearCommands.aoBufferB); } commandList.push(copyCommands[i % 2]); From c7a431b82430c8d7636a7f419a99164c9cc3bb61 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Thu, 31 Aug 2017 05:59:39 -0400 Subject: [PATCH 213/240] Inherits destroyed/isDestroyed documentation --- Source/Scene/PointCloudPostProcessor.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 193cc7804c17..335418e11bf5 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -1032,14 +1032,14 @@ define([ }; /** - * Part of the {@link Cesium3DTileContent} interface. + * @inheritdoc Cesium3DTileContent#isDestroyed */ PointCloudPostProcessor.prototype.isDestroyed = function() { return false; }; /** - * Part of the {@link Cesium3DTileContent} interface. + * @inheritdoc Cesium3DTileContent#destroy */ PointCloudPostProcessor.prototype.destroy = function() { // TODO: actually destroy stuff From 08f5cc1a776deefafd9707fdd83a56edcbab8ad5 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Thu, 31 Aug 2017 06:18:41 -0400 Subject: [PATCH 214/240] Now adhering to the GLSL coding convention --- .../DensityEdgeCullPass.glsl | 64 ++--- .../PointCloudPostProcessorBlendPass.glsl | 19 +- .../PointOcclusionPassGL1.glsl | 187 +++++++++----- .../PointOcclusionPassGL2.glsl | 93 ++++--- .../RegionGrowingPassGL1.glsl | 231 +++++++++--------- .../RegionGrowingPassGL2.glsl | 204 +++++++--------- 6 files changed, 433 insertions(+), 365 deletions(-) diff --git a/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl b/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl index a35d0bf2b7ec..ebc13b908b9f 100644 --- a/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl +++ b/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl @@ -11,65 +11,73 @@ uniform float u_maxAbsRatio; uniform float u_dropoutFactor; varying vec2 v_textureCoordinates; -float random(vec2 st) { +float random(vec2 st) +{ return fract(sin(dot(st.xy, vec2(12.9898, 78.233))) * 43758.5453123); } -void main() { - float center = length(texture2D(pointCloud_ecTexture, - v_textureCoordinates)); +void main() +{ + float center = length(texture2D(pointCloud_ecTexture, v_textureCoordinates)); ivec2 pos = ivec2(int(gl_FragCoord.x), int(gl_FragCoord.y)); - + float closestNeighbor = float(neighborhoodHalfWidth) + 1.0; vec2 neighborhoodAccum = vec2(0.0); vec2 absNeighborhoodAccum = vec2(0.0); - - if (center < epsilon8) { + + if (center < epsilon8) + { int width = neighborhoodHalfWidth; - + #ifdef dropoutEnabled float seed = random(v_textureCoordinates); - if (seed < u_dropoutFactor) { + if (seed < u_dropoutFactor) + { width = int(float(width) * (1.0 - u_dropoutFactor)); } #endif //dropoutEnabled - + #ifdef dropoutEnabled - for (int i = -width; i <= width; i++) { - for (int j = -width; j <= width; j++) { + for (int i = -width; i <= width; i++) + { + for (int j = -width; j <= width; j++) + { #else - for (int i = -neighborhoodHalfWidth; i <= neighborhoodHalfWidth; i++) { - for (int j = -neighborhoodHalfWidth; j <= neighborhoodHalfWidth; j++) { + for (int i = -neighborhoodHalfWidth; i <= neighborhoodHalfWidth; i++) + { + for (int j = -neighborhoodHalfWidth; j <= neighborhoodHalfWidth; j++) + { #endif // dropoutEnabled ivec2 d = ivec2(i, j); ivec2 pI = pos + d; vec2 normPI = vec2(pI) / czm_viewport.zw; - + float neighbor = length(texture2D(pointCloud_ecTexture, normPI)); - if (neighbor < epsilon8 || pI == pos) { + if (neighbor < epsilon8 || pI == pos) + { continue; } - + neighborhoodAccum += vec2(d); absNeighborhoodAccum += abs(vec2(d)); - closestNeighbor = min(closestNeighbor, - max(abs(float(i)), - abs(float(j)))); + closestNeighbor = min(closestNeighbor, max(abs(float(i)), abs(float(j)))); } } - - float absRatio = length(neighborhoodAccum) / - length(absNeighborhoodAccum); - if (int(closestNeighbor) <= neighborhoodHalfWidth && - !(absRatio > u_maxAbsRatio && - length(neighborhoodAccum) > u_neighborhoodVectorSize)) { + + float absRatio = length(neighborhoodAccum) / length(absNeighborhoodAccum); + if (int(closestNeighbor) <= neighborhoodHalfWidth && !(absRatio > u_maxAbsRatio && length(neighborhoodAccum) > u_neighborhoodVectorSize)) + { gl_FragData[0] = vec4(vec3(closestNeighbor / densityScaleFactor), 0.0); - } else { + } + else + { gl_FragData[0] = vec4(vec4(0.0)); } - } else { + } + else + { gl_FragData[0] = vec4(1.0 / densityScaleFactor, 0.0, 0.0, 0.0); } } diff --git a/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl b/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl index 140453bbbca5..fc493607a82e 100644 --- a/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl +++ b/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl @@ -9,23 +9,26 @@ uniform float u_sigmoidDomainOffset; uniform float u_sigmoidSharpness; varying vec2 v_textureCoordinates; -float sigmoid(float x, float sharpness) { +float sigmoid(float x, float sharpness) +{ return sharpness * x / (sharpness - x + 1.0); } -void main() { +void main() +{ vec4 color = texture2D(pointCloud_colorTexture, v_textureCoordinates); #ifdef enableAO - float ao = czm_unpackDepth(texture2D(pointCloud_aoTexture, - v_textureCoordinates)); - ao = clamp(sigmoid(clamp(ao + u_sigmoidDomainOffset, 0.0, 1.0), u_sigmoidSharpness), - 0.0, 1.0); + float ao = czm_unpackDepth(texture2D(pointCloud_aoTexture, v_textureCoordinates)); + ao = clamp(sigmoid(clamp(ao + u_sigmoidDomainOffset, 0.0, 1.0), u_sigmoidSharpness), 0.0, 1.0); color.xyz = color.xyz * ao; #endif // enableAO vec4 ec = texture2D(pointCloud_ecTexture, v_textureCoordinates); - if (length(ec) < epsilon8) { + if (length(ec) < epsilon8) + { discard; - } else { + } + else + { float depth = czm_eyeToWindowCoordinates(vec4(ec.xyz, 1.0)).z; gl_FragColor = color; gl_FragDepthEXT = depth; diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl index 0bc6169a1555..cea651fadfc6 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl @@ -19,43 +19,66 @@ uniform float u_occlusionAngle; uniform sampler2D sectorLUT; varying vec2 v_textureCoordinates; -float acosFast(in float inX) { +float acosFast(in float inX) +{ float x = abs(inX); float res = ((C3 * x + C2) * x + C1) * x + C0; // p(x) res *= sqrt(1.0 - x); - + return (inX >= 0.0) ? res : PI - res; } void modifySectorHistogram(in int index, in float value, inout vec4 shFirst, - inout vec4 shSecond) { - if (index < 4) { - if (index < 2) { - if (index == 0) { + inout vec4 shSecond) +{ + if (index < 4) + { + if (index < 2) + { + if (index == 0) + { shFirst.x = value; - } else { + } + else + { shFirst.y = value; } - } else { - if (index == 2) { + } + else + { + if (index == 2) + { shFirst.z = value; - } else { + } + else + { shFirst.w = value; } } - } else { - if (index < 6) { - if (index == 4) { + } + else + { + if (index < 6) + { + if (index == 4) + { shSecond.x = value; - } else { + } + else + { shSecond.y = value; } - } else { - if (index == 6) { + } + else + { + if (index == 6) + { shSecond.z = value; - } else { + } + else + { shSecond.w = value; } } @@ -64,61 +87,85 @@ void modifySectorHistogram(in int index, float readSectorHistogram(in int index, in vec4 shFirst, - in vec4 shSecond) { - if (index < 4) { - if (index < 2) { - if (index == 0) { + in vec4 shSecond) +{ + if (index < 4) + { + if (index < 2) + { + if (index == 0) + { return shFirst.x; - } else { + } + else + { return shFirst.y; } - } else { - if (index == 2) { + } + else + { + if (index == 2) + { return shFirst.z; - } else { + } + else + { return shFirst.w; } } - } else { - if (index < 6) { - if (index == 4) { + } + else + { + if (index < 6) + { + if (index == 4) + { return shSecond.x; - } else { + } + else + { return shSecond.y; } - } else { - if (index == 6) { + } + else + { + if (index == 6) + { return shSecond.z; - } else { + } + else + { return shSecond.w; } } } } -ivec2 readSectors(in ivec2 sectorPosition) { - vec2 texCoordinate = vec2(sectorPosition + ivec2(neighborhoodHalfWidth)) / - float(neighborhoodHalfWidth * 2); +ivec2 readSectors(in ivec2 sectorPosition) +{ + vec2 texCoordinate = vec2(sectorPosition + ivec2(neighborhoodHalfWidth)) / float(neighborhoodHalfWidth * 2); vec2 unscaled = texture2D(sectorLUT, texCoordinate).rg; return ivec2(unscaled * float(numSectors)); } -void main() { +void main() +{ float near = czm_currentFrustum.x; float far = czm_currentFrustum.y; ivec2 pos = ivec2(int(gl_FragCoord.x), int(gl_FragCoord.y)); - + // The position of this pixel in 3D (i.e the position of the point) vec3 centerPosition = texture2D(pointCloud_ecTexture, v_textureCoordinates).xyz; bool invalid = false; - + // If the EC of this pixel is zero, that means that it's not a valid // pixel. We don't care about reprojecting it. - if (length(centerPosition) < czm_epsilon6) { + if (length(centerPosition) < czm_epsilon6) + { gl_FragData[0] = vec4(0.0); gl_FragData[1] = vec4(1.0 - czm_epsilon6); } - + // We split our region of interest (the point of interest and its // neighbors) // into sectors. For the purposes of this shader, we have eight @@ -126,78 +173,81 @@ void main() { // // Each entry of sector_histogram contains the current best horizon // pixel angle - ivec2 halfNeighborhood = ivec2(neighborhoodHalfWidth / 2, - neighborhoodHalfWidth / 2); + ivec2 halfNeighborhood = ivec2(neighborhoodHalfWidth / 2, neighborhoodHalfWidth / 2); // Upper left corner of the neighborhood ivec2 upperLeftCorner = pos - halfNeighborhood; // Lower right corner of the neighborhood ivec2 lowerRightCorner = pos + halfNeighborhood; - + // The widest the cone can be is 90 degrees float maxAngle = PI / 2.0; - + vec4 shFirst = vec4(maxAngle); vec4 shSecond = vec4(maxAngle); - + // Right now this is obvious because everything happens in eye space, // but this kind of statement is nice for a reference implementation vec3 viewer = vec3(0.0); - - for (int i = -neighborhoodHalfWidth; i <= neighborhoodHalfWidth; i++) { - for (int j = -neighborhoodHalfWidth; j <= neighborhoodHalfWidth; j++) { + + for (int i = -neighborhoodHalfWidth; i <= neighborhoodHalfWidth; i++) + { + for (int j = -neighborhoodHalfWidth; j <= neighborhoodHalfWidth; j++) + { // d is the relative offset from the horizon pixel to the center pixel // in 2D ivec2 d = ivec2(i, j); ivec2 pI = pos + d; - + // We now calculate the actual 3D position of the horizon pixel (the horizon point) - vec3 neighborPosition = texture2D(pointCloud_ecTexture, - vec2(pI) / czm_viewport.zw).xyz; - + vec3 neighborPosition = texture2D(pointCloud_ecTexture, vec2(pI) / czm_viewport.zw).xyz; + // If our horizon pixel doesn't exist, ignore it and move on - if (length(neighborPosition) < czm_epsilon6 || pI == pos) { + if (length(neighborPosition) < czm_epsilon6 || pI == pos) + { continue; } - + // sectors contains both possible sectors that the // neighbor pixel could be in ivec2 sectors = readSectors(d); - + // This is the offset of the horizon point from the center in 3D // (a 3D analog of d) vec3 c = neighborPosition - centerPosition; - + // Now we calculate the dot product between the vector // from the viewer to the center and the vector to the horizon pixel. // We normalize both vectors first because we only care about their relative // directions // TODO: Redo the math and figure out whether the result should be negated or not - float dotProduct = dot(normalize(viewer - centerPosition), - normalize(c)); - + float dotProduct = dot(normalize(viewer - centerPosition), normalize(c)); + // We calculate the angle that this horizon pixel would make // in the cone. The dot product is be equal to // |vec_1| * |vec_2| * cos(angle_between), and in this case, // the magnitude of both vectors is 1 because they are both // normalized. float angle = acosFast(dotProduct); - + // This horizon point is behind the current point. That means that it can't // occlude the current point. So we ignore it and move on. if (angle > maxAngle || angle <= 0.0) continue; // If we've found a horizon pixel, store it in the histogram - if (readSectorHistogram(sectors.x, shFirst, shSecond) > angle) { + if (readSectorHistogram(sectors.x, shFirst, shSecond) > angle) + { modifySectorHistogram(sectors.x, angle, shFirst, shSecond); } - if (readSectorHistogram(sectors.y, shFirst, shSecond) > angle) { + if (readSectorHistogram(sectors.y, shFirst, shSecond) > angle) + { modifySectorHistogram(sectors.y, angle, shFirst, shSecond); } } } - + float accumulator = 0.0; - for (int i = 0; i < numSectors; i++) { + for (int i = 0; i < numSectors; i++) + { float angle = readSectorHistogram(i, shFirst, shSecond); // If the z component is less than zero, // that means that there is no valid horizon pixel @@ -205,12 +255,15 @@ void main() { angle = maxAngle; accumulator += angle; } - + // The solid angle is too small, so we occlude this point - if (accumulator < (2.0 * PI) * (1.0 - u_occlusionAngle)) { + if (accumulator < (2.0 * PI) * (1.0 - u_occlusionAngle)) + { gl_FragData[0] = vec4(0.0); gl_FragData[1] = vec4(1.0 - czm_epsilon6); - } else { + } + else + { float occlusion = clamp(accumulator / (4.0 * PI), 0.0, 1.0); gl_FragData[1] = czm_packDepth(occlusion); gl_FragData[0] = vec4(centerPosition, 0.0); diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl index b8392e2a4d0d..fd5003c7febd 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl @@ -24,41 +24,45 @@ in vec2 v_textureCoordinates; layout(location = 0) out vec4 depthOut; layout(location = 1) out vec4 aoOut; -float acosFast(in float inX) { +float acosFast(in float inX) +{ float x = abs(inX); float res = ((C3 * x + C2) * x + C1) * x + C0; // p(x) res *= sqrt(1.0 - x); - + return (inX >= 0.0) ? res : PI - res; } -ivec2 readSectors(in ivec2 sectorPosition) { - vec2 texCoordinate = vec2(sectorPosition + ivec2(neighborhoodHalfWidth)) / - float(neighborhoodHalfWidth * 2); +ivec2 readSectors(in ivec2 sectorPosition) +{ + vec2 texCoordinate = vec2(sectorPosition + ivec2(neighborhoodHalfWidth)) / float(neighborhoodHalfWidth * 2); vec2 unscaled = texture(sectorLUT, texCoordinate).rg; return ivec2(unscaled * float(numSectors)); } -float random(vec2 st) { +float random(vec2 st) +{ return fract(sin(dot(st.xy, vec2(12.9898, 78.233))) * 43758.5453123); } -void main() { +void main() +{ float near = czm_entireFrustum.x; float far = czm_entireFrustum.y; ivec2 pos = ivec2(int(gl_FragCoord.x), int(gl_FragCoord.y)); - + // The position of this pixel in 3D (i.e the position of the point) vec3 centerPosition = texture(pointCloud_ecTexture, v_textureCoordinates).xyz; bool invalid = false; - + // If the EC of this pixel is zero, that means that it's not a valid // pixel. We don't care about reprojecting it. - if (length(centerPosition) < czm_epsilon6) { + if (length(centerPosition) < czm_epsilon6) + { depthOut = vec4(0.0); aoOut = vec4(1.0 - czm_epsilon6); } - + // We split our region of interest (the point of interest and its // neighbors) // into sectors. For the purposes of this shader, we have eight @@ -66,90 +70,96 @@ void main() { // // Each entry of sector_histogram contains the current best horizon // pixel angle - ivec2 halfNeighborhood = ivec2(neighborhoodHalfWidth / 2, - neighborhoodHalfWidth / 2); + ivec2 halfNeighborhood = ivec2(neighborhoodHalfWidth / 2, neighborhoodHalfWidth / 2); // Upper left corner of the neighborhood ivec2 upperLeftCorner = pos - halfNeighborhood; // Lower right corner of the neighborhood ivec2 lowerRightCorner = pos + halfNeighborhood; - + // The widest the cone can be is 90 degrees float maxAngle = PI / 2.0; - + // Our sector array defaults to an angle of "maxAngle" in each sector // (i.e no horizon pixels!) float sh[numSectors]; - for (int i = 0; i < numSectors; i++) { + for (int i = 0; i < numSectors; i++) + { sh[i] = maxAngle; } - + // Right now this is obvious because everything happens in eye space, // but this kind of statement is nice for a reference implementation vec3 viewer = vec3(0.0); - + int width = neighborhoodHalfWidth; - + #ifdef dropoutEnabled float seed = random(v_textureCoordinates); - if (seed < u_dropoutFactor) { + if (seed < u_dropoutFactor) + { width = int(float(width) * (1.0 - u_dropoutFactor)); } #endif //dropoutEnabled - - for (int i = -width; i <= width; i++) { - for (int j = -width; j <= width; j++) { + + for (int i = -width; i <= width; i++) + { + for (int j = -width; j <= width; j++) + { // d is the relative offset from the horizon pixel to the center pixel // in 2D ivec2 d = ivec2(i, j); ivec2 pI = pos + d; - + // We now calculate the actual 3D position of the horizon pixel (the horizon point) vec3 neighborPosition = texelFetch(pointCloud_ecTexture, ivec2(pI), 0).xyz; - + // If our horizon pixel doesn't exist, ignore it and move on - if (length(neighborPosition) < czm_epsilon6 || pI == pos) { + if (length(neighborPosition) < czm_epsilon6 || pI == pos) + { continue; } - + // sectors contains both possible sectors that the // neighbor pixel could be in ivec2 sectors = readSectors(d); - + // This is the offset of the horizon point from the center in 3D // (a 3D analog of d) vec3 c = neighborPosition - centerPosition; - + // Now we calculate the dot product between the vector // from the viewer to the center and the vector to the horizon pixel. // We normalize both vectors first because we only care about their relative // directions // TODO: Redo the math and figure out whether the result should be negated or not - float dotProduct = dot(normalize(viewer - centerPosition), - normalize(c)); - + float dotProduct = dot(normalize(viewer - centerPosition), normalize(c)); + // We calculate the angle that this horizon pixel would make // in the cone. The dot product is be equal to // |vec_1| * |vec_2| * cos(angle_between), and in this case, // the magnitude of both vectors is 1 because they are both // normalized. float angle = acosFast(dotProduct); - + // This horizon point is behind the current point. That means that it can't // occlude the current point. So we ignore it and move on. if (angle > maxAngle || angle <= 0.0) continue; // If we've found a horizon pixel, store it in the histogram - if (sh[sectors.x] > angle) { + if (sh[sectors.x] > angle) + { sh[sectors.x] = angle; } - if (sh[sectors.y] > angle) { + if (sh[sectors.y] > angle) + { sh[sectors.y] = angle; } } } - + float accumulator = 0.0; - for (int i = 0; i < numSectors; i++) { + for (int i = 0; i < numSectors; i++) + { float angle = sh[i]; // If the z component is less than zero, // that means that there is no valid horizon pixel @@ -157,12 +167,15 @@ void main() { angle = maxAngle; accumulator += angle; } - + // The solid angle is too small, so we occlude this point - if (accumulator < (2.0 * PI) * (1.0 - u_occlusionAngle)) { + if (accumulator < (2.0 * PI) * (1.0 - u_occlusionAngle)) + { depthOut = vec4(0); aoOut = vec4(1.0 - czm_epsilon6); - } else { + } + else + { float occlusion = clamp(accumulator / (4.0 * PI), 0.0, 1.0); aoOut = czm_packDepth(occlusion); depthOut = vec4(centerPosition, 0.0); diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl index 0cb1e187b383..a155abac4ee3 100644 --- a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl @@ -23,26 +23,46 @@ varying vec2 v_textureCoordinates; #define otherswap(a, b, aO, bO, aC, bC) if (a > b) { temp = a; a = b; b = temp; tempAO = aO; aO = bO; bO = tempAO; tempColor = aC; aC = bC; bC = tempColor; } -vec4 testColor(in int value) { - if (value == 0) { +vec4 testColor(in int value) +{ + if (value == 0) + { return vec4(1.0, 0.0, 0.0, 1.0); - } else if (value == 1) { + } + else if (value == 1) + { return vec4(1.0, 0.5, 0.0, 1.0); - } else if (value == 2) { + } + else if (value == 2) + { return vec4(1.0, 1.0, 0.0, 1.0); - } else if (value == 3) { + } + else if (value == 3) + { return vec4(0.5, 1.0, 0.0, 1.0); - } else if (value == 4) { + } + else if (value == 4) + { return vec4(0.0, 1.0, 0.0, 1.0); - } else if (value == 5) { + } + else if (value == 5) + { return vec4(0.0, 1.0, 0.5, 1.0); - } else if (value == 6) { + } + else if (value == 6) + { return vec4(0.0, 1.0, 1.0, 1.0); - } else if (value == 7) { + } + else if (value == 7) + { return vec4(0.0, 0.5, 1.0, 1.0); - } else if (value == 8) { + } + else if (value == 8) + { return vec4(0.0, 0.0, 1.0, 1.0); - } else { + } + else + { return vec4(1.0, 1.0, 1.0, 1.0); } } @@ -50,49 +70,31 @@ vec4 testColor(in int value) { void comparisonNetwork8(inout float[neighborhoodSize] neighbors, inout float[neighborhoodSize] aoNeighbors, - inout vec4[neighborhoodSize] neighborsColor) { + inout vec4[neighborhoodSize] neighborsColor) +{ float temp; float tempAO; vec4 tempColor; - - otherswap(neighbors[0], neighbors[1], aoNeighbors[0], aoNeighbors[1], - neighborsColor[0], neighborsColor[1]); - otherswap(neighbors[2], neighbors[3], aoNeighbors[2], aoNeighbors[3], - neighborsColor[2], neighborsColor[3]); - otherswap(neighbors[0], neighbors[2], aoNeighbors[0], aoNeighbors[2], - neighborsColor[0], neighborsColor[2]); - otherswap(neighbors[1], neighbors[3], aoNeighbors[1], aoNeighbors[3], - neighborsColor[1], neighborsColor[3]); - otherswap(neighbors[1], neighbors[2], aoNeighbors[1], aoNeighbors[2], - neighborsColor[1], neighborsColor[2]); - otherswap(neighbors[4], neighbors[5], aoNeighbors[4], aoNeighbors[5], - neighborsColor[4], neighborsColor[5]); - otherswap(neighbors[6], neighbors[7], aoNeighbors[6], aoNeighbors[7], - neighborsColor[6], neighborsColor[7]); - otherswap(neighbors[4], neighbors[6], aoNeighbors[4], aoNeighbors[6], - neighborsColor[4], neighborsColor[6]); - otherswap(neighbors[5], neighbors[7], aoNeighbors[5], aoNeighbors[7], - neighborsColor[5], neighborsColor[7]); - otherswap(neighbors[5], neighbors[6], aoNeighbors[5], aoNeighbors[6], - neighborsColor[5], neighborsColor[6]); - otherswap(neighbors[0], neighbors[4], aoNeighbors[0], aoNeighbors[4], - neighborsColor[0], neighborsColor[4]); - otherswap(neighbors[1], neighbors[5], aoNeighbors[1], aoNeighbors[5], - neighborsColor[1], neighborsColor[5]); - otherswap(neighbors[1], neighbors[4], aoNeighbors[1], aoNeighbors[4], - neighborsColor[1], neighborsColor[4]); - otherswap(neighbors[2], neighbors[6], aoNeighbors[2], aoNeighbors[6], - neighborsColor[2], neighborsColor[6]); - otherswap(neighbors[3], neighbors[7], aoNeighbors[3], aoNeighbors[7], - neighborsColor[3], neighborsColor[7]); - otherswap(neighbors[3], neighbors[6], aoNeighbors[3], aoNeighbors[6], - neighborsColor[3], neighborsColor[6]); - otherswap(neighbors[2], neighbors[4], aoNeighbors[2], aoNeighbors[4], - neighborsColor[2], neighborsColor[4]); - otherswap(neighbors[3], neighbors[5], aoNeighbors[3], aoNeighbors[5], - neighborsColor[3], neighborsColor[5]); - otherswap(neighbors[3], neighbors[4], aoNeighbors[3], aoNeighbors[4], - neighborsColor[3], neighborsColor[4]); + + otherswap(neighbors[0], neighbors[1], aoNeighbors[0], aoNeighbors[1], neighborsColor[0], neighborsColor[1]); + otherswap(neighbors[2], neighbors[3], aoNeighbors[2], aoNeighbors[3], neighborsColor[2], neighborsColor[3]); + otherswap(neighbors[0], neighbors[2], aoNeighbors[0], aoNeighbors[2], neighborsColor[0], neighborsColor[2]); + otherswap(neighbors[1], neighbors[3], aoNeighbors[1], aoNeighbors[3], neighborsColor[1], neighborsColor[3]); + otherswap(neighbors[1], neighbors[2], aoNeighbors[1], aoNeighbors[2], neighborsColor[1], neighborsColor[2]); + otherswap(neighbors[4], neighbors[5], aoNeighbors[4], aoNeighbors[5], neighborsColor[4], neighborsColor[5]); + otherswap(neighbors[6], neighbors[7], aoNeighbors[6], aoNeighbors[7], neighborsColor[6], neighborsColor[7]); + otherswap(neighbors[4], neighbors[6], aoNeighbors[4], aoNeighbors[6], neighborsColor[4], neighborsColor[6]); + otherswap(neighbors[5], neighbors[7], aoNeighbors[5], aoNeighbors[7], neighborsColor[5], neighborsColor[7]); + otherswap(neighbors[5], neighbors[6], aoNeighbors[5], aoNeighbors[6], neighborsColor[5], neighborsColor[6]); + otherswap(neighbors[0], neighbors[4], aoNeighbors[0], aoNeighbors[4], neighborsColor[0], neighborsColor[4]); + otherswap(neighbors[1], neighbors[5], aoNeighbors[1], aoNeighbors[5], neighborsColor[1], neighborsColor[5]); + otherswap(neighbors[1], neighbors[4], aoNeighbors[1], aoNeighbors[4], neighborsColor[1], neighborsColor[4]); + otherswap(neighbors[2], neighbors[6], aoNeighbors[2], aoNeighbors[6], neighborsColor[2], neighborsColor[6]); + otherswap(neighbors[3], neighbors[7], aoNeighbors[3], aoNeighbors[7], neighborsColor[3], neighborsColor[7]); + otherswap(neighbors[3], neighbors[6], aoNeighbors[3], aoNeighbors[6], neighborsColor[3], neighborsColor[6]); + otherswap(neighbors[2], neighbors[4], aoNeighbors[2], aoNeighbors[4], neighborsColor[2], neighborsColor[4]); + otherswap(neighbors[3], neighbors[5], aoNeighbors[3], aoNeighbors[5], neighborsColor[3], neighborsColor[5]); + otherswap(neighbors[3], neighbors[4], aoNeighbors[3], aoNeighbors[4], neighborsColor[3], neighborsColor[4]); } // NOTE: This can be sped up a lot by replacing the depth @@ -103,18 +105,21 @@ void fastMedian3(in float[neighborhoodSize] neighbors, in vec4[neighborhoodSize] colorNeighbors, out float outDepth, out float outAO, - out vec4 outColor) { + out vec4 outColor) +{ comparisonNetwork8(neighbors, aoNeighbors, colorNeighbors); - - for (int i = 0; i < neighborhoodSize; i++) { - if (abs(neighbors[i]) > epsilon8) { + + for (int i = 0; i < neighborhoodSize; i++) + { + if (abs(neighbors[i]) > epsilon8) + { outDepth = neighbors[i + (neighborhoodSize - 1 - i) / 2]; outAO = aoNeighbors[i + (neighborhoodSize - 1 - i) / 2]; outColor = colorNeighbors[i + (neighborhoodSize - 1 - i) / 2]; return; } } - + outDepth = 0.0; outAO = 1.0; outColor = vec4(0, 0, 0, 0); @@ -125,7 +130,8 @@ void genericMedianFinder(in float[neighborhoodSize] neighbors, in vec4[neighborhoodSize] colorNeighbors, out float outDepth, out float outAO, - out vec4 outColor) { + out vec4 outColor) +{ // Perhaps we should have a valid way of handling the // difficult-to-optimize cases. // For now this does nothing. @@ -137,56 +143,54 @@ void genericMedianFinder(in float[neighborhoodSize] neighbors, void loadIntoArray(inout vec4[neighborhoodSize] ecNeighbors, inout float[neighborhoodSize] depthNeighbors, inout float[neighborhoodSize] aoNeighbors, - inout vec4[neighborhoodSize] colorNeighbors) { + inout vec4[neighborhoodSize] colorNeighbors) +{ bool pastCenter = false; - for (int j = -neighborhoodHalfWidth; j <= neighborhoodHalfWidth; j++) { - for (int i = -neighborhoodHalfWidth; i <= neighborhoodHalfWidth; i++) { + for (int j = -neighborhoodHalfWidth; j <= neighborhoodHalfWidth; j++) + { + for (int i = -neighborhoodHalfWidth; i <= neighborhoodHalfWidth; i++) + { ivec2 d = ivec2(i, j); - if (d == ivec2(0, 0)) { + if (d == ivec2(0, 0)) + { pastCenter = true; continue; } vec2 neighborCoords = vec2(vec2(d) + gl_FragCoord.xy) / czm_viewport.zw; - vec4 neighborEC = texture2D(pointCloud_ecTexture, - neighborCoords); + vec4 neighborEC = texture2D(pointCloud_ecTexture, neighborCoords); float neighbor = length(neighborEC); - float aoNeighbor = czm_unpackDepth(texture2D(pointCloud_aoTexture, - neighborCoords)); + float aoNeighbor = czm_unpackDepth(texture2D(pointCloud_aoTexture, neighborCoords)); vec4 colorNeighbor = texture2D(pointCloud_colorTexture, neighborCoords); - if (pastCenter) { - ecNeighbors[(j + 1) * neighborhoodFullWidth + i] = - neighborEC; - depthNeighbors[(j + 1) * neighborhoodFullWidth + i] = - neighbor; - aoNeighbors[(j + 1) * neighborhoodFullWidth + i] = - aoNeighbor; - colorNeighbors[(j + 1) * neighborhoodFullWidth + i] = - colorNeighbor; - } else { - ecNeighbors[(j + 1) * neighborhoodFullWidth + i + 1] = - neighborEC; - depthNeighbors[(j + 1) * neighborhoodFullWidth + i + 1] = - neighbor; - aoNeighbors[(j + 1) * neighborhoodFullWidth + i + 1] = - aoNeighbor; - colorNeighbors[(j + 1) * neighborhoodFullWidth + i + 1] = - colorNeighbor; + if (pastCenter) + { + ecNeighbors[(j + 1) * neighborhoodFullWidth + i] = neighborEC; + depthNeighbors[(j + 1) * neighborhoodFullWidth + i] = neighbor; + aoNeighbors[(j + 1) * neighborhoodFullWidth + i] = aoNeighbor; + colorNeighbors[(j + 1) * neighborhoodFullWidth + i] = colorNeighbor; + } + else + { + ecNeighbors[(j + 1) * neighborhoodFullWidth + i + 1] = neighborEC; + depthNeighbors[(j + 1) * neighborhoodFullWidth + i + 1] = neighbor; + aoNeighbors[(j + 1) * neighborhoodFullWidth + i + 1] = aoNeighbor; + colorNeighbors[(j + 1) * neighborhoodFullWidth + i + 1] = colorNeighbor; } } } } -void main() { +void main() +{ vec4 color = texture2D(pointCloud_colorTexture, v_textureCoordinates); vec4 ec = texture2D(pointCloud_ecTexture, v_textureCoordinates); float depth = length(ec); float ao = czm_unpackDepth(texture2D(pointCloud_aoTexture, v_textureCoordinates)); - + vec4 finalColor = color; float finalAO = ao; vec4 finalEC = ec; - + vec4 ecNeighbors[neighborhoodSize]; float depthNeighbors[neighborhoodSize]; float aoNeighbors[neighborhoodSize]; @@ -200,65 +204,68 @@ void main() { rIs[5] = SQRT2; rIs[6] = 1.0; rIs[7] = SQRT2; - + loadIntoArray(ecNeighbors, depthNeighbors, aoNeighbors, colorNeighbors); - - float density = ceil(densityScaleFactor * - texture2D(pointCloud_densityTexture, v_textureCoordinates).r); - + + float density = ceil(densityScaleFactor * texture2D(pointCloud_densityTexture, v_textureCoordinates).r); + // If our depth value is invalid - if (abs(depth) < epsilon8) { + if (abs(depth) < epsilon8) + { // If the area that we want to region grow is sufficently sparse - if (float(u_iterationNumber - DELAY) <= density + epsilon8) { + if (float(u_iterationNumber - DELAY) <= density + epsilon8) + { float finalDepth = depth; #if neighborhoodFullWidth == 3 - fastMedian3(depthNeighbors, aoNeighbors, colorNeighbors, - finalDepth, finalAO, finalColor); + fastMedian3(depthNeighbors, aoNeighbors, colorNeighbors, finalDepth, finalAO, finalColor); #else - genericMedianFinder(depthNeighbors, aoNeighbors, colorNeighbors, - finalDepth, finalAO, finalColor); + genericMedianFinder(depthNeighbors, aoNeighbors, colorNeighbors, finalDepth, finalAO, finalColor); #endif - for (int i = 0; i < neighborhoodSize; i++) { - if (abs(depthNeighbors[i] - finalDepth) < epsilon8) { + for (int i = 0; i < neighborhoodSize; i++) + { + if (abs(depthNeighbors[i] - finalDepth) < epsilon8) + { finalEC = ecNeighbors[i]; } } } } // Otherwise if our depth value is valid - else { + else + { vec4 ecAccum = vec4(0.0); float aoAccum = 0.0; vec4 colorAccum = vec4(0); float normalization = 0.0; - - for (int i = 0; i < neighborhoodSize; i++) { + + for (int i = 0; i < neighborhoodSize; i++) + { vec4 ecNeighbor = ecNeighbors[i]; float aoNeighbor = aoNeighbors[i]; vec4 colorNeighbor = colorNeighbors[i]; float rI = rIs[i]; - - if (length(ecNeighbor) > epsilon8) { + + if (length(ecNeighbor) > epsilon8) + { float ecDelta = length(ecNeighbor - ec); - - float weight = - (1.0 - rI / 2.0) * - (1.0 - min(1.0, ecDelta / max(1e-38, u_rangeParameter))); - + + float weight = (1.0 - rI / 2.0) * (1.0 - min(1.0, ecDelta / max(1e-38, u_rangeParameter))); + ecAccum += ecNeighbor * weight; aoAccum += aoNeighbor * weight; colorAccum += colorNeighbor * weight; normalization += weight; } } - - if (length(ecAccum) > epsilon8) { + + if (length(ecAccum) > epsilon8) + { finalEC = ecAccum / normalization; finalColor = colorAccum / normalization; finalAO = aoAccum / normalization; } } - + #ifdef densityView gl_FragData[0] = vec4(vec3(density / float(u_densityHalfWidth)), 1.0); #else diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl index 7b44a5e001c8..b534c4436cff 100644 --- a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl @@ -25,8 +25,10 @@ layout(location = 2) out vec4 aoOut; #define otherswap(a, b, aO, bO, aC, bC) if (a > b) { temp = a; a = b; b = temp; tempAO = aO; aO = bO; bO = tempAO; tempColor = aC; aC = bC; bC = tempColor; } -vec4 testColor(in int value) { - switch (value) { +vec4 testColor(in int value) +{ + switch (value) + { case 0: return vec4(1.0, 0.0, 0.0, 1.0); case 1: @@ -52,49 +54,31 @@ vec4 testColor(in int value) { void comparisonNetwork8(inout float[neighborhoodSize] neighbors, inout float[neighborhoodSize] aoNeighbors, - inout vec4[neighborhoodSize] neighborsColor) { + inout vec4[neighborhoodSize] neighborsColor) +{ float temp; float tempAO; vec4 tempColor; - - otherswap(neighbors[0], neighbors[1], aoNeighbors[0], aoNeighbors[1], - neighborsColor[0], neighborsColor[1]); - otherswap(neighbors[2], neighbors[3], aoNeighbors[2], aoNeighbors[3], - neighborsColor[2], neighborsColor[3]); - otherswap(neighbors[0], neighbors[2], aoNeighbors[0], aoNeighbors[2], - neighborsColor[0], neighborsColor[2]); - otherswap(neighbors[1], neighbors[3], aoNeighbors[1], aoNeighbors[3], - neighborsColor[1], neighborsColor[3]); - otherswap(neighbors[1], neighbors[2], aoNeighbors[1], aoNeighbors[2], - neighborsColor[1], neighborsColor[2]); - otherswap(neighbors[4], neighbors[5], aoNeighbors[4], aoNeighbors[5], - neighborsColor[4], neighborsColor[5]); - otherswap(neighbors[6], neighbors[7], aoNeighbors[6], aoNeighbors[7], - neighborsColor[6], neighborsColor[7]); - otherswap(neighbors[4], neighbors[6], aoNeighbors[4], aoNeighbors[6], - neighborsColor[4], neighborsColor[6]); - otherswap(neighbors[5], neighbors[7], aoNeighbors[5], aoNeighbors[7], - neighborsColor[5], neighborsColor[7]); - otherswap(neighbors[5], neighbors[6], aoNeighbors[5], aoNeighbors[6], - neighborsColor[5], neighborsColor[6]); - otherswap(neighbors[0], neighbors[4], aoNeighbors[0], aoNeighbors[4], - neighborsColor[0], neighborsColor[4]); - otherswap(neighbors[1], neighbors[5], aoNeighbors[1], aoNeighbors[5], - neighborsColor[1], neighborsColor[5]); - otherswap(neighbors[1], neighbors[4], aoNeighbors[1], aoNeighbors[4], - neighborsColor[1], neighborsColor[4]); - otherswap(neighbors[2], neighbors[6], aoNeighbors[2], aoNeighbors[6], - neighborsColor[2], neighborsColor[6]); - otherswap(neighbors[3], neighbors[7], aoNeighbors[3], aoNeighbors[7], - neighborsColor[3], neighborsColor[7]); - otherswap(neighbors[3], neighbors[6], aoNeighbors[3], aoNeighbors[6], - neighborsColor[3], neighborsColor[6]); - otherswap(neighbors[2], neighbors[4], aoNeighbors[2], aoNeighbors[4], - neighborsColor[2], neighborsColor[4]); - otherswap(neighbors[3], neighbors[5], aoNeighbors[3], aoNeighbors[5], - neighborsColor[3], neighborsColor[5]); - otherswap(neighbors[3], neighbors[4], aoNeighbors[3], aoNeighbors[4], - neighborsColor[3], neighborsColor[4]); + + otherswap(neighbors[0], neighbors[1], aoNeighbors[0], aoNeighbors[1], neighborsColor[0], neighborsColor[1]); + otherswap(neighbors[2], neighbors[3], aoNeighbors[2], aoNeighbors[3], neighborsColor[2], neighborsColor[3]); + otherswap(neighbors[0], neighbors[2], aoNeighbors[0], aoNeighbors[2], neighborsColor[0], neighborsColor[2]); + otherswap(neighbors[1], neighbors[3], aoNeighbors[1], aoNeighbors[3], neighborsColor[1], neighborsColor[3]); + otherswap(neighbors[1], neighbors[2], aoNeighbors[1], aoNeighbors[2], neighborsColor[1], neighborsColor[2]); + otherswap(neighbors[4], neighbors[5], aoNeighbors[4], aoNeighbors[5], neighborsColor[4], neighborsColor[5]); + otherswap(neighbors[6], neighbors[7], aoNeighbors[6], aoNeighbors[7], neighborsColor[6], neighborsColor[7]); + otherswap(neighbors[4], neighbors[6], aoNeighbors[4], aoNeighbors[6], neighborsColor[4], neighborsColor[6]); + otherswap(neighbors[5], neighbors[7], aoNeighbors[5], aoNeighbors[7], neighborsColor[5], neighborsColor[7]); + otherswap(neighbors[5], neighbors[6], aoNeighbors[5], aoNeighbors[6], neighborsColor[5], neighborsColor[6]); + otherswap(neighbors[0], neighbors[4], aoNeighbors[0], aoNeighbors[4], neighborsColor[0], neighborsColor[4]); + otherswap(neighbors[1], neighbors[5], aoNeighbors[1], aoNeighbors[5], neighborsColor[1], neighborsColor[5]); + otherswap(neighbors[1], neighbors[4], aoNeighbors[1], aoNeighbors[4], neighborsColor[1], neighborsColor[4]); + otherswap(neighbors[2], neighbors[6], aoNeighbors[2], aoNeighbors[6], neighborsColor[2], neighborsColor[6]); + otherswap(neighbors[3], neighbors[7], aoNeighbors[3], aoNeighbors[7], neighborsColor[3], neighborsColor[7]); + otherswap(neighbors[3], neighbors[6], aoNeighbors[3], aoNeighbors[6], neighborsColor[3], neighborsColor[6]); + otherswap(neighbors[2], neighbors[4], aoNeighbors[2], aoNeighbors[4], neighborsColor[2], neighborsColor[4]); + otherswap(neighbors[3], neighbors[5], aoNeighbors[3], aoNeighbors[5], neighborsColor[3], neighborsColor[5]); + otherswap(neighbors[3], neighbors[4], aoNeighbors[3], aoNeighbors[4], neighborsColor[3], neighborsColor[4]); } // NOTE: This can be sped up a lot by replacing the depth @@ -105,18 +89,21 @@ void fastMedian3(in float[neighborhoodSize] neighbors, in vec4[neighborhoodSize] colorNeighbors, out float outDepth, out float outAO, - out vec4 outColor) { + out vec4 outColor) +{ comparisonNetwork8(neighbors, aoNeighbors, colorNeighbors); - - for (int i = 0; i < neighborhoodSize; i++) { - if (abs(neighbors[i]) > epsilon8) { + + for (int i = 0; i < neighborhoodSize; i++) + { + if (abs(neighbors[i]) > epsilon8) + { outDepth = neighbors[i + (neighborhoodSize - 1 - i) / 2]; outAO = aoNeighbors[i + (neighborhoodSize - 1 - i) / 2]; outColor = colorNeighbors[i + (neighborhoodSize - 1 - i) / 2]; return; } } - + outDepth = 0.0; outAO = 1.0; outColor = vec4(0, 0, 0, 0); @@ -127,7 +114,8 @@ void genericMedianFinder(in float[neighborhoodSize] neighbors, in vec4[neighborhoodSize] colorNeighbors, out float outDepth, out float outAO, - out vec4 outColor) { + out vec4 outColor) +{ // Perhaps we should have a valid way of handling the // difficult-to-optimize cases. // For now this does nothing. @@ -139,60 +127,53 @@ void genericMedianFinder(in float[neighborhoodSize] neighbors, void loadIntoArray(inout vec4[neighborhoodSize] ecNeighbors, inout float[neighborhoodSize] depthNeighbors, inout float[neighborhoodSize] aoNeighbors, - inout vec4[neighborhoodSize] colorNeighbors) { + inout vec4[neighborhoodSize] colorNeighbors) +{ bool pastCenter = false; - for (int j = -neighborhoodHalfWidth; j <= neighborhoodHalfWidth; j++) { - for (int i = -neighborhoodHalfWidth; i <= neighborhoodHalfWidth; i++) { + for (int j = -neighborhoodHalfWidth; j <= neighborhoodHalfWidth; j++) + { + for (int i = -neighborhoodHalfWidth; i <= neighborhoodHalfWidth; i++) + { ivec2 d = ivec2(i, j); - if (d == ivec2(0, 0)) { + if (d == ivec2(0, 0)) + { pastCenter = true; continue; } ivec2 neighborCoords = d + ivec2(gl_FragCoord.xy); - vec4 neighborEC = texelFetch(pointCloud_ecTexture, - neighborCoords, - 0); + vec4 neighborEC = texelFetch(pointCloud_ecTexture, neighborCoords, 0); float neighbor = length(neighborEC); - float aoNeighbor = czm_unpackDepth(texelFetch(pointCloud_aoTexture, - neighborCoords, - 0)); - vec4 colorNeighbor = texelFetch(pointCloud_colorTexture, - neighborCoords, - 0); - if (pastCenter) { - ecNeighbors[(j + 1) * neighborhoodFullWidth + i] = - neighborEC; - depthNeighbors[(j + 1) * neighborhoodFullWidth + i] = - neighbor; - aoNeighbors[(j + 1) * neighborhoodFullWidth + i] = - aoNeighbor; - colorNeighbors[(j + 1) * neighborhoodFullWidth + i] = - colorNeighbor; - } else { - ecNeighbors[(j + 1) * neighborhoodFullWidth + i + 1] = - neighborEC; - depthNeighbors[(j + 1) * neighborhoodFullWidth + i + 1] = - neighbor; - aoNeighbors[(j + 1) * neighborhoodFullWidth + i + 1] = - aoNeighbor; - colorNeighbors[(j + 1) * neighborhoodFullWidth + i + 1] = - colorNeighbor; + float aoNeighbor = czm_unpackDepth(texelFetch(pointCloud_aoTexture, neighborCoords, 0)); + vec4 colorNeighbor = texelFetch(pointCloud_colorTexture, neighborCoords, 0); + if (pastCenter) + { + ecNeighbors[(j + 1) * neighborhoodFullWidth + i] = neighborEC; + depthNeighbors[(j + 1) * neighborhoodFullWidth + i] = neighbor; + aoNeighbors[(j + 1) * neighborhoodFullWidth + i] = aoNeighbor; + colorNeighbors[(j + 1) * neighborhoodFullWidth + i] = colorNeighbor; + } + else + { + ecNeighbors[(j + 1) * neighborhoodFullWidth + i + 1] = neighborEC; + depthNeighbors[(j + 1) * neighborhoodFullWidth + i + 1] = neighbor; + aoNeighbors[(j + 1) * neighborhoodFullWidth + i + 1] = aoNeighbor; + colorNeighbors[(j + 1) * neighborhoodFullWidth + i + 1] = colorNeighbor; } } } } -void main() { +void main() +{ vec4 color = texture(pointCloud_colorTexture, v_textureCoordinates); vec4 ec = texture(pointCloud_ecTexture, v_textureCoordinates); float depth = length(ec); - float ao = czm_unpackDepth(texture(pointCloud_aoTexture, - v_textureCoordinates)); - + float ao = czm_unpackDepth(texture(pointCloud_aoTexture, v_textureCoordinates)); + vec4 finalColor = color; float finalAO = ao; vec4 finalEC = ec; - + vec4 ecNeighbors[neighborhoodSize]; float depthNeighbors[neighborhoodSize]; float aoNeighbors[neighborhoodSize]; @@ -206,65 +187,68 @@ void main() { rIs[5] = SQRT2; rIs[6] = 1.0; rIs[7] = SQRT2; - + loadIntoArray(ecNeighbors, depthNeighbors, aoNeighbors, colorNeighbors); - - float density = ceil(densityScaleFactor * - texture(pointCloud_densityTexture, v_textureCoordinates).r); - + + float density = ceil(densityScaleFactor * texture(pointCloud_densityTexture, v_textureCoordinates).r); + // If our depth value is invalid - if (abs(depth) < epsilon8) { + if (abs(depth) < epsilon8) + { // If the area that we want to region grow is sufficently sparse - if (float(u_iterationNumber - DELAY) <= density + epsilon8) { + if (float(u_iterationNumber - DELAY) <= density + epsilon8) + { float finalDepth = depth; #if neighborhoodFullWidth == 3 - fastMedian3(depthNeighbors, aoNeighbors, colorNeighbors, - finalDepth, finalAO, finalColor); + fastMedian3(depthNeighbors, aoNeighbors, colorNeighbors, finalDepth, finalAO, finalColor); #else - genericMedianFinder(depthNeighbors, aoNeighbors, colorNeighbors, - finalDepth, finalAO, finalColor); + genericMedianFinder(depthNeighbors, aoNeighbors, colorNeighbors, finalDepth, finalAO, finalColor); #endif - for (int i = 0; i < neighborhoodSize; i++) { - if (abs(depthNeighbors[i] - finalDepth) < epsilon8) { + for (int i = 0; i < neighborhoodSize; i++) + { + if (abs(depthNeighbors[i] - finalDepth) < epsilon8) + { finalEC = ecNeighbors[i]; } } } } // Otherwise if our depth value is valid - else { + else + { vec4 ecAccum = vec4(0.0); float aoAccum = 0.0; vec4 colorAccum = vec4(0); float normalization = 0.0; - - for (int i = 0; i < neighborhoodSize; i++) { + + for (int i = 0; i < neighborhoodSize; i++) + { vec4 ecNeighbor = ecNeighbors[i]; float aoNeighbor = aoNeighbors[i]; vec4 colorNeighbor = colorNeighbors[i]; float rI = rIs[i]; - - if (length(ecNeighbor) > epsilon8) { + + if (length(ecNeighbor) > epsilon8) + { float ecDelta = length(ecNeighbor - ec); - - float weight = - (1.0 - rI / 2.0) * - (1.0 - min(1.0, ecDelta / max(1e-38, u_rangeParameter))); - + + float weight = (1.0 - rI / 2.0) * (1.0 - min(1.0, ecDelta / max(1e-38, u_rangeParameter))); + ecAccum += ecNeighbor * weight; aoAccum += aoNeighbor * weight; colorAccum += colorNeighbor * weight; normalization += weight; } } - - if (length(ecAccum) > epsilon8) { + + if (length(ecAccum) > epsilon8) + { finalEC = ecAccum / normalization; finalColor = colorAccum / normalization; finalAO = aoAccum / normalization; } } - + #ifdef densityView colorOut = vec4(vec3(density / float(u_densityHalfWidth)), 1.0); #else From d544e2e3de7cfaf2cd877b942248e4b3be061420 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Sun, 3 Sep 2017 14:00:42 -0500 Subject: [PATCH 215/240] Renames all the uniforms so that they have a "u_" --- Source/Scene/PointCloudPostProcessor.js | 56 +++++++++---------- .../DensityEdgeCullPass.glsl | 6 +- .../PointCloudPostProcessorBlendPass.glsl | 12 ++-- .../PointOcclusionPassGL1.glsl | 10 ++-- .../PointOcclusionPassGL2.glsl | 10 ++-- .../RegionGrowingPassGL1.glsl | 22 ++++---- .../RegionGrowingPassGL2.glsl | 22 ++++---- 7 files changed, 69 insertions(+), 69 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 335418e11bf5..930a9c5f586f 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -392,10 +392,10 @@ define([ function pointOcclusionStage(processor, context) { var uniformMap = { - sectorLUT : function() { + u_sectorLUT : function() { return processor._sectorLUTTexture; }, - pointCloud_ecTexture : function() { + u_pointCloud_ecTexture : function() { return processor._ecTextures[1]; }, u_occlusionAngle : function() { @@ -438,7 +438,7 @@ define([ function densityEdgeCullStage(processor, context) { var uniformMap = { - pointCloud_ecTexture : function() { + u_pointCloud_ecTexture : function() { return processor._ecTextures[0]; }, u_neighborhoodVectorSize : function() { @@ -482,16 +482,16 @@ define([ var rangeMax = processor.rangeMax; var uniformMap = { - pointCloud_colorTexture : function() { + u_pointCloud_colorTexture : function() { return processor._colorTextures[i]; }, - pointCloud_ecTexture : function() { + u_pointCloud_ecTexture : function() { return processor._ecTextures[i]; }, - pointCloud_densityTexture : function() { + u_pointCloud_densityTexture : function() { return processor._densityTexture; }, - pointCloud_aoTexture : function() { + u_pointCloud_aoTexture : function() { return processor._aoTextures[i]; }, u_rangeParameter : function() { @@ -550,16 +550,16 @@ define([ function copyRegionGrowingColorStage(processor, context, i) { var uniformMap = { - pointCloud_colorTexture : function() { + u_pointCloud_colorTexture : function() { return processor._colorTextures[i]; }, - pointCloud_ecTexture : function() { + u_pointCloud_ecTexture : function() { return processor._ecTextures[i]; }, - pointCloud_aoTexture : function() { + u_pointCloud_aoTexture : function() { return processor._aoTextures[i]; }, - pointCloud_densityTexture : function() { + u_pointCloud_densityTexture : function() { return processor._densityTexture; }, u_densityHalfWidth : function() { @@ -576,21 +576,21 @@ define([ '#define densityView \n' + '#define densityScaleFactor 10.0 \n' + 'uniform int u_densityHalfWidth; \n' + - 'uniform sampler2D pointCloud_colorTexture; \n' + - 'uniform sampler2D pointCloud_ecTexture; \n' + - 'uniform sampler2D pointCloud_aoTexture; \n' + - 'uniform sampler2D pointCloud_densityTexture; \n' + + 'uniform sampler2D u_pointCloud_colorTexture; \n' + + 'uniform sampler2D u_pointCloud_ecTexture; \n' + + 'uniform sampler2D u_pointCloud_aoTexture; \n' + + 'uniform sampler2D u_pointCloud_densityTexture; \n' + 'varying vec2 v_textureCoordinates; \n' + 'void main() \n' + '{ \n' + - ' vec4 ec = texture2D(pointCloud_ecTexture, v_textureCoordinates); \n' + - ' vec4 rawAO = texture2D(pointCloud_aoTexture, v_textureCoordinates); \n' + + ' vec4 ec = texture2D(u_pointCloud_ecTexture, v_textureCoordinates); \n' + + ' vec4 rawAO = texture2D(u_pointCloud_aoTexture, v_textureCoordinates); \n' + ' if (length(ec) > czm_epsilon6) { \n' + ' #ifdef densityView \n' + - ' float density = ceil(densityScaleFactor * texture2D(pointCloud_densityTexture, v_textureCoordinates).r); \n' + + ' float density = ceil(densityScaleFactor * texture2D(u_pointCloud_densityTexture, v_textureCoordinates).r); \n' + ' gl_FragData[0] = vec4(vec3(density / float(u_densityHalfWidth)), 1.0); \n' + ' #else \n' + - ' gl_FragData[0] = texture2D(pointCloud_colorTexture, v_textureCoordinates); \n' + + ' gl_FragData[0] = texture2D(u_pointCloud_colorTexture, v_textureCoordinates); \n' + ' #endif \n' + ' gl_FragData[1] = ec; \n' + ' gl_FragData[2] = rawAO; \n' + @@ -618,7 +618,7 @@ define([ function stencilMaskStage(processor, context, iteration) { var uniformMap = { - pointCloud_densityTexture : function() { + u_pointCloud_densityTexture : function() { return processor._densityTexture; } }; @@ -628,11 +628,11 @@ define([ '#define cutoff 0 \n' + '#define DELAY 1 \n' + '#define densityScaleFactor 10.0 \n' + - 'uniform sampler2D pointCloud_densityTexture; \n' + + 'uniform sampler2D u_pointCloud_densityTexture; \n' + 'varying vec2 v_textureCoordinates; \n' + 'void main() \n' + '{ \n' + - ' float density = ceil(densityScaleFactor * texture2D(pointCloud_densityTexture, v_textureCoordinates).r); \n' + + ' float density = ceil(densityScaleFactor * texture2D(u_pointCloud_densityTexture, v_textureCoordinates).r); \n' + ' if (float(cutoff - DELAY) + epsilon8 > density) \n' + ' discard; \n' + '} \n'; @@ -664,18 +664,18 @@ define([ function debugViewStage(processor, context, texture, unpack) { var uniformMap = { - debugTexture : function() { + u_debugTexture : function() { return texture; } }; var debugViewStageFS = '#define unpack \n' + - 'uniform sampler2D debugTexture; \n' + + 'uniform sampler2D u_debugTexture; \n' + 'varying vec2 v_textureCoordinates; \n' + 'void main() \n' + '{ \n' + - ' vec4 value = texture2D(debugTexture, v_textureCoordinates); \n' + + ' vec4 value = texture2D(u_debugTexture, v_textureCoordinates); \n' + '#ifdef unpack \n' + ' value = vec4(czm_unpackDepth(value)); \n' + '#endif // unpack \n' + @@ -738,13 +738,13 @@ define([ ); var blendUniformMap = { - pointCloud_colorTexture : function() { + u_pointCloud_colorTexture : function() { return processor._colorTextures[1 - numRegionGrowingPasses % 2]; }, - pointCloud_ecTexture : function() { + u_pointCloud_ecTexture : function() { return processor._ecTextures[1 - numRegionGrowingPasses % 2]; }, - pointCloud_aoTexture : function() { + u_pointCloud_aoTexture : function() { return processor._aoTextures[1 - numRegionGrowingPasses % 2]; }, u_sigmoidDomainOffset : function() { diff --git a/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl b/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl index ebc13b908b9f..c8e49f6bfd36 100644 --- a/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl +++ b/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl @@ -5,7 +5,7 @@ #define densityScaleFactor 10.0 #define dropoutEnabled -uniform sampler2D pointCloud_ecTexture; +uniform sampler2D u_pointCloud_ecTexture; uniform float u_neighborhoodVectorSize; uniform float u_maxAbsRatio; uniform float u_dropoutFactor; @@ -18,7 +18,7 @@ float random(vec2 st) void main() { - float center = length(texture2D(pointCloud_ecTexture, v_textureCoordinates)); + float center = length(texture2D(u_pointCloud_ecTexture, v_textureCoordinates)); ivec2 pos = ivec2(int(gl_FragCoord.x), int(gl_FragCoord.y)); float closestNeighbor = float(neighborhoodHalfWidth) + 1.0; @@ -52,7 +52,7 @@ void main() ivec2 pI = pos + d; vec2 normPI = vec2(pI) / czm_viewport.zw; - float neighbor = length(texture2D(pointCloud_ecTexture, + float neighbor = length(texture2D(u_pointCloud_ecTexture, normPI)); if (neighbor < epsilon8 || pI == pos) { diff --git a/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl b/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl index fc493607a82e..284dc334d6dc 100644 --- a/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl +++ b/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl @@ -2,9 +2,9 @@ #define enableAO #extension GL_EXT_frag_depth : enable -uniform sampler2D pointCloud_colorTexture; -uniform sampler2D pointCloud_ecTexture; -uniform sampler2D pointCloud_aoTexture; +uniform sampler2D u_pointCloud_colorTexture; +uniform sampler2D u_pointCloud_ecTexture; +uniform sampler2D u_pointCloud_aoTexture; uniform float u_sigmoidDomainOffset; uniform float u_sigmoidSharpness; varying vec2 v_textureCoordinates; @@ -16,13 +16,13 @@ float sigmoid(float x, float sharpness) void main() { - vec4 color = texture2D(pointCloud_colorTexture, v_textureCoordinates); + vec4 color = texture2D(u_pointCloud_colorTexture, v_textureCoordinates); #ifdef enableAO - float ao = czm_unpackDepth(texture2D(pointCloud_aoTexture, v_textureCoordinates)); + float ao = czm_unpackDepth(texture2D(u_pointCloud_aoTexture, v_textureCoordinates)); ao = clamp(sigmoid(clamp(ao + u_sigmoidDomainOffset, 0.0, 1.0), u_sigmoidSharpness), 0.0, 1.0); color.xyz = color.xyz * ao; #endif // enableAO - vec4 ec = texture2D(pointCloud_ecTexture, v_textureCoordinates); + vec4 ec = texture2D(u_pointCloud_ecTexture, v_textureCoordinates); if (length(ec) < epsilon8) { discard; diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl index cea651fadfc6..51c97437ffb6 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl @@ -14,9 +14,9 @@ #define trianglePeriod 1.0 #define useTriangle -uniform sampler2D pointCloud_ecTexture; +uniform sampler2D u_pointCloud_ecTexture; uniform float u_occlusionAngle; -uniform sampler2D sectorLUT; +uniform sampler2D u_sectorLUT; varying vec2 v_textureCoordinates; float acosFast(in float inX) @@ -144,7 +144,7 @@ float readSectorHistogram(in int index, ivec2 readSectors(in ivec2 sectorPosition) { vec2 texCoordinate = vec2(sectorPosition + ivec2(neighborhoodHalfWidth)) / float(neighborhoodHalfWidth * 2); - vec2 unscaled = texture2D(sectorLUT, texCoordinate).rg; + vec2 unscaled = texture2D(u_sectorLUT, texCoordinate).rg; return ivec2(unscaled * float(numSectors)); } @@ -155,7 +155,7 @@ void main() ivec2 pos = ivec2(int(gl_FragCoord.x), int(gl_FragCoord.y)); // The position of this pixel in 3D (i.e the position of the point) - vec3 centerPosition = texture2D(pointCloud_ecTexture, v_textureCoordinates).xyz; + vec3 centerPosition = texture2D(u_pointCloud_ecTexture, v_textureCoordinates).xyz; bool invalid = false; // If the EC of this pixel is zero, that means that it's not a valid @@ -199,7 +199,7 @@ void main() ivec2 pI = pos + d; // We now calculate the actual 3D position of the horizon pixel (the horizon point) - vec3 neighborPosition = texture2D(pointCloud_ecTexture, vec2(pI) / czm_viewport.zw).xyz; + vec3 neighborPosition = texture2D(u_pointCloud_ecTexture, vec2(pI) / czm_viewport.zw).xyz; // If our horizon pixel doesn't exist, ignore it and move on if (length(neighborPosition) < czm_epsilon6 || pI == pos) diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl index fd5003c7febd..199a5cc10142 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl @@ -15,10 +15,10 @@ #define useTriangle #define dropoutEnabled -uniform sampler2D pointCloud_ecTexture; +uniform sampler2D u_pointCloud_ecTexture; uniform float u_occlusionAngle; uniform float u_dropoutFactor; -uniform sampler2D sectorLUT; +uniform sampler2D u_sectorLUT; in vec2 v_textureCoordinates; layout(location = 0) out vec4 depthOut; @@ -36,7 +36,7 @@ float acosFast(in float inX) ivec2 readSectors(in ivec2 sectorPosition) { vec2 texCoordinate = vec2(sectorPosition + ivec2(neighborhoodHalfWidth)) / float(neighborhoodHalfWidth * 2); - vec2 unscaled = texture(sectorLUT, texCoordinate).rg; + vec2 unscaled = texture(u_sectorLUT, texCoordinate).rg; return ivec2(unscaled * float(numSectors)); } @@ -52,7 +52,7 @@ void main() ivec2 pos = ivec2(int(gl_FragCoord.x), int(gl_FragCoord.y)); // The position of this pixel in 3D (i.e the position of the point) - vec3 centerPosition = texture(pointCloud_ecTexture, v_textureCoordinates).xyz; + vec3 centerPosition = texture(u_pointCloud_ecTexture, v_textureCoordinates).xyz; bool invalid = false; // If the EC of this pixel is zero, that means that it's not a valid @@ -111,7 +111,7 @@ void main() ivec2 pI = pos + d; // We now calculate the actual 3D position of the horizon pixel (the horizon point) - vec3 neighborPosition = texelFetch(pointCloud_ecTexture, ivec2(pI), 0).xyz; + vec3 neighborPosition = texelFetch(u_pointCloud_ecTexture, ivec2(pI), 0).xyz; // If our horizon pixel doesn't exist, ignore it and move on if (length(neighborPosition) < czm_epsilon6 || pI == pos) diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl index a155abac4ee3..e2d26e43c974 100644 --- a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl @@ -11,10 +11,10 @@ #define stencilView #define DELAY 1 -uniform sampler2D pointCloud_colorTexture; -uniform sampler2D pointCloud_densityTexture; -uniform sampler2D pointCloud_ecTexture; -uniform sampler2D pointCloud_aoTexture; +uniform sampler2D u_pointCloud_colorTexture; +uniform sampler2D u_pointCloud_densityTexture; +uniform sampler2D u_pointCloud_ecTexture; +uniform sampler2D u_pointCloud_aoTexture; uniform float u_rangeParameter; uniform int u_densityHalfWidth; uniform int u_iterationNumber; @@ -157,10 +157,10 @@ void loadIntoArray(inout vec4[neighborhoodSize] ecNeighbors, continue; } vec2 neighborCoords = vec2(vec2(d) + gl_FragCoord.xy) / czm_viewport.zw; - vec4 neighborEC = texture2D(pointCloud_ecTexture, neighborCoords); + vec4 neighborEC = texture2D(u_pointCloud_ecTexture, neighborCoords); float neighbor = length(neighborEC); - float aoNeighbor = czm_unpackDepth(texture2D(pointCloud_aoTexture, neighborCoords)); - vec4 colorNeighbor = texture2D(pointCloud_colorTexture, neighborCoords); + float aoNeighbor = czm_unpackDepth(texture2D(u_pointCloud_aoTexture, neighborCoords)); + vec4 colorNeighbor = texture2D(u_pointCloud_colorTexture, neighborCoords); if (pastCenter) { ecNeighbors[(j + 1) * neighborhoodFullWidth + i] = neighborEC; @@ -181,10 +181,10 @@ void loadIntoArray(inout vec4[neighborhoodSize] ecNeighbors, void main() { - vec4 color = texture2D(pointCloud_colorTexture, v_textureCoordinates); - vec4 ec = texture2D(pointCloud_ecTexture, v_textureCoordinates); + vec4 color = texture2D(u_pointCloud_colorTexture, v_textureCoordinates); + vec4 ec = texture2D(u_pointCloud_ecTexture, v_textureCoordinates); float depth = length(ec); - float ao = czm_unpackDepth(texture2D(pointCloud_aoTexture, + float ao = czm_unpackDepth(texture2D(u_pointCloud_aoTexture, v_textureCoordinates)); vec4 finalColor = color; @@ -207,7 +207,7 @@ void main() loadIntoArray(ecNeighbors, depthNeighbors, aoNeighbors, colorNeighbors); - float density = ceil(densityScaleFactor * texture2D(pointCloud_densityTexture, v_textureCoordinates).r); + float density = ceil(densityScaleFactor * texture2D(u_pointCloud_densityTexture, v_textureCoordinates).r); // If our depth value is invalid if (abs(depth) < epsilon8) diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl index b534c4436cff..4bb769f83ddf 100644 --- a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl @@ -10,10 +10,10 @@ #define stencilView #define DELAY 1 -uniform sampler2D pointCloud_colorTexture; -uniform sampler2D pointCloud_densityTexture; -uniform sampler2D pointCloud_ecTexture; -uniform sampler2D pointCloud_aoTexture; +uniform sampler2D u_pointCloud_colorTexture; +uniform sampler2D u_pointCloud_densityTexture; +uniform sampler2D u_pointCloud_ecTexture; +uniform sampler2D u_pointCloud_aoTexture; uniform float u_rangeParameter; uniform int u_densityHalfWidth; uniform int u_iterationNumber; @@ -141,10 +141,10 @@ void loadIntoArray(inout vec4[neighborhoodSize] ecNeighbors, continue; } ivec2 neighborCoords = d + ivec2(gl_FragCoord.xy); - vec4 neighborEC = texelFetch(pointCloud_ecTexture, neighborCoords, 0); + vec4 neighborEC = texelFetch(u_pointCloud_ecTexture, neighborCoords, 0); float neighbor = length(neighborEC); - float aoNeighbor = czm_unpackDepth(texelFetch(pointCloud_aoTexture, neighborCoords, 0)); - vec4 colorNeighbor = texelFetch(pointCloud_colorTexture, neighborCoords, 0); + float aoNeighbor = czm_unpackDepth(texelFetch(u_pointCloud_aoTexture, neighborCoords, 0)); + vec4 colorNeighbor = texelFetch(u_pointCloud_colorTexture, neighborCoords, 0); if (pastCenter) { ecNeighbors[(j + 1) * neighborhoodFullWidth + i] = neighborEC; @@ -165,10 +165,10 @@ void loadIntoArray(inout vec4[neighborhoodSize] ecNeighbors, void main() { - vec4 color = texture(pointCloud_colorTexture, v_textureCoordinates); - vec4 ec = texture(pointCloud_ecTexture, v_textureCoordinates); + vec4 color = texture(u_pointCloud_colorTexture, v_textureCoordinates); + vec4 ec = texture(u_pointCloud_ecTexture, v_textureCoordinates); float depth = length(ec); - float ao = czm_unpackDepth(texture(pointCloud_aoTexture, v_textureCoordinates)); + float ao = czm_unpackDepth(texture(u_pointCloud_aoTexture, v_textureCoordinates)); vec4 finalColor = color; float finalAO = ao; @@ -190,7 +190,7 @@ void main() loadIntoArray(ecNeighbors, depthNeighbors, aoNeighbors, colorNeighbors); - float density = ceil(densityScaleFactor * texture(pointCloud_densityTexture, v_textureCoordinates).r); + float density = ceil(densityScaleFactor * texture(u_pointCloud_densityTexture, v_textureCoordinates).r); // If our depth value is invalid if (abs(depth) < epsilon8) From 25843dfce0787918e2d2b53808bc809a50343477 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Mon, 4 Sep 2017 19:31:34 -0500 Subject: [PATCH 216/240] Replaced splice with unshift --- Source/Scene/PointCloudPostProcessor.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 930a9c5f586f..eece1d19dd28 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -878,8 +878,7 @@ define([ ' czm_point_cloud_post_process_main(); \n' + ' v_positionECPS = (czm_inverseProjection * gl_Position).xyz; \n' + '}'); - fs.sources.splice(0, 0, - '#extension GL_EXT_draw_buffers : enable \n'); + fs.sources.unshift('#extension GL_EXT_draw_buffers : enable \n'); fs.sources.push( 'varying vec3 v_positionECPS; \n' + 'void main() \n' + From 4ed165485a3b46a40d2d97b799785f553dd66743 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Mon, 4 Sep 2017 19:32:33 -0500 Subject: [PATCH 217/240] Removes useless code/comments --- Source/Scene/PointCloudPostProcessor.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index eece1d19dd28..0b44fadc9fc0 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -903,7 +903,6 @@ define([ } var dirty = false; - // Set options here if (tileset.pointCloudPostProcessorOptions.occlusionAngle !== this.occlusionAngle || tileset.pointCloudPostProcessorOptions.rangeParameter !== this.rangeParameter || tileset.pointCloudPostProcessorOptions.neighborhoodHalfWidth !== this.neighborhoodHalfWidth || @@ -984,7 +983,6 @@ define([ derivedCommand.uniformMap = derivedCommandUniformMap; derivedCommand.pass = Pass.CESIUM_3D_TILE; // Overrides translucent commands - command.dirty = false; } commandList[i] = derivedCommand; From 96a3efd8f920f8d09ad45d69af4431a46539424d Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Mon, 4 Sep 2017 19:37:43 -0500 Subject: [PATCH 218/240] Now cloning UniformMap and RenderState --- Source/Scene/PointCloudPostProcessor.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 0b44fadc9fc0..f8628eeb2c85 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -970,7 +970,7 @@ define([ derivedCommand.castShadows = false; derivedCommand.receiveShadows = false; - var derivedCommandRenderState = derivedCommand.renderState; + var derivedCommandRenderState = new RenderState(derivedCommand.renderState); derivedCommandRenderState.stencilTest = this._stencilWrite; derivedCommand.renderState = RenderState.fromCache( derivedCommandRenderState @@ -978,7 +978,7 @@ define([ // TODO: Even if the filter is disabled, // point attenuation settings are not! Fix this behavior. - var derivedCommandUniformMap = derivedCommand.uniformMap; + var derivedCommandUniformMap = Object.assign({}, derivedCommand.uniformMap); derivedCommandUniformMap['u_pointAttenuationMaxSize'] = attenuationUniformFunction; derivedCommand.uniformMap = derivedCommandUniformMap; From 0d6975067d0b52a508aadb284c08c741394f2ce1 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Mon, 4 Sep 2017 19:42:29 -0500 Subject: [PATCH 219/240] Now using the combine() function --- Source/Scene/PointCloudPostProcessor.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index f8628eeb2c85..f90f552c1022 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -1,6 +1,7 @@ /*global define*/ define([ '../Core/Color', + '../Core/combine', '../Core/ComponentDatatype', '../Core/defined', '../Core/destroyObject', @@ -36,6 +37,7 @@ define([ '../Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass' ], function( Color, + combine, ComponentDatatype, defined, destroyObject, @@ -978,9 +980,11 @@ define([ // TODO: Even if the filter is disabled, // point attenuation settings are not! Fix this behavior. - var derivedCommandUniformMap = Object.assign({}, derivedCommand.uniformMap); - derivedCommandUniformMap['u_pointAttenuationMaxSize'] = attenuationUniformFunction; - derivedCommand.uniformMap = derivedCommandUniformMap; + var derivedCommandUniformMap = derivedCommand.uniformMap; + var newUniformMap = { + 'u_pointAttenuationMaxSize' : attenuationUniformFunction + }; + derivedCommand.uniformMap = combine(derivedCommandUniformMap, newUniformMap); derivedCommand.pass = Pass.CESIUM_3D_TILE; // Overrides translucent commands } From e65689a16c1cfd5873a45791c27a755fc11d7e80 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Mon, 4 Sep 2017 19:45:19 -0500 Subject: [PATCH 220/240] Removes pi defines from shader file --- .../PostProcessFilters/PointOcclusionPassGL1.glsl | 11 ++++------- .../PostProcessFilters/PointOcclusionPassGL2.glsl | 11 ++++------- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl index 51c97437ffb6..b6c34768ee6a 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl @@ -1,9 +1,6 @@ #extension GL_EXT_draw_buffers : enable #extension GL_EXT_frag_depth : enable -#define TAU 6.28318530718 -#define PI 3.14159265359 -#define PI_4 0.785398163 #define C0 1.57073 #define C1 -0.212053 #define C2 0.0740935 @@ -25,7 +22,7 @@ float acosFast(in float inX) float res = ((C3 * x + C2) * x + C1) * x + C0; // p(x) res *= sqrt(1.0 - x); - return (inX >= 0.0) ? res : PI - res; + return (inX >= 0.0) ? res : czm_pi - res; } void modifySectorHistogram(in int index, @@ -180,7 +177,7 @@ void main() ivec2 lowerRightCorner = pos + halfNeighborhood; // The widest the cone can be is 90 degrees - float maxAngle = PI / 2.0; + float maxAngle = czm_pi / 2.0; vec4 shFirst = vec4(maxAngle); vec4 shSecond = vec4(maxAngle); @@ -257,14 +254,14 @@ void main() } // The solid angle is too small, so we occlude this point - if (accumulator < (2.0 * PI) * (1.0 - u_occlusionAngle)) + if (accumulator < (2.0 * czm_pi) * (1.0 - u_occlusionAngle)) { gl_FragData[0] = vec4(0.0); gl_FragData[1] = vec4(1.0 - czm_epsilon6); } else { - float occlusion = clamp(accumulator / (4.0 * PI), 0.0, 1.0); + float occlusion = clamp(accumulator / (4.0 * czm_pi), 0.0, 1.0); gl_FragData[1] = czm_packDepth(occlusion); gl_FragData[0] = vec4(centerPosition, 0.0); } diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl index 199a5cc10142..1574bfb8817e 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl @@ -1,8 +1,5 @@ #version 300 es -#define TAU 6.28318530718 -#define PI 3.14159265359 -#define PI_4 0.785398163 #define C0 1.57073 #define C1 -0.212053 #define C2 0.0740935 @@ -30,7 +27,7 @@ float acosFast(in float inX) float res = ((C3 * x + C2) * x + C1) * x + C0; // p(x) res *= sqrt(1.0 - x); - return (inX >= 0.0) ? res : PI - res; + return (inX >= 0.0) ? res : czm_pi - res; } ivec2 readSectors(in ivec2 sectorPosition) @@ -77,7 +74,7 @@ void main() ivec2 lowerRightCorner = pos + halfNeighborhood; // The widest the cone can be is 90 degrees - float maxAngle = PI / 2.0; + float maxAngle = czm_pi / 2.0; // Our sector array defaults to an angle of "maxAngle" in each sector // (i.e no horizon pixels!) @@ -169,14 +166,14 @@ void main() } // The solid angle is too small, so we occlude this point - if (accumulator < (2.0 * PI) * (1.0 - u_occlusionAngle)) + if (accumulator < (2.0 * czm_pi) * (1.0 - u_occlusionAngle)) { depthOut = vec4(0); aoOut = vec4(1.0 - czm_epsilon6); } else { - float occlusion = clamp(accumulator / (4.0 * PI), 0.0, 1.0); + float occlusion = clamp(accumulator / (4.0 * czm_pi), 0.0, 1.0); aoOut = czm_packDepth(occlusion); depthOut = vec4(centerPosition, 0.0); } From e08fa641b7f5e40b2103a6f2d884f2b7b5996cac Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Mon, 4 Sep 2017 19:54:11 -0500 Subject: [PATCH 221/240] Removes empty line --- Specs/Scene/PointCloudPostProcessorSpec.js | 1 - 1 file changed, 1 deletion(-) diff --git a/Specs/Scene/PointCloudPostProcessorSpec.js b/Specs/Scene/PointCloudPostProcessorSpec.js index 527a0994d090..6f897cf781e8 100644 --- a/Specs/Scene/PointCloudPostProcessorSpec.js +++ b/Specs/Scene/PointCloudPostProcessorSpec.js @@ -75,7 +75,6 @@ defineSuite([ scene.renderForSpecs(); var originalLength = scene.frameState.commandList.length; - tileset.pointCloudPostProcessorOptions.enabled = true; scene.renderForSpecs(); var newLength = scene.frameState.commandList.length; From fbb8ba1bdf9088d210d5749ce930199039282d7b Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Mon, 4 Sep 2017 19:54:55 -0500 Subject: [PATCH 222/240] Removes the morphTo3D call --- Specs/Scene/PointCloudPostProcessorSpec.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/Specs/Scene/PointCloudPostProcessorSpec.js b/Specs/Scene/PointCloudPostProcessorSpec.js index 6f897cf781e8..aeea592f4137 100644 --- a/Specs/Scene/PointCloudPostProcessorSpec.js +++ b/Specs/Scene/PointCloudPostProcessorSpec.js @@ -56,8 +56,6 @@ defineSuite([ }); beforeEach(function() { - scene.morphTo3D(0.0); - var camera = scene.camera; camera.frustum = new PerspectiveFrustum(); camera.frustum.aspectRatio = scene.drawingBufferWidth / scene.drawingBufferHeight; From 297c1ca73f2d4d3a4e7abe286d76be8cb3de1ee2 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Mon, 4 Sep 2017 20:14:34 -0500 Subject: [PATCH 223/240] Removes files from spec --- Specs/Scene/PointCloudPostProcessorSpec.js | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/Specs/Scene/PointCloudPostProcessorSpec.js b/Specs/Scene/PointCloudPostProcessorSpec.js index aeea592f4137..67cb0082cc50 100644 --- a/Specs/Scene/PointCloudPostProcessorSpec.js +++ b/Specs/Scene/PointCloudPostProcessorSpec.js @@ -2,36 +2,28 @@ defineSuite([ 'Scene/PointCloudPostProcessor', 'Core/Cartesian3', 'Core/Color', - 'Core/ComponentDatatype', 'Core/defined', 'Core/HeadingPitchRange', 'Core/HeadingPitchRoll', 'Core/Math', 'Core/Transforms', - 'Scene/Cesium3DTileStyle', - 'Scene/Expression', 'Scene/PerspectiveFrustum', 'Scene/PointCloud3DTileContent', 'Specs/Cesium3DTilesTester', - 'Specs/createScene', - 'ThirdParty/when' + 'Specs/createScene' ], function( PointCloudPostProcessor, Cartesian3, Color, - ComponentDatatype, defined, HeadingPitchRange, HeadingPitchRoll, CesiumMath, Transforms, - Cesium3DTileStyle, - Expression, PerspectiveFrustum, PointCloud3DTileContent, Cesium3DTilesTester, - createScene, - when) { + createScene) { 'use strict'; var scene; From 81243b3a63521dd1e5e02fc8a4e6e49a2d55d5bf Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Tue, 5 Sep 2017 11:14:05 -0400 Subject: [PATCH 224/240] Removes TODOs --- Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl | 1 - Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl | 1 - 2 files changed, 2 deletions(-) diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl index b6c34768ee6a..1ea1045cae34 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl @@ -216,7 +216,6 @@ void main() // from the viewer to the center and the vector to the horizon pixel. // We normalize both vectors first because we only care about their relative // directions - // TODO: Redo the math and figure out whether the result should be negated or not float dotProduct = dot(normalize(viewer - centerPosition), normalize(c)); // We calculate the angle that this horizon pixel would make diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl index 1574bfb8817e..eab655dc4649 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl @@ -128,7 +128,6 @@ void main() // from the viewer to the center and the vector to the horizon pixel. // We normalize both vectors first because we only care about their relative // directions - // TODO: Redo the math and figure out whether the result should be negated or not float dotProduct = dot(normalize(viewer - centerPosition), normalize(c)); // We calculate the angle that this horizon pixel would make From 5e6ad069e9f319f730490ec2424aa65d6563afa3 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Tue, 5 Sep 2017 11:23:33 -0400 Subject: [PATCH 225/240] Destroy method now destroys the processor --- Source/Scene/PointCloudPostProcessor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index f90f552c1022..8ae0cf655168 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -1043,7 +1043,7 @@ define([ * @inheritdoc Cesium3DTileContent#destroy */ PointCloudPostProcessor.prototype.destroy = function() { - // TODO: actually destroy stuff + destroyFramebuffers(this); return destroyObject(this); }; From 255216efe5954331e70d488b61b563469915d7fd Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Tue, 5 Sep 2017 11:25:00 -0400 Subject: [PATCH 226/240] Adds method documentation for the PointCloudPostProcessor --- Source/Scene/PointCloudPostProcessor.js | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 8ae0cf655168..8fa2d0c4a4ee 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -1033,14 +1033,35 @@ define([ }; /** - * @inheritdoc Cesium3DTileContent#isDestroyed + * Returns true if this object was destroyed; otherwise, false. + *

+ * If this object was destroyed, it should not be used; calling any function other than + * isDestroyed will result in a {@link DeveloperError} exception. + * + * @returns {Boolean} true if this object was destroyed; otherwise, false. + * + * @see PointCloudPostProcessor#destroy */ PointCloudPostProcessor.prototype.isDestroyed = function() { return false; }; /** - * @inheritdoc Cesium3DTileContent#destroy + * 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. + *

+ * Once an object is destroyed, it should not be used; calling any function other than + * isDestroyed will result in a {@link DeveloperError} exception. Therefore, + * assign the return value (undefined) to the object as done in the example. + * + * @returns {undefined} + * + * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called. + * + * @example + * processor = processor && processor.destroy(); + * + * @see PointCloudPostProcessor#isDestroyed */ PointCloudPostProcessor.prototype.destroy = function() { destroyFramebuffers(this); From a5b474ec9cb420d2cede593ffc92172530e5fe54 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Tue, 5 Sep 2017 11:30:15 -0400 Subject: [PATCH 227/240] Removes old comment --- Source/Scene/PointCloudPostProcessor.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 8fa2d0c4a4ee..134c9c7a6edf 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -978,8 +978,6 @@ define([ derivedCommandRenderState ); - // TODO: Even if the filter is disabled, - // point attenuation settings are not! Fix this behavior. var derivedCommandUniformMap = derivedCommand.uniformMap; var newUniformMap = { 'u_pointAttenuationMaxSize' : attenuationUniformFunction From 1503713799c145ba85071f803250f5e12ee2e931 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Tue, 5 Sep 2017 11:34:03 -0400 Subject: [PATCH 228/240] Formatting changes --- Source/Scene/PointCloudPostProcessor.js | 2 +- Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 134c9c7a6edf..69de22b7ecc5 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -386,7 +386,7 @@ define([ r = '#define\\s' + constantName; return sourceFS.replace(new RegExp(r, 'g'), '/*#define ' + constantName + '*/'); } - return sourceFS; + return sourceFS; } r = '#define\\s' + constantName + '\\s([0-9.]+)'; return sourceFS.replace(new RegExp(r, 'g'), '#define ' + constantName + ' ' + replacement); diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl index 1ea1045cae34..1d186f468ed5 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl @@ -1,5 +1,4 @@ #extension GL_EXT_draw_buffers : enable -#extension GL_EXT_frag_depth : enable #define C0 1.57073 #define C1 -0.212053 From 05a3cda96fb273efe67f3a6a71f2830689a58c9a Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 13 Sep 2017 15:09:53 -0400 Subject: [PATCH 229/240] All the defines are now added at runtime --- Source/Scene/PointCloudPostProcessor.js | 173 ++++++++++++++---- .../DensityEdgeCullPass.glsl | 7 - .../PointCloudPostProcessorBlendPass.glsl | 2 - .../PointOcclusionPassGL1.glsl | 10 - .../PointOcclusionPassGL2.glsl | 12 -- .../RegionGrowingPassGL1.glsl | 10 - .../RegionGrowingPassGL2.glsl | 10 - 7 files changed, 137 insertions(+), 87 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 69de22b7ecc5..2dedf66fb889 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -152,6 +152,11 @@ define([ this.rangeMin = 1e-6; this.rangeMax = 5e-2; + + this.C0 = 1.57073; + this.C1 = -0.212053; + this.C2 = 0.0740935; + this.C3 = -0.0186166; } function createSampler() { @@ -379,17 +384,16 @@ define([ processor._stencilMaskTexture = stencilMaskTexture; } - function replaceConstants(sourceFS, constantName, replacement) { - var r; + function addConstants(sourceFS, constantName, replacement) { + var finalSource = sourceFS; if (typeof(replacement) === 'boolean') { - if (replacement === false) { - r = '#define\\s' + constantName; - return sourceFS.replace(new RegExp(r, 'g'), '/*#define ' + constantName + '*/'); + if (replacement !== false) { + finalSource = '#define ' + constantName + '\n' + sourceFS; } - return sourceFS; + } else { + finalSource = '#define ' + constantName + ' ' + replacement + '\n' + sourceFS; } - r = '#define\\s' + constantName + '\\s([0-9.]+)'; - return sourceFS.replace(new RegExp(r, 'g'), '#define ' + constantName + ' ' + replacement); + return finalSource; } function pointOcclusionStage(processor, context) { @@ -408,24 +412,58 @@ define([ } }; - var pointOcclusionFS = replaceConstants( + var pointOcclusionFS = addConstants( (context.webgl2) ? PointOcclusionPassGL2 : PointOcclusionPassGL1, 'neighborhoodHalfWidth', processor.neighborhoodHalfWidth ); - pointOcclusionFS = replaceConstants( + pointOcclusionFS = addConstants( + pointOcclusionFS, + 'C0', + processor.C0 + ); + + pointOcclusionFS = addConstants( + pointOcclusionFS, + 'C1', + processor.C1 + ); + + pointOcclusionFS = addConstants( + pointOcclusionFS, + 'C2', + processor.C2 + ); + + pointOcclusionFS = addConstants( + pointOcclusionFS, + 'C3', + processor.C3 + ); + + pointOcclusionFS = addConstants( + pointOcclusionFS, + 'numSectors', + 8 + ); + + pointOcclusionFS = addConstants( pointOcclusionFS, 'useTriangle', processor.useTriangle ); - if (processor.dropoutFactor < 1e-6) { - pointOcclusionFS = replaceConstants( - pointOcclusionFS, - 'dropoutEnabled', - false); - } + pointOcclusionFS = addConstants( + pointOcclusionFS, + 'trianglePeriod', + 1.0 + ); + + pointOcclusionFS = addConstants( + pointOcclusionFS, + 'dropoutEnabled', + processor.dropoutFactor > 1e-6 && context.webgl2); return context.createViewportQuadCommand(pointOcclusionFS, { uniformMap : uniformMap, @@ -454,18 +492,28 @@ define([ } }; - var densityEdgeCullFS = replaceConstants( + var densityEdgeCullFS = addConstants( DensityEdgeCullPass, 'neighborhoodHalfWidth', processor.densityHalfWidth ); - if (processor.dropoutFactor < 1e-6 || !context.webgl2) { - densityEdgeCullFS = replaceConstants( + densityEdgeCullFS = addConstants( + densityEdgeCullFS, + 'epsilon8', + 1e-8 + ); + + densityEdgeCullFS = addConstants( + densityEdgeCullFS, + 'densityScaleFactor', + '10.0' + ); + + densityEdgeCullFS = addConstants( densityEdgeCullFS, 'dropoutEnabled', - false); - } + processor.dropoutFactor > 1e-6 && context.webgl2); return context.createViewportQuadCommand(densityEdgeCullFS, { uniformMap : uniformMap, @@ -521,19 +569,55 @@ define([ RegionGrowingPassGL2 : RegionGrowingPassGL1; - regionGrowingPassFS = replaceConstants( + regionGrowingPassFS = addConstants( + regionGrowingPassFS, + 'neighborhoodHalfWidth', + 1 + ); + + regionGrowingPassFS = addConstants( + regionGrowingPassFS, + 'neighborhoodFullWidth', + 3 + ); + + regionGrowingPassFS = addConstants( + regionGrowingPassFS, + 'neighborhoodSize', + 8 + ); + + regionGrowingPassFS = addConstants( + regionGrowingPassFS, + 'epsilon8', + 1e-8 + ); + + regionGrowingPassFS = addConstants( + regionGrowingPassFS, + 'SQRT2', + 1.414213562 + ); + + regionGrowingPassFS = addConstants( + regionGrowingPassFS, + 'densityScaleFactor', + '10.0' + ); + + regionGrowingPassFS = addConstants( regionGrowingPassFS, 'densityView', processor.densityViewEnabled ); - regionGrowingPassFS = replaceConstants( + regionGrowingPassFS = addConstants( regionGrowingPassFS, 'stencilView', processor.stencilViewEnabled ); - regionGrowingPassFS = replaceConstants( + regionGrowingPassFS = addConstants( regionGrowingPassFS, 'DELAY', processor.delay @@ -575,8 +659,6 @@ define([ var copyStageFS = '#extension GL_EXT_draw_buffers : enable \n' + - '#define densityView \n' + - '#define densityScaleFactor 10.0 \n' + 'uniform int u_densityHalfWidth; \n' + 'uniform sampler2D u_pointCloud_colorTexture; \n' + 'uniform sampler2D u_pointCloud_ecTexture; \n' + @@ -602,12 +684,18 @@ define([ ' } \n' + '} \n'; - copyStageFS = replaceConstants( + copyStageFS = addConstants( copyStageFS, 'densityView', processor.densityViewEnabled ); + copyStageFS = addConstants( + copyStageFS, + 'densityScaleFactor', + processor.densityScaleFactor + ); + return context.createViewportQuadCommand(copyStageFS, { uniformMap : uniformMap, framebuffer : framebuffer, @@ -626,10 +714,6 @@ define([ }; var stencilMaskStageFS = - '#define epsilon8 1e-8 \n' + - '#define cutoff 0 \n' + - '#define DELAY 1 \n' + - '#define densityScaleFactor 10.0 \n' + 'uniform sampler2D u_pointCloud_densityTexture; \n' + 'varying vec2 v_textureCoordinates; \n' + 'void main() \n' + @@ -639,13 +723,25 @@ define([ ' discard; \n' + '} \n'; - stencilMaskStageFS = replaceConstants( + stencilMaskStageFS = addConstants( stencilMaskStageFS, 'cutoff', iteration ); - stencilMaskStageFS = replaceConstants( + stencilMaskStageFS = addConstants( + stencilMaskStageFS, + 'epsilon8', + 1e-8 + ); + + stencilMaskStageFS = addConstants( + stencilMaskStageFS, + 'densityScaleFactor', + '10.0' + ); + + stencilMaskStageFS = addConstants( stencilMaskStageFS, 'DELAY', processor.delay @@ -672,7 +768,6 @@ define([ }; var debugViewStageFS = - '#define unpack \n' + 'uniform sampler2D u_debugTexture; \n' + 'varying vec2 v_textureCoordinates; \n' + 'void main() \n' + @@ -684,7 +779,7 @@ define([ ' gl_FragColor = vec4(value); \n' + '} \n'; - debugViewStageFS = replaceConstants( + debugViewStageFS = addConstants( debugViewStageFS, 'unpack', unpack @@ -733,12 +828,18 @@ define([ }); } - var blendFS = replaceConstants( + var blendFS = addConstants( PointCloudPostProcessorBlendPass, 'enableAO', processor.enableAO && !processor.densityViewEnabled && !processor.stencilViewEnabled ); + blendFS = addConstants( + blendFS, + 'epsilon8', + 1e-8 + ); + var blendUniformMap = { u_pointCloud_colorTexture : function() { return processor._colorTextures[1 - numRegionGrowingPasses % 2]; diff --git a/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl b/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl index c8e49f6bfd36..0b4e5d4513b0 100644 --- a/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl +++ b/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl @@ -1,10 +1,3 @@ -#define neighborhoodHalfWidth 4 // TUNABLE PARAMETER -- half-width of region-growing kernel - -#define epsilon8 1e-8 - -#define densityScaleFactor 10.0 -#define dropoutEnabled - uniform sampler2D u_pointCloud_ecTexture; uniform float u_neighborhoodVectorSize; uniform float u_maxAbsRatio; diff --git a/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl b/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl index 284dc334d6dc..6d4fc9224796 100644 --- a/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl +++ b/Source/Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass.glsl @@ -1,5 +1,3 @@ -#define epsilon8 1e-8 -#define enableAO #extension GL_EXT_frag_depth : enable uniform sampler2D u_pointCloud_colorTexture; diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl index 1d186f468ed5..239fffa6a402 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL1.glsl @@ -1,15 +1,5 @@ #extension GL_EXT_draw_buffers : enable -#define C0 1.57073 -#define C1 -0.212053 -#define C2 0.0740935 -#define C3 -0.0186166 -#define neighborhoodHalfWidth 4 // TUNABLE PARAMETER -- half-width of point-occlusion neighborhood -#define numSectors 8 - -#define trianglePeriod 1.0 -#define useTriangle - uniform sampler2D u_pointCloud_ecTexture; uniform float u_occlusionAngle; uniform sampler2D u_sectorLUT; diff --git a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl index eab655dc4649..d0b559fca8e2 100644 --- a/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/PointOcclusionPassGL2.glsl @@ -1,17 +1,5 @@ #version 300 es -#define C0 1.57073 -#define C1 -0.212053 -#define C2 0.0740935 -#define C3 -0.0186166 -#define neighborhoodHalfWidth 4 // TUNABLE PARAMETER -- half-width of point-occlusion neighborhood -#define neighborhoodSize 9 -#define numSectors 8 - -#define trianglePeriod 1.0 -#define useTriangle -#define dropoutEnabled - uniform sampler2D u_pointCloud_ecTexture; uniform float u_occlusionAngle; uniform float u_dropoutFactor; diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl index e2d26e43c974..57883988dac6 100644 --- a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL1.glsl @@ -1,16 +1,6 @@ #extension GL_EXT_frag_depth : enable #extension GL_EXT_draw_buffers : enable -#define neighborhoodHalfWidth 1 // TUNABLE PARAMETER -- half-width of region-growing kernel -#define neighborhoodFullWidth 3 -#define neighborhoodSize 8 -#define epsilon8 1e-8 -#define SQRT2 1.414213562 -#define densityScaleFactor 10.0 -#define densityView -#define stencilView -#define DELAY 1 - uniform sampler2D u_pointCloud_colorTexture; uniform sampler2D u_pointCloud_densityTexture; uniform sampler2D u_pointCloud_ecTexture; diff --git a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl index 4bb769f83ddf..89cff0b9c2b5 100644 --- a/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl +++ b/Source/Shaders/PostProcessFilters/RegionGrowingPassGL2.glsl @@ -1,15 +1,5 @@ #version 300 es -#define neighborhoodHalfWidth 1 // TUNABLE PARAMETER -- half-width of region-growing kernel -#define neighborhoodFullWidth 3 -#define neighborhoodSize 8 -#define epsilon8 1e-8 -#define SQRT2 1.414213562 -#define densityScaleFactor 10.0 -#define densityView -#define stencilView -#define DELAY 1 - uniform sampler2D u_pointCloud_colorTexture; uniform sampler2D u_pointCloud_densityTexture; uniform sampler2D u_pointCloud_ecTexture; From d46ebb41ec0d1eaeb01929dc50e92831586ac417 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 13 Sep 2017 15:11:33 -0400 Subject: [PATCH 230/240] Removes unnecessary line --- Source/Scene/PointCloudPostProcessor.js | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 2dedf66fb889..de06db8187fe 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -197,7 +197,6 @@ define([ processor._edgeCullingTexture = undefined; processor._sectorLUTTexture = undefined; processor._aoTextures = undefined; - processor._dirty = undefined; processor._drawCommands = undefined; } From 0cc0aaada4d51a11b73f4d6f9a0ca175a66da633 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 13 Sep 2017 15:23:37 -0400 Subject: [PATCH 231/240] Style fixes --- Source/Scene/PointCloud3DTileContent.js | 2 +- Source/Scene/PointCloudPostProcessor.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Scene/PointCloud3DTileContent.js b/Source/Scene/PointCloud3DTileContent.js index 26c44e1b6e01..df9d5b48edc5 100644 --- a/Source/Scene/PointCloud3DTileContent.js +++ b/Source/Scene/PointCloud3DTileContent.js @@ -256,7 +256,7 @@ define([ get : function() { return this._batchTable; } - }, + } }); var sizeOfUint32 = Uint32Array.BYTES_PER_ELEMENT; diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index de06db8187fe..c64d839d96d6 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -1080,7 +1080,7 @@ define([ var derivedCommandUniformMap = derivedCommand.uniformMap; var newUniformMap = { - 'u_pointAttenuationMaxSize' : attenuationUniformFunction + u_pointAttenuationMaxSize : attenuationUniformFunction }; derivedCommand.uniformMap = combine(derivedCommandUniformMap, newUniformMap); @@ -1127,7 +1127,7 @@ define([ commandList.push(debugViewCommand); } - commandList.push(clearCommands['prior']); + commandList.push(clearCommands.prior); }; /** From 9da4c9e74ded43fd1d1056658a3d08386215e031 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 13 Sep 2017 15:26:30 -0400 Subject: [PATCH 232/240] Fixes sectors array iteration --- Source/Scene/PointCloudPostProcessor.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index c64d839d96d6..db8d43ee318a 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -214,11 +214,12 @@ define([ var first = sectors[0]; var second = sectors[0]; - sectors.forEach(function(element) { + for (var i = 0; i < sectors.length; i++) { + var element = sectors[i]; if (element !== first) { second = element; } - }); + } return [first, second]; } From a95f9ca83a0fe9d5c2abbc6050a3e842ae6f67e4 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 13 Sep 2017 15:27:31 -0400 Subject: [PATCH 233/240] Render state now created from cache --- Source/Scene/PointCloudPostProcessor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index db8d43ee318a..5704bf00298a 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -1073,7 +1073,7 @@ define([ derivedCommand.castShadows = false; derivedCommand.receiveShadows = false; - var derivedCommandRenderState = new RenderState(derivedCommand.renderState); + var derivedCommandRenderState = RenderState.fromCache(derivedCommand.renderState); derivedCommandRenderState.stencilTest = this._stencilWrite; derivedCommand.renderState = RenderState.fromCache( derivedCommandRenderState From 3dc4d2f71bd0b713d312cb071eff42d8da750d2f Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 13 Sep 2017 15:28:45 -0400 Subject: [PATCH 234/240] Renames AOView to aoView --- Source/Scene/Cesium3DTileset.js | 6 +++--- Source/Scene/PointCloudPostProcessor.js | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Source/Scene/Cesium3DTileset.js b/Source/Scene/Cesium3DTileset.js index 1285c6f1f22b..699b30f8d7d8 100644 --- a/Source/Scene/Cesium3DTileset.js +++ b/Source/Scene/Cesium3DTileset.js @@ -651,7 +651,7 @@ define([ * @param {Boolean} useTriangle Whether or not to use the triangle wave optimization * @param {Boolean} enableAO Whether or not to blend with ambient occlusion * @param {Boolean} depthViewEnabled Whether or not the depth view is enabled - * @param {Boolean} AOViewEnabled Whether or not the ambient occlusion view is enabled + * @param {Boolean} aoViewEnabled Whether or not the ambient occlusion view is enabled * @param {Number} sigmoidSharpness The "sharpness" of the sigmoid function used for AO; closer to 0 is sharper * @param {Number} sigmoidDomainOffset The offset into the domain of the sigmoid function -- used for brightness control * @param {Number} dropoutFactor Used to probabilistically tune the neighbor search; closer to 1.0 means smaller neighborhoods @@ -662,7 +662,7 @@ define([ * @default {enabled : true, occlusionAngle : 0.1, rangeParameter : 1.0, neighborhoodHalfWidth : 4 * numRegionGrowingPasses : 4, densityHalfWidth : 4, neighborhoodVectorSize : 10.0, maxAbsRatio : 0.9 * densityViewEnabled : false, stencilViewEnabled : false, pointAttenuationMultiplier : 2.0, - * useTriangle : false, enableAO : true, depthViewEnabled : false, AOViewEnabled : true, sigmoidSharpness : 0.2, + * useTriangle : false, enableAO : true, depthViewEnabled : false, aoViewEnabled : true, sigmoidSharpness : 0.2, * sigmoidDomainOffset : 0.2, dropoutFactor : 0.0, delay : 0} */ this.pointCloudPostProcessorOptions = { @@ -680,7 +680,7 @@ define([ useTriangle : false, enableAO : true, depthViewEnabled : false, - AOViewEnabled : false, + aoViewEnabled : false, sigmoidSharpness : 0.2, sigmoidDomainOffset : 0.2, dropoutFactor : 0.0, diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 5704bf00298a..cb71c1d6c633 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -102,7 +102,7 @@ define([ this.pointAttenuationMultiplier = options.pointAttenuationMultiplier; this.useTriangle = options.useTriangle; this.enableAO = options.enableAO; - this.AOViewEnabled = options.AOViewEnabled; + this.aoViewEnabled = options.aoViewEnabled; this.depthViewEnabled = options.depthViewEnabled; this.sigmoidDomainOffset = options.sigmoidDomainOffset; this.sigmoidSharpness = options.sigmoidSharpness; @@ -866,7 +866,7 @@ define([ }); var debugViewCommand; - if (processor.AOViewEnabled) { + if (processor.aoViewEnabled) { debugViewCommand = debugViewStage(processor, context, processor._aoTextures[0], true); } else if (processor.depthViewEnabled) { debugViewCommand = debugViewStage(processor, context, processor._ecTextures[0], false); @@ -1019,7 +1019,7 @@ define([ tileset.pointCloudPostProcessorOptions.pointAttenuationMultiplier !== this.pointAttenuationMultiplier || tileset.pointCloudPostProcessorOptions.useTriangle !== this.useTriangle || tileset.pointCloudPostProcessorOptions.enableAO !== this.enableAO || - tileset.pointCloudPostProcessorOptions.AOViewEnabled !== this.AOViewEnabled || + tileset.pointCloudPostProcessorOptions.aoViewEnabled !== this.aoViewEnabled || tileset.pointCloudPostProcessorOptions.sigmoidDomainOffset !== this.sigmoidDomainOffset || tileset.pointCloudPostProcessorOptions.sigmoidSharpness !== this.sigmoidSharpness || tileset.pointCloudPostProcessorOptions.dropoutFactor !== this.dropoutFactor || @@ -1037,7 +1037,7 @@ define([ this.pointAttenuationMultiplier = tileset.pointCloudPostProcessorOptions.pointAttenuationMultiplier; this.useTriangle = tileset.pointCloudPostProcessorOptions.useTriangle; this.enableAO = tileset.pointCloudPostProcessorOptions.enableAO; - this.AOViewEnabled = tileset.pointCloudPostProcessorOptions.AOViewEnabled; + this.aoViewEnabled = tileset.pointCloudPostProcessorOptions.aoViewEnabled; this.sigmoidDomainOffset = tileset.pointCloudPostProcessorOptions.sigmoidDomainOffset; this.sigmoidSharpness = tileset.pointCloudPostProcessorOptions.sigmoidSharpness; this.dropoutFactor = tileset.pointCloudPostProcessorOptions.dropoutFactor; @@ -1124,7 +1124,7 @@ define([ // Blend final result back into the main FBO commandList.push(blendCommand); - if ((this.AOViewEnabled && this.enableAO) || this.depthViewEnabled) { + if ((this.aoViewEnabled && this.enableAO) || this.depthViewEnabled) { commandList.push(debugViewCommand); } From 8c3439a6adb0f5c742319dcd4f1c3211c940ae67 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 13 Sep 2017 15:35:10 -0400 Subject: [PATCH 235/240] Renames one occurrence of position_absolute to positionWC --- Source/Scene/PointCloud3DTileContent.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Scene/PointCloud3DTileContent.js b/Source/Scene/PointCloud3DTileContent.js index df9d5b48edc5..b5ec87a67295 100644 --- a/Source/Scene/PointCloud3DTileContent.js +++ b/Source/Scene/PointCloud3DTileContent.js @@ -770,7 +770,7 @@ define([ } // Edit the function header to accept the point position, color, and normal - return source.replace('()', '(vec3 position, vec3 positionWC, vec4 color, vec3 normal)'); + return source.replace('()', '(vec3 position, vec3 position_absolute, vec4 color, vec3 normal)'); } function createShaders(content, frameState, style) { From 0923e7359a34f908fbab2d5c319f5e352ae34f24 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Mon, 18 Sep 2017 14:07:01 -0400 Subject: [PATCH 236/240] Fixes change that broke density view --- Source/Scene/PointCloudPostProcessor.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index cb71c1d6c633..18d54a29f85a 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -89,7 +89,7 @@ define([ this._drawCommands = undefined; this._clearCommands = undefined; - this.densityScaleFactor = 10.0; + this.densityScaleFactor = '10.0'; this.occlusionAngle = options.occlusionAngle; this.rangeParameter = options.rangeParameter; this.neighborhoodHalfWidth = options.neighborhoodHalfWidth; @@ -507,13 +507,14 @@ define([ densityEdgeCullFS = addConstants( densityEdgeCullFS, 'densityScaleFactor', - '10.0' + processor.densityScaleFactor ); densityEdgeCullFS = addConstants( - densityEdgeCullFS, - 'dropoutEnabled', - processor.dropoutFactor > 1e-6 && context.webgl2); + densityEdgeCullFS, + 'dropoutEnabled', + processor.dropoutFactor > 1e-6 && context.webgl2 + ); return context.createViewportQuadCommand(densityEdgeCullFS, { uniformMap : uniformMap, @@ -602,7 +603,7 @@ define([ regionGrowingPassFS = addConstants( regionGrowingPassFS, 'densityScaleFactor', - '10.0' + processor.densityScaleFactor ); regionGrowingPassFS = addConstants( @@ -738,7 +739,7 @@ define([ stencilMaskStageFS = addConstants( stencilMaskStageFS, 'densityScaleFactor', - '10.0' + processor.densityScaleFactor ); stencilMaskStageFS = addConstants( From 0deb54773f52540a6e113a306a8058063d2cca14 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Mon, 18 Sep 2017 14:26:54 -0400 Subject: [PATCH 237/240] Adds a new edge culling metric -- distanceConstraint --- .../gallery/3D Tiles Point Cloud Post Processing.html | 9 +++++++++ Source/Scene/Cesium3DTileset.js | 2 ++ Source/Scene/PointCloudPostProcessor.js | 6 ++++++ .../Shaders/PostProcessFilters/DensityEdgeCullPass.glsl | 6 +++++- 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html index d0fdcaddc623..650b3933a888 100644 --- a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html +++ b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Post Processing.html @@ -68,6 +68,13 @@ + + Max Distance Constraint + + + + + Point Attenuation Multiplier @@ -137,6 +144,7 @@ neighborhoodHalfWidth : tileset.pointCloudPostProcessorOptions.neighborhoodHalfWidth, neighborhoodVectorSize : tileset.pointCloudPostProcessorOptions.neighborhoodVectorSize, maxAbsRatio : tileset.pointCloudPostProcessorOptions.maxAbsRatio, + distanceConstraint : tileset.pointCloudPostProcessorOptions.distanceConstraint, pointAttenuationMultiplier : tileset.pointCloudPostProcessorOptions.pointAttenuationMultiplier, sigmoidDomainOffset : tileset.pointCloudPostProcessorOptions.sigmoidDomainOffset, sigmoidSharpness : tileset.pointCloudPostProcessorOptions.sigmoidSharpness, @@ -163,6 +171,7 @@ subscribeParameter('numRegionGrowingPasses'); subscribeParameter('neighborhoodVectorSize'); subscribeParameter('maxAbsRatio'); +subscribeParameter('distanceConstraint'); subscribeParameter('pointAttenuationMultiplier'); subscribeParameter('sigmoidDomainOffset'); subscribeParameter('sigmoidSharpness'); diff --git a/Source/Scene/Cesium3DTileset.js b/Source/Scene/Cesium3DTileset.js index 699b30f8d7d8..217ff764b011 100644 --- a/Source/Scene/Cesium3DTileset.js +++ b/Source/Scene/Cesium3DTileset.js @@ -645,6 +645,7 @@ define([ * @param {Number} densityHalfWidth Half of the width of the density estimation operator's kernel size minus 1 * @param {Number} neighborhoodVectorSize Parameter for the edge culling algorithm; decrease to make edge culling more aggressive * @param {Number} maxAbsRatio Parameter for the edge culling algorithm; decrease to make edge culling more aggressive + * @param {Number} distanceConstraint Parameter for the edge culling algorithm; decrease to make edge culling more aggressive * @param {Boolean} densityViewEnabled Whether or not the density view is enabled * @param {Boolean} stencilViewEnabled Whether or not the stencil view is enabled * @param {Boolean} pointAttenuationMultiplier The factor by which points at the near plane are larger than points at the far plane @@ -674,6 +675,7 @@ define([ densityHalfWidth : 4, neighborhoodVectorSize : 10.0, maxAbsRatio : 0.9, + distanceConstraint : 200, densityViewEnabled : false, stencilViewEnabled : false, pointAttenuationMultiplier : 2.0, diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 18d54a29f85a..3c74f921c399 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -97,6 +97,7 @@ define([ this.densityHalfWidth = options.densityHalfWidth; this.neighborhoodVectorSize = options.neighborhoodVectorSize; this.maxAbsRatio = options.maxAbsRatio; + this.distanceConstraint = options.distanceConstraint; this.densityViewEnabled = options.densityViewEnabled; this.stencilViewEnabled = options.stencilViewEnabled; this.pointAttenuationMultiplier = options.pointAttenuationMultiplier; @@ -487,6 +488,9 @@ define([ u_maxAbsRatio : function() { return processor.maxAbsRatio; }, + u_distanceConstraint : function() { + return processor.distanceConstraint; + }, u_dropoutFactor : function() { return processor.dropoutFactor; } @@ -1014,6 +1018,7 @@ define([ tileset.pointCloudPostProcessorOptions.densityHalfWidth !== this.densityHalfWidth || tileset.pointCloudPostProcessorOptions.neighborhoodVectorSize !== this.neighborhoodVectorSize || tileset.pointCloudPostProcessorOptions.maxAbsRatio !== this.maxAbsRatio || + tileset.pointCloudPostProcessorOptions.distanceConstraint !== this.distanceConstraint || tileset.pointCloudPostProcessorOptions.densityViewEnabled !== this.densityViewEnabled || tileset.pointCloudPostProcessorOptions.depthViewEnabled !== this.depthViewEnabled || tileset.pointCloudPostProcessorOptions.stencilViewEnabled !== this.stencilViewEnabled || @@ -1034,6 +1039,7 @@ define([ this.densityViewEnabled = tileset.pointCloudPostProcessorOptions.densityViewEnabled; this.depthViewEnabled = tileset.pointCloudPostProcessorOptions.depthViewEnabled; this.stencilViewEnabled = tileset.pointCloudPostProcessorOptions.stencilViewEnabled; + this.distanceConstraint = tileset.pointCloudPostProcessorOptions.distanceConstraint; this.maxAbsRatio = tileset.pointCloudPostProcessorOptions.maxAbsRatio; this.pointAttenuationMultiplier = tileset.pointCloudPostProcessorOptions.pointAttenuationMultiplier; this.useTriangle = tileset.pointCloudPostProcessorOptions.useTriangle; diff --git a/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl b/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl index 0b4e5d4513b0..72d544495033 100644 --- a/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl +++ b/Source/Shaders/PostProcessFilters/DensityEdgeCullPass.glsl @@ -1,6 +1,7 @@ uniform sampler2D u_pointCloud_ecTexture; uniform float u_neighborhoodVectorSize; uniform float u_maxAbsRatio; +uniform float u_distanceConstraint; uniform float u_dropoutFactor; varying vec2 v_textureCoordinates; @@ -15,6 +16,7 @@ void main() ivec2 pos = ivec2(int(gl_FragCoord.x), int(gl_FragCoord.y)); float closestNeighbor = float(neighborhoodHalfWidth) + 1.0; + float closestNeighborDist = 1e10; vec2 neighborhoodAccum = vec2(0.0); vec2 absNeighborhoodAccum = vec2(0.0); @@ -55,11 +57,13 @@ void main() neighborhoodAccum += vec2(d); absNeighborhoodAccum += abs(vec2(d)); closestNeighbor = min(closestNeighbor, max(abs(float(i)), abs(float(j)))); + closestNeighborDist = min(closestNeighborDist, neighbor); } } float absRatio = length(neighborhoodAccum) / length(absNeighborhoodAccum); - if (int(closestNeighbor) <= neighborhoodHalfWidth && !(absRatio > u_maxAbsRatio && length(neighborhoodAccum) > u_neighborhoodVectorSize)) + if (int(closestNeighbor) <= neighborhoodHalfWidth && !(absRatio > u_maxAbsRatio && length(neighborhoodAccum) > u_neighborhoodVectorSize) && + closestNeighborDist * closestNeighbor < u_distanceConstraint) { gl_FragData[0] = vec4(vec3(closestNeighbor / densityScaleFactor), 0.0); From b3df08553a730a7b137b6106fb165253c9558160 Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Thu, 28 Sep 2017 14:20:01 -0400 Subject: [PATCH 238/240] Clone fixes --- Source/Scene/PointCloudPostProcessor.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Source/Scene/PointCloudPostProcessor.js b/Source/Scene/PointCloudPostProcessor.js index 3c74f921c399..05ed1b1e2b4d 100644 --- a/Source/Scene/PointCloudPostProcessor.js +++ b/Source/Scene/PointCloudPostProcessor.js @@ -1,5 +1,6 @@ /*global define*/ define([ + '../Core/clone', '../Core/Color', '../Core/combine', '../Core/ComponentDatatype', @@ -36,6 +37,7 @@ define([ '../Shaders/PostProcessFilters/DensityEdgeCullPass', '../Shaders/PostProcessFilters/PointCloudPostProcessorBlendPass' ], function( + clone, Color, combine, ComponentDatatype, @@ -385,14 +387,14 @@ define([ processor._stencilMaskTexture = stencilMaskTexture; } - function addConstants(sourceFS, constantName, replacement) { + function addConstants(sourceFS, constantName, value) { var finalSource = sourceFS; - if (typeof(replacement) === 'boolean') { - if (replacement !== false) { + if (typeof(value) === 'boolean') { + if (value !== false) { finalSource = '#define ' + constantName + '\n' + sourceFS; } } else { - finalSource = '#define ' + constantName + ' ' + replacement + '\n' + sourceFS; + finalSource = '#define ' + constantName + ' ' + value + '\n' + sourceFS; } return finalSource; } @@ -1080,7 +1082,7 @@ define([ derivedCommand.castShadows = false; derivedCommand.receiveShadows = false; - var derivedCommandRenderState = RenderState.fromCache(derivedCommand.renderState); + var derivedCommandRenderState = clone(derivedCommand.renderState); derivedCommandRenderState.stencilTest = this._stencilWrite; derivedCommand.renderState = RenderState.fromCache( derivedCommandRenderState From 0fbdb398b02d96cb35fb2ea9d57abc9b81047e2d Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Thu, 28 Sep 2017 14:23:06 -0400 Subject: [PATCH 239/240] Tests should hopefully no longer break CI --- Specs/Scene/PointCloudPostProcessorSpec.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Specs/Scene/PointCloudPostProcessorSpec.js b/Specs/Scene/PointCloudPostProcessorSpec.js index 67cb0082cc50..55eb3a0494c4 100644 --- a/Specs/Scene/PointCloudPostProcessorSpec.js +++ b/Specs/Scene/PointCloudPostProcessorSpec.js @@ -62,6 +62,10 @@ defineSuite([ it('enabling the point cloud post processor increases the number of draw calls', function() { return Cesium3DTilesTester.loadTileset(scene, pointCloudRGBUrl).then(function(tileset) { + if (!tileset.pointCloudPostProcessor.processingSupported()) { + return; + } + scene.renderForSpecs(); var originalLength = scene.frameState.commandList.length; From 4b1a918884ccd971c72a7601e140425d9ddba55a Mon Sep 17 00:00:00 2001 From: Srinivas Kaza Date: Wed, 18 Oct 2017 13:23:51 -0400 Subject: [PATCH 240/240] Tests longer assume that pointCloudPostProcessor has been created --- Specs/Scene/PointCloudPostProcessorSpec.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Specs/Scene/PointCloudPostProcessorSpec.js b/Specs/Scene/PointCloudPostProcessorSpec.js index 55eb3a0494c4..3f3b5373552b 100644 --- a/Specs/Scene/PointCloudPostProcessorSpec.js +++ b/Specs/Scene/PointCloudPostProcessorSpec.js @@ -62,7 +62,8 @@ defineSuite([ it('enabling the point cloud post processor increases the number of draw calls', function() { return Cesium3DTilesTester.loadTileset(scene, pointCloudRGBUrl).then(function(tileset) { - if (!tileset.pointCloudPostProcessor.processingSupported()) { + if (!defined(tileset.pointCloudPostProcessor) || + !tileset.pointCloudPostProcessor.processingSupported()) { return; }