Skip to content

Commit

Permalink
Merge pull request #6984 from AnalyticalGraphicsInc/groundRectangleIdl2D
Browse files Browse the repository at this point in the history
fix ground primitives crossing IDL in 2D
  • Loading branch information
bagnell authored Aug 31, 2018
2 parents 94e7113 + 1557e89 commit 685e3f3
Show file tree
Hide file tree
Showing 6 changed files with 180 additions and 29 deletions.
2 changes: 1 addition & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ Change Log
* Fixed an issue where switching from 2D to 3D could cause a crash. [#6929](https://github.com/AnalyticalGraphicsInc/cesium/issues/6929)
* Fixed an issue where point primitives behind the camera would appear in view. [#6904](https://github.com/AnalyticalGraphicsInc/cesium/issues/6904)
* The `createGroundPolylineGeometry` web worker no longer depends on `GroundPolylinePrimitive`, making the worker smaller and potentially avoiding a hanging build in some webpack configurations.
* Fixed an issue that cause terrain entities (entities with unspecified `height`) and `GroundPrimitives` to fail when crossing the international date line in 3D. [#6951](https://github.com/AnalyticalGraphicsInc/cesium/issues/6951)
* Fixed an issue that cause terrain entities (entities with unspecified `height`) and `GroundPrimitives` to fail when crossing the international date line. [#6951](https://github.com/AnalyticalGraphicsInc/cesium/issues/6951)
* Fixed normal calculation for `CylinderGeometry` when the top radius is not equal to the bottom radius [#6863](https://github.com/AnalyticalGraphicsInc/cesium/pull/6863)

### 1.48 - 2018-08-01
Expand Down
8 changes: 4 additions & 4 deletions Source/Scene/ClassificationPrimitive.js
Original file line number Diff line number Diff line change
Expand Up @@ -589,7 +589,7 @@ define([
vsPick = Primitive._updatePickColorAttribute(vsPick);

var pickFS3D = shadowVolumeAppearance.createPickFragmentShader(false);
var pickVS3D = shadowVolumeAppearance.createPickVertexShader([extrudedDefine, disableGlPositionLogDepth], vsPick, false);
var pickVS3D = shadowVolumeAppearance.createPickVertexShader([extrudedDefine, disableGlPositionLogDepth], vsPick, false, frameState.mapProjection);

classificationPrimitive._spPick = ShaderProgram.replaceCache({
context : context,
Expand All @@ -605,7 +605,7 @@ define([
var pickProgram2D = context.shaderCache.getDerivedShaderProgram(classificationPrimitive._spPick, '2dPick');
if (!defined(pickProgram2D)) {
var pickFS2D = shadowVolumeAppearance.createPickFragmentShader(true);
var pickVS2D = shadowVolumeAppearance.createPickVertexShader([extrudedDefine, disableGlPositionLogDepth], vsPick, true);
var pickVS2D = shadowVolumeAppearance.createPickVertexShader([extrudedDefine, disableGlPositionLogDepth], vsPick, true, frameState.mapProjection);

pickProgram2D = context.shaderCache.createDerivedShaderProgram(classificationPrimitive._spPick, '2dPick', {
vertexShaderSource : pickVS2D,
Expand Down Expand Up @@ -640,7 +640,7 @@ define([

// Create a fragment shader that computes only required material hookups using screen space techniques
var fsColorSource = shadowVolumeAppearance.createFragmentShader(false);
var vsColorSource = shadowVolumeAppearance.createVertexShader([extrudedDefine, disableGlPositionLogDepth], vs, false);
var vsColorSource = shadowVolumeAppearance.createVertexShader([extrudedDefine, disableGlPositionLogDepth], vs, false, frameState.mapProjection);

classificationPrimitive._spColor = ShaderProgram.replaceCache({
context : context,
Expand All @@ -657,7 +657,7 @@ define([
var colorProgram2D = context.shaderCache.getDerivedShaderProgram(classificationPrimitive._spColor, '2dColor');
if (!defined(colorProgram2D)) {
var fsColorSource2D = shadowVolumeAppearance.createFragmentShader(true);
var vsColorSource2D = shadowVolumeAppearance.createVertexShader([extrudedDefine, disableGlPositionLogDepth], vs, true);
var vsColorSource2D = shadowVolumeAppearance.createVertexShader([extrudedDefine, disableGlPositionLogDepth], vs, true, frameState.mapProjection);

colorProgram2D = context.shaderCache.createDerivedShaderProgram(classificationPrimitive._spColor, '2dColor', {
vertexShaderSource : vsColorSource2D,
Expand Down
54 changes: 49 additions & 5 deletions Source/Scene/ShadowVolumeAppearance.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ define([
ShadowVolumeAppearanceFS) {
'use strict';

var projectionExtentDefines = {
eastMostYhighDefine : '',
eastMostYlowDefine : '',
westMostYhighDefine : '',
westMostYlowDefine : ''
};

/**
* Creates shaders for a ClassificationPrimitive to use a given Appearance, as well as for picking.
*
Expand Down Expand Up @@ -183,15 +190,17 @@ define([
* @param {String[]} defines External defines to pass to the vertex shader.
* @param {String} vertexShaderSource ShadowVolumeAppearanceVS with any required modifications for computing position.
* @param {Boolean} columbusView2D Whether the shader will be used for Columbus View or 2D.
* @param {MapProjection} mapProjection Current scene's map projection.
* @returns {String} Shader source for the vertex shader.
*/
ShadowVolumeAppearance.prototype.createVertexShader = function(defines, vertexShaderSource, columbusView2D) {
ShadowVolumeAppearance.prototype.createVertexShader = function(defines, vertexShaderSource, columbusView2D, mapProjection) {
//>>includeStart('debug', pragmas.debug);
Check.defined('defines', defines);
Check.typeOf.string('vertexShaderSource', vertexShaderSource);
Check.typeOf.bool('columbusView2D', columbusView2D);
Check.defined('mapProjection', mapProjection);
//>>includeEnd('debug');
return createShadowVolumeAppearanceVS(this._colorShaderDependencies, this._planarExtents, columbusView2D, defines, vertexShaderSource, this._appearance);
return createShadowVolumeAppearanceVS(this._colorShaderDependencies, this._planarExtents, columbusView2D, defines, vertexShaderSource, this._appearance, mapProjection);
};

/**
Expand All @@ -200,20 +209,55 @@ define([
* @param {String[]} defines External defines to pass to the vertex shader.
* @param {String} vertexShaderSource ShadowVolumeAppearanceVS with any required modifications for computing position and picking.
* @param {Boolean} columbusView2D Whether the shader will be used for Columbus View or 2D.
* @param {MapProjection} mapProjection Current scene's map projection.
* @returns {String} Shader source for the vertex shader.
*/
ShadowVolumeAppearance.prototype.createPickVertexShader = function(defines, vertexShaderSource, columbusView2D) {
ShadowVolumeAppearance.prototype.createPickVertexShader = function(defines, vertexShaderSource, columbusView2D, mapProjection) {
//>>includeStart('debug', pragmas.debug);
Check.defined('defines', defines);
Check.typeOf.string('vertexShaderSource', vertexShaderSource);
Check.typeOf.bool('columbusView2D', columbusView2D);
Check.defined('mapProjection', mapProjection);
//>>includeEnd('debug');
return createShadowVolumeAppearanceVS(this._pickShaderDependencies, this._planarExtents, columbusView2D, defines, vertexShaderSource);
return createShadowVolumeAppearanceVS(this._pickShaderDependencies, this._planarExtents, columbusView2D, defines, vertexShaderSource, undefined, mapProjection);
};

function createShadowVolumeAppearanceVS(shaderDependencies, planarExtents, columbusView2D, defines, vertexShaderSource, appearance) {
var longitudeExtentsCartesianScratch = new Cartesian3();
var longitudeExtentsCartographicScratch = new Cartographic();
var longitudeExtentsEncodeScratch = {
high : 0.0,
low : 0.0
};
function createShadowVolumeAppearanceVS(shaderDependencies, planarExtents, columbusView2D, defines, vertexShaderSource, appearance, mapProjection) {
var allDefines = defines.slice();

if (projectionExtentDefines.eastMostYhighDefine === '') {
var eastMostCartographic = longitudeExtentsCartographicScratch;
eastMostCartographic.longitude = CesiumMath.PI;
eastMostCartographic.latitude = 0.0;
eastMostCartographic.height = 0.0;
var eastMostCartesian = mapProjection.project(eastMostCartographic, longitudeExtentsCartesianScratch);
var encoded = EncodedCartesian3.encode(eastMostCartesian.x, longitudeExtentsEncodeScratch);
projectionExtentDefines.eastMostYhighDefine = 'EAST_MOST_X_HIGH ' + encoded.high.toFixed((encoded.high + '').length + 1);
projectionExtentDefines.eastMostYlowDefine = 'EAST_MOST_X_LOW ' + encoded.low.toFixed((encoded.low + '').length + 1);

var westMostCartographic = longitudeExtentsCartographicScratch;
westMostCartographic.longitude = -CesiumMath.PI;
westMostCartographic.latitude = 0.0;
westMostCartographic.height = 0.0;
var westMostCartesian = mapProjection.project(westMostCartographic, longitudeExtentsCartesianScratch);
encoded = EncodedCartesian3.encode(westMostCartesian.x, longitudeExtentsEncodeScratch);
projectionExtentDefines.westMostYhighDefine = 'WEST_MOST_X_HIGH ' + encoded.high.toFixed((encoded.high + '').length + 1);
projectionExtentDefines.westMostYlowDefine = 'WEST_MOST_X_LOW ' + encoded.low.toFixed((encoded.low + '').length + 1);
}

if (columbusView2D) {
allDefines.push(projectionExtentDefines.eastMostYhighDefine);
allDefines.push(projectionExtentDefines.eastMostYlowDefine);
allDefines.push(projectionExtentDefines.westMostYhighDefine);
allDefines.push(projectionExtentDefines.westMostYlowDefine);
}

if (defined(appearance) && appearance instanceof PerInstanceColorAppearance) {
allDefines.push('PER_INSTANCE_COLOR');
}
Expand Down
18 changes: 18 additions & 0 deletions Source/Shaders/ShadowVolumeAppearanceVS.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,24 @@ void main()
#ifdef COLUMBUS_VIEW_2D
vec4 planes2D_high = czm_batchTable_planes2D_HIGH(batchId);
vec4 planes2D_low = czm_batchTable_planes2D_LOW(batchId);

// If the primitive is split across the IDL (planes2D_high.x > planes2D_high.w):
// - If this vertex is on the east side of the IDL (position3DLow.y > 0.0, comparison with position3DHigh may produce artifacts)
// - existing "east" is on the wrong side of the world, far away (planes2D_high/low.w)
// - so set "east" as beyond the eastmost extent of the projection (idlSplitNewPlaneHiLow)
vec2 idlSplitNewPlaneHiLow = vec2(EAST_MOST_X_HIGH - (WEST_MOST_X_HIGH - planes2D_high.w), EAST_MOST_X_LOW - (WEST_MOST_X_LOW - planes2D_low.w));
bool idlSplit = planes2D_high.x > planes2D_high.w && position3DLow.y > 0.0;
planes2D_high.w = czm_branchFreeTernary(idlSplit, idlSplitNewPlaneHiLow.x, planes2D_high.w);
planes2D_low.w = czm_branchFreeTernary(idlSplit, idlSplitNewPlaneHiLow.y, planes2D_low.w);

// - else, if this vertex is on the west side of the IDL (position3DLow.y < 0.0)
// - existing "west" is on the wrong side of the world, far away (planes2D_high/low.x)
// - so set "west" as beyond the westmost extent of the projection (idlSplitNewPlaneHiLow)
idlSplit = planes2D_high.x > planes2D_high.w && position3DLow.y < 0.0;
idlSplitNewPlaneHiLow = vec2(WEST_MOST_X_HIGH - (EAST_MOST_X_HIGH - planes2D_high.x), WEST_MOST_X_LOW - (EAST_MOST_X_LOW - planes2D_low.x));
planes2D_high.x = czm_branchFreeTernary(idlSplit, idlSplitNewPlaneHiLow.x, planes2D_high.x);
planes2D_low.x = czm_branchFreeTernary(idlSplit, idlSplitNewPlaneHiLow.y, planes2D_low.x);

vec3 southWestCorner = (czm_modelViewRelativeToEye * czm_translateRelativeToEye(vec3(0.0, planes2D_high.xy), vec3(0.0, planes2D_low.xy))).xyz;
vec3 northWestCorner = (czm_modelViewRelativeToEye * czm_translateRelativeToEye(vec3(0.0, planes2D_high.x, planes2D_high.z), vec3(0.0, planes2D_low.x, planes2D_low.z))).xyz;
vec3 southEastCorner = (czm_modelViewRelativeToEye * czm_translateRelativeToEye(vec3(0.0, planes2D_high.w, planes2D_high.y), vec3(0.0, planes2D_low.w, planes2D_low.y))).xyz;
Expand Down
32 changes: 31 additions & 1 deletion Specs/Scene/GroundPrimitiveSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,7 @@ defineSuite([
geometryInstances : new GeometryInstance({
geometry : new RectangleGeometry({
ellipsoid : ellipsoid,
rectangle : rectangle
rectangle : Rectangle.fromDegrees(-180 + CesiumMath.EPSILON4, -90 + CesiumMath.EPSILON4, 180 - CesiumMath.EPSILON4, 90 - CesiumMath.EPSILON4)
}),
id : 'depth rectangle',
attributes : {
Expand Down Expand Up @@ -600,6 +600,36 @@ defineSuite([
verifyLargerScene(largeRectanglePrimitive, [255, 255, 255, 255], largeRectangle);
});

it('renders GeometryInstances with texture classifying terrain across the IDL', function() {
if (!GroundPrimitive.isSupported(scene) || !GroundPrimitive.supportsMaterials(scene)) {
return;
}

var whiteImageMaterial = Material.fromType(Material.DiffuseMapType);
whiteImageMaterial.uniforms.image = './Data/Images/White.png';

var largeRectangle = Rectangle.fromDegrees(179.0, 30.0, -179.0, 31.0);
var largeRectanglePrimitive = new GroundPrimitive({
geometryInstances : new GeometryInstance({
geometry : new RectangleGeometry({
ellipsoid : ellipsoid,
rectangle : largeRectangle
})
}),
id : 'largeRectangle',
appearance : new EllipsoidSurfaceAppearance({
aboveGround : false,
flat : true,
material : whiteImageMaterial
}),
asynchronous : false,
classificationType : ClassificationType.TERRAIN
});

scene.morphToColumbusView(0);
verifyLargerScene(largeRectanglePrimitive, [255, 255, 255, 255], largeRectangle);
});

it('renders with invert classification and an opaque color', function() {
if (!GroundPrimitive.isSupported(scene)) {
return;
Expand Down
Loading

0 comments on commit 685e3f3

Please sign in to comment.