Skip to content

Commit

Permalink
fix crash due to undefined clipping planes texture
Browse files Browse the repository at this point in the history
  • Loading branch information
likangning93 committed May 8, 2018
1 parent 404f286 commit eda6e52
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 33 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Change Log

##### Fixes :wrench:
* Fixed a bug causing custom TilingScheme classes to not be able to use a GeographicProjection. [#6524](https://github.com/AnalyticalGraphicsInc/cesium/pull/6524)
* Fixed a bug causing intermittent crashes with clippin planes due to uninitialized textures. [#6566](https://github.com/AnalyticalGraphicsInc/cesium/issues/6566)

### 1.45 - 2018-05-01

Expand Down
30 changes: 29 additions & 1 deletion Source/Scene/ClippingPlaneCollection.js
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,8 @@ define([

if (!defined(clippingPlanesTexture)) {
// Allocate twice as much space as needed to avoid frequent texture reallocation.
requiredResolution.x *= 2;
// Allocate in the Y direction, since texture may be as wide as context texture support.
requiredResolution.y *= 2;

var sampler = new Sampler({
wrapS : TextureWrap.CLAMP_TO_EDGE,
Expand Down Expand Up @@ -665,6 +666,33 @@ define([
return context.floatingPointTexture;
};

/**
* Function for getting the clipping plane collection's texture resolution.
* If the ClippingPlaneCollection hasn't been updated, returns the resolution that will be
* allocated based on the current plane count.
*
* @param {ClippingPlaneCollection} clippingPlaneCollection The clipping plane collection
* @param {Context} context The rendering context
* @param {Cartesian2} result A Cartesian2 for the result.
* @returns {Cartesian2} The required resolution.
* @private
*/
ClippingPlaneCollection.getTextureResolution = function(clippingPlaneCollection, context, result) {
var texture = clippingPlaneCollection.texture;
if (defined(texture)) {
result.x = texture.width;
result.y = texture.height;
return result;
}

var pixelsNeeded = ClippingPlaneCollection.useFloatTexture(context) ? clippingPlaneCollection.length : clippingPlaneCollection.length * 2;
var requiredResolution = computeTextureResolution(pixelsNeeded, result);

// Allocate twice as much space as needed to avoid frequent texture reallocation.
requiredResolution.y *= 2;
return requiredResolution;
};

/**
* Returns true if this object was destroyed; otherwise, false.
* <br /><br />
Expand Down
2 changes: 1 addition & 1 deletion Source/Scene/GlobeSurfaceShaderSet.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ define([
var fs = this.baseFragmentShaderSource.clone();

if (currentClippingShaderState !== 0) {
fs.sources.unshift(getClippingFunction(clippingPlanes)); // Need to go before GlobeFS
fs.sources.unshift(getClippingFunction(clippingPlanes, frameState.context)); // Need to go before GlobeFS
}

vs.defines.push(quantizationDefine);
Expand Down
8 changes: 4 additions & 4 deletions Source/Scene/Model.js
Original file line number Diff line number Diff line change
Expand Up @@ -2035,7 +2035,7 @@ define([
finalFS = Model._modifyShaderForColor(finalFS, model._hasPremultipliedAlpha);
}
if (addClippingPlaneCode) {
finalFS = modifyShaderForClippingPlanes(finalFS, clippingPlaneCollection);
finalFS = modifyShaderForClippingPlanes(finalFS, clippingPlaneCollection, context);
}

var drawVS = modifyShader(vs, id, model._vertexShaderLoaded);
Expand All @@ -2055,7 +2055,7 @@ define([
}

if (addClippingPlaneCode) {
pickFS = modifyShaderForClippingPlanes(pickFS, clippingPlaneCollection);
pickFS = modifyShaderForClippingPlanes(pickFS, clippingPlaneCollection, context);
}

pickVS = ModelUtility.modifyVertexShaderForLogDepth(pickVS, toClipCoordinatesGLSL);
Expand Down Expand Up @@ -3947,9 +3947,9 @@ define([
}
}

function modifyShaderForClippingPlanes(shader, clippingPlaneCollection) {
function modifyShaderForClippingPlanes(shader, clippingPlaneCollection, context) {
shader = ShaderSource.replaceMain(shader, 'gltf_clip_main');
shader += Model._getClippingFunction(clippingPlaneCollection) + '\n';
shader += Model._getClippingFunction(clippingPlaneCollection, context) + '\n';
shader +=
'uniform sampler2D gltf_clippingPlanes; \n' +
'uniform mat4 gltf_clippingPlanesMatrix; \n' +
Expand Down
2 changes: 1 addition & 1 deletion Source/Scene/PointCloud3DTileContent.js
Original file line number Diff line number Diff line change
Expand Up @@ -1126,7 +1126,7 @@ define([
'uniform mat4 u_clippingPlanesMatrix; \n' +
'uniform vec4 u_clippingPlanesEdgeStyle; \n';
fs += '\n';
fs += getClippingFunction(clippingPlanes);
fs += getClippingFunction(clippingPlanes, context);
fs += '\n';
}

Expand Down
27 changes: 17 additions & 10 deletions Source/Scene/getClippingFunction.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,43 @@
define([
'../Core/Cartesian2',
'../Core/Check',
'../Renderer/PixelDatatype'
'../Renderer/PixelDatatype',
'./ClippingPlaneCollection'
], function(
Cartesian2,
Check,
PixelDatatype) {
PixelDatatype,
ClippingPlaneCollection) {
'use strict';

var textureResolutionScratch = new Cartesian2();
/**
* Gets the GLSL functions needed to retrieve clipping planes from a ClippingPlaneCollection's texture.
*
* @param {ClippingPlaneCollection} clippingPlaneCollection ClippingPlaneCollection with a defined texture.
* @param {Context} context The current rendering context.
* @returns {String} A string containing GLSL functions for retrieving clipping planes.
* @private
*/
function getClippingFunction(clippingPlaneCollection) {
function getClippingFunction(clippingPlaneCollection, context) {
//>>includeStart('debug', pragmas.debug);
Check.typeOf.object('clippingPlaneCollection', clippingPlaneCollection);
Check.typeOf.object('context', context);
//>>includeEnd('debug');
var unionClippingRegions = clippingPlaneCollection.unionClippingRegions;
var clippingPlanesLength = clippingPlaneCollection.length;
var texture = clippingPlaneCollection.texture;
var usingFloatTexture = texture.pixelDatatype === PixelDatatype.FLOAT;
var width = texture.width;
var height = texture.height;
var usingFloatTexture = ClippingPlaneCollection.useFloatTexture(context);
var textureResolution = ClippingPlaneCollection.getTextureResolution(clippingPlaneCollection, context, textureResolutionScratch);
var width = textureResolution.x;
var height = textureResolution.y;

var functions = usingFloatTexture ? getClippingPlaneFloat(width, height) : getClippingPlaneUint8(width, height);
functions += '\n';
functions += unionClippingRegions ? clippingFunctionUnion(usingFloatTexture, clippingPlanesLength) : clippingFunctionIntersect(usingFloatTexture, clippingPlanesLength);
functions += unionClippingRegions ? clippingFunctionUnion(clippingPlanesLength) : clippingFunctionIntersect(clippingPlanesLength);
return functions;
}

function clippingFunctionUnion(usingFloatTexture, clippingPlanesLength) {
function clippingFunctionUnion(clippingPlanesLength) {
var functionString =
'float clip(vec4 fragCoord, sampler2D clippingPlanes, mat4 clippingPlanesMatrix)\n' +
'{\n' +
Expand Down Expand Up @@ -66,7 +73,7 @@ define([
return functionString;
}

function clippingFunctionIntersect(usingFloatTexture, clippingPlanesLength) {
function clippingFunctionIntersect(clippingPlanesLength) {
var functionString =
'float clip(vec4 fragCoord, sampler2D clippingPlanes, mat4 clippingPlanesMatrix)\n' +
'{\n' +
Expand Down
59 changes: 43 additions & 16 deletions Specs/Scene/ClippingPlaneCollectionSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,8 +158,8 @@ defineSuite([
expect(packedTexture).toBeDefined();

// Two RGBA uint8 clipping planes consume 4 pixels of texture, allocation to be double that
expect(packedTexture.width).toEqual(8);
expect(packedTexture.height).toEqual(1);
expect(packedTexture.width).toEqual(4);
expect(packedTexture.height).toEqual(2);

expect(packedTexture.pixelFormat).toEqual(PixelFormat.RGBA);
expect(packedTexture.pixelDatatype).toEqual(PixelDatatype.UNSIGNED_BYTE);
Expand Down Expand Up @@ -230,8 +230,8 @@ defineSuite([
var packedTexture = clippingPlanes.texture;

// Two RGBA uint8 clipping planes consume 4 pixels of texture, allocation to be double that
expect(packedTexture.width).toEqual(8);
expect(packedTexture.height).toEqual(1);
expect(packedTexture.width).toEqual(4);
expect(packedTexture.height).toEqual(2);

clippingPlanes.add(new ClippingPlane(Cartesian3.UNIT_X, 1.0));
clippingPlanes.add(new ClippingPlane(Cartesian3.UNIT_X, 1.0));
Expand All @@ -243,8 +243,8 @@ defineSuite([
packedTexture = clippingPlanes.texture;

// Five RGBA uint8 clipping planes consume 10 pixels of texture, allocation to be double that
expect(packedTexture.width).toEqual(20);
expect(packedTexture.height).toEqual(1);
expect(packedTexture.width).toEqual(10);
expect(packedTexture.height).toEqual(2);

clippingPlanes.removeAll();
clippingPlanes.add(new ClippingPlane(Cartesian3.UNIT_X, 1.0));
Expand All @@ -255,8 +255,8 @@ defineSuite([
packedTexture = clippingPlanes.texture;

// One RGBA uint8 clipping plane consume 2 pixels of texture, allocation to be double that
expect(packedTexture.width).toEqual(4);
expect(packedTexture.height).toEqual(1);
expect(packedTexture.width).toEqual(2);
expect(packedTexture.height).toEqual(2);

clippingPlanes.destroy();
scene.destroyForSpecs();
Expand Down Expand Up @@ -284,8 +284,8 @@ defineSuite([

var packedTexture = clippingPlanes.texture;
expect(packedTexture).toBeDefined();
expect(packedTexture.width).toEqual(4);
expect(packedTexture.height).toEqual(1);
expect(packedTexture.width).toEqual(2);
expect(packedTexture.height).toEqual(2);
expect(packedTexture.pixelFormat).toEqual(PixelFormat.RGBA);
expect(packedTexture.pixelDatatype).toEqual(PixelDatatype.FLOAT);

Expand Down Expand Up @@ -362,8 +362,8 @@ defineSuite([
var packedTexture = clippingPlanes.texture;

// Two RGBA float clipping planes consume 2 pixels of texture, allocation to be double that
expect(packedTexture.width).toEqual(4);
expect(packedTexture.height).toEqual(1);
expect(packedTexture.width).toEqual(2);
expect(packedTexture.height).toEqual(2);

clippingPlanes.add(new ClippingPlane(Cartesian3.UNIT_X, 1.0));
clippingPlanes.add(new ClippingPlane(Cartesian3.UNIT_X, 1.0));
Expand All @@ -375,8 +375,8 @@ defineSuite([
packedTexture = clippingPlanes.texture;

// Five RGBA float clipping planes consume 5 pixels of texture, allocation to be double that
expect(packedTexture.width).toEqual(10);
expect(packedTexture.height).toEqual(1);
expect(packedTexture.width).toEqual(5);
expect(packedTexture.height).toEqual(2);

clippingPlanes.removeAll();
clippingPlanes.add(new ClippingPlane(Cartesian3.UNIT_X, 1.0));
Expand All @@ -387,8 +387,8 @@ defineSuite([
packedTexture = clippingPlanes.texture;

// One RGBA float clipping plane consume 1 pixels of texture, allocation to be double that
expect(packedTexture.width).toEqual(2);
expect(packedTexture.height).toEqual(1);
expect(packedTexture.width).toEqual(1);
expect(packedTexture.height).toEqual(2);

clippingPlanes.destroy();
scene.destroyForSpecs();
Expand Down Expand Up @@ -596,4 +596,31 @@ defineSuite([
clippingPlanes.remove(holdThisPlane);
expect(clippingPlanes.clippingPlanesState).toEqual(1);
});

it('provides a function for checking the texture resolution', function() {
spyOn(ClippingPlaneCollection, 'useFloatTexture').and.returnValue(false);

var scene = createScene();
clippingPlanes = new ClippingPlaneCollection({
planes : planes,
enabled : false,
edgeColor : Color.RED,
modelMatrix : transform
});

// Predicted resolution before texture has been allocated
var predictedResolution = ClippingPlaneCollection.getTextureResolution(clippingPlanes, scene.frameState.context, new Cartesian2());

expect(predictedResolution.x).toEqual(4);
expect(predictedResolution.y).toEqual(2);

clippingPlanes.update(scene.frameState);
var actualResolution = ClippingPlaneCollection.getTextureResolution(clippingPlanes, scene.frameState.context, new Cartesian2());

expect(predictedResolution.x).toEqual(actualResolution.x);
expect(predictedResolution.y).toEqual(actualResolution.y);

clippingPlanes.destroy();
scene.destroyForSpecs();
});
});

0 comments on commit eda6e52

Please sign in to comment.