From 2f6d88de60d049713e2eaf778a7633692f80357d Mon Sep 17 00:00:00 2001 From: hpinkos Date: Thu, 8 Dec 2016 12:13:25 -0500 Subject: [PATCH 01/14] add isBottom attribute --- Source/Core/CorridorGeometry.js | 22 ++++++- Source/Core/EllipseGeometry.js | 33 ++++++++++ Source/Core/GeometryPipeline.js | 1 + Source/Core/PolygonGeometry.js | 16 ++++- Source/Core/PolygonGeometryLibrary.js | 26 +++++++- Source/Core/RectangleGeometry.js | 34 ++++++++++- Source/Renderer/AutomaticUniforms.js | 88 +++++++++++++++------------ Source/Scene/GroundPrimitive.js | 8 ++- Source/Shaders/ShadowVolumeVS.glsl | 12 +++- 9 files changed, 190 insertions(+), 50 deletions(-) diff --git a/Source/Core/CorridorGeometry.js b/Source/Core/CorridorGeometry.js index 4fd13ea735a9..4252c69d082d 100644 --- a/Source/Core/CorridorGeometry.js +++ b/Source/Core/CorridorGeometry.js @@ -561,7 +561,7 @@ define([ function computePositionsExtruded(params, vertexFormat) { var topVertexFormat = new VertexFormat({ - position : vertexFormat.positon, + position : vertexFormat.position, normal : (vertexFormat.normal || vertexFormat.binormal), tangent : vertexFormat.tangent, binormal : (vertexFormat.normal || vertexFormat.binormal), @@ -590,6 +590,26 @@ define([ newPositions.set(wallPositions, length * 2); attributes.position.values = newPositions; + var sectionLength = length / 3; + var isBottom = new Uint8Array(sectionLength * 6); + if (typeof Uint8Array.prototype.fill === 'function') { + isBottom.fill(1, sectionLength, sectionLength * 2); + isBottom.fill(1, sectionLength * 4); + } else { //IE doesn't support fill + for (i = sectionLength; i < sectionLength * 2; i++) { + isBottom[i] = 1; + } + for (i = sectionLength * 4; i < sectionLength * 6; i++) { + isBottom[i] = 1; + } + } + + attributes.isBottom = new GeometryAttribute({ + componentDatatype : ComponentDatatype.UNSIGNED_BYTE, + componentsPerAttribute : 1, + values : isBottom + }); + length /= 3; var i; var iLength = indices.length; diff --git a/Source/Core/EllipseGeometry.js b/Source/Core/EllipseGeometry.js index 59193cf043d3..bab539441f9a 100644 --- a/Source/Core/EllipseGeometry.js +++ b/Source/Core/EllipseGeometry.js @@ -229,6 +229,23 @@ define([ values : binormals }); } + + if (extrude) { + var isBottom = new Uint8Array(size); + if (typeof Uint8Array.prototype.fill === 'function') { + isBottom.fill(1, size / 2); + } else { //IE doesn't support fill + for (i = size / 2; i < size; i++) { + isBottom[i] = 1; + } + } + + attributes.isBottom = new GeometryAttribute({ + componentDatatype : ComponentDatatype.UNSIGNED_BYTE, + componentsPerAttribute : 1, + values : isBottom + }); + } return attributes; } @@ -527,6 +544,22 @@ define([ values : binormals }); } + + var isBottom = new Uint8Array(size); + if (typeof Uint8Array.prototype.fill === 'function') { + isBottom.fill(1, size / 2); + } else { //IE doesn't support fill + for (i = size / 2; i < size; i++) { + isBottom[i] = 1; + } + } + + attributes.isBottom = new GeometryAttribute({ + componentDatatype : ComponentDatatype.UNSIGNED_BYTE, + componentsPerAttribute : 1, + values : isBottom + }); + return attributes; } diff --git a/Source/Core/GeometryPipeline.js b/Source/Core/GeometryPipeline.js index c27a9dda80cd..adf740039b00 100644 --- a/Source/Core/GeometryPipeline.js +++ b/Source/Core/GeometryPipeline.js @@ -281,6 +281,7 @@ define([ 'st', 'binormal', 'tangent', + 'isBottom', // From compressing texture coordinates and normals 'compressedAttributes' diff --git a/Source/Core/PolygonGeometry.js b/Source/Core/PolygonGeometry.js index f8276fa5880b..73d76d2fcfcb 100644 --- a/Source/Core/PolygonGeometry.js +++ b/Source/Core/PolygonGeometry.js @@ -363,15 +363,24 @@ define([ var numPositions; var newIndices; + var isBottom; if (closeTop && closeBottom) { var topBottomPositions = edgePoints.concat(edgePoints); + isBottom = new Uint8Array(topBottomPositions.length / 3); + if (typeof Uint8Array.prototype.fill === 'function') { + isBottom.fill(1, isBottom.length / 2); + } else { //IE doesn't support fill + for (i = isBottom.length / 2; i < isBottom.length; i++) { + isBottom[i] = 1; + } + } + numPositions = topBottomPositions.length / 3; newIndices = IndexDatatype.createTypedArray(numPositions, indices.length * 2); newIndices.set(indices); var ilength = indices.length; - var length = numPositions / 2; for (i = 0; i < ilength; i += 3) { @@ -390,6 +399,11 @@ define([ topGeo.attributes.normal.values = new Float32Array(topBottomPositions.length); topGeo.attributes.normal.values.set(normals); } + topGeo.attributes.isBottom = new GeometryAttribute({ + componentDatatype : ComponentDatatype.UNSIGNED_BYTE, + componentsPerAttribute : 1, + values : isBottom + }); topGeo.indices = newIndices; } else if (closeBottom) { numPositions = edgePoints.length / 3; diff --git a/Source/Core/PolygonGeometryLibrary.js b/Source/Core/PolygonGeometryLibrary.js index f36e24764715..603cb215c0f3 100644 --- a/Source/Core/PolygonGeometryLibrary.js +++ b/Source/Core/PolygonGeometryLibrary.js @@ -346,6 +346,7 @@ define([ PolygonGeometryLibrary.computeWallGeometry = function(positions, ellipsoid, granularity, perPositionHeight) { var edgePositions; var topEdgeLength; + var positionLength; var i; var p1; var p2; @@ -353,6 +354,7 @@ define([ var length = positions.length; var index = 0; + var isBottom; if (!perPositionHeight) { var minDistance = CesiumMath.chordLength(granularity, ellipsoid.maximumRadius); @@ -361,7 +363,8 @@ define([ numVertices += PolygonGeometryLibrary.subdivideLineCount(positions[i], positions[(i + 1) % length], minDistance); } - topEdgeLength = (numVertices + length) * 3; + positionLength = numVertices + length; + topEdgeLength = positionLength * 3; edgePositions = new Array(topEdgeLength * 2); for (i = 0; i < length; i++) { p1 = positions[i]; @@ -387,7 +390,8 @@ define([ ++index; } } else { - topEdgeLength = length * 3 * 2; + positionLength = length * 2; + topEdgeLength = positionLength * 3; edgePositions = new Array(topEdgeLength * 2); for (i = 0; i < length; i++) { p1 = positions[i]; @@ -407,6 +411,15 @@ define([ } } + isBottom = new Uint8Array(positionLength * 2); + if (typeof Uint8Array.prototype.fill === 'function') { + isBottom.fill(1, positionLength); + } else { //IE doesn't support fill + for (i = positionLength; i < positionLength * 2; i++) { + isBottom[i] = 1; + } + } + length = edgePositions.length; var indices = IndexDatatype.createTypedArray(length / 3, length - positions.length * 6); var edgeIndex = 0; @@ -432,7 +445,7 @@ define([ indices[edgeIndex++] = LR; } - return new Geometry({ + var geometry = new Geometry({ attributes : new GeometryAttributes({ position : new GeometryAttribute({ componentDatatype : ComponentDatatype.DOUBLE, @@ -443,6 +456,13 @@ define([ indices : indices, primitiveType : PrimitiveType.TRIANGLES }); + geometry.attributes.isBottom = new GeometryAttribute({ + componentDatatype : ComponentDatatype.UNSIGNED_BYTE, + componentsPerAttribute : 1, + values : isBottom + }); + + return geometry; }; return PolygonGeometryLibrary; diff --git a/Source/Core/RectangleGeometry.js b/Source/Core/RectangleGeometry.js index 420b95cceeb4..e85033a88fa1 100644 --- a/Source/Core/RectangleGeometry.js +++ b/Source/Core/RectangleGeometry.js @@ -356,6 +356,21 @@ define([ positions.set(bottomPositions, length); topBottomGeo.attributes.position.values = positions; + var isBottom = new Uint8Array(newLength / 3); + if (typeof Uint8Array.prototype.fill === 'function') { + isBottom.fill(1, length / 3); + } else { //IE doesn't support fill + for (i = length / 3; i < newLength / 3; i++) { + isBottom[i] = 1; + } + } + + topBottomGeo.attributes.isBottom = new GeometryAttribute({ + componentDatatype : ComponentDatatype.UNSIGNED_BYTE, + componentsPerAttribute : 1, + values : isBottom + }); + var normals = (vertexFormat.normal) ? new Float32Array(newLength) : undefined; var tangents = (vertexFormat.tangent) ? new Float32Array(newLength) : undefined; var binormals = (vertexFormat.binormal) ? new Float32Array(newLength) : undefined; @@ -408,10 +423,12 @@ define([ var wallCount = (perimeterPositions + 4) * 2; var wallPositions = new Float64Array(wallCount * 3); + var wallisBottom = new Uint8Array(wallCount); var wallTextures = (vertexFormat.st) ? new Float32Array(wallCount * 2) : undefined; var posIndex = 0; var stIndex = 0; + var isBottomIndex = 0; var area = width * height; for (i = 0; i < area; i+=width) { wallPositions = addWallPositions(wallPositions, posIndex, i*3, topPositions, bottomPositions); @@ -420,6 +437,8 @@ define([ wallTextures = addWallTextureCoordinates(wallTextures, stIndex, i*2, topSt); stIndex += 4; } + wallisBottom[isBottomIndex++] = 0; + wallisBottom[isBottomIndex++] = 1; } for (i = area-width; i < area; i++) { @@ -429,6 +448,8 @@ define([ wallTextures = addWallTextureCoordinates(wallTextures, stIndex, i*2, topSt); stIndex += 4; } + wallisBottom[isBottomIndex++] = 0; + wallisBottom[isBottomIndex++] = 1; } for (i = area-1; i > 0; i-=width) { @@ -438,6 +459,8 @@ define([ wallTextures = addWallTextureCoordinates(wallTextures, stIndex, i*2, topSt); stIndex += 4; } + wallisBottom[isBottomIndex++] = 0; + wallisBottom[isBottomIndex++] = 1; } for (i = width-1; i >= 0; i--) { @@ -447,6 +470,8 @@ define([ wallTextures = addWallTextureCoordinates(wallTextures, stIndex, i*2, topSt); stIndex += 4; } + wallisBottom[isBottomIndex++] = 0; + wallisBottom[isBottomIndex++] = 1; } var geo = calculateAttributesWall(wallPositions, vertexFormat, ellipsoid); @@ -458,6 +483,11 @@ define([ values : wallTextures }); } + geo.attributes.isBottom = new GeometryAttribute({ + componentDatatype: ComponentDatatype.UNSIGNED_BYTE, + componentsPerAttribute: 1, + values: wallisBottom + }); var wallIndices = IndexDatatype.createTypedArray(wallCount, perimeterPositions * 6); @@ -819,7 +849,7 @@ define([ } return new Geometry({ - attributes : new GeometryAttributes(geometry.attributes), + attributes : geometry.attributes, indices : geometry.indices, primitiveType : geometry.primitiveType, boundingSphere : boundingSphere @@ -847,7 +877,7 @@ define([ height : minHeight, closeTop : true, closeBottom : true, - vertexFormat : VertexFormat.POSITION_ONLY + vertexFormat : VertexFormat.POSITION_AND_NORMAL }); }; diff --git a/Source/Renderer/AutomaticUniforms.js b/Source/Renderer/AutomaticUniforms.js index 59ee77626ce3..e347e63ffaaf 100644 --- a/Source/Renderer/AutomaticUniforms.js +++ b/Source/Renderer/AutomaticUniforms.js @@ -75,7 +75,7 @@ define([ * // Scale the window coordinate components to [0, 1] by dividing * // by the viewport's width and height. * vec2 v = gl_FragCoord.xy / czm_viewport.zw; - * + * * @see Context#getViewport */ czm_viewport : new AutomaticUniform({ @@ -108,7 +108,7 @@ define([ * * // Example * gl_Position = czm_viewportOrthographic * vec4(windowPosition, 0.0, 1.0); - * + * * @see UniformState#viewportOrthographic * @see czm_viewport * @see czm_viewportTransformation @@ -150,7 +150,7 @@ define([ * vec4 q = czm_modelViewProjection * positionMC; // model to clip coordinates * q.xyz /= q.w; // clip to normalized device coordinates (ndc) * q.xyz = (czm_viewportTransformation * vec4(q.xyz, 1.0)).xyz; // ndc to window coordinates - * + * * @see UniformState#viewportTransformation * @see czm_viewport * @see czm_viewportOrthographic @@ -204,7 +204,7 @@ define([ * * // Example * vec4 worldPosition = czm_model * modelPosition; - * + * * @see UniformState#model * @see czm_inverseModel * @see czm_modelView @@ -232,7 +232,7 @@ define([ * * // Example * vec4 modelPosition = czm_inverseModel * worldPosition; - * + * * @see UniformState#inverseModel * @see czm_model * @see czm_inverseModelView @@ -259,7 +259,7 @@ define([ * * // Example * vec4 eyePosition = czm_view * worldPosition; - * + * * @see UniformState#view * @see czm_viewRotation * @see czm_modelView @@ -292,7 +292,7 @@ define([ * * // Example * vec4 eyePosition3D = czm_view3D * worldPosition3D; - * + * * @see UniformState#view3D * @see czm_view */ @@ -318,7 +318,7 @@ define([ * * // Example * vec3 eyeVector = czm_viewRotation * worldVector; - * + * * @see UniformState#viewRotation * @see czm_view * @see czm_inverseView @@ -349,7 +349,7 @@ define([ * * // Example * vec3 eyeVector = czm_viewRotation3D * worldVector; - * + * * @see UniformState#viewRotation3D * @see czm_viewRotation */ @@ -375,7 +375,7 @@ define([ * * // Example * vec4 worldPosition = czm_inverseView * eyePosition; - * + * * @see UniformState#inverseView * @see czm_view * @see czm_inverseNormal @@ -405,7 +405,7 @@ define([ * * // Example * vec4 worldPosition = czm_inverseView3D * eyePosition; - * + * * @see UniformState#inverseView3D * @see czm_inverseView */ @@ -431,7 +431,7 @@ define([ * * // Example * vec4 worldVector = czm_inverseViewRotation * eyeVector; - * + * * @see UniformState#inverseView * @see czm_view * @see czm_viewRotation @@ -462,7 +462,7 @@ define([ * * // Example * vec4 worldVector = czm_inverseViewRotation3D * eyeVector; - * + * * @see UniformState#inverseView3D * @see czm_inverseViewRotation */ @@ -489,7 +489,7 @@ define([ * * // Example * gl_Position = czm_projection * eyePosition; - * + * * @see UniformState#projection * @see czm_viewProjection * @see czm_modelViewProjection @@ -518,7 +518,7 @@ define([ * * // Example * vec4 eyePosition = czm_inverseProjection * clipPosition; - * + * * @see UniformState#inverseProjection * @see czm_projection */ @@ -558,7 +558,7 @@ define([ * * // Example * gl_Position = czm_infiniteProjection * eyePosition; - * + * * @see UniformState#infiniteProjection * @see czm_projection * @see czm_modelViewInfiniteProjection @@ -591,7 +591,7 @@ define([ * * // The above is equivalent to, but more efficient than: * vec4 eyePosition = czm_view * czm_model * modelPosition; - * + * * @see UniformState#modelView * @see czm_model * @see czm_view @@ -629,7 +629,7 @@ define([ * * // The above is equivalent to, but more efficient than: * vec4 eyePosition = czm_view3D * czm_model * modelPosition; - * + * * @see UniformState#modelView3D * @see czm_modelView */ @@ -689,7 +689,7 @@ define([ * * // Example * vec4 modelPosition = czm_inverseModelView * eyePosition; - * + * * @see UniformState#inverseModelView * @see czm_modelView */ @@ -718,7 +718,7 @@ define([ * * // Example * vec4 modelPosition = czm_inverseModelView3D * eyePosition; - * + * * @see UniformState#inverseModelView * @see czm_inverseModelView * @see czm_modelView3D @@ -749,7 +749,7 @@ define([ * * // The above is equivalent to, but more efficient than: * gl_Position = czm_projection * czm_view * czm_model * modelPosition; - * + * * @see UniformState#viewProjection * @see czm_view * @see czm_projection @@ -779,7 +779,7 @@ define([ * * // Example * vec4 worldPosition = czm_inverseViewProjection * clipPosition; - * + * * @see UniformState#inverseViewProjection * @see czm_viewProjection */ @@ -809,7 +809,7 @@ define([ * * // The above is equivalent to, but more efficient than: * gl_Position = czm_projection * czm_view * czm_model * modelPosition; - * + * * @see UniformState#modelViewProjection * @see czm_model * @see czm_view @@ -842,7 +842,7 @@ define([ * * // Example * vec4 modelPosition = czm_inverseModelViewProjection * clipPosition; - * + * * @see UniformState#modelViewProjection * @see czm_modelViewProjection */ @@ -909,7 +909,7 @@ define([ * * // The above is equivalent to, but more efficient than: * gl_Position = czm_infiniteProjection * czm_view * czm_model * modelPosition; - * + * * @see UniformState#modelViewInfiniteProjection * @see czm_model * @see czm_view @@ -941,7 +941,7 @@ define([ * * // Example * vec3 eyeNormal = czm_normal * normal; - * + * * @see UniformState#normal * @see czm_inverseNormal * @see czm_modelView @@ -975,7 +975,7 @@ define([ * * // Example * vec3 eyeNormal = czm_normal3D * normal; - * + * * @see UniformState#normal3D * @see czm_normal */ @@ -1002,7 +1002,7 @@ define([ * * // Example * vec3 normalMC = czm_inverseNormal * normalEC; - * + * * @see UniformState#inverseNormal * @see czm_normal * @see czm_modelView @@ -1035,7 +1035,7 @@ define([ * * // Example * vec3 normalMC = czm_inverseNormal3D * normalEC; - * + * * @see UniformState#inverseNormal3D * @see czm_inverseNormal */ @@ -1079,7 +1079,7 @@ define([ * * // Example * float frustumLength = czm_entireFrustum.y - czm_entireFrustum.x; - * + * * @see UniformState#entireFrustum * @see czm_currentFrustum */ @@ -1106,7 +1106,7 @@ define([ * * // Example * float frustumLength = czm_currentFrustum.y - czm_currentFrustum.x; - * + * * @see UniformState#currentFrustum * @see czm_entireFrustum */ @@ -1143,7 +1143,7 @@ define([ * @example * // GLSL declaration * uniform vec3 czm_sunPositionWC; - * + * * @see UniformState#sunPositionWC * @see czm_sunPositionColumbusView * @see czm_sunDirectionWC @@ -1166,7 +1166,7 @@ define([ * @example * // GLSL declaration * uniform vec3 czm_sunPositionColumbusView; - * + * * @see UniformState#sunPositionColumbusView * @see czm_sunPositionWC */ @@ -1192,7 +1192,7 @@ define([ * * // Example * float diffuse = max(dot(czm_sunDirectionEC, normalEC), 0.0); - * + * * @see UniformState#sunDirectionEC * @see czm_moonDirectionEC * @see czm_sunDirectionWC @@ -1216,7 +1216,7 @@ define([ * @example * // GLSL declaration * uniform vec3 czm_sunDirectionWC; - * + * * @see UniformState#sunDirectionWC * @see czm_sunPositionWC * @see czm_sunDirectionEC @@ -1243,7 +1243,7 @@ define([ * * // Example * float diffuse = max(dot(czm_moonDirectionEC, normalEC), 0.0); - * + * * @see UniformState#moonDirectionEC * @see czm_sunDirectionEC */ @@ -1267,7 +1267,7 @@ define([ * @example * // GLSL declaration * uniform vec3 czm_encodedCameraPositionMCHigh; - * + * * @see czm_encodedCameraPositionMCLow * @see czm_modelViewRelativeToEye * @see czm_modelViewProjectionRelativeToEye @@ -1292,7 +1292,7 @@ define([ * @example * // GLSL declaration * uniform vec3 czm_encodedCameraPositionMCLow; - * + * * @see czm_encodedCameraPositionMCHigh * @see czm_modelViewRelativeToEye * @see czm_modelViewProjectionRelativeToEye @@ -1381,7 +1381,7 @@ define([ * { * eyeHeightSq = czm_eyeHeight2D.y; * } - * + * * @see czm_sceneMode2D * @see czm_sceneModeColumbusView * @see czm_sceneMode3D @@ -1433,7 +1433,7 @@ define([ * * // Example * vec3 pseudoFixed = czm_temeToPseudoFixed * teme; - * + * * @see UniformState#temeToPseudoFixedMatrix * @see Transforms.computeTemeToPseudoFixedMatrix */ @@ -1476,6 +1476,14 @@ define([ getValue : function(uniformState) { return uniformState.fogDensity; } + }), + + czm_LODNegativeGeometricToleranceOverDistance : new AutomaticUniform({ + size: 1, + datatype: WebGLConstants.FLOAT, + getValue: function(uniformState) { + return -10000; //TODO + } }) }; diff --git a/Source/Scene/GroundPrimitive.js b/Source/Scene/GroundPrimitive.js index c35c4b1828c5..0bbd7b85e3e5 100644 --- a/Source/Scene/GroundPrimitive.js +++ b/Source/Scene/GroundPrimitive.js @@ -215,7 +215,11 @@ define([ this._rsColorPass = undefined; this._rsPickPass = undefined; - this._uniformMap = {}; + this._uniformMap = { + u_globeMinimumAltitude: function() { + return -11000; //TODO verify + } + }; this._boundingVolumes = []; this._boundingVolumes2D = []; @@ -252,7 +256,7 @@ define([ releaseGeometryInstances : defaultValue(options.releaseGeometryInstances, true), allowPicking : defaultValue(options.allowPicking, true), asynchronous : defaultValue(options.asynchronous, true), - compressVertices : defaultValue(options.compressVertices, true), + compressVertices : false,//defaultValue(options.compressVertices, true), _readOnlyInstanceAttributes : readOnlyAttributes, _createRenderStatesFunction : undefined, _createShaderProgramFunction : undefined, diff --git a/Source/Shaders/ShadowVolumeVS.glsl b/Source/Shaders/ShadowVolumeVS.glsl index a97b96c1752b..0a2c4b59d2b6 100644 --- a/Source/Shaders/ShadowVolumeVS.glsl +++ b/Source/Shaders/ShadowVolumeVS.glsl @@ -1,5 +1,9 @@ +uniform float u_globeMinimumAltitude; + attribute vec3 position3DHigh; attribute vec3 position3DLow; +attribute vec3 normal; +attribute float isBottom; attribute vec4 color; attribute float batchId; @@ -17,7 +21,13 @@ vec4 depthClampFarPlane(vec4 vertexInClipCoordinates) void main() { v_color = color; - + vec4 position = czm_computePosition(); + float delta = min(u_globeMinimumAltitude, czm_LODNegativeGeometricToleranceOverDistance * length(position.xyz)); + + if (isBottom == 1.0) + { + position = position + vec4(normal.xyz * 40.0, 0); + } gl_Position = depthClampFarPlane(czm_modelViewProjectionRelativeToEye * position); } From 73dfdd412bf8b8942de2dc1e0e4ad7cd675cad06 Mon Sep 17 00:00:00 2001 From: hpinkos Date: Thu, 8 Dec 2016 16:04:01 -0500 Subject: [PATCH 02/14] pixelSizePerMeter, fix rectangle normals --- Source/Core/GeometryPipeline.js | 3 +- Source/Core/RectangleGeometry.js | 132 +++++++++++++++++++-------- Source/Renderer/AutomaticUniforms.js | 4 +- Source/Renderer/UniformState.js | 22 +++++ Source/Scene/FrameState.js | 2 + Source/Scene/GroundPrimitive.js | 2 +- Source/Scene/Scene.js | 5 + Source/Shaders/ShadowVolumeVS.glsl | 11 +-- 8 files changed, 130 insertions(+), 51 deletions(-) diff --git a/Source/Core/GeometryPipeline.js b/Source/Core/GeometryPipeline.js index adf740039b00..e681e1543112 100644 --- a/Source/Core/GeometryPipeline.js +++ b/Source/Core/GeometryPipeline.js @@ -281,7 +281,8 @@ define([ 'st', 'binormal', 'tangent', - 'isBottom', + + 'extrudeDirection', //TODO: do I need this? // From compressing texture coordinates and normals 'compressedAttributes' diff --git a/Source/Core/RectangleGeometry.js b/Source/Core/RectangleGeometry.js index e85033a88fa1..57f07a67f45b 100644 --- a/Source/Core/RectangleGeometry.js +++ b/Source/Core/RectangleGeometry.js @@ -330,7 +330,9 @@ define([ return wallTextures; } + var scratchVertexFormat = new VertexFormat(); function constructExtrudedRectangle(options) { + var shadowVolume = options.shadowVolume; var vertexFormat = options.vertexFormat; var surfaceHeight = options.surfaceHeight; var extrudedHeight = options.extrudedHeight; @@ -342,10 +344,15 @@ define([ var ellipsoid = options.ellipsoid; var i; + if (shadowVolume) { + options.vertexFormat = VertexFormat.clone(vertexFormat, scratchVertexFormat); + options.vertexFormat.normal = true; + } var topBottomGeo = constructRectangle(options); if (CesiumMath.equalsEpsilon(minHeight, maxHeight, CesiumMath.EPSILON10)) { return topBottomGeo; } + var topPositions = PolygonPipeline.scaleToGeodeticHeight(topBottomGeo.attributes.position.values, maxHeight, ellipsoid, false); topPositions = new Float64Array(topPositions); var length = topPositions.length; @@ -356,28 +363,14 @@ define([ positions.set(bottomPositions, length); topBottomGeo.attributes.position.values = positions; - var isBottom = new Uint8Array(newLength / 3); - if (typeof Uint8Array.prototype.fill === 'function') { - isBottom.fill(1, length / 3); - } else { //IE doesn't support fill - for (i = length / 3; i < newLength / 3; i++) { - isBottom[i] = 1; - } - } - - topBottomGeo.attributes.isBottom = new GeometryAttribute({ - componentDatatype : ComponentDatatype.UNSIGNED_BYTE, - componentsPerAttribute : 1, - values : isBottom - }); - var normals = (vertexFormat.normal) ? new Float32Array(newLength) : undefined; var tangents = (vertexFormat.tangent) ? new Float32Array(newLength) : undefined; var binormals = (vertexFormat.binormal) ? new Float32Array(newLength) : undefined; var textures = (vertexFormat.st) ? new Float32Array(newLength/3*2) : undefined; var topSt; + var topNormals; if (vertexFormat.normal) { - var topNormals = topBottomGeo.attributes.normal.values; + topNormals = topBottomGeo.attributes.normal.values; normals.set(topNormals); for (i = 0; i < length; i ++) { topNormals[i] = -topNormals[i]; @@ -385,6 +378,21 @@ define([ normals.set(topNormals, length); topBottomGeo.attributes.normal.values = normals; } + if (shadowVolume) { + topNormals = topBottomGeo.attributes.normal.values; + topBottomGeo.attributes.normal = undefined; + var extrudeNormals = new Float32Array(newLength); + for (i = 0; i < length; i ++) { + topNormals[i] = -topNormals[i]; + } + extrudeNormals.set(topNormals, length); //only get normals for bottom layer that's going to be pushed down + topBottomGeo.attributes.extrudeDirection = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : extrudeNormals + }); + } + if (vertexFormat.tangent) { var topTangents = topBottomGeo.attributes.tangent.values; tangents.set(topTangents); @@ -423,55 +431,88 @@ define([ var wallCount = (perimeterPositions + 4) * 2; var wallPositions = new Float64Array(wallCount * 3); - var wallisBottom = new Uint8Array(wallCount); + var wallExtrudeNormals = shadowVolume ? new Float32Array(wallCount * 3) : undefined; var wallTextures = (vertexFormat.st) ? new Float32Array(wallCount * 2) : undefined; var posIndex = 0; var stIndex = 0; - var isBottomIndex = 0; + var extrudeNormalIndex = 0; var area = width * height; + var threeI; for (i = 0; i < area; i+=width) { - wallPositions = addWallPositions(wallPositions, posIndex, i*3, topPositions, bottomPositions); + threeI = i * 3; + wallPositions = addWallPositions(wallPositions, posIndex, threeI, topPositions, bottomPositions); posIndex += 6; if (vertexFormat.st) { wallTextures = addWallTextureCoordinates(wallTextures, stIndex, i*2, topSt); stIndex += 4; } - wallisBottom[isBottomIndex++] = 0; - wallisBottom[isBottomIndex++] = 1; + if (shadowVolume) { + wallExtrudeNormals[extrudeNormalIndex++] = 0; + wallExtrudeNormals[extrudeNormalIndex++] = 0; + wallExtrudeNormals[extrudeNormalIndex++] = 0; + + wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI]; + wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 1]; + wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 2]; + } } for (i = area-width; i < area; i++) { - wallPositions = addWallPositions(wallPositions, posIndex, i*3, topPositions, bottomPositions); + threeI = i * 3; + wallPositions = addWallPositions(wallPositions, posIndex, threeI, topPositions, bottomPositions); posIndex += 6; if (vertexFormat.st) { wallTextures = addWallTextureCoordinates(wallTextures, stIndex, i*2, topSt); stIndex += 4; } - wallisBottom[isBottomIndex++] = 0; - wallisBottom[isBottomIndex++] = 1; + if (shadowVolume) { + wallExtrudeNormals[extrudeNormalIndex++] = 0; + wallExtrudeNormals[extrudeNormalIndex++] = 0; + wallExtrudeNormals[extrudeNormalIndex++] = 0; + + wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI]; + wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 1]; + wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 2]; + } } for (i = area-1; i > 0; i-=width) { - wallPositions = addWallPositions(wallPositions, posIndex, i*3, topPositions, bottomPositions); + threeI = i * 3; + wallPositions = addWallPositions(wallPositions, posIndex, threeI, topPositions, bottomPositions); posIndex += 6; if (vertexFormat.st) { wallTextures = addWallTextureCoordinates(wallTextures, stIndex, i*2, topSt); stIndex += 4; } - wallisBottom[isBottomIndex++] = 0; - wallisBottom[isBottomIndex++] = 1; + if (shadowVolume) { + wallExtrudeNormals[extrudeNormalIndex++] = 0; + wallExtrudeNormals[extrudeNormalIndex++] = 0; + wallExtrudeNormals[extrudeNormalIndex++] = 0; + + wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI]; + wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 1]; + wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 2]; + } } for (i = width-1; i >= 0; i--) { - wallPositions = addWallPositions(wallPositions, posIndex, i*3, topPositions, bottomPositions); + threeI = i * 3; + wallPositions = addWallPositions(wallPositions, posIndex, threeI, topPositions, bottomPositions); posIndex += 6; if (vertexFormat.st) { wallTextures = addWallTextureCoordinates(wallTextures, stIndex, i*2, topSt); stIndex += 4; } - wallisBottom[isBottomIndex++] = 0; - wallisBottom[isBottomIndex++] = 1; + if (shadowVolume) { + wallExtrudeNormals[extrudeNormalIndex++] = 0; + wallExtrudeNormals[extrudeNormalIndex++] = 0; + wallExtrudeNormals[extrudeNormalIndex++] = 0; + + wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI]; + wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 1]; + wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 2]; + } } var geo = calculateAttributesWall(wallPositions, vertexFormat, ellipsoid); @@ -483,11 +524,13 @@ define([ values : wallTextures }); } - geo.attributes.isBottom = new GeometryAttribute({ - componentDatatype: ComponentDatatype.UNSIGNED_BYTE, - componentsPerAttribute: 1, - values: wallisBottom - }); + if (shadowVolume) { + geo.attributes.extrudeDirection = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : wallExtrudeNormals + }); + } var wallIndices = IndexDatatype.createTypedArray(wallCount, perimeterPositions * 6); @@ -622,6 +665,7 @@ define([ var extrude = defined(extrudedHeight); var closeTop = defaultValue(options.closeTop, true); var closeBottom = defaultValue(options.closeBottom, true); + var shadowVolume = defaultValue(options.shadowVolume, false); //>>includeStart('debug', pragmas.debug); if (!defined(rectangle)) { @@ -646,13 +690,14 @@ define([ this._closeBottom = closeBottom; this._workerName = 'createRectangleGeometry'; this._rotatedRectangle = computeRectangle(this._rectangle, this._ellipsoid, rotation); + this._shadowVolume = shadowVolume; } /** * The number of elements used to pack the object into an array. * @type {Number} */ - RectangleGeometry.packedLength = Rectangle.packedLength + Ellipsoid.packedLength + VertexFormat.packedLength + Rectangle.packedLength + 8; + RectangleGeometry.packedLength = Rectangle.packedLength + Ellipsoid.packedLength + VertexFormat.packedLength + Rectangle.packedLength + 9; /** * Stores the provided instance into the provided array. @@ -695,7 +740,8 @@ define([ array[startingIndex++] = value._extrudedHeight; array[startingIndex++] = value._extrude ? 1.0 : 0.0; array[startingIndex++] = value._closeTop ? 1.0 : 0.0; - array[startingIndex] = value._closeBottom ? 1.0 : 0.0; + array[startingIndex++] = value._closeBottom ? 1.0 : 0.0; + array[startingIndex] = value._shadowVolume? 1.0 : 0.0; return array; }; @@ -714,7 +760,8 @@ define([ stRotation : undefined, extrudedHeight : undefined, closeTop : undefined, - closeBottom : undefined + closeBottom : undefined, + shadowVolume: undefined }; /** @@ -753,7 +800,8 @@ define([ var extrudedHeight = array[startingIndex++]; var extrude = array[startingIndex++] === 1.0; var closeTop = array[startingIndex++] === 1.0; - var closeBottom = array[startingIndex] === 1.0; + var closeBottom = array[startingIndex++] === 1.0; + var shadowVolume = array[startingIndex] === 1.0; if (!defined(result)) { scratchOptions.granularity = granularity; @@ -763,6 +811,7 @@ define([ scratchOptions.extrudedHeight = extrude ? extrudedHeight : undefined; scratchOptions.closeTop = closeTop; scratchOptions.closeBottom = closeBottom; + scratchOptions.shadowVolume = shadowVolume; return new RectangleGeometry(scratchOptions); } @@ -778,6 +827,7 @@ define([ result._closeTop = closeTop; result._closeBottom = closeBottom; result._rotatedRectangle = rotatedRectangle; + result._shadowVolume = shadowVolume; return result; }; @@ -829,6 +879,7 @@ define([ options.stRotation = stRotation; options.tangentRotationMatrix = tangentRotationMatrix; options.size = options.width * options.height; + options.shadowVolume = rectangleGeometry._shadowVolume; var geometry; var boundingSphere; @@ -877,7 +928,8 @@ define([ height : minHeight, closeTop : true, closeBottom : true, - vertexFormat : VertexFormat.POSITION_AND_NORMAL + vertexFormat : VertexFormat.POSITION_ONLY, + shadowVolume: true }); }; diff --git a/Source/Renderer/AutomaticUniforms.js b/Source/Renderer/AutomaticUniforms.js index e347e63ffaaf..d8144388cf34 100644 --- a/Source/Renderer/AutomaticUniforms.js +++ b/Source/Renderer/AutomaticUniforms.js @@ -1478,11 +1478,11 @@ define([ } }), - czm_LODNegativeGeometricToleranceOverDistance : new AutomaticUniform({ + czm_geometricToleranceOverDistance : new AutomaticUniform({ size: 1, datatype: WebGLConstants.FLOAT, getValue: function(uniformState) { - return -10000; //TODO + return uniformState.pixelSizePerMeter * uniformState.maximumScreenSpaceError; } }) }; diff --git a/Source/Renderer/UniformState.js b/Source/Renderer/UniformState.js index 49ddc5cd50dd..574a213744c5 100644 --- a/Source/Renderer/UniformState.js +++ b/Source/Renderer/UniformState.js @@ -149,6 +149,8 @@ define([ this._resolutionScale = 1.0; this._fogDensity = undefined; + + this._pixelSizePerMeter = undefined; } defineProperties(UniformState.prototype, { @@ -767,6 +769,18 @@ define([ } }, + maximumScreenSpaceError: { + get: function() { + return this._frameState.maximumScreenSpaceError; + } + }, + + pixelSizePerMeter: { + get: function() { + return this._pixelSizePerMeter; + } + }, + /** * @memberof UniformState.prototype * @type {Pass} @@ -935,6 +949,14 @@ define([ this._frameState = frameState; this._temeToPseudoFixed = Transforms.computeTemeToPseudoFixedMatrix(frameState.time, this._temeToPseudoFixed); + + var fov = camera.frustum.fov; + var viewport = this._viewport; + if (viewport.width > viewport.height * camera.frustum.aspectRatio) { + this._pixelSizePerMeter = Math.tan(0.5 * fov) * 2.0 / viewport.width; + } else { + this._pixelSizePerMeter = Math.tan(0.5 * fov) * 2.0 / viewport.height; + } }; function cleanViewport(uniformState) { diff --git a/Source/Scene/FrameState.js b/Source/Scene/FrameState.js index f64149f62758..29c163b357e2 100644 --- a/Source/Scene/FrameState.js +++ b/Source/Scene/FrameState.js @@ -95,6 +95,8 @@ define([ */ this.occluder = undefined; + this.maximumScreenSpaceError = undefined; + this.passes = { /** * true if the primitive should update for a render pass, false otherwise. diff --git a/Source/Scene/GroundPrimitive.js b/Source/Scene/GroundPrimitive.js index 0bbd7b85e3e5..278e5a2f1885 100644 --- a/Source/Scene/GroundPrimitive.js +++ b/Source/Scene/GroundPrimitive.js @@ -217,7 +217,7 @@ define([ this._uniformMap = { u_globeMinimumAltitude: function() { - return -11000; //TODO verify + return 1100.0; //TODO verify } }; diff --git a/Source/Scene/Scene.js b/Source/Scene/Scene.js index 439e70b1baef..07913b581f05 100644 --- a/Source/Scene/Scene.js +++ b/Source/Scene/Scene.js @@ -1173,6 +1173,11 @@ define([ frameState.cullingVolume = camera.frustum.computeCullingVolume(camera.positionWC, camera.directionWC, camera.upWC); frameState.occluder = getOccluder(scene); frameState.terrainExaggeration = scene._terrainExaggeration; + if (defined(scene.globe)) { + frameState.maximumScreenSpaceError = scene.globe.maximumScreenSpaceError; + } else { + frameState.maximumScreenSpaceError = 2; + } clearPasses(frameState.passes); } diff --git a/Source/Shaders/ShadowVolumeVS.glsl b/Source/Shaders/ShadowVolumeVS.glsl index 0a2c4b59d2b6..14f072145918 100644 --- a/Source/Shaders/ShadowVolumeVS.glsl +++ b/Source/Shaders/ShadowVolumeVS.glsl @@ -2,8 +2,7 @@ uniform float u_globeMinimumAltitude; attribute vec3 position3DHigh; attribute vec3 position3DLow; -attribute vec3 normal; -attribute float isBottom; +attribute vec3 extrudeDirection; attribute vec4 color; attribute float batchId; @@ -23,11 +22,9 @@ void main() v_color = color; vec4 position = czm_computePosition(); - float delta = min(u_globeMinimumAltitude, czm_LODNegativeGeometricToleranceOverDistance * length(position.xyz)); + float delta = min(u_globeMinimumAltitude, czm_geometricToleranceOverDistance * length(position.xyz)); - if (isBottom == 1.0) - { - position = position + vec4(normal.xyz * 40.0, 0); - } + //extrudeDirection is zero for the top layer + position = position + vec4(extrudeDirection.xyz * delta, 0); gl_Position = depthClampFarPlane(czm_modelViewProjectionRelativeToEye * position); } From 77fd93ccc23907350b008e15e66a93aa631d6cd4 Mon Sep 17 00:00:00 2001 From: hpinkos Date: Mon, 12 Dec 2016 16:46:09 -0500 Subject: [PATCH 03/14] update other ground geometry for extrude normals --- Source/Core/CorridorGeometry.js | 74 ++++++++------ Source/Core/EllipseGeometry.js | 134 +++++++++++++------------- Source/Core/PolygonGeometry.js | 45 +++++---- Source/Core/PolygonGeometryLibrary.js | 19 +--- Source/Core/RectangleGeometry.js | 41 +++----- 5 files changed, 155 insertions(+), 158 deletions(-) diff --git a/Source/Core/CorridorGeometry.js b/Source/Core/CorridorGeometry.js index 4252c69d082d..7ab047cfa002 100644 --- a/Source/Core/CorridorGeometry.js +++ b/Source/Core/CorridorGeometry.js @@ -562,7 +562,7 @@ define([ function computePositionsExtruded(params, vertexFormat) { var topVertexFormat = new VertexFormat({ position : vertexFormat.position, - normal : (vertexFormat.normal || vertexFormat.binormal), + normal : (vertexFormat.normal || vertexFormat.binormal || params.shadowVolume), tangent : vertexFormat.tangent, binormal : (vertexFormat.normal || vertexFormat.binormal), st : vertexFormat.st @@ -590,48 +590,50 @@ define([ newPositions.set(wallPositions, length * 2); attributes.position.values = newPositions; - var sectionLength = length / 3; - var isBottom = new Uint8Array(sectionLength * 6); - if (typeof Uint8Array.prototype.fill === 'function') { - isBottom.fill(1, sectionLength, sectionLength * 2); - isBottom.fill(1, sectionLength * 4); - } else { //IE doesn't support fill - for (i = sectionLength; i < sectionLength * 2; i++) { - isBottom[i] = 1; + attributes = extrudedAttributes(attributes, vertexFormat); + var size = length / 3; + if (params.shadowVolume) { + var topNormals = attributes.normal.values; + length = topNormals.length; + + var extrudeNormals = new Float32Array(length * 6); + for (i = 0; i < length; i ++) { + topNormals[i] = -topNormals[i]; } - for (i = sectionLength * 4; i < sectionLength * 6; i++) { - isBottom[i] = 1; + //only get normals for bottom layer that's going to be pushed down + extrudeNormals.set(topNormals, length); //bottom face + extrudeNormals.set(topNormals, length * 4); //bottom wall positions + extrudeNormals.set(topNormals, length * 5); //duplicate bottom wall positions + attributes.extrudeDirection = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : extrudeNormals + }); + if (!vertexFormat.normal) { + attributes.normal = undefined; } } - attributes.isBottom = new GeometryAttribute({ - componentDatatype : ComponentDatatype.UNSIGNED_BYTE, - componentsPerAttribute : 1, - values : isBottom - }); - - length /= 3; var i; var iLength = indices.length; - var twoLength = length + length; - var newIndices = IndexDatatype.createTypedArray(newPositions.length / 3, iLength * 2 + twoLength * 3); + var twoSize = size + size; + var newIndices = IndexDatatype.createTypedArray(newPositions.length / 3, iLength * 2 + twoSize * 3); newIndices.set(indices); var index = iLength; for (i = 0; i < iLength; i += 3) { // bottom indices var v0 = indices[i]; var v1 = indices[i + 1]; var v2 = indices[i + 2]; - newIndices[index++] = v2 + length; - newIndices[index++] = v1 + length; - newIndices[index++] = v0 + length; + newIndices[index++] = v2 + size; + newIndices[index++] = v1 + size; + newIndices[index++] = v0 + size; } - attributes = extrudedAttributes(attributes, vertexFormat); var UL, LL, UR, LR; - for (i = 0; i < twoLength; i += 2) { //wall indices - UL = i + twoLength; - LL = UL + twoLength; + for (i = 0; i < twoSize; i += 2) { //wall indices + UL = i + twoSize; + LL = UL + twoSize; UR = UL + 1; LR = LL + 1; newIndices[index++] = UL; @@ -813,6 +815,7 @@ define([ this._extrudedHeight = defaultValue(options.extrudedHeight, this._height); this._cornerType = defaultValue(options.cornerType, CornerType.ROUNDED); this._granularity = defaultValue(options.granularity, CesiumMath.RADIANS_PER_DEGREE); + this._shadowVolume = defaultValue(options.shadowVolume, false); this._workerName = 'createCorridorGeometry'; this._rectangle = computeRectangle(positions, this._ellipsoid, width, this._cornerType); @@ -820,7 +823,7 @@ define([ * The number of elements used to pack the object into an array. * @type {Number} */ - this.packedLength = 1 + positions.length * Cartesian3.packedLength + Ellipsoid.packedLength + VertexFormat.packedLength + Rectangle.packedLength + 5; + this.packedLength = 1 + positions.length * Cartesian3.packedLength + Ellipsoid.packedLength + VertexFormat.packedLength + Rectangle.packedLength + 6; } /** @@ -865,7 +868,8 @@ define([ array[startingIndex++] = value._height; array[startingIndex++] = value._extrudedHeight; array[startingIndex++] = value._cornerType; - array[startingIndex] = value._granularity; + array[startingIndex++] = value._granularity; + array[startingIndex] = value._shadowVolume ? 1.0 : 0.0; return array; }; @@ -881,7 +885,8 @@ define([ height : undefined, extrudedHeight : undefined, cornerType : undefined, - granularity : undefined + granularity : undefined, + shadowVolume: undefined }; /** @@ -921,7 +926,8 @@ define([ var height = array[startingIndex++]; var extrudedHeight = array[startingIndex++]; var cornerType = array[startingIndex++]; - var granularity = array[startingIndex]; + var granularity = array[startingIndex++]; + var shadowVolume = array[startingIndex] === 1.0; if (!defined(result)) { scratchOptions.positions = positions; @@ -930,6 +936,7 @@ define([ scratchOptions.extrudedHeight = extrudedHeight; scratchOptions.cornerType = cornerType; scratchOptions.granularity = granularity; + scratchOptions.shadowVolume = shadowVolume; return new CorridorGeometry(scratchOptions); } @@ -942,6 +949,7 @@ define([ result._cornerType = cornerType; result._granularity = granularity; result._rectangle = Rectangle.clone(rectangle); + result._shadowVolume = shadowVolume; return result; }; @@ -982,6 +990,7 @@ define([ height = h; params.height = height; params.extrudedHeight = extrudedHeight; + params.shadowVolume = corridorGeometry._shadowVolume; attr = computePositionsExtruded(params, vertexFormat); } else { var computedPositions = CorridorGeometryLibrary.computePositions(params); @@ -1020,7 +1029,8 @@ define([ granularity : granularity, extrudedHeight : minHeight, height : maxHeight, - vertexFormat : VertexFormat.POSITION_ONLY + vertexFormat : VertexFormat.POSITION_ONLY, + shadowVolume: true }); }; diff --git a/Source/Core/EllipseGeometry.js b/Source/Core/EllipseGeometry.js index bab539441f9a..3020da7a2cc0 100644 --- a/Source/Core/EllipseGeometry.js +++ b/Source/Core/EllipseGeometry.js @@ -81,12 +81,15 @@ define([ var ellipsoid = options.ellipsoid; var stRotation = options.stRotation; var size = (extrude) ? positions.length / 3 * 2 : positions.length / 3; + var shadowVolume = options.shadowVolume; var textureCoordinates = (vertexFormat.st) ? new Float32Array(size * 2) : undefined; var normals = (vertexFormat.normal) ? new Float32Array(size * 3) : undefined; var tangents = (vertexFormat.tangent) ? new Float32Array(size * 3) : undefined; var binormals = (vertexFormat.binormal) ? new Float32Array(size * 3) : undefined; + var extrudeNormals = (shadowVolume) ? new Float32Array(size * 3) : undefined; + var textureCoordIndex = 0; // Raise positions to a height above the ellipsoid and compute the @@ -136,44 +139,52 @@ define([ textureCoordinates[textureCoordIndex++] = texCoordScratch.y; } - normal = ellipsoid.geodeticSurfaceNormal(position, normal); + if (vertexFormat.normal || vertexFormat.tangent || vertexFormat.binormal || shadowVolume) { + normal = ellipsoid.geodeticSurfaceNormal(position, normal); - if (vertexFormat.normal || vertexFormat.tangent || vertexFormat.binormal) { - if (vertexFormat.tangent || vertexFormat.binormal) { - tangent = Cartesian3.normalize(Cartesian3.cross(Cartesian3.UNIT_Z, normal, tangent), tangent); - Matrix3.multiplyByVector(textureMatrix, tangent, tangent); + if (shadowVolume) { + extrudeNormals[i + bottomOffset] = -normal.x; + extrudeNormals[i1 + bottomOffset] = -normal.y; + extrudeNormals[i2 + bottomOffset] = -normal.z; } - if (vertexFormat.normal) { - normals[i] = normal.x; - normals[i1] = normal.y; - normals[i2] = normal.z; - if (extrude) { - normals[i + bottomOffset] = -normal.x; - normals[i1 + bottomOffset] = -normal.y; - normals[i2 + bottomOffset] = -normal.z; + + if (vertexFormat.normal || vertexFormat.tangent || vertexFormat.binormal) { + if (vertexFormat.tangent || vertexFormat.binormal) { + tangent = Cartesian3.normalize(Cartesian3.cross(Cartesian3.UNIT_Z, normal, tangent), tangent); + Matrix3.multiplyByVector(textureMatrix, tangent, tangent); + } + if (vertexFormat.normal) { + normals[i] = normal.x; + normals[i1] = normal.y; + normals[i2] = normal.z; + if (extrude) { + normals[i + bottomOffset] = -normal.x; + normals[i1 + bottomOffset] = -normal.y; + normals[i2 + bottomOffset] = -normal.z; + } } - } - if (vertexFormat.tangent) { - tangents[i] = tangent.x; - tangents[i1] = tangent.y; - tangents[i2] = tangent.z; - if (extrude) { - tangents[i + bottomOffset] = -tangent.x; - tangents[i1 + bottomOffset] = -tangent.y; - tangents[i2 + bottomOffset] = -tangent.z; + if (vertexFormat.tangent) { + tangents[i] = tangent.x; + tangents[i1] = tangent.y; + tangents[i2] = tangent.z; + if (extrude) { + tangents[i + bottomOffset] = -tangent.x; + tangents[i1 + bottomOffset] = -tangent.y; + tangents[i2 + bottomOffset] = -tangent.z; + } } - } - if (vertexFormat.binormal) { - binormal = Cartesian3.normalize(Cartesian3.cross(normal, tangent, binormal), binormal); - binormals[i] = binormal.x; - binormals[i1] = binormal.y; - binormals[i2] = binormal.z; - if (extrude) { - binormals[i + bottomOffset] = binormal.x; - binormals[i1 + bottomOffset] = binormal.y; - binormals[i2 + bottomOffset] = binormal.z; + if (vertexFormat.binormal) { + binormal = Cartesian3.normalize(Cartesian3.cross(normal, tangent, binormal), binormal); + binormals[i] = binormal.x; + binormals[i1] = binormal.y; + binormals[i2] = binormal.z; + if (extrude) { + binormals[i + bottomOffset] = binormal.x; + binormals[i1 + bottomOffset] = binormal.y; + binormals[i2 + bottomOffset] = binormal.z; + } } } } @@ -230,20 +241,11 @@ define([ }); } - if (extrude) { - var isBottom = new Uint8Array(size); - if (typeof Uint8Array.prototype.fill === 'function') { - isBottom.fill(1, size / 2); - } else { //IE doesn't support fill - for (i = size / 2; i < size; i++) { - isBottom[i] = 1; - } - } - - attributes.isBottom = new GeometryAttribute({ - componentDatatype : ComponentDatatype.UNSIGNED_BYTE, - componentsPerAttribute : 1, - values : isBottom + if (shadowVolume) { + attributes.extrudeDirection = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : extrudeNormals }); } return attributes; @@ -545,21 +547,6 @@ define([ }); } - var isBottom = new Uint8Array(size); - if (typeof Uint8Array.prototype.fill === 'function') { - isBottom.fill(1, size / 2); - } else { //IE doesn't support fill - for (i = size / 2; i < size; i++) { - isBottom[i] = 1; - } - } - - attributes.isBottom = new GeometryAttribute({ - componentDatatype : ComponentDatatype.UNSIGNED_BYTE, - componentsPerAttribute : 1, - values : isBottom - }); - return attributes; } @@ -623,6 +610,13 @@ define([ }); var wallAttributes = computeWallAttributes(outerPositions, options); + if (options.shadowVolume) { + wallAttributes.extrudeDirection = new GeometryAttribute({ + componentDatatype: ComponentDatatype.FLOAT, + componentsPerAttribute: 3, + values: topBottomAttributes.extrudeDirection.slice() + }); + } indices = computeWallIndices(outerPositions); var wallIndices = IndexDatatype.createTypedArray(outerPositions.length * 2 / 3, indices); @@ -757,6 +751,7 @@ define([ this._vertexFormat = VertexFormat.clone(vertexFormat); this._extrudedHeight = defaultValue(extrudedHeight, height); this._extrude = extrude; + this._shadowVolume = defaultValue(options.shadowVolume, false); this._workerName = 'createEllipseGeometry'; this._rectangle = computeRectangle(this._center, this._ellipsoid, semiMajorAxis, semiMinorAxis, this._rotation); @@ -766,7 +761,7 @@ define([ * The number of elements used to pack the object into an array. * @type {Number} */ - EllipseGeometry.packedLength = Cartesian3.packedLength + Ellipsoid.packedLength + VertexFormat.packedLength + Rectangle.packedLength + 8; + EllipseGeometry.packedLength = Cartesian3.packedLength + Ellipsoid.packedLength + VertexFormat.packedLength + Rectangle.packedLength + 9; /** * Stores the provided instance into the provided array. @@ -808,7 +803,8 @@ define([ array[startingIndex++] = value._height; array[startingIndex++] = value._granularity; array[startingIndex++] = value._extrudedHeight; - array[startingIndex] = value._extrude ? 1.0 : 0.0; + array[startingIndex++] = value._extrude ? 1.0 : 0.0; + array[startingIndex] = value._shadowVolume ? 1.0 : 0.0; return array; }; @@ -827,7 +823,8 @@ define([ stRotation : undefined, height : undefined, granularity : undefined, - extrudedHeight : undefined + extrudedHeight : undefined, + shadowVolume: undefined }; /** @@ -866,7 +863,8 @@ define([ var height = array[startingIndex++]; var granularity = array[startingIndex++]; var extrudedHeight = array[startingIndex++]; - var extrude = array[startingIndex] === 1.0; + var extrude = array[startingIndex++] === 1.0; + var shadowVolume = array[startingIndex] === 1.0; if (!defined(result)) { scratchOptions.height = height; @@ -876,6 +874,7 @@ define([ scratchOptions.rotation = rotation; scratchOptions.semiMajorAxis = semiMajorAxis; scratchOptions.semiMinorAxis = semiMinorAxis; + scratchOptions.shadowVolume = shadowVolume; return new EllipseGeometry(scratchOptions); } @@ -890,6 +889,7 @@ define([ result._granularity = granularity; result._extrudedHeight = extrudedHeight; result._extrude = extrude; + result._shadowVoluem = shadowVolume; result._rectangle = Rectangle.clone(rectangle); return result; @@ -923,6 +923,7 @@ define([ if (ellipseGeometry._extrude) { options.extrudedHeight = Math.min(ellipseGeometry._extrudedHeight, ellipseGeometry._height); options.height = Math.max(ellipseGeometry._extrudedHeight, ellipseGeometry._height); + options.shadowVolume = ellipseGeometry._shadowVolume; geometry = computeExtrudedEllipse(options); } else { geometry = computeEllipse(options); @@ -956,7 +957,8 @@ define([ granularity : granularity, extrudedHeight : minHeight, height : maxHeight, - vertexFormat : VertexFormat.POSITION_ONLY + vertexFormat : VertexFormat.POSITION_ONLY, + shadowVolume: true }); }; diff --git a/Source/Core/PolygonGeometry.js b/Source/Core/PolygonGeometry.js index 73d76d2fcfcb..d1bb0a542c4b 100644 --- a/Source/Core/PolygonGeometry.js +++ b/Source/Core/PolygonGeometry.js @@ -134,6 +134,7 @@ define([ var top = options.top || wall; var bottom = options.bottom || wall; var perPositionHeight = options.perPositionHeight; + var shadowVolume = options.shadowVolume; var origin = appendTextureCoordinatesOrigin; origin.x = boundingRectangle.x; @@ -153,6 +154,7 @@ define([ } var tangents = vertexFormat.tangent ? new Float32Array(length) : undefined; var binormals = vertexFormat.binormal ? new Float32Array(length) : undefined; + var extrudeNormals = shadowVolume ? new Float32Array(length) : undefined; var textureCoordIndex = 0; var attrIndex = 0; @@ -198,7 +200,7 @@ define([ textureCoordIndex += 2; } - if (vertexFormat.normal || vertexFormat.tangent || vertexFormat.binormal) { + if (vertexFormat.normal || vertexFormat.tangent || vertexFormat.binormal || shadowVolume) { var attrIndex1 = attrIndex + 1; var attrIndex2 = attrIndex + 2; @@ -266,6 +268,15 @@ define([ } } + if (shadowVolume) { + if (wall) { + normal = ellipsoid.geodeticSurfaceNormal(position, normal); + } + extrudeNormals[attrIndex + bottomOffset] = -normal.x; + extrudeNormals[attrIndex1 + bottomOffset] = -normal.y; + extrudeNormals[attrIndex2 + bottomOffset] = -normal.z; + } + if (vertexFormat.tangent) { if (options.wall) { tangents[attrIndex + bottomOffset] = tangent.x; @@ -343,6 +354,14 @@ define([ values : binormals }); } + + if (shadowVolume) { + geometry.attributes.extrudeDirection = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : extrudeNormals + }); + } } return geometry; } @@ -363,17 +382,8 @@ define([ var numPositions; var newIndices; - var isBottom; if (closeTop && closeBottom) { var topBottomPositions = edgePoints.concat(edgePoints); - isBottom = new Uint8Array(topBottomPositions.length / 3); - if (typeof Uint8Array.prototype.fill === 'function') { - isBottom.fill(1, isBottom.length / 2); - } else { //IE doesn't support fill - for (i = isBottom.length / 2; i < isBottom.length; i++) { - isBottom[i] = 1; - } - } numPositions = topBottomPositions.length / 3; @@ -399,11 +409,6 @@ define([ topGeo.attributes.normal.values = new Float32Array(topBottomPositions.length); topGeo.attributes.normal.values.set(normals); } - topGeo.attributes.isBottom = new GeometryAttribute({ - componentDatatype : ComponentDatatype.UNSIGNED_BYTE, - componentsPerAttribute : 1, - values : isBottom - }); topGeo.indices = newIndices; } else if (closeBottom) { numPositions = edgePoints.length / 3; @@ -593,6 +598,7 @@ define([ this._closeBottom = defaultValue(options.closeBottom, true); this._polygonHierarchy = polygonHierarchy; this._perPositionHeight = perPositionHeight; + this._shadowVolume = defaultValue(options.shadowVolume, false); this._workerName = 'createPolygonGeometry'; var positions = polygonHierarchy.positions; @@ -606,7 +612,7 @@ define([ * The number of elements used to pack the object into an array. * @type {Number} */ - this.packedLength = PolygonGeometryLibrary.computeHierarchyPackedLength(polygonHierarchy) + Ellipsoid.packedLength + VertexFormat.packedLength + Rectangle.packedLength + 9; + this.packedLength = PolygonGeometryLibrary.computeHierarchyPackedLength(polygonHierarchy) + Ellipsoid.packedLength + VertexFormat.packedLength + Rectangle.packedLength + 10; } /** @@ -707,6 +713,7 @@ define([ array[startingIndex++] = value._perPositionHeight ? 1.0 : 0.0; array[startingIndex++] = value._closeTop ? 1.0 : 0.0; array[startingIndex++] = value._closeBottom ? 1.0 : 0.0; + array[startingIndex++] = value._shadowVolume ? 1.0 : 0.0; array[startingIndex] = value.packedLength; return array; @@ -758,6 +765,7 @@ define([ var perPositionHeight = array[startingIndex++] === 1.0; var closeTop = array[startingIndex++] === 1.0; var closeBottom = array[startingIndex++] === 1.0; + var shadowVolume = array[startingIndex++] === 1.0; var packedLength = array[startingIndex]; if (!defined(result)) { @@ -776,6 +784,7 @@ define([ result._closeTop = closeTop; result._closeBottom = closeBottom; result._rectangle = Rectangle.clone(rectangle); + result._shadowVolume = shadowVolume; result.packedLength = packedLength; return result; }; @@ -838,6 +847,7 @@ define([ if (extrude) { options.top = closeTop; options.bottom = closeBottom; + options.shadowVolume = polygonGeometry._shadowVolume; for (i = 0; i < polygons.length; i++) { geometry = createGeometryFromPositionsExtruded(ellipsoid, polygons[i], granularity, hierarchy[i], perPositionHeight, closeTop, closeBottom, vertexFormat); @@ -918,7 +928,8 @@ define([ perPositionHeight : false, extrudedHeight : minHeight, height : maxHeight, - vertexFormat : VertexFormat.POSITION_ONLY + vertexFormat : VertexFormat.POSITION_ONLY, + shadowVolume: true }); }; diff --git a/Source/Core/PolygonGeometryLibrary.js b/Source/Core/PolygonGeometryLibrary.js index 603cb215c0f3..12bb78deec5c 100644 --- a/Source/Core/PolygonGeometryLibrary.js +++ b/Source/Core/PolygonGeometryLibrary.js @@ -354,7 +354,6 @@ define([ var length = positions.length; var index = 0; - var isBottom; if (!perPositionHeight) { var minDistance = CesiumMath.chordLength(granularity, ellipsoid.maximumRadius); @@ -411,15 +410,6 @@ define([ } } - isBottom = new Uint8Array(positionLength * 2); - if (typeof Uint8Array.prototype.fill === 'function') { - isBottom.fill(1, positionLength); - } else { //IE doesn't support fill - for (i = positionLength; i < positionLength * 2; i++) { - isBottom[i] = 1; - } - } - length = edgePositions.length; var indices = IndexDatatype.createTypedArray(length / 3, length - positions.length * 6); var edgeIndex = 0; @@ -445,7 +435,7 @@ define([ indices[edgeIndex++] = LR; } - var geometry = new Geometry({ + return new Geometry({ attributes : new GeometryAttributes({ position : new GeometryAttribute({ componentDatatype : ComponentDatatype.DOUBLE, @@ -456,13 +446,6 @@ define([ indices : indices, primitiveType : PrimitiveType.TRIANGLES }); - geometry.attributes.isBottom = new GeometryAttribute({ - componentDatatype : ComponentDatatype.UNSIGNED_BYTE, - componentsPerAttribute : 1, - values : isBottom - }); - - return geometry; }; return PolygonGeometryLibrary; diff --git a/Source/Core/RectangleGeometry.js b/Source/Core/RectangleGeometry.js index 57f07a67f45b..8b4d18e94fbf 100644 --- a/Source/Core/RectangleGeometry.js +++ b/Source/Core/RectangleGeometry.js @@ -380,7 +380,9 @@ define([ } if (shadowVolume) { topNormals = topBottomGeo.attributes.normal.values; - topBottomGeo.attributes.normal = undefined; + if (!vertexFormat.normal) { + topBottomGeo.attributes.normal = undefined; + } var extrudeNormals = new Float32Array(newLength); for (i = 0; i < length; i ++) { topNormals[i] = -topNormals[i]; @@ -655,17 +657,6 @@ define([ options = defaultValue(options, defaultValue.EMPTY_OBJECT); var rectangle = options.rectangle; - var granularity = defaultValue(options.granularity, CesiumMath.RADIANS_PER_DEGREE); - var ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84); - var surfaceHeight = defaultValue(options.height, 0.0); - var rotation = defaultValue(options.rotation, 0.0); - var stRotation = defaultValue(options.stRotation, 0.0); - var vertexFormat = defaultValue(options.vertexFormat, VertexFormat.DEFAULT); - var extrudedHeight = options.extrudedHeight; - var extrude = defined(extrudedHeight); - var closeTop = defaultValue(options.closeTop, true); - var closeBottom = defaultValue(options.closeBottom, true); - var shadowVolume = defaultValue(options.shadowVolume, false); //>>includeStart('debug', pragmas.debug); if (!defined(rectangle)) { @@ -678,19 +669,19 @@ define([ //>>includeEnd('debug'); this._rectangle = rectangle; - this._granularity = granularity; - this._ellipsoid = Ellipsoid.clone(ellipsoid); - this._surfaceHeight = surfaceHeight; - this._rotation = rotation; - this._stRotation = stRotation; - this._vertexFormat = VertexFormat.clone(vertexFormat); - this._extrudedHeight = defaultValue(extrudedHeight, 0.0); - this._extrude = extrude; - this._closeTop = closeTop; - this._closeBottom = closeBottom; + this._granularity = defaultValue(options.granularity, CesiumMath.RADIANS_PER_DEGREE); + this._ellipsoid = Ellipsoid.clone(defaultValue(options.ellipsoid, Ellipsoid.WGS84)); + this._surfaceHeight = defaultValue(options.height, 0.0); + this._rotation = defaultValue(options.rotation, 0.0); + this._stRotation = defaultValue(options.stRotation, 0.0); + this._vertexFormat = VertexFormat.clone(defaultValue(options.vertexFormat, VertexFormat.DEFAULT)); + this._extrudedHeight = defaultValue(options.extrudedHeight, 0.0); + this._extrude = defined(options.extrudedHeight); + this._closeTop = defaultValue(options.closeTop, true); + this._closeBottom = defaultValue(options.closeBottom, true); + this._shadowVolume = defaultValue(options.shadowVolume, false); this._workerName = 'createRectangleGeometry'; this._rotatedRectangle = computeRectangle(this._rectangle, this._ellipsoid, rotation); - this._shadowVolume = shadowVolume; } /** @@ -741,7 +732,7 @@ define([ array[startingIndex++] = value._extrude ? 1.0 : 0.0; array[startingIndex++] = value._closeTop ? 1.0 : 0.0; array[startingIndex++] = value._closeBottom ? 1.0 : 0.0; - array[startingIndex] = value._shadowVolume? 1.0 : 0.0; + array[startingIndex] = value._shadowVolume ? 1.0 : 0.0; return array; }; @@ -879,12 +870,12 @@ define([ options.stRotation = stRotation; options.tangentRotationMatrix = tangentRotationMatrix; options.size = options.width * options.height; - options.shadowVolume = rectangleGeometry._shadowVolume; var geometry; var boundingSphere; rectangle = rectangleGeometry._rectangle; if (extrude) { + options.shadowVolume = rectangleGeometry._shadowVolume; geometry = constructExtrudedRectangle(options); var topBS = BoundingSphere.fromRectangle3D(rectangle, ellipsoid, surfaceHeight, topBoundingSphere); var bottomBS = BoundingSphere.fromRectangle3D(rectangle, ellipsoid, extrudedHeight, bottomBoundingSphere); From a952cdc9f13e89b01222ea718e722f68775664dc Mon Sep 17 00:00:00 2001 From: hpinkos Date: Tue, 13 Dec 2016 17:07:16 -0500 Subject: [PATCH 04/14] fix specs --- Source/Core/CircleGeometry.js | 10 +++++--- Source/Core/EllipseGeometry.js | 26 +++++++++++++------ Source/Core/GeometryPipeline.js | 39 +++++++++++++++++++++++------ Source/Core/PolygonGeometry.js | 4 +-- Source/Core/RectangleGeometry.js | 3 ++- Source/Scene/GroundPrimitive.js | 4 +-- Specs/Core/CircleGeometrySpec.js | 2 +- Specs/Core/CorridorGeometrySpec.js | 2 +- Specs/Core/EllipseGeometrySpec.js | 2 +- Specs/Core/PolygonGeometrySpec.js | 2 +- Specs/Core/RectangleGeometrySpec.js | 2 +- 11 files changed, 69 insertions(+), 27 deletions(-) diff --git a/Source/Core/CircleGeometry.js b/Source/Core/CircleGeometry.js index 8aa557d4c33b..1d938bb2d64e 100644 --- a/Source/Core/CircleGeometry.js +++ b/Source/Core/CircleGeometry.js @@ -68,7 +68,8 @@ define([ extrudedHeight : options.extrudedHeight, granularity : options.granularity, vertexFormat : options.vertexFormat, - stRotation : options.stRotation + stRotation : options.stRotation, + shadowVolume: options.shadowVolume }; this._ellipseGeometry = new EllipseGeometry(ellipseGeometryOptions); this._workerName = 'createCircleGeometry'; @@ -113,7 +114,8 @@ define([ vertexFormat : new VertexFormat(), stRotation : undefined, semiMajorAxis : undefined, - semiMinorAxis : undefined + semiMinorAxis : undefined, + shadowVolume: undefined }; /** @@ -133,6 +135,7 @@ define([ scratchOptions.granularity = ellipseGeometry._granularity; scratchOptions.vertexFormat = VertexFormat.clone(ellipseGeometry._vertexFormat, scratchOptions.vertexFormat); scratchOptions.stRotation = ellipseGeometry._stRotation; + scratchOptions.shadowVolume = ellipseGeometry._shadowVolume; if (!defined(result)) { scratchOptions.radius = ellipseGeometry._semiMajorAxis; @@ -173,7 +176,8 @@ define([ granularity : granularity, extrudedHeight : minHeight, height : maxHeight, - vertexFormat : VertexFormat.POSITION_ONLY + vertexFormat : VertexFormat.POSITION_ONLY, + shadowVolume: true }); }; diff --git a/Source/Core/EllipseGeometry.js b/Source/Core/EllipseGeometry.js index 3020da7a2cc0..34fd0e3503ed 100644 --- a/Source/Core/EllipseGeometry.js +++ b/Source/Core/EllipseGeometry.js @@ -248,6 +248,7 @@ define([ values : extrudeNormals }); } + return attributes; } @@ -390,6 +391,9 @@ define([ var tangents = (vertexFormat.tangent) ? new Float32Array(size * 3) : undefined; var binormals = (vertexFormat.binormal) ? new Float32Array(size * 3) : undefined; + var shadowVolume = options.shadowVolume; + var extrudeNormals = (shadowVolume) ? new Float32Array(size * 3) : undefined; + var textureCoordIndex = 0; // Raise positions to a height above the ellipsoid and compute the @@ -440,6 +444,13 @@ define([ position = ellipsoid.scaleToGeodeticSurface(position, position); extrudedPosition = Cartesian3.clone(position, scratchCartesian2); normal = ellipsoid.geodeticSurfaceNormal(position, normal); + + if (shadowVolume) { + extrudeNormals[i + length] = -normal.x; + extrudeNormals[i1 + length] = -normal.y; + extrudeNormals[i2 + length] = -normal.z; + } + var scaledNormal = Cartesian3.multiplyByScalar(normal, height, scratchCartesian4); position = Cartesian3.add(position, scaledNormal, position); scaledNormal = Cartesian3.multiplyByScalar(normal, extrudedHeight, scaledNormal); @@ -547,6 +558,14 @@ define([ }); } + if (shadowVolume) { + attributes.extrudeDirection = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : extrudeNormals + }); + } + return attributes; } @@ -610,13 +629,6 @@ define([ }); var wallAttributes = computeWallAttributes(outerPositions, options); - if (options.shadowVolume) { - wallAttributes.extrudeDirection = new GeometryAttribute({ - componentDatatype: ComponentDatatype.FLOAT, - componentsPerAttribute: 3, - values: topBottomAttributes.extrudeDirection.slice() - }); - } indices = computeWallIndices(outerPositions); var wallIndices = IndexDatatype.createTypedArray(outerPositions.length * 2 / 3, indices); diff --git a/Source/Core/GeometryPipeline.js b/Source/Core/GeometryPipeline.js index e681e1543112..448396bf69b1 100644 --- a/Source/Core/GeometryPipeline.js +++ b/Source/Core/GeometryPipeline.js @@ -282,7 +282,8 @@ define([ 'binormal', 'tangent', - 'extrudeDirection', //TODO: do I need this? + // For shadow volumes + 'extrudeDirection', // From compressing texture coordinates and normals 'compressedAttributes' @@ -1879,8 +1880,8 @@ define([ var s1Scratch = new Cartesian2(); var s2Scratch = new Cartesian2(); - function computeTriangleAttributes(i0, i1, i2, point, positions, normals, binormals, tangents, texCoords, currentAttributes, insertedIndex) { - if (!defined(normals) && !defined(binormals) && !defined(tangents) && !defined(texCoords)) { + function computeTriangleAttributes(i0, i1, i2, point, positions, normals, binormals, tangents, texCoords, extrudeDirections, currentAttributes, insertedIndex) { + if (!defined(normals) && !defined(binormals) && !defined(tangents) && !defined(texCoords) && !defined(extrudeDirections)) { return; } @@ -1905,6 +1906,29 @@ define([ Cartesian3.pack(normal, currentAttributes.normal.values, insertedIndex * 3); } + if (defined(extrudeDirections)) { + var d0 = Cartesian3.fromArray(extrudeDirections, i0 * 3, p0Scratch); + var d1 = Cartesian3.fromArray(extrudeDirections, i1 * 3, p1Scratch); + var d2 = Cartesian3.fromArray(extrudeDirections, i2 * 3, p2Scratch); + + Cartesian3.multiplyByScalar(d0, coords.x, d0); + Cartesian3.multiplyByScalar(d1, coords.y, d1); + Cartesian3.multiplyByScalar(d2, coords.z, d2); + + var direction; + if (!Cartesian3.equals(d0, Cartesian3.ZERO) || !Cartesian3.equals(d1, Cartesian3.ZERO) || !Cartesian3.equals(d2, Cartesian3.ZERO)) { + direction = Cartesian3.add(d0, d1, d0); + Cartesian3.add(direction, d2, direction); + Cartesian3.normalize(direction, direction); + } else { + direction = p0Scratch; + direction.x = 0; + direction.y = 0; + direction.z = 0; + } + Cartesian3.pack(direction, currentAttributes.extrudeDirection.values, insertedIndex * 3); + } + if (defined(binormals)) { var b0 = Cartesian3.fromArray(binormals, i0 * 3, p0Scratch); var b1 = Cartesian3.fromArray(binormals, i1 * 3, p1Scratch); @@ -1984,6 +2008,7 @@ define([ var binormals = (defined(attributes.binormal)) ? attributes.binormal.values : undefined; var tangents = (defined(attributes.tangent)) ? attributes.tangent.values : undefined; var texCoords = (defined(attributes.st)) ? attributes.st.values : undefined; + var extrudeDirections = (defined(attributes.extrudeDirection)) ? attributes.extrudeDirection.values : undefined; var indices = geometry.indices; var eastGeometry = copyGeometryForSplit(geometry); @@ -2037,7 +2062,7 @@ define([ } insertedIndex = insertSplitPoint(currentAttributes, currentIndices, currentIndexMap, indices, resultIndex < 3 ? i + resultIndex : -1, point); - computeTriangleAttributes(i0, i1, i2, point, positions, normals, binormals, tangents, texCoords, currentAttributes, insertedIndex); + computeTriangleAttributes(i0, i1, i2, point, positions, normals, binormals, tangents, texCoords, extrudeDirections, currentAttributes, insertedIndex); } } else { if (defined(result)) { @@ -2057,13 +2082,13 @@ define([ } insertedIndex = insertSplitPoint(currentAttributes, currentIndices, currentIndexMap, indices, i, p0); - computeTriangleAttributes(i0, i1, i2, p0, positions, normals, binormals, tangents, texCoords, currentAttributes, insertedIndex); + computeTriangleAttributes(i0, i1, i2, p0, positions, normals, binormals, tangents, texCoords, extrudeDirections, currentAttributes, insertedIndex); insertedIndex = insertSplitPoint(currentAttributes, currentIndices, currentIndexMap, indices, i + 1, p1); - computeTriangleAttributes(i0, i1, i2, p1, positions, normals, binormals, tangents, texCoords, currentAttributes, insertedIndex); + computeTriangleAttributes(i0, i1, i2, p1, positions, normals, binormals, tangents, texCoords, extrudeDirections, currentAttributes, insertedIndex); insertedIndex = insertSplitPoint(currentAttributes, currentIndices, currentIndexMap, indices, i + 2, p2); - computeTriangleAttributes(i0, i1, i2, p2, positions, normals, binormals, tangents, texCoords, currentAttributes, insertedIndex); + computeTriangleAttributes(i0, i1, i2, p2, positions, normals, binormals, tangents, texCoords, extrudeDirections, currentAttributes, insertedIndex); } } diff --git a/Source/Core/PolygonGeometry.js b/Source/Core/PolygonGeometry.js index d1bb0a542c4b..44c569bde91d 100644 --- a/Source/Core/PolygonGeometry.js +++ b/Source/Core/PolygonGeometry.js @@ -123,7 +123,8 @@ define([ function computeAttributes(options) { var vertexFormat = options.vertexFormat; var geometry = options.geometry; - if (vertexFormat.st || vertexFormat.normal || vertexFormat.tangent || vertexFormat.binormal) { + var shadowVolume = options.shadowVolume; + if (vertexFormat.st || vertexFormat.normal || vertexFormat.tangent || vertexFormat.binormal || shadowVolume) { // PERFORMANCE_IDEA: Compute before subdivision, then just interpolate during subdivision. // PERFORMANCE_IDEA: Compute with createGeometryFromPositions() for fast path when there's no holes. var boundingRectangle = options.boundingRectangle; @@ -134,7 +135,6 @@ define([ var top = options.top || wall; var bottom = options.bottom || wall; var perPositionHeight = options.perPositionHeight; - var shadowVolume = options.shadowVolume; var origin = appendTextureCoordinatesOrigin; origin.x = boundingRectangle.x; diff --git a/Source/Core/RectangleGeometry.js b/Source/Core/RectangleGeometry.js index 8b4d18e94fbf..6d2247715f59 100644 --- a/Source/Core/RectangleGeometry.js +++ b/Source/Core/RectangleGeometry.js @@ -668,11 +668,12 @@ define([ } //>>includeEnd('debug'); + var rotation = defaultValue(options.rotation, 0.0); this._rectangle = rectangle; this._granularity = defaultValue(options.granularity, CesiumMath.RADIANS_PER_DEGREE); this._ellipsoid = Ellipsoid.clone(defaultValue(options.ellipsoid, Ellipsoid.WGS84)); this._surfaceHeight = defaultValue(options.height, 0.0); - this._rotation = defaultValue(options.rotation, 0.0); + this._rotation = rotation; this._stRotation = defaultValue(options.stRotation, 0.0); this._vertexFormat = VertexFormat.clone(defaultValue(options.vertexFormat, VertexFormat.DEFAULT)); this._extrudedHeight = defaultValue(options.extrudedHeight, 0.0); diff --git a/Source/Scene/GroundPrimitive.js b/Source/Scene/GroundPrimitive.js index 278e5a2f1885..a8013a2d339d 100644 --- a/Source/Scene/GroundPrimitive.js +++ b/Source/Scene/GroundPrimitive.js @@ -217,7 +217,7 @@ define([ this._uniformMap = { u_globeMinimumAltitude: function() { - return 1100.0; //TODO verify + return 33000.0; } }; @@ -256,7 +256,7 @@ define([ releaseGeometryInstances : defaultValue(options.releaseGeometryInstances, true), allowPicking : defaultValue(options.allowPicking, true), asynchronous : defaultValue(options.asynchronous, true), - compressVertices : false,//defaultValue(options.compressVertices, true), + compressVertices : defaultValue(options.compressVertices, true), _readOnlyInstanceAttributes : readOnlyAttributes, _createRenderStatesFunction : undefined, _createShaderProgramFunction : undefined, diff --git a/Specs/Core/CircleGeometrySpec.js b/Specs/Core/CircleGeometrySpec.js index d41fc2a3c42a..ec7fdac5fb63 100644 --- a/Specs/Core/CircleGeometrySpec.js +++ b/Specs/Core/CircleGeometrySpec.js @@ -178,6 +178,6 @@ defineSuite([ radius : 1.0, stRotation : CesiumMath.PI_OVER_TWO }); - var packedInstance = [center.x, center.y, center.z, ellipsoid.radii.x, ellipsoid.radii.y, ellipsoid.radii.z, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, rectangle.west, rectangle.south, rectangle.east, rectangle.north, 1.0, 1.0, 0.0, CesiumMath.PI_OVER_TWO, 0.0, 0.1, 0.0, 0.0]; + var packedInstance = [center.x, center.y, center.z, ellipsoid.radii.x, ellipsoid.radii.y, ellipsoid.radii.z, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, rectangle.west, rectangle.south, rectangle.east, rectangle.north, 1.0, 1.0, 0.0, CesiumMath.PI_OVER_TWO, 0.0, 0.1, 0.0, 0.0, 0.0]; createPackableSpecs(CircleGeometry, packableInstance, packedInstance); }); diff --git a/Specs/Core/CorridorGeometrySpec.js b/Specs/Core/CorridorGeometrySpec.js index 1862108eabbc..4bac8615e1ba 100644 --- a/Specs/Core/CorridorGeometrySpec.js +++ b/Specs/Core/CorridorGeometrySpec.js @@ -291,6 +291,6 @@ defineSuite([ packedInstance.push(Ellipsoid.WGS84.radii.x, Ellipsoid.WGS84.radii.y, Ellipsoid.WGS84.radii.z); packedInstance.push(1.0, 0.0, 0.0, 0.0, 0.0, 0.0); packedInstance.push(rectangle.west, rectangle.south, rectangle.east, rectangle.north); - packedInstance.push(30000.0, 0.0, 0.0, 2.0, 0.1); + packedInstance.push(30000.0, 0.0, 0.0, 2.0, 0.1, 0.0); createPackableSpecs(CorridorGeometry, corridor, packedInstance); }); diff --git a/Specs/Core/EllipseGeometrySpec.js b/Specs/Core/EllipseGeometrySpec.js index df9f86701a16..0af786c8bf03 100644 --- a/Specs/Core/EllipseGeometrySpec.js +++ b/Specs/Core/EllipseGeometrySpec.js @@ -265,7 +265,7 @@ defineSuite([ semiMinorAxis : 1.0, stRotation : CesiumMath.PI_OVER_TWO }); - var packedInstance = [center.x, center.y, center.z, ellipsoid.radii.x, ellipsoid.radii.y, ellipsoid.radii.z, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, rectangle.west, rectangle.south, rectangle.east, rectangle.north, 1.0, 1.0, 0.0, CesiumMath.PI_OVER_TWO, 0.0, 0.1, 0.0, 0.0]; + var packedInstance = [center.x, center.y, center.z, ellipsoid.radii.x, ellipsoid.radii.y, ellipsoid.radii.z, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, rectangle.west, rectangle.south, rectangle.east, rectangle.north, 1.0, 1.0, 0.0, CesiumMath.PI_OVER_TWO, 0.0, 0.1, 0.0, 0.0, 0.0]; createPackableSpecs(EllipseGeometry, packableInstance, packedInstance); }); diff --git a/Specs/Core/PolygonGeometrySpec.js b/Specs/Core/PolygonGeometrySpec.js index 2d2aae6b3d41..d29fdb8bbc43 100644 --- a/Specs/Core/PolygonGeometrySpec.js +++ b/Specs/Core/PolygonGeometrySpec.js @@ -699,6 +699,6 @@ defineSuite([ packedInstance.push(Ellipsoid.WGS84.radii.x, Ellipsoid.WGS84.radii.y, Ellipsoid.WGS84.radii.z); packedInstance.push(1.0, 0.0, 0.0, 0.0, 0.0, 0.0); packedInstance.push(rectangle.west, rectangle.south, rectangle.east, rectangle.north); - packedInstance.push(0.0, 0.0, CesiumMath.PI_OVER_THREE, 0.0, 0.0, 1.0, 0, 1, 55); + packedInstance.push(0.0, 0.0, CesiumMath.PI_OVER_THREE, 0.0, 0.0, 1.0, 0, 1, 0, 56); createPackableSpecs(PolygonGeometry, polygon, packedInstance); }); diff --git a/Specs/Core/RectangleGeometrySpec.js b/Specs/Core/RectangleGeometrySpec.js index 5ed3b14f5b39..0e1e51f92d7e 100644 --- a/Specs/Core/RectangleGeometrySpec.js +++ b/Specs/Core/RectangleGeometrySpec.js @@ -349,6 +349,6 @@ defineSuite([ granularity : 1.0, ellipsoid : Ellipsoid.UNIT_SPHERE }); - var packedInstance = [-2.0, -1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, -2.0, -1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0]; + var packedInstance = [-2.0, -1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, -2.0, -1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0]; createPackableSpecs(RectangleGeometry, rectangle, packedInstance); }); From f14a19e848a5cfcece4d075b2b02a546e43d49c6 Mon Sep 17 00:00:00 2001 From: hpinkos Date: Tue, 13 Dec 2016 17:10:16 -0500 Subject: [PATCH 05/14] jshint --- Source/Core/RectangleGeometry.js | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/Core/RectangleGeometry.js b/Source/Core/RectangleGeometry.js index 6d2247715f59..73dcdfeb60f6 100644 --- a/Source/Core/RectangleGeometry.js +++ b/Source/Core/RectangleGeometry.js @@ -741,7 +741,6 @@ define([ var scratchRectangle = new Rectangle(); var scratchRotatedRectangle = new Rectangle(); var scratchEllipsoid = Ellipsoid.clone(Ellipsoid.UNIT_SPHERE); - var scratchVertexFormat = new VertexFormat(); var scratchOptions = { rectangle : scratchRectangle, ellipsoid : scratchEllipsoid, From db2e9ca78e70e407e3f404bd7772b6600c23e47b Mon Sep 17 00:00:00 2001 From: hpinkos Date: Tue, 13 Dec 2016 17:33:51 -0500 Subject: [PATCH 06/14] cleanup --- Source/Core/CorridorGeometry.js | 4 ++-- Source/Core/PolygonGeometryLibrary.js | 7 ++----- Source/Core/RectangleGeometry.js | 16 ---------------- Source/Renderer/AutomaticUniforms.js | 6 ++++++ Source/Renderer/UniformState.js | 12 ++++++++++++ Source/Scene/FrameState.js | 7 +++++++ 6 files changed, 29 insertions(+), 23 deletions(-) diff --git a/Source/Core/CorridorGeometry.js b/Source/Core/CorridorGeometry.js index 7ab047cfa002..73bdc2fb5475 100644 --- a/Source/Core/CorridorGeometry.js +++ b/Source/Core/CorridorGeometry.js @@ -868,8 +868,8 @@ define([ array[startingIndex++] = value._height; array[startingIndex++] = value._extrudedHeight; array[startingIndex++] = value._cornerType; - array[startingIndex++] = value._granularity; - array[startingIndex] = value._shadowVolume ? 1.0 : 0.0; + array[startingIndex++] = value._granularity; + array[startingIndex] = value._shadowVolume ? 1.0 : 0.0; return array; }; diff --git a/Source/Core/PolygonGeometryLibrary.js b/Source/Core/PolygonGeometryLibrary.js index 12bb78deec5c..f36e24764715 100644 --- a/Source/Core/PolygonGeometryLibrary.js +++ b/Source/Core/PolygonGeometryLibrary.js @@ -346,7 +346,6 @@ define([ PolygonGeometryLibrary.computeWallGeometry = function(positions, ellipsoid, granularity, perPositionHeight) { var edgePositions; var topEdgeLength; - var positionLength; var i; var p1; var p2; @@ -362,8 +361,7 @@ define([ numVertices += PolygonGeometryLibrary.subdivideLineCount(positions[i], positions[(i + 1) % length], minDistance); } - positionLength = numVertices + length; - topEdgeLength = positionLength * 3; + topEdgeLength = (numVertices + length) * 3; edgePositions = new Array(topEdgeLength * 2); for (i = 0; i < length; i++) { p1 = positions[i]; @@ -389,8 +387,7 @@ define([ ++index; } } else { - positionLength = length * 2; - topEdgeLength = positionLength * 3; + topEdgeLength = length * 3 * 2; edgePositions = new Array(topEdgeLength * 2); for (i = 0; i < length; i++) { p1 = positions[i]; diff --git a/Source/Core/RectangleGeometry.js b/Source/Core/RectangleGeometry.js index 73dcdfeb60f6..afc6c9896a04 100644 --- a/Source/Core/RectangleGeometry.js +++ b/Source/Core/RectangleGeometry.js @@ -450,10 +450,6 @@ define([ stIndex += 4; } if (shadowVolume) { - wallExtrudeNormals[extrudeNormalIndex++] = 0; - wallExtrudeNormals[extrudeNormalIndex++] = 0; - wallExtrudeNormals[extrudeNormalIndex++] = 0; - wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI]; wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 1]; wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 2]; @@ -469,10 +465,6 @@ define([ stIndex += 4; } if (shadowVolume) { - wallExtrudeNormals[extrudeNormalIndex++] = 0; - wallExtrudeNormals[extrudeNormalIndex++] = 0; - wallExtrudeNormals[extrudeNormalIndex++] = 0; - wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI]; wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 1]; wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 2]; @@ -488,10 +480,6 @@ define([ stIndex += 4; } if (shadowVolume) { - wallExtrudeNormals[extrudeNormalIndex++] = 0; - wallExtrudeNormals[extrudeNormalIndex++] = 0; - wallExtrudeNormals[extrudeNormalIndex++] = 0; - wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI]; wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 1]; wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 2]; @@ -507,10 +495,6 @@ define([ stIndex += 4; } if (shadowVolume) { - wallExtrudeNormals[extrudeNormalIndex++] = 0; - wallExtrudeNormals[extrudeNormalIndex++] = 0; - wallExtrudeNormals[extrudeNormalIndex++] = 0; - wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI]; wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 1]; wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 2]; diff --git a/Source/Renderer/AutomaticUniforms.js b/Source/Renderer/AutomaticUniforms.js index 5507b53b907a..f7da008bbc4a 100644 --- a/Source/Renderer/AutomaticUniforms.js +++ b/Source/Renderer/AutomaticUniforms.js @@ -1478,6 +1478,12 @@ define([ } }), + /** + * An automatic GLSL uniform scalar representing the geometric tolerance per distance + * + * @alias czm_geometricToleranceOverDistance + * @glslUniform + */ czm_geometricToleranceOverDistance : new AutomaticUniform({ size: 1, datatype: WebGLConstants.FLOAT, diff --git a/Source/Renderer/UniformState.js b/Source/Renderer/UniformState.js index 574a213744c5..6818f9f5e222 100644 --- a/Source/Renderer/UniformState.js +++ b/Source/Renderer/UniformState.js @@ -769,12 +769,24 @@ define([ } }, + /** + * The maximum screen-space error used to drive level-of-detail refinement. Higher + * values will provide better performance but lower visual quality. + * + * @type {Number} + * @default 2 + */ maximumScreenSpaceError: { get: function() { return this._frameState.maximumScreenSpaceError; } }, + /** + * The size of one pixel in meters + * + * @type {Number} + */ pixelSizePerMeter: { get: function() { return this._pixelSizePerMeter; diff --git a/Source/Scene/FrameState.js b/Source/Scene/FrameState.js index 29c163b357e2..e3f87f3fcea6 100644 --- a/Source/Scene/FrameState.js +++ b/Source/Scene/FrameState.js @@ -95,6 +95,13 @@ define([ */ this.occluder = undefined; + /** + * The maximum screen-space error used to drive level-of-detail refinement. Higher + * values will provide better performance but lower visual quality. + * + * @type {Number} + * @default 2 + */ this.maximumScreenSpaceError = undefined; this.passes = { From a9d93e5cb98e14288923378f1a65f0aa2ef3323d Mon Sep 17 00:00:00 2001 From: hpinkos Date: Mon, 19 Dec 2016 15:44:26 -0500 Subject: [PATCH 07/14] fix rectangle, circle and corridor updates from review --- Source/Core/CorridorGeometry.js | 3 +-- Source/Core/EllipseGeometry.js | 2 +- Source/Core/RectangleGeometry.js | 4 ++++ Source/Renderer/AutomaticUniforms.js | 6 +++--- Source/Shaders/ShadowVolumeVS.glsl | 4 ++-- 5 files changed, 11 insertions(+), 8 deletions(-) diff --git a/Source/Core/CorridorGeometry.js b/Source/Core/CorridorGeometry.js index 73bdc2fb5475..49992368288d 100644 --- a/Source/Core/CorridorGeometry.js +++ b/Source/Core/CorridorGeometry.js @@ -602,8 +602,7 @@ define([ } //only get normals for bottom layer that's going to be pushed down extrudeNormals.set(topNormals, length); //bottom face - extrudeNormals.set(topNormals, length * 4); //bottom wall positions - extrudeNormals.set(topNormals, length * 5); //duplicate bottom wall positions + extrudeNormals = addWallPositions(topNormals, length*4, extrudeNormals); //bottom wall attributes.extrudeDirection = new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 3, diff --git a/Source/Core/EllipseGeometry.js b/Source/Core/EllipseGeometry.js index 34fd0e3503ed..3faca9185f5d 100644 --- a/Source/Core/EllipseGeometry.js +++ b/Source/Core/EllipseGeometry.js @@ -901,7 +901,7 @@ define([ result._granularity = granularity; result._extrudedHeight = extrudedHeight; result._extrude = extrude; - result._shadowVoluem = shadowVolume; + result._shadowVolume = shadowVolume; result._rectangle = Rectangle.clone(rectangle); return result; diff --git a/Source/Core/RectangleGeometry.js b/Source/Core/RectangleGeometry.js index afc6c9896a04..4ee7ff3bb69d 100644 --- a/Source/Core/RectangleGeometry.js +++ b/Source/Core/RectangleGeometry.js @@ -450,6 +450,7 @@ define([ stIndex += 4; } if (shadowVolume) { + extrudeNormalIndex += 3; wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI]; wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 1]; wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 2]; @@ -465,6 +466,7 @@ define([ stIndex += 4; } if (shadowVolume) { + extrudeNormalIndex += 3; wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI]; wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 1]; wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 2]; @@ -480,6 +482,7 @@ define([ stIndex += 4; } if (shadowVolume) { + extrudeNormalIndex += 3; wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI]; wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 1]; wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 2]; @@ -495,6 +498,7 @@ define([ stIndex += 4; } if (shadowVolume) { + extrudeNormalIndex += 3; wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI]; wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 1]; wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 2]; diff --git a/Source/Renderer/AutomaticUniforms.js b/Source/Renderer/AutomaticUniforms.js index f7da008bbc4a..f520cf0aedf4 100644 --- a/Source/Renderer/AutomaticUniforms.js +++ b/Source/Renderer/AutomaticUniforms.js @@ -1479,12 +1479,12 @@ define([ }), /** - * An automatic GLSL uniform scalar representing the geometric tolerance per distance + * An automatic GLSL uniform scalar representing the geometric tolerance per meter * - * @alias czm_geometricToleranceOverDistance + * @alias czm_geometricToleranceOverMeter * @glslUniform */ - czm_geometricToleranceOverDistance : new AutomaticUniform({ + czm_geometricToleranceOverMeter : new AutomaticUniform({ size: 1, datatype: WebGLConstants.FLOAT, getValue: function(uniformState) { diff --git a/Source/Shaders/ShadowVolumeVS.glsl b/Source/Shaders/ShadowVolumeVS.glsl index 14f072145918..a20b00d1ed9a 100644 --- a/Source/Shaders/ShadowVolumeVS.glsl +++ b/Source/Shaders/ShadowVolumeVS.glsl @@ -22,9 +22,9 @@ void main() v_color = color; vec4 position = czm_computePosition(); - float delta = min(u_globeMinimumAltitude, czm_geometricToleranceOverDistance * length(position.xyz)); + float delta = min(u_globeMinimumAltitude, czm_geometricToleranceOverMeter * length(position.xyz)); //extrudeDirection is zero for the top layer - position = position + vec4(extrudeDirection.xyz * delta, 0); + position = position + vec4(extrudeDirection * delta, 0.0); gl_Position = depthClampFarPlane(czm_modelViewProjectionRelativeToEye * position); } From a83ad44b1b5e76f285ccc5a7eee6db7e25bbee61 Mon Sep 17 00:00:00 2001 From: hpinkos Date: Mon, 19 Dec 2016 16:25:32 -0500 Subject: [PATCH 08/14] adjust u_globeMinimumAltitude --- Source/Scene/GroundPrimitive.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Scene/GroundPrimitive.js b/Source/Scene/GroundPrimitive.js index 7fc4443ddf63..78f93572bf28 100644 --- a/Source/Scene/GroundPrimitive.js +++ b/Source/Scene/GroundPrimitive.js @@ -217,7 +217,7 @@ define([ this._uniformMap = { u_globeMinimumAltitude: function() { - return 33000.0; + return 55000.0; } }; From 258eb007e2e0c4c8721caac4e72e3c601764b886 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Wed, 4 Jan 2017 06:51:31 -0500 Subject: [PATCH 09/14] Fixed running just GroundPrimitive tests --- Specs/Scene/GroundPrimitiveSpec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Specs/Scene/GroundPrimitiveSpec.js b/Specs/Scene/GroundPrimitiveSpec.js index 4b46d3a7a17a..35201b444668 100644 --- a/Specs/Scene/GroundPrimitiveSpec.js +++ b/Specs/Scene/GroundPrimitiveSpec.js @@ -1,5 +1,6 @@ /*global defineSuite*/ defineSuite([ + 'Scene/GroundPrimitive', 'Core/Color', 'Core/ColorGeometryInstanceAttribute', 'Core/destroyObject', @@ -13,12 +14,12 @@ defineSuite([ 'Core/RectangleGeometry', 'Core/ShowGeometryInstanceAttribute', 'Renderer/Pass', - 'Scene/GroundPrimitive', 'Scene/PerInstanceColorAppearance', 'Scene/Primitive', 'Specs/createScene', 'Specs/pollToPromise' ], function( + GroundPrimitive, Color, ColorGeometryInstanceAttribute, destroyObject, @@ -32,7 +33,6 @@ defineSuite([ RectangleGeometry, ShowGeometryInstanceAttribute, Pass, - GroundPrimitive, PerInstanceColorAppearance, Primitive, createScene, From 2d50df1ef5a9c878e5fd75020fc58c4bcc8c9191 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Wed, 4 Jan 2017 08:25:16 -0500 Subject: [PATCH 10/14] Make debugShowShadowVolume show the actual volume rendered --- Source/Scene/GroundPrimitive.js | 284 +++++++++++++++----------------- 1 file changed, 130 insertions(+), 154 deletions(-) diff --git a/Source/Scene/GroundPrimitive.js b/Source/Scene/GroundPrimitive.js index 43536a54a362..b01058f7e7fe 100644 --- a/Source/Scene/GroundPrimitive.js +++ b/Source/Scene/GroundPrimitive.js @@ -5,6 +5,7 @@ define([ '../Core/Cartesian2', '../Core/Cartesian3', '../Core/Cartographic', + '../Core/clone', '../Core/Color', '../Core/ColorGeometryInstanceAttribute', '../Core/defaultValue', @@ -40,6 +41,7 @@ define([ Cartesian2, Cartesian3, Cartographic, + clone, Color, ColorGeometryInstanceAttribute, defaultValue, @@ -196,9 +198,7 @@ define([ /** * This property is for debugging only; it is not for production use nor is it optimized. *

- * Draws the shadow volume for each geometry in the primitive. Must be true on - * creation for the volumes to be created before the geometry is released or releaseGeometryInstances - * must be false + * Draws the shadow volume for each geometry in the primitive. *

* * @type {Boolean} @@ -206,6 +206,7 @@ define([ * @default false */ this.debugShowShadowVolume = defaultValue(options.debugShowShadowVolume, false); + this._debugShowShadowVolume = false; this._sp = undefined; this._spPick = undefined; @@ -228,7 +229,6 @@ define([ this._readyPromise = when.defer(); this._primitive = undefined; - this._debugPrimitive = undefined; this._maxHeight = undefined; this._minHeight = undefined; @@ -423,91 +423,98 @@ define([ }; } - var stencilPreloadRenderState = { - colorMask : { - red : false, - green : false, - blue : false, - alpha : false - }, - stencilTest : { - enabled : true, - frontFunction : StencilFunction.ALWAYS, - frontOperation : { - fail : StencilOperation.KEEP, - zFail : StencilOperation.DECREMENT_WRAP, - zPass : StencilOperation.DECREMENT_WRAP + function getStencilPreloadRenderState(enableStencil) { + return { + colorMask : { + red : false, + green : false, + blue : false, + alpha : false }, - backFunction : StencilFunction.ALWAYS, - backOperation : { - fail : StencilOperation.KEEP, - zFail : StencilOperation.INCREMENT_WRAP, - zPass : StencilOperation.INCREMENT_WRAP + stencilTest : { + enabled : enableStencil, + frontFunction : StencilFunction.ALWAYS, + frontOperation : { + fail : StencilOperation.KEEP, + zFail : StencilOperation.DECREMENT_WRAP, + zPass : StencilOperation.DECREMENT_WRAP + }, + backFunction : StencilFunction.ALWAYS, + backOperation : { + fail : StencilOperation.KEEP, + zFail : StencilOperation.INCREMENT_WRAP, + zPass : StencilOperation.INCREMENT_WRAP + }, + reference : 0, + mask : ~0 }, - reference : 0, - mask : ~0 - }, - depthTest : { - enabled : false - }, - depthMask : false - }; + depthTest : { + enabled : false + }, + depthMask : false + }; + } - var stencilDepthRenderState = { - colorMask : { - red : false, - green : false, - blue : false, - alpha : false - }, - stencilTest : { - enabled : true, - frontFunction : StencilFunction.ALWAYS, - frontOperation : { - fail : StencilOperation.KEEP, - zFail : StencilOperation.KEEP, - zPass : StencilOperation.INCREMENT_WRAP + function getStencilDepthRenderState(enableStencil) { + return { + colorMask : { + red : false, + green : false, + blue : false, + alpha : false }, - backFunction : StencilFunction.ALWAYS, - backOperation : { - fail : StencilOperation.KEEP, - zFail : StencilOperation.KEEP, - zPass : StencilOperation.DECREMENT_WRAP + stencilTest : { + enabled : enableStencil, + frontFunction : StencilFunction.ALWAYS, + frontOperation : { + fail : StencilOperation.KEEP, + zFail : StencilOperation.KEEP, + zPass : StencilOperation.INCREMENT_WRAP + }, + backFunction : StencilFunction.ALWAYS, + backOperation : { + fail : StencilOperation.KEEP, + zFail : StencilOperation.KEEP, + zPass : StencilOperation.DECREMENT_WRAP + }, + reference : 0, + mask : ~0 }, - reference : 0, - mask : ~0 - }, - depthTest : { - enabled : true, - func : DepthFunction.LESS_OR_EQUAL - }, - depthMask : false - }; + depthTest : { + enabled : true, + func : DepthFunction.LESS_OR_EQUAL + }, + depthMask : false + }; + } - var colorRenderState = { - stencilTest : { - enabled : true, - frontFunction : StencilFunction.NOT_EQUAL, - frontOperation : { - fail : StencilOperation.KEEP, - zFail : StencilOperation.KEEP, - zPass : StencilOperation.DECREMENT_WRAP + + function getColorRenderState(enableStencil) { + return { + stencilTest : { + enabled : enableStencil, + frontFunction : StencilFunction.NOT_EQUAL, + frontOperation : { + fail : StencilOperation.KEEP, + zFail : StencilOperation.KEEP, + zPass : StencilOperation.DECREMENT_WRAP + }, + backFunction : StencilFunction.NOT_EQUAL, + backOperation : { + fail : StencilOperation.KEEP, + zFail : StencilOperation.KEEP, + zPass : StencilOperation.DECREMENT_WRAP + }, + reference : 0, + mask : ~0 }, - backFunction : StencilFunction.NOT_EQUAL, - backOperation : { - fail : StencilOperation.KEEP, - zFail : StencilOperation.KEEP, - zPass : StencilOperation.DECREMENT_WRAP + depthTest : { + enabled : false }, - reference : 0, - mask : ~0 - }, - depthTest : { - enabled : false - }, - depthMask : false, - blending : BlendingState.ALPHA_BLEND - }; + depthMask : false, + blending : BlendingState.ALPHA_BLEND + }; + } var pickRenderState = { stencilTest : { @@ -692,66 +699,67 @@ define([ return BoundingSphere.union(result, scratchBoundingSphere, result); } - function createBoundingVolume(primitive, frameState, geometry) { + function createBoundingVolume(groundPrimitive, frameState, geometry) { var ellipsoid = frameState.mapProjection.ellipsoid; var rectangle = getRectangle(frameState, geometry); // Use an oriented bounding box by default, but switch to a bounding sphere if bounding box creation would fail. if (rectangle.width < CesiumMath.PI) { - var obb = OrientedBoundingBox.fromRectangle(rectangle, primitive._maxHeight, primitive._minHeight, ellipsoid); - primitive._boundingVolumes.push(obb); + var obb = OrientedBoundingBox.fromRectangle(rectangle, groundPrimitive._maxHeight, groundPrimitive._minHeight, ellipsoid); + groundPrimitive._boundingVolumes.push(obb); } else { var highPositions = geometry.attributes.position3DHigh.values; var lowPositions = geometry.attributes.position3DLow.values; - primitive._boundingVolumes.push(BoundingSphere.fromEncodedCartesianVertices(highPositions, lowPositions)); + groundPrimitive._boundingVolumes.push(BoundingSphere.fromEncodedCartesianVertices(highPositions, lowPositions)); } if (!frameState.scene3DOnly) { var projection = frameState.mapProjection; - var boundingVolume = BoundingSphere.fromRectangleWithHeights2D(rectangle, projection, primitive._maxHeight, primitive._minHeight); + var boundingVolume = BoundingSphere.fromRectangleWithHeights2D(rectangle, projection, groundPrimitive._maxHeight, groundPrimitive._minHeight); Cartesian3.fromElements(boundingVolume.center.z, boundingVolume.center.x, boundingVolume.center.y, boundingVolume.center); - primitive._boundingVolumes2D.push(boundingVolume); + groundPrimitive._boundingVolumes2D.push(boundingVolume); } } - function createRenderStates(primitive, context, appearance, twoPasses) { - if (defined(primitive._rsStencilPreloadPass)) { + function createRenderStates(groundPrimitive, context, appearance, twoPasses) { + if (defined(groundPrimitive._rsStencilPreloadPass)) { return; } + var stencilEnabled = !groundPrimitive.debugShowShadowVolume; - primitive._rsStencilPreloadPass = RenderState.fromCache(stencilPreloadRenderState); - primitive._rsStencilDepthPass = RenderState.fromCache(stencilDepthRenderState); - primitive._rsColorPass = RenderState.fromCache(colorRenderState); - primitive._rsPickPass = RenderState.fromCache(pickRenderState); + groundPrimitive._rsStencilPreloadPass = RenderState.fromCache(getStencilPreloadRenderState(stencilEnabled)); + groundPrimitive._rsStencilDepthPass = RenderState.fromCache(getStencilDepthRenderState(stencilEnabled)); + groundPrimitive._rsColorPass = RenderState.fromCache(getColorRenderState(stencilEnabled)); + groundPrimitive._rsPickPass = RenderState.fromCache(pickRenderState); } - function createShaderProgram(primitive, frameState, appearance) { - if (defined(primitive._sp)) { + function createShaderProgram(groundPrimitive, frameState, appearance) { + if (defined(groundPrimitive._sp)) { return; } var context = frameState.context; var vs = ShadowVolumeVS; - vs = primitive._primitive._batchTable.getVertexShaderCallback()(vs); - vs = Primitive._appendShowToShader(primitive._primitive, vs); - vs = Primitive._appendDistanceDisplayConditionToShader(primitive._primitive, vs); - vs = Primitive._modifyShaderPosition(primitive, vs, frameState.scene3DOnly); - vs = Primitive._updateColorAttribute(primitive._primitive, vs); + vs = groundPrimitive._primitive._batchTable.getVertexShaderCallback()(vs); + vs = Primitive._appendShowToShader(groundPrimitive._primitive, vs); + vs = Primitive._appendDistanceDisplayConditionToShader(groundPrimitive._primitive, vs); + vs = Primitive._modifyShaderPosition(groundPrimitive, vs, frameState.scene3DOnly); + vs = Primitive._updateColorAttribute(groundPrimitive._primitive, vs); var fs = ShadowVolumeFS; - var attributeLocations = primitive._primitive._attributeLocations; + var attributeLocations = groundPrimitive._primitive._attributeLocations; - primitive._sp = ShaderProgram.replaceCache({ + groundPrimitive._sp = ShaderProgram.replaceCache({ context : context, - shaderProgram : primitive._sp, + shaderProgram : groundPrimitive._sp, vertexShaderSource : vs, fragmentShaderSource : fs, attributeLocations : attributeLocations }); - if (primitive._primitive.allowPicking) { + if (groundPrimitive._primitive.allowPicking) { var vsPick = ShaderSource.createPickVertexShaderSource(vs); vsPick = Primitive._updatePickColorAttribute(vsPick); @@ -759,15 +767,15 @@ define([ sources : [fs], pickColorQualifier : 'varying' }); - primitive._spPick = ShaderProgram.replaceCache({ + groundPrimitive._spPick = ShaderProgram.replaceCache({ context : context, - shaderProgram : primitive._spPick, + shaderProgram : groundPrimitive._spPick, vertexShaderSource : vsPick, fragmentShaderSource : pickFS, attributeLocations : attributeLocations }); } else { - primitive._spPick = ShaderProgram.fromCache({ + groundPrimitive._spPick = ShaderProgram.fromCache({ context : context, vertexShaderSource : vs, fragmentShaderSource : fs, @@ -1011,8 +1019,10 @@ define([ return; } + var that = this; + var primitiveOptions = this._primitiveOptions; + if (!defined(this._primitive)) { - var primitiveOptions = this._primitiveOptions; var ellipsoid = frameState.mapProjection.ellipsoid; var instance; @@ -1086,7 +1096,6 @@ define([ primitiveOptions.geometryInstances = groundInstances; - var that = this; primitiveOptions._createBoundingVolumeFunction = function(frameState, geometry) { createBoundingVolume(that, frameState, geometry); }; @@ -1120,52 +1129,20 @@ define([ }); } - this._primitive.debugShowBoundingVolume = this.debugShowBoundingVolume; - this._primitive.update(frameState); - - if (this.debugShowShadowVolume && !defined(this._debugPrimitive) && defined(this.geometryInstances)) { - var debugInstances = isArray(this.geometryInstances) ? this.geometryInstances : [this.geometryInstances]; - var debugLength = debugInstances.length; - var debugVolumeInstances = new Array(debugLength); - - for (var j = 0 ; j < debugLength; ++j) { - var debugInstance = debugInstances[j]; - var debugGeometry = debugInstance.geometry; - var debugInstanceType = debugGeometry.constructor; - if (defined(debugInstanceType) && defined(debugInstanceType.createShadowVolume)) { - var debugColorArray = debugInstance.attributes.color.value; - var debugColor = Color.fromBytes(debugColorArray[0], debugColorArray[1], debugColorArray[2], debugColorArray[3]); - Color.subtract(new Color(1.0, 1.0, 1.0, 0.0), debugColor, debugColor); - debugVolumeInstances[j] = new GeometryInstance({ - geometry : debugInstanceType.createShadowVolume(debugGeometry, getComputeMinimumHeightFunction(this), getComputeMaximumHeightFunction(this)), - attributes : { - color : ColorGeometryInstanceAttribute.fromColor(debugColor) - }, - id : debugInstance.id, - pickPrimitive : this - }); - } - } - - this._debugPrimitive = new Primitive({ - geometryInstances : debugVolumeInstances, - releaseGeometryInstances : true, - allowPicking : false, - asynchronous : false, - appearance : new PerInstanceColorAppearance({ - flat : true - }) - }); + if (this.debugShowShadowVolume && !this._debugShowShadowVolume && this._ready) { + this._debugShowShadowVolume = true; + this._rsStencilPreloadPass = RenderState.fromCache(getStencilPreloadRenderState(false)); + this._rsStencilDepthPass = RenderState.fromCache(getStencilDepthRenderState(false)); + this._rsColorPass = RenderState.fromCache(getColorRenderState(false)); + } else if (!this.debugShowShadowVolume && this._debugShowShadowVolume) { + this._debugShowShadowVolume = false; + this._rsStencilPreloadPass = RenderState.fromCache(getStencilPreloadRenderState(true)); + this._rsStencilDepthPass = RenderState.fromCache(getStencilDepthRenderState(true)); + this._rsColorPass = RenderState.fromCache(getColorRenderState(true)); } - if (defined(this._debugPrimitive)) { - if (this.debugShowShadowVolume) { - this._debugPrimitive.update(frameState); - } else { - this._debugPrimitive.destroy(); - this._debugPrimitive = undefined; - } - } + this._primitive.debugShowBoundingVolume = this.debugShowBoundingVolume; + this._primitive.update(frameState); }; /** @@ -1237,7 +1214,6 @@ define([ */ GroundPrimitive.prototype.destroy = function() { this._primitive = this._primitive && this._primitive.destroy(); - this._debugPrimitive = this._debugPrimitive && this._debugPrimitive.destroy(); this._sp = this._sp && this._sp.destroy(); this._spPick = this._spPick && this._spPick.destroy(); return destroyObject(this); From 0f5b872900446a581d282af02b4aa248b63ddaab Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Wed, 4 Jan 2017 08:56:54 -0500 Subject: [PATCH 11/14] Style --- Source/Shaders/ShadowVolumeVS.glsl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Shaders/ShadowVolumeVS.glsl b/Source/Shaders/ShadowVolumeVS.glsl index a20b00d1ed9a..888eca6500dd 100644 --- a/Source/Shaders/ShadowVolumeVS.glsl +++ b/Source/Shaders/ShadowVolumeVS.glsl @@ -1,11 +1,11 @@ -uniform float u_globeMinimumAltitude; - attribute vec3 position3DHigh; attribute vec3 position3DLow; attribute vec3 extrudeDirection; attribute vec4 color; attribute float batchId; +uniform float u_globeMinimumAltitude; + // emulated noperspective varying float v_WindowZ; varying vec4 v_color; From fdcb9aefed63b1faf6c839025417942601825439 Mon Sep 17 00:00:00 2001 From: hpinkos Date: Wed, 4 Jan 2017 16:11:47 -0500 Subject: [PATCH 12/14] cleanup, octencode extrudeDirection --- Source/Core/GeometryPipeline.js | 76 ++++++++++++++----- Source/Renderer/AutomaticUniforms.js | 2 +- Source/Renderer/UniformState.js | 31 +++----- Source/Scene/GroundPrimitive.js | 37 ++++++++- .../Shaders/Builtin/Functions/octDecode.glsl | 3 + 5 files changed, 103 insertions(+), 46 deletions(-) diff --git a/Source/Core/GeometryPipeline.js b/Source/Core/GeometryPipeline.js index 448396bf69b1..13e121e2c431 100644 --- a/Source/Core/GeometryPipeline.js +++ b/Source/Core/GeometryPipeline.js @@ -1363,53 +1363,87 @@ define([ } //>>includeEnd('debug'); + var extrudeAttribute = geometry.attributes.extrudeDirection; + var i; + var index; + var numVertices; + if (defined(extrudeAttribute)) { + //only shadow volumes use extrudeDirection, and shadow volumes use vertexFormat: POSITION_ONLY so we don't need to check other attributes + var extrudeDirections = extrudeAttribute.values; + numVertices = extrudeDirections.length / 3.0; + var compressedDirections = new Float32Array(numVertices); + + for (i = 0; i < numVertices; ++i) { + index = i * 3.0; + Cartesian3.fromArray(extrudeDirections, index, toEncode1); + if (Cartesian3.equals(toEncode1, Cartesian3.ZERO)) { + continue; + } + compressedDirections[i] = AttributeCompression.octEncodeFloat(toEncode1); + } + + geometry.attributes.compressedAttributes = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 1, + values : compressedDirections + }); + delete geometry.attributes.extrudeDirection; + return geometry; + } + var normalAttribute = geometry.attributes.normal; var stAttribute = geometry.attributes.st; - if (!defined(normalAttribute) && !defined(stAttribute)) { + + var hasNormal = defined(normalAttribute); + var hasSt = defined(stAttribute); + if (!hasNormal && !hasSt) { return geometry; } var tangentAttribute = geometry.attributes.tangent; var binormalAttribute = geometry.attributes.binormal; + var hasTangent = defined(tangentAttribute); + var hasBinormal = defined(binormalAttribute); + var normals; var st; var tangents; var binormals; - if (defined(normalAttribute)) { + if (hasNormal) { normals = normalAttribute.values; } - if (defined(stAttribute)) { + if (hasSt) { st = stAttribute.values; } - if (defined(tangentAttribute)) { + if (hasTangent) { tangents = tangentAttribute.values; } - if (binormalAttribute) { + if (hasBinormal) { binormals = binormalAttribute.values; } - var length = defined(normals) ? normals.length : st.length; - var numComponents = defined(normals) ? 3.0 : 2.0; - var numVertices = length / numComponents; + var length = hasNormal ? normals.length : st.length; + var numComponents = hasNormal ? 3.0 : 2.0; + numVertices = length / numComponents; var compressedLength = numVertices; - var numCompressedComponents = defined(st) && defined(normals) ? 2.0 : 1.0; - numCompressedComponents += defined(tangents) || defined(binormals) ? 1.0 : 0.0; + var numCompressedComponents = hasSt && hasNormal ? 2.0 : 1.0; + numCompressedComponents += hasTangent || hasBinormal ? 1.0 : 0.0; compressedLength *= numCompressedComponents; var compressedAttributes = new Float32Array(compressedLength); var normalIndex = 0; - for (var i = 0; i < numVertices; ++i) { - if (defined(st)) { + for (i = 0; i < numVertices; ++i) { + if (hasSt) { Cartesian2.fromArray(st, i * 2.0, scratchCartesian2); compressedAttributes[normalIndex++] = AttributeCompression.compressTextureCoordinates(scratchCartesian2); } - var index = i * 3.0; - if (defined(normals) && defined(tangents) && defined(binormals)) { + index = i * 3.0; + if (hasNormal && defined(tangents) && defined(binormals)) { Cartesian3.fromArray(normals, index, toEncode1); Cartesian3.fromArray(tangents, index, toEncode2); Cartesian3.fromArray(binormals, index, toEncode3); @@ -1418,17 +1452,17 @@ define([ compressedAttributes[normalIndex++] = scratchCartesian2.x; compressedAttributes[normalIndex++] = scratchCartesian2.y; } else { - if (defined(normals)) { + if (hasNormal) { Cartesian3.fromArray(normals, index, toEncode1); compressedAttributes[normalIndex++] = AttributeCompression.octEncodeFloat(toEncode1); } - if (defined(tangents)) { + if (hasTangent) { Cartesian3.fromArray(tangents, index, toEncode1); compressedAttributes[normalIndex++] = AttributeCompression.octEncodeFloat(toEncode1); } - if (defined(binormals)) { + if (hasBinormal) { Cartesian3.fromArray(binormals, index, toEncode1); compressedAttributes[normalIndex++] = AttributeCompression.octEncodeFloat(toEncode1); } @@ -1441,16 +1475,16 @@ define([ values : compressedAttributes }); - if (defined(normals)) { + if (hasNormal) { delete geometry.attributes.normal; } - if (defined(st)) { + if (hasSt) { delete geometry.attributes.st; } - if (defined(tangents)) { + if (hasTangent) { delete geometry.attributes.tangent; } - if (defined(binormals)) { + if (hasBinormal) { delete geometry.attributes.binormal; } diff --git a/Source/Renderer/AutomaticUniforms.js b/Source/Renderer/AutomaticUniforms.js index f520cf0aedf4..6f71025bf1cb 100644 --- a/Source/Renderer/AutomaticUniforms.js +++ b/Source/Renderer/AutomaticUniforms.js @@ -1488,7 +1488,7 @@ define([ size: 1, datatype: WebGLConstants.FLOAT, getValue: function(uniformState) { - return uniformState.pixelSizePerMeter * uniformState.maximumScreenSpaceError; + return uniformState.geometricToleranceOverMeter; } }) }; diff --git a/Source/Renderer/UniformState.js b/Source/Renderer/UniformState.js index 6818f9f5e222..e0f77ea724d3 100644 --- a/Source/Renderer/UniformState.js +++ b/Source/Renderer/UniformState.js @@ -151,6 +151,7 @@ define([ this._fogDensity = undefined; this._pixelSizePerMeter = undefined; + this._geometricToleranceOverMeter = undefined; } defineProperties(UniformState.prototype, { @@ -770,26 +771,13 @@ define([ }, /** - * The maximum screen-space error used to drive level-of-detail refinement. Higher - * values will provide better performance but lower visual quality. - * - * @type {Number} - * @default 2 - */ - maximumScreenSpaceError: { - get: function() { - return this._frameState.maximumScreenSpaceError; - } - }, - - /** - * The size of one pixel in meters - * + * A scalar that represents the geometric tolerance per meter + * @memberof UniformStat.prototype * @type {Number} */ - pixelSizePerMeter: { + geometricToleranceOverMeter: { get: function() { - return this._pixelSizePerMeter; + return this._geometricToleranceOverMeter; } }, @@ -964,11 +952,14 @@ define([ var fov = camera.frustum.fov; var viewport = this._viewport; - if (viewport.width > viewport.height * camera.frustum.aspectRatio) { - this._pixelSizePerMeter = Math.tan(0.5 * fov) * 2.0 / viewport.width; + var pixelSizePerMeter; + if (viewport.height > viewport.width) { + pixelSizePerMeter = Math.tan(0.5 * fov) * 2.0 / viewport.height; } else { - this._pixelSizePerMeter = Math.tan(0.5 * fov) * 2.0 / viewport.height; + pixelSizePerMeter = Math.tan(0.5 * fov) * 2.0 / viewport.width; } + + this._geometricToleranceOverMeter = pixelSizePerMeter * frameState.maximumScreenSpaceError; }; function cleanViewport(uniformState) { diff --git a/Source/Scene/GroundPrimitive.js b/Source/Scene/GroundPrimitive.js index b01058f7e7fe..d87ef7ed5bb4 100644 --- a/Source/Scene/GroundPrimitive.js +++ b/Source/Scene/GroundPrimitive.js @@ -734,19 +734,48 @@ define([ groundPrimitive._rsPickPass = RenderState.fromCache(pickRenderState); } + function modifyForEncodedNormals(primitive, vertexShaderSource) { + if (!primitive.compressVertices) { + return vertexShaderSource; + } + + if (vertexShaderSource.search(/attribute\s+vec3\s+extrudeDirection;/g) !== -1) { + var attributeName = 'compressedAttributes'; + + //only shadow volumes use extrudeDirection, and shadow volumes use vertexFormat: POSITION_ONLY so we don't need to check other attributes + var attributeDecl = 'attribute float ' + attributeName + ';'; + + var globalDecl = 'vec3 extrudeDirection;\n'; + var decode = ' extrudeDirection = czm_octDecode(' + attributeName + ');\n'; + + var modifiedVS = vertexShaderSource; + modifiedVS = modifiedVS.replace(/attribute\s+vec3\s+extrudeDirection;/g, ''); + modifiedVS = ShaderSource.replaceMain(modifiedVS, 'czm_non_compressed_main'); + var compressedMain = + 'void main() \n' + + '{ \n' + + decode + + ' czm_non_compressed_main(); \n' + + '}'; + + return [attributeDecl, globalDecl, modifiedVS, compressedMain].join('\n'); + } + } + function createShaderProgram(groundPrimitive, frameState, appearance) { if (defined(groundPrimitive._sp)) { return; } var context = frameState.context; - + var primitive = groundPrimitive._primitive; var vs = ShadowVolumeVS; vs = groundPrimitive._primitive._batchTable.getVertexShaderCallback()(vs); - vs = Primitive._appendShowToShader(groundPrimitive._primitive, vs); - vs = Primitive._appendDistanceDisplayConditionToShader(groundPrimitive._primitive, vs); + vs = Primitive._appendShowToShader(primitive, vs); + vs = Primitive._appendDistanceDisplayConditionToShader(primitive, vs); vs = Primitive._modifyShaderPosition(groundPrimitive, vs, frameState.scene3DOnly); - vs = Primitive._updateColorAttribute(groundPrimitive._primitive, vs); + vs = Primitive._updateColorAttribute(primitive, vs); + vs = modifyForEncodedNormals(primitive, vs); var fs = ShadowVolumeFS; var attributeLocations = groundPrimitive._primitive._attributeLocations; diff --git a/Source/Shaders/Builtin/Functions/octDecode.glsl b/Source/Shaders/Builtin/Functions/octDecode.glsl index 4fe85a220bb6..5a224b9552c1 100644 --- a/Source/Shaders/Builtin/Functions/octDecode.glsl +++ b/Source/Shaders/Builtin/Functions/octDecode.glsl @@ -30,6 +30,9 @@ */ vec3 czm_octDecode(float encoded) { + if (encoded == 0.0) { + return vec3(0.0, 0.0, 0.0); + } float temp = encoded / 256.0; float x = floor(temp); float y = (temp - x) * 256.0; From 56eec834e8d24d4e631c8baf88c10079b2a2f9ad Mon Sep 17 00:00:00 2001 From: hpinkos Date: Wed, 4 Jan 2017 16:15:52 -0500 Subject: [PATCH 13/14] CHANGES.md --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index 9bbc1d66ba52..7119c3548f4e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,6 +4,7 @@ Change Log ### 1.30 - 2017-02-01 * Updated the morph so the default view in Columbus View is now angled. [#3878](https://github.com/AnalyticalGraphicsInc/cesium/issues/3878) +* Fixed bug where `GroundPrimitives` where rendering incorrectly or disappearing at different zoom levels. [#4161](https://github.com/AnalyticalGraphicsInc/cesium/issues/4161) [#4326](https://github.com/AnalyticalGraphicsInc/cesium/issues/4326) * Fixed sky atmosphere from causing incorrect picking and hanging drill picking. [#4783](https://github.com/AnalyticalGraphicsInc/cesium/issues/4783) and [#4784](https://github.com/AnalyticalGraphicsInc/cesium/issues/4784) ### 1.29 - 2017-01-02 From 2d672d7a54d689b140a1c710c427a64357a8d783 Mon Sep 17 00:00:00 2001 From: hpinkos Date: Thu, 5 Jan 2017 15:48:02 -0500 Subject: [PATCH 14/14] octencode 32P --- Source/Core/GeometryPipeline.js | 18 +++++---- Source/Scene/GroundPrimitive.js | 4 +- .../Shaders/Builtin/Functions/octDecode.glsl | 38 +++++++++++++------ 3 files changed, 39 insertions(+), 21 deletions(-) diff --git a/Source/Core/GeometryPipeline.js b/Source/Core/GeometryPipeline.js index 13e121e2c431..23bbeb25a91a 100644 --- a/Source/Core/GeometryPipeline.js +++ b/Source/Core/GeometryPipeline.js @@ -1346,7 +1346,7 @@ define([ var toEncode1 = new Cartesian3(); var toEncode2 = new Cartesian3(); var toEncode3 = new Cartesian3(); - + var encodeResult2 = new Cartesian2(); /** * Compresses and packs geometry normal attribute values to save memory. * @@ -1365,26 +1365,28 @@ define([ var extrudeAttribute = geometry.attributes.extrudeDirection; var i; - var index; var numVertices; if (defined(extrudeAttribute)) { //only shadow volumes use extrudeDirection, and shadow volumes use vertexFormat: POSITION_ONLY so we don't need to check other attributes var extrudeDirections = extrudeAttribute.values; numVertices = extrudeDirections.length / 3.0; - var compressedDirections = new Float32Array(numVertices); + var compressedDirections = new Float32Array(numVertices * 2); + var i2 = 0; for (i = 0; i < numVertices; ++i) { - index = i * 3.0; - Cartesian3.fromArray(extrudeDirections, index, toEncode1); + Cartesian3.fromArray(extrudeDirections, i * 3.0, toEncode1); if (Cartesian3.equals(toEncode1, Cartesian3.ZERO)) { + i2 += 2; continue; } - compressedDirections[i] = AttributeCompression.octEncodeFloat(toEncode1); + encodeResult2 = AttributeCompression.octEncodeInRange(toEncode1, 65535, encodeResult2); + compressedDirections[i2++] = encodeResult2.x; + compressedDirections[i2++] = encodeResult2.y; } geometry.attributes.compressedAttributes = new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, - componentsPerAttribute : 1, + componentsPerAttribute : 2, values : compressedDirections }); delete geometry.attributes.extrudeDirection; @@ -1442,7 +1444,7 @@ define([ compressedAttributes[normalIndex++] = AttributeCompression.compressTextureCoordinates(scratchCartesian2); } - index = i * 3.0; + var index = i * 3.0; if (hasNormal && defined(tangents) && defined(binormals)) { Cartesian3.fromArray(normals, index, toEncode1); Cartesian3.fromArray(tangents, index, toEncode2); diff --git a/Source/Scene/GroundPrimitive.js b/Source/Scene/GroundPrimitive.js index d87ef7ed5bb4..eadf4b5cfe50 100644 --- a/Source/Scene/GroundPrimitive.js +++ b/Source/Scene/GroundPrimitive.js @@ -743,10 +743,10 @@ define([ var attributeName = 'compressedAttributes'; //only shadow volumes use extrudeDirection, and shadow volumes use vertexFormat: POSITION_ONLY so we don't need to check other attributes - var attributeDecl = 'attribute float ' + attributeName + ';'; + var attributeDecl = 'attribute vec2 ' + attributeName + ';'; var globalDecl = 'vec3 extrudeDirection;\n'; - var decode = ' extrudeDirection = czm_octDecode(' + attributeName + ');\n'; + var decode = ' extrudeDirection = czm_octDecode(' + attributeName + ', 65535.0);\n'; var modifiedVS = vertexShaderSource; modifiedVS = modifiedVS.replace(/attribute\s+vec3\s+extrudeDirection;/g, ''); diff --git a/Source/Shaders/Builtin/Functions/octDecode.glsl b/Source/Shaders/Builtin/Functions/octDecode.glsl index 5a224b9552c1..ce4df362da12 100644 --- a/Source/Shaders/Builtin/Functions/octDecode.glsl +++ b/Source/Shaders/Builtin/Functions/octDecode.glsl @@ -1,3 +1,29 @@ + /** + * Decodes a unit-length vector in 'oct' encoding to a normalized 3-component Cartesian vector. + * The 'oct' encoding is described in "A Survey of Efficient Representations of Independent Unit Vectors", + * Cigolle et al 2014: http://jcgt.org/published/0003/02/01/ + * + * @name czm_octDecode + * @param {vec2} encoded The oct-encoded, unit-length vector + * @param {float} range The maximum value of the SNORM range. The encoded vector is stored in log2(rangeMax+1) bits. + * @returns {vec3} The decoded and normalized vector + */ + vec3 czm_octDecode(vec2 encoded, float range) + { + if (encoded.x == 0.0 && encoded.y == 0.0) { + return vec3(0.0, 0.0, 0.0); + } + + encoded = encoded / range * 2.0 - 1.0; + vec3 v = vec3(encoded.x, encoded.y, 1.0 - abs(encoded.x) - abs(encoded.y)); + if (v.z < 0.0) + { + v.xy = (1.0 - abs(v.yx)) * czm_signNotZero(v.xy); + } + + return normalize(v); + } + /** * Decodes a unit-length vector in 'oct' encoding to a normalized 3-component Cartesian vector. * The 'oct' encoding is described in "A Survey of Efficient Representations of Independent Unit Vectors", @@ -9,14 +35,7 @@ */ vec3 czm_octDecode(vec2 encoded) { - encoded = encoded / 255.0 * 2.0 - 1.0; - vec3 v = vec3(encoded.x, encoded.y, 1.0 - abs(encoded.x) - abs(encoded.y)); - if (v.z < 0.0) - { - v.xy = (1.0 - abs(v.yx)) * czm_signNotZero(v.xy); - } - - return normalize(v); + return czm_octDecode(encoded, 255.0); } /** @@ -30,9 +49,6 @@ */ vec3 czm_octDecode(float encoded) { - if (encoded == 0.0) { - return vec3(0.0, 0.0, 0.0); - } float temp = encoded / 256.0; float x = floor(temp); float y = (temp - x) * 256.0;