Skip to content

Commit

Permalink
Merge pull request #5836 from AnalyticalGraphicsInc/invert-classifica…
Browse files Browse the repository at this point in the history
…tion

Invert classification
  • Loading branch information
lilleyse authored Oct 19, 2017
2 parents 9b912da + c4e886f commit d568775
Show file tree
Hide file tree
Showing 20 changed files with 1,084 additions and 204 deletions.
299 changes: 169 additions & 130 deletions Apps/Sandcastle/gallery/Classification.html

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Change Log
* Added function that inserts missing namespace declarations into KML files. [#5860](https://github.com/AnalyticalGraphicsInc/cesium/pull/5860)
* Added support for the layer.json `parentUrl` property in `CesiumTerrainProvider` to allow for compositing of tilesets.
* Fixed a bug that caused KML ground overlays to appear distorted when rotation was applied. [#5914](https://github.com/AnalyticalGraphicsInc/cesium/issues/5914)
* Adds `invertClassification` and `invertClassificationColor` to `Scene`. When `invertClassification` is `true`, any 3D Tiles geometry that is not classified by a `ClassificationPrimitive` or `GroundPrimitive` will have its color multiplied by `invertClassificationColor`. [#5836](https://github.com/AnalyticalGraphicsInc/cesium/pull/5836)

### 1.38 - 2017-10-02

Expand Down
14 changes: 14 additions & 0 deletions Source/Renderer/AutomaticUniforms.js
Original file line number Diff line number Diff line change
Expand Up @@ -1588,6 +1588,20 @@ define([
getValue : function(uniformState) {
return uniformState.minimumDisableDepthTestDistance;
}
}),

/**
* An automatic GLSL uniform that will be the highlight color of unclassified 3D Tiles.
*
* @alias czm_invertClassificationColor
* @glslUniform
*/
czm_invertClassificationColor : new AutomaticUniform({
size : 1,
datatype : WebGLConstants.FLOAT_VEC4,
getValue : function(uniformState) {
return uniformState.invertClassificationColor;
}
})
};

Expand Down
9 changes: 5 additions & 4 deletions Source/Renderer/Pass.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,11 @@ define([
TERRAIN_CLASSIFICATION : 3,
CESIUM_3D_TILE : 4,
CESIUM_3D_TILE_CLASSIFICATION : 5,
OPAQUE : 6,
TRANSLUCENT : 7,
OVERLAY : 8,
NUMBER_OF_PASSES : 9
CESIUM_3D_TILE_CLASSIFICATION_IGNORE_SHOW : 6,
OPAQUE : 7,
TRANSLUCENT : 8,
OVERLAY : 9,
NUMBER_OF_PASSES : 10
};

return freezeObject(Pass);
Expand Down
16 changes: 16 additions & 0 deletions Source/Renderer/UniformState.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@ define([

this._fogDensity = undefined;

this._invertClassificationColor = undefined;

this._imagerySplitPosition = 0.0;
this._pixelSizePerMeter = undefined;
this._geometricToleranceOverMeter = undefined;
Expand Down Expand Up @@ -847,6 +849,18 @@ define([
get : function() {
return this._minimumDisableDepthTestDistance;
}
},

/**
* The highlight color of unclassified 3D Tiles.
*
* @memberof UniformState.prototype
* @type {Color}
*/
invertClassificationColor : {
get : function() {
return this._invertClassificationColor;
}
}
});

Expand Down Expand Up @@ -1012,6 +1026,8 @@ define([

this._fogDensity = frameState.fog.density;

this._invertClassificationColor = frameState.invertClassificationColor;

this._frameState = frameState;
this._temeToPseudoFixed = Transforms.computeTemeToPseudoFixedMatrix(frameState.time, this._temeToPseudoFixed);

Expand Down
6 changes: 5 additions & 1 deletion Source/Scene/Cesium3DTileBatchTable.js
Original file line number Diff line number Diff line change
Expand Up @@ -1342,8 +1342,12 @@ define([
// selection depth to the stencil buffer to prevent ancestor tiles from drawing on top
derivedCommand = DrawCommand.shallowClone(command);
var rs = clone(derivedCommand.renderState, true);
// Stencil test is masked to the most significant 4 bits so the reference is shifted.
// This is to prevent clearing the stencil before classification which needs the least significant
// bits for increment/decrement operations.
rs.stencilTest.enabled = true;
rs.stencilTest.reference = reference;
rs.stencilTest.mask = 0xF0;
rs.stencilTest.reference = reference << 4;
rs.stencilTest.frontFunction = StencilFunction.GREATER_OR_EQUAL;
rs.stencilTest.frontOperation.zPass = StencilOperation.REPLACE;
derivedCommand.renderState = RenderState.fromCache(rs);
Expand Down
2 changes: 1 addition & 1 deletion Source/Scene/Cesium3DTileset.js
Original file line number Diff line number Diff line change
Expand Up @@ -1495,7 +1495,7 @@ define([
var addedCommandsLength = (lengthAfterUpdate - lengthBeforeUpdate);
var backfaceCommandsLength = backfaceCommands.length;

commandList.length += backfaceCommands.length;
commandList.length += backfaceCommandsLength;

// copy commands to the back of the commandList
for (i = addedCommandsLength - 1; i >= 0; --i) {
Expand Down
3 changes: 3 additions & 0 deletions Source/Scene/Cesium3DTilesetTraversal.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,9 @@ define([
* NOTE: this will no longer work when there is a chain of selected tiles that is longer than the size of the
* stencil buffer (usually 8 bits). In other words, the subset of the tree containing only selected tiles must be
* no deeper than 255. It is very, very unlikely this will cause a problem.
*
* NOTE: when the scene has inverted classification enabled, the stencil buffer will be masked to 4 bits. So, the
* selected tiles must be no deeper than 15. This is still very unlikely.
*/
function traverseAndSelect(tileset, root, frameState) {
var stack = scratchStack;
Expand Down
95 changes: 77 additions & 18 deletions Source/Scene/ClassificationPrimitive.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,13 +164,16 @@ define([
this._uniformMap = options._uniformMap;

this._sp = undefined;
this._spStencil = undefined;
this._spPick = undefined;

this._rsStencilPreloadPass = undefined;
this._rsStencilDepthPass = undefined;
this._rsColorPass = undefined;
this._rsPickPass = undefined;

this._commandsIgnoreShow = [];

this._ready = false;
this._readyPromise = when.defer();

Expand Down Expand Up @@ -344,6 +347,12 @@ define([
return scene.context.stencilBuffer;
};

// The stencil mask only uses the least significant 4 bits.
// This is so 3D Tiles with the skip LOD optimization, which uses the most significant 4 bits,
// can be classified.
var stencilMask = 0x0F;
var stencilReference = 0;

function getStencilPreloadRenderState(enableStencil) {
return {
colorMask : {
Expand All @@ -366,8 +375,8 @@ define([
zFail : StencilOperation.INCREMENT_WRAP,
zPass : StencilOperation.INCREMENT_WRAP
},
reference : 0,
mask : ~0
reference : stencilReference,
mask : stencilMask
},
depthTest : {
enabled : false
Expand Down Expand Up @@ -398,8 +407,8 @@ define([
zFail : StencilOperation.KEEP,
zPass : StencilOperation.DECREMENT_WRAP
},
reference : 0,
mask : ~0
reference : stencilReference,
mask : stencilMask
},
depthTest : {
enabled : true,
Expand All @@ -426,8 +435,8 @@ define([
zFail : StencilOperation.KEEP,
zPass : StencilOperation.DECREMENT_WRAP
},
reference : 0,
mask : ~0
reference : stencilReference,
mask : stencilMask
},
depthTest : {
enabled : false
Expand All @@ -452,8 +461,8 @@ define([
zFail : StencilOperation.KEEP,
zPass : StencilOperation.DECREMENT_WRAP
},
reference : 0,
mask : ~0
reference : stencilReference,
mask : stencilMask
},
depthTest : {
enabled : false
Expand Down Expand Up @@ -510,7 +519,6 @@ define([
var primitive = classificationPrimitive._primitive;
var vs = ShadowVolumeVS;
vs = classificationPrimitive._primitive._batchTable.getVertexShaderCallback()(vs);
vs = Primitive._appendShowToShader(primitive, vs);
vs = Primitive._appendDistanceDisplayConditionToShader(primitive, vs);
vs = Primitive._modifyShaderPosition(classificationPrimitive, vs, frameState.scene3DOnly);
vs = Primitive._updateColorAttribute(primitive, vs);
Expand All @@ -530,9 +538,9 @@ define([
});
var attributeLocations = classificationPrimitive._primitive._attributeLocations;

classificationPrimitive._sp = ShaderProgram.replaceCache({
classificationPrimitive._spStencil = ShaderProgram.replaceCache({
context : context,
shaderProgram : classificationPrimitive._sp,
shaderProgram : classificationPrimitive._spStencil,
vertexShaderSource : vsSource,
fragmentShaderSource : fsSource,
attributeLocations : attributeLocations
Expand Down Expand Up @@ -567,6 +575,20 @@ define([
attributeLocations : attributeLocations
});
}

vs = Primitive._appendShowToShader(primitive, vs);
vsSource = new ShaderSource({
defines : [extrudedDefine],
sources : [vs]
});

classificationPrimitive._sp = ShaderProgram.replaceCache({
context : context,
shaderProgram : classificationPrimitive._sp,
vertexShaderSource : vsSource,
fragmentShaderSource : fsSource,
attributeLocations : attributeLocations
});
}

function createColorCommands(classificationPrimitive, colorCommands) {
Expand Down Expand Up @@ -632,6 +654,24 @@ define([
command = colorCommands[length + i] = DrawCommand.shallowClone(colorCommands[i], colorCommands[length + i]);
command.pass = Pass.CESIUM_3D_TILE_CLASSIFICATION;
}

var commandsIgnoreShow = classificationPrimitive._commandsIgnoreShow;
var spStencil = classificationPrimitive._spStencil;

var commandIndex = 0;
length = commandsIgnoreShow.length = length / 3 * 2;

for (var j = 0; j < length; j += 2) {
var commandIgnoreShow = commandsIgnoreShow[j] = DrawCommand.shallowClone(colorCommands[commandIndex], commandsIgnoreShow[j]);
commandIgnoreShow.shaderProgram = spStencil;
commandIgnoreShow.pass = Pass.CESIUM_3D_TILE_CLASSIFICATION_IGNORE_SHOW;

commandIgnoreShow = commandsIgnoreShow[j + 1] = DrawCommand.shallowClone(colorCommands[commandIndex + 1], commandsIgnoreShow[j + 1]);
commandIgnoreShow.shaderProgram = spStencil;
commandIgnoreShow.pass = Pass.CESIUM_3D_TILE_CLASSIFICATION_IGNORE_SHOW;

commandIndex += 3;
}
}

function createPickCommands(classificationPrimitive, pickCommands) {
Expand Down Expand Up @@ -665,7 +705,7 @@ define([
command.offset = offset;
command.count = count;
command.renderState = classificationPrimitive._rsStencilPreloadPass;
command.shaderProgram = classificationPrimitive._sp;
command.shaderProgram = classificationPrimitive._spStencil;
command.uniformMap = uniformMap;
command.pass = Pass.TERRAIN_CLASSIFICATION;

Expand All @@ -682,7 +722,7 @@ define([
command.offset = offset;
command.count = count;
command.renderState = classificationPrimitive._rsStencilDepthPass;
command.shaderProgram = classificationPrimitive._sp;
command.shaderProgram = classificationPrimitive._spStencil;
command.uniformMap = uniformMap;
command.pass = Pass.TERRAIN_CLASSIFICATION;

Expand Down Expand Up @@ -761,26 +801,45 @@ define([
var commandList = frameState.commandList;
var passes = frameState.passes;

var i;
var indices;
var startIndex;
var endIndex;
var classificationType = classificationPrimitive.classificationType;

if (passes.render) {
var colorCommand;
var colorLength = colorCommands.length;
indices = getCommandIndices(classificationType, colorLength);
startIndex = indices.start;
endIndex = indices.end;

for (var i = startIndex; i < endIndex; ++i) {
var colorCommand = colorCommands[i];
for (i = startIndex; i < endIndex; ++i) {
colorCommand = colorCommands[i];
colorCommand.modelMatrix = modelMatrix;
colorCommand.boundingVolume = boundingVolumes[boundingVolumeIndex(i, colorLength)];
colorCommand.cull = cull;
colorCommand.debugShowBoundingVolume = debugShowBoundingVolume;

commandList.push(colorCommand);
}

if (frameState.invertClassification) {
var ignoreShowCommands = classificationPrimitive._commandsIgnoreShow;
startIndex = 0;
endIndex = ignoreShowCommands.length;

for (i = startIndex; i < endIndex; ++i) {
var bvIndex = Math.floor(i / 2);
colorCommand = ignoreShowCommands[i];
colorCommand.modelMatrix = modelMatrix;
colorCommand.boundingVolume = boundingVolumes[bvIndex];
colorCommand.cull = cull;
colorCommand.debugShowBoundingVolume = debugShowBoundingVolume;

commandList.push(colorCommand);
}
}
}

if (passes.pick) {
Expand All @@ -790,9 +849,9 @@ define([
endIndex = indices.end;

var pickOffsets = primitive._pickOffsets;
for (var j = startIndex; j < endIndex; ++j) {
var pickOffset = pickOffsets[boundingVolumeIndex(j, pickLength)];
var pickCommand = pickCommands[j];
for (i = startIndex; i < endIndex; ++i) {
var pickOffset = pickOffsets[boundingVolumeIndex(i, pickLength)];
var pickCommand = pickCommands[i];
pickCommand.modelMatrix = modelMatrix;
pickCommand.boundingVolume = boundingVolumes[pickOffset.index];
pickCommand.cull = cull;
Expand Down
14 changes: 14 additions & 0 deletions Source/Scene/FrameState.js
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,20 @@ define([
* @type {Number}
*/
this.minimumDisableDepthTestDistance = undefined;

/**
* When <code>false</code>, 3D Tiles will render normally. When <code>true</code>, classified 3D Tile geometry will render normally and
* unclassified 3D Tile geometry will render with the color multiplied with {@link FrameState#invertClassificationColor}.
* @type {Boolean}
* @default false
*/
this.invertClassification = false;

/**
* The highlight color of unclassified 3D Tile geometry when {@link FrameState#invertClassification} is <code>true</code>.
* @type {Color}
*/
this.invertClassificationColor = undefined;
}

/**
Expand Down
24 changes: 22 additions & 2 deletions Source/Scene/GroundPrimitive.js
Original file line number Diff line number Diff line change
Expand Up @@ -614,8 +614,11 @@ define([
startIndex = indices.start;
endIndex = indices.end;

for (var i = startIndex; i < endIndex; ++i) {
var colorCommand = colorCommands[i];
var i;
var colorCommand;

for (i = startIndex; i < endIndex; ++i) {
colorCommand = colorCommands[i];
colorCommand.owner = groundPrimitive;
colorCommand.modelMatrix = modelMatrix;
colorCommand.boundingVolume = boundingVolumes[boundingVolumeIndex(i, colorLength)];
Expand All @@ -624,6 +627,23 @@ define([

commandList.push(colorCommand);
}

if (frameState.invertClassification) {
var ignoreShowCommands = groundPrimitive._primitive._commandsIgnoreShow;
startIndex = 0;
endIndex = ignoreShowCommands.length;

for (i = startIndex; i < endIndex; ++i) {
var bvIndex = Math.floor(i / 2);
colorCommand = ignoreShowCommands[i];
colorCommand.modelMatrix = modelMatrix;
colorCommand.boundingVolume = boundingVolumes[bvIndex];
colorCommand.cull = cull;
colorCommand.debugShowBoundingVolume = debugShowBoundingVolume;

commandList.push(colorCommand);
}
}
}

if (passes.pick) {
Expand Down
Loading

0 comments on commit d568775

Please sign in to comment.