From 6fafa6001d70b7f7be19ea03b6b79b6008086120 Mon Sep 17 00:00:00 2001 From: Kanging Li Date: Sun, 16 Dec 2018 22:46:56 -0500 Subject: [PATCH 1/7] improve attribute reliability for ground primitive materials --- Source/Scene/ShadowVolumeAppearance.js | 162 +++++++++++++------ Source/Shaders/ShadowVolumeAppearanceVS.glsl | 97 ++++++++++- Specs/Scene/ShadowVolumeAppearanceSpec.js | 140 ++++++++++------ 3 files changed, 292 insertions(+), 107 deletions(-) diff --git a/Source/Scene/ShadowVolumeAppearance.js b/Source/Scene/ShadowVolumeAppearance.js index 42adc5d7e093..88434cea7f75 100644 --- a/Source/Scene/ShadowVolumeAppearance.js +++ b/Source/Scene/ShadowVolumeAppearance.js @@ -403,6 +403,75 @@ define([ }); } + function encodeLowLessThan100k(value, valueName, attributes) { + // Encode a value like 12,345.678 to 4 uint8 values: 12 34 56 78 + var fract = Math.abs(value); + var d12 = Math.floor(fract / 1000); + fract -= d12 * 1000; // 345.678 + var d34 = Math.floor(fract / 10); + fract -= d34 * 10; // 5.678 + var d56 = Math.floor(fract * 10); + fract -= d56 * 0.1; // 0.078 + var d78 = Math.floor(fract * 1000); + + if (value < 0) { + d12 = 255 - d12; + } + + attributes[valueName] = new GeometryInstanceAttribute({ + componentDatatype: ComponentDatatype.UNSIGNED_BYTE, + componentsPerAttribute: 4, + normalize: false, + value : [d12, d34, d56, d78] + }); + } + + function encodeHighLessThan100Million(value, valueName, attributes) { + // Encode a value like -12,345,678 to 4 uint8 values: sign+12 34 56 78 + var fract = Math.abs(value); + var d12 = Math.floor(fract / 1000000); + fract -= d12 * 1000000; // 345678 + var d34 = Math.floor(fract / 10000); + fract -= d34 * 10000; // 5678 + var d56 = Math.floor(fract / 100); + fract -= d56 * 100; // 78 + var d78 = Math.floor(fract); + + if (value < 0) { + d12 = 255 - d12; + } + + attributes[valueName] = new GeometryInstanceAttribute({ + componentDatatype: ComponentDatatype.UNSIGNED_BYTE, + componentsPerAttribute: 4, + normalize: false, + value : [d12, d34, d56, d78] + }); + } + + function encodeLessThan1000k(value, valueName, attributes) { + // Encode a value like -123456.78 to 4 uint8 values sign+12 34 56 78 + var fract = Math.abs(value); + var d12 = Math.floor(fract / 10000); + fract -= d12 * 10000; // 3456.78 + var d34 = Math.floor(fract / 100); + fract -= d34 * 100; // 56.78 + var d56 = Math.floor(fract); + fract -= d56; // 0.78 + var d78 = Math.floor(fract / 0.001); + + if (value < 0) { + d12 = 255 - d12; + } + + attributes[valueName] = new GeometryInstanceAttribute({ + componentDatatype: ComponentDatatype.UNSIGNED_BYTE, + componentsPerAttribute: 4, + normalize: false, + value : [d12, d34, d56, d78] + }); + } + var cartographicScratch = new Cartographic(); var cornerScratch = new Cartesian3(); var northWestScratch = new Cartesian3(); @@ -432,37 +501,22 @@ define([ // y: y value for southWestCorner // z: y value for northWest // w: x value for southEast - var valuesHigh = [0, 0, 0, 0]; - var valuesLow = [0, 0, 0, 0]; + var encoded = EncodedCartesian3.encode(southWestCorner.x, highLowScratch); - valuesHigh[0] = encoded.high; - valuesLow[0] = encoded.low; + encodeHighLessThan100Million(encoded.high, 'planes2D_HIGH_x', attributes); + encodeLowLessThan100k(encoded.low, 'planes2D_LOW_x', attributes); encoded = EncodedCartesian3.encode(southWestCorner.y, highLowScratch); - valuesHigh[1] = encoded.high; - valuesLow[1] = encoded.low; + encodeHighLessThan100Million(encoded.high, 'planes2D_HIGH_y', attributes); + encodeLowLessThan100k(encoded.low, 'planes2D_LOW_y', attributes); encoded = EncodedCartesian3.encode(northWest.y, highLowScratch); - valuesHigh[2] = encoded.high; - valuesLow[2] = encoded.low; + encodeHighLessThan100Million(encoded.high, 'planes2D_HIGH_z', attributes); + encodeLowLessThan100k(encoded.low, 'planes2D_LOW_z', attributes); encoded = EncodedCartesian3.encode(southEast.x, highLowScratch); - valuesHigh[3] = encoded.high; - valuesLow[3] = encoded.low; - - attributes.planes2D_HIGH = new GeometryInstanceAttribute({ - componentDatatype: ComponentDatatype.FLOAT, - componentsPerAttribute: 4, - normalize: false, - value : valuesHigh - }); - - attributes.planes2D_LOW = new GeometryInstanceAttribute({ - componentDatatype: ComponentDatatype.FLOAT, - componentsPerAttribute: 4, - normalize: false, - value : valuesLow - }); + encodeHighLessThan100Million(encoded.high, 'planes2D_HIGH_w', attributes); + encodeLowLessThan100k(encoded.low, 'planes2D_LOW_w', attributes); } var enuMatrixScratch = new Matrix4(); @@ -598,30 +652,24 @@ define([ addTextureCoordinateRotationAttributes(attributes, textureCoordinateRotationPoints); var encoded = EncodedCartesian3.fromCartesian(corner, encodeScratch); - attributes.southWest_HIGH = new GeometryInstanceAttribute({ - componentDatatype: ComponentDatatype.FLOAT, - componentsPerAttribute: 3, - normalize: false, - value : Cartesian3.pack(encoded.high, [0, 0, 0]) - }); - attributes.southWest_LOW = new GeometryInstanceAttribute({ - componentDatatype: ComponentDatatype.FLOAT, - componentsPerAttribute: 3, - normalize: false, - value : Cartesian3.pack(encoded.low, [0, 0, 0]) - }); - attributes.eastward = new GeometryInstanceAttribute({ - componentDatatype: ComponentDatatype.FLOAT, - componentsPerAttribute: 3, - normalize: false, - value : Cartesian3.pack(eastward, [0, 0, 0]) - }); - attributes.northward = new GeometryInstanceAttribute({ - componentDatatype: ComponentDatatype.FLOAT, - componentsPerAttribute: 3, - normalize: false, - value : Cartesian3.pack(northward, [0, 0, 0]) - }); + + var high = encoded.high; + encodeHighLessThan100Million(high.x, 'southWest_HIGH_x', attributes); + encodeHighLessThan100Million(high.y, 'southWest_HIGH_y', attributes); + encodeHighLessThan100Million(high.z, 'southWest_HIGH_z', attributes); + + var low = encoded.low; + encodeLowLessThan100k(low.x, 'southWest_LOW_x', attributes); + encodeLowLessThan100k(low.y, 'southWest_LOW_y', attributes); + encodeLowLessThan100k(low.z, 'southWest_LOW_z', attributes); + + encodeLessThan1000k(eastward.x, 'eastward_x', attributes); + encodeLessThan1000k(eastward.y, 'eastward_y', attributes); + encodeLessThan1000k(eastward.z, 'eastward_z', attributes); + + encodeLessThan1000k(northward.x, 'northward_x', attributes); + encodeLessThan1000k(northward.y, 'northward_y', attributes); + encodeLessThan1000k(northward.z, 'northward_z', attributes); add2DTextureCoordinateAttributes(boundingRectangle, projection, attributes); return attributes; @@ -726,15 +774,25 @@ define([ }; ShadowVolumeAppearance.hasAttributesForTextureCoordinatePlanes = function(attributes) { - return defined(attributes.southWest_HIGH) && defined(attributes.southWest_LOW) && - defined(attributes.northward) && defined(attributes.eastward) && - defined(attributes.planes2D_HIGH) && defined(attributes.planes2D_LOW) && + return defined(attributes.southWest_HIGH_x) && defined(attributes.southWest_LOW_x) && + defined(attributes.southWest_HIGH_y) && defined(attributes.southWest_LOW_y) && + defined(attributes.southWest_HIGH_z) && defined(attributes.southWest_LOW_z) && + defined(attributes.northward_x) && defined(attributes.eastward_x) && + defined(attributes.northward_y) && defined(attributes.eastward_y) && + defined(attributes.northward_z) && defined(attributes.eastward_z) && + defined(attributes.planes2D_HIGH_x) && defined(attributes.planes2D_LOW_x) && + defined(attributes.planes2D_HIGH_y) && defined(attributes.planes2D_LOW_y) && + defined(attributes.planes2D_HIGH_z) && defined(attributes.planes2D_LOW_z) && + defined(attributes.planes2D_HIGH_w) && defined(attributes.planes2D_LOW_w) && defined(attributes.uMaxVmax) && defined(attributes.uvMinAndExtents); }; ShadowVolumeAppearance.hasAttributesForSphericalExtents = function(attributes) { return defined(attributes.sphericalExtents) && defined(attributes.longitudeRotation) && - defined(attributes.planes2D_HIGH) && defined(attributes.planes2D_LOW) && + defined(attributes.planes2D_HIGH_x) && defined(attributes.planes2D_LOW_x) && + defined(attributes.planes2D_HIGH_y) && defined(attributes.planes2D_LOW_y) && + defined(attributes.planes2D_HIGH_z) && defined(attributes.planes2D_LOW_z) && + defined(attributes.planes2D_HIGH_w) && defined(attributes.planes2D_LOW_w) && defined(attributes.uMaxVmax) && defined(attributes.uvMinAndExtents); }; diff --git a/Source/Shaders/ShadowVolumeAppearanceVS.glsl b/Source/Shaders/ShadowVolumeAppearanceVS.glsl index 0f2b1c456a3b..5cd0d118b42e 100644 --- a/Source/Shaders/ShadowVolumeAppearanceVS.glsl +++ b/Source/Shaders/ShadowVolumeAppearanceVS.glsl @@ -25,6 +25,78 @@ varying vec3 v_uMaxAndInverseDistance; varying vec3 v_vMaxAndInverseDistance; #endif // TEXTURE_COORDINATES +#if defined(TEXTURE_COORDINATES) && !defined(SPHERICAL) +vec4 clampAndMagnitude(vec4 sd) { + vec4 d = sd; + d.x = czm_branchFreeTernary(sd.x < 128.0, d.x, (255.0 - sd.x)); + d.x = floor(0.5 + d.x); + d.y = floor(0.5 + d.y); + d.z = floor(0.5 + d.z); + d.w = floor(0.5 + d.w); + return d; +} + +float unpackLowLessThan100k(vec4 sd) { + vec4 d = clampAndMagnitude(sd); + return (1000.0 * d.x + 10.0 * d.y + 0.1 * d.z + 0.001 * d.w) * czm_branchFreeTernary(sd.x < 128.0, 1.0, -1.0); +} + +vec3 southwest_LOW(vec4 x, vec4 y, vec4 z) { + vec3 value; + value.x = unpackLowLessThan100k(x); + value.y = unpackLowLessThan100k(y); + value.z = unpackLowLessThan100k(z); + return value; +} + +float unpackHighMagLessThan100Million(vec4 sd) { + vec4 d = clampAndMagnitude(sd); + return (1000000.0 * d.x + 10000.0 * d.y + 100.0 * d.z + d.w) * czm_branchFreeTernary(sd.x < 128.0, 1.0, -1.0); +} +vec3 southwest_HIGH(vec4 x, vec4 y, vec4 z) { + vec3 value; + value.x = unpackHighMagLessThan100Million(x); + value.y = unpackHighMagLessThan100Million(y); + value.z = unpackHighMagLessThan100Million(z); + return value; +} + +#ifdef COLUMBUS_VIEW_2D +vec4 unpackPlanes2D_HIGH(vec4 x, vec4 y, vec4 z, vec4 w) { + vec4 value; + value.x = unpackHighMagLessThan100Million(x); + value.y = unpackHighMagLessThan100Million(y); + value.z = unpackHighMagLessThan100Million(z); + value.w = unpackHighMagLessThan100Million(w); + return value; +} + +vec4 unpackPlanes2D_LOW(vec4 x, vec4 y, vec4 z, vec4 w) { + vec4 value; + value.x = unpackLowLessThan100k(x); + value.y = unpackLowLessThan100k(y); + value.z = unpackLowLessThan100k(z); + value.w = unpackLowLessThan100k(w); + return value; +} + +#else +float unpackLowLessThan1000k(vec4 sd) { + vec4 d = clampAndMagnitude(sd); + return (10000.0 * d.x + 100.0 * d.y + d.z + 0.01 * d.w) * czm_branchFreeTernary(sd.x < 128.0, 1.0, -1.0); +} + +vec3 unpackExtent(vec4 x, vec4 y, vec4 z) { + vec3 value; + value.x = unpackLowLessThan1000k(x); + value.y = unpackLowLessThan1000k(y); + value.z = unpackLowLessThan1000k(z); + return value; +} + +#endif +#endif + void main() { vec4 position = czm_computePosition(); @@ -43,8 +115,14 @@ void main() v_uvMinAndSphericalLongitudeRotation.z = czm_batchTable_longitudeRotation(batchId); #else // SPHERICAL #ifdef COLUMBUS_VIEW_2D - vec4 planes2D_high = czm_batchTable_planes2D_HIGH(batchId); - vec4 planes2D_low = czm_batchTable_planes2D_LOW(batchId); + vec4 planes2D_high = unpackPlanes2D_HIGH(czm_batchTable_planes2D_HIGH_x(batchId), + czm_batchTable_planes2D_HIGH_y(batchId), + czm_batchTable_planes2D_HIGH_z(batchId), + czm_batchTable_planes2D_HIGH_w(batchId)); + vec4 planes2D_low = unpackPlanes2D_LOW(czm_batchTable_planes2D_LOW_x(batchId), + czm_batchTable_planes2D_LOW_y(batchId), + czm_batchTable_planes2D_LOW_z(batchId), + czm_batchTable_planes2D_LOW_w(batchId)); // If the primitive is split across the IDL (planes2D_high.x > planes2D_high.w): // - If this vertex is on the east side of the IDL (position3DLow.y > 0.0, comparison with position3DHigh may produce artifacts) @@ -68,9 +146,18 @@ void main() vec3 southEastCorner = (czm_modelViewRelativeToEye * czm_translateRelativeToEye(vec3(0.0, planes2D_high.w, planes2D_high.y), vec3(0.0, planes2D_low.w, planes2D_low.y))).xyz; #else // COLUMBUS_VIEW_2D // 3D case has smaller "plane extents," so planes encoded as a 64 bit position and 2 vec3s for distances/direction - vec3 southWestCorner = (czm_modelViewRelativeToEye * czm_translateRelativeToEye(czm_batchTable_southWest_HIGH(batchId), czm_batchTable_southWest_LOW(batchId))).xyz; - vec3 northWestCorner = czm_normal * czm_batchTable_northward(batchId) + southWestCorner; - vec3 southEastCorner = czm_normal * czm_batchTable_eastward(batchId) + southWestCorner; + vec3 low = southwest_LOW(czm_batchTable_southWest_LOW_x(batchId), czm_batchTable_southWest_LOW_y(batchId), czm_batchTable_southWest_LOW_z(batchId)); + vec3 high = southwest_HIGH(czm_batchTable_southWest_HIGH_x(batchId), czm_batchTable_southWest_HIGH_y(batchId), czm_batchTable_southWest_HIGH_z(batchId)); + vec3 southWestCorner = (czm_modelViewRelativeToEye * czm_translateRelativeToEye(high, low)).xyz; + vec3 northWestCorner = czm_normal * unpackExtent( + czm_batchTable_northward_x(batchId), + czm_batchTable_northward_y(batchId), + czm_batchTable_northward_z(batchId)) + southWestCorner; + + vec3 southEastCorner = czm_normal * unpackExtent( + czm_batchTable_eastward_x(batchId), + czm_batchTable_eastward_y(batchId), + czm_batchTable_eastward_z(batchId)) + southWestCorner; #endif // COLUMBUS_VIEW_2D vec3 eastWard = southEastCorner - southWestCorner; diff --git a/Specs/Scene/ShadowVolumeAppearanceSpec.js b/Specs/Scene/ShadowVolumeAppearanceSpec.js index 8f08ce10f26f..0a761185c848 100644 --- a/Specs/Scene/ShadowVolumeAppearanceSpec.js +++ b/Specs/Scene/ShadowVolumeAppearanceSpec.js @@ -115,89 +115,129 @@ defineSuite([ expect(value[0]).toEqualEpsilon(0.0, CesiumMath.EPSILON4); }); - function checkGeometryInstanceAttributeVec3(attribute) { - expect(attribute.componentDatatype).toEqual(ComponentDatatype.FLOAT); - expect(attribute.componentsPerAttribute).toEqual(3); - expect(attribute.normalize).toEqual(false); + function clampAndMagnitude(signedVec4Attribute) { + var signedVec4 = signedVec4Attribute.value; + var unsigned = signedVec4.slice(); + unsigned[0] = signedVec4[0] < 128.0 ? signedVec4[0] : (255.0 - signedVec4[0]); + unsigned[0] = Math.floor(0.5 + unsigned[0]); + unsigned[1] = Math.floor(0.5 + unsigned[1]); + unsigned[2] = Math.floor(0.5 + unsigned[2]); + unsigned[3] = Math.floor(0.5 + unsigned[3]); + return unsigned; + } + + function unpackLowLessThan100k(signedVec4Attribute) { + var signed = signedVec4Attribute.value; + var unsigned = clampAndMagnitude(signedVec4Attribute); + return (1000.0 * unsigned[0] + 10.0 * unsigned[1] + 0.1 * unsigned[2] + 0.001 * unsigned[3]) * (signed[0] < 128.0 ? 1.0 : -1.0); + } + + function unpackHighMagLessThan100Million(signedVec4Attribute) { + var signed = signedVec4Attribute.value; + var unsigned = clampAndMagnitude(signedVec4Attribute); + return (1000000.0 * unsigned[0] + 10000.0 * unsigned[1] + 100.0 * unsigned[2] + unsigned[3]) * (signed[0] < 128.0 ? 1.0 : -1.0); + } + + function unpackLowLessThan1000k(signedVec4Attribute) { + var signed = signedVec4Attribute.value; + var unsigned = clampAndMagnitude(signedVec4Attribute); + return (10000.0 * unsigned[0] + 100.0 * unsigned[1] + unsigned[2] + 0.01 * unsigned[3]) * (signed[0] < 128.0 ? 1.0 : -1.0); } it('provides attributes for computing texture coordinates using planes in 3D', function() { var attributes = smallRectangleAttributes; - var southWest_LOW = attributes.southWest_LOW; - var southWest_HIGH = attributes.southWest_HIGH; - var eastward = attributes.eastward; - var northward = attributes.northward; + var southWest_LOW = [0, 0, 0]; + southWest_LOW[0] = unpackLowLessThan100k(attributes.southWest_LOW_x); + southWest_LOW[1] = unpackLowLessThan100k(attributes.southWest_LOW_y); + southWest_LOW[2] = unpackLowLessThan100k(attributes.southWest_LOW_z); - checkGeometryInstanceAttributeVec3(southWest_LOW); - checkGeometryInstanceAttributeVec3(southWest_HIGH); - checkGeometryInstanceAttributeVec3(eastward); - checkGeometryInstanceAttributeVec3(northward); + var southWest_HIGH = [0, 0, 0]; + southWest_HIGH[0] = unpackHighMagLessThan100Million(attributes.southWest_HIGH_x); + southWest_HIGH[1] = unpackHighMagLessThan100Million(attributes.southWest_HIGH_y); + southWest_HIGH[2] = unpackHighMagLessThan100Million(attributes.southWest_HIGH_z); + + var eastward = [0, 0, 0]; + eastward[0] = unpackLowLessThan1000k(attributes.eastward_x); + eastward[1] = unpackLowLessThan1000k(attributes.eastward_y); + eastward[2] = unpackLowLessThan1000k(attributes.eastward_z); + + var northward = [0, 0, 0]; + northward[0] = unpackLowLessThan1000k(attributes.northward_x); + northward[1] = unpackLowLessThan1000k(attributes.northward_y); + northward[2] = unpackLowLessThan1000k(attributes.northward_z); // We're using a unit sphere, so expect all HIGH values to be basically 0 // and LOW value to be within a small cone around UNIT_X - expect(southWest_HIGH.value[0]).toEqualEpsilon(0.0, CesiumMath.EPSILON7); - expect(southWest_HIGH.value[1]).toEqualEpsilon(0.0, CesiumMath.EPSILON7); - expect(southWest_HIGH.value[2]).toEqualEpsilon(0.0, CesiumMath.EPSILON7); + expect(southWest_HIGH[0]).toEqualEpsilon(0.0, CesiumMath.EPSILON2); + expect(southWest_HIGH[1]).toEqualEpsilon(0.0, CesiumMath.EPSILON2); + expect(southWest_HIGH[2]).toEqualEpsilon(0.0, CesiumMath.EPSILON2); - expect(southWest_LOW.value[0]).toBeGreaterThan(Math.cos(CesiumMath.toRadians(0.2))); + expect(southWest_LOW[0]).toBeGreaterThan(Math.cos(CesiumMath.toRadians(0.2))); // Expect eastward and northward to be unit-direction vectors in the ENU coordinate system at the rectangle center var smallRectangleCenter = Cartographic.toCartesian(Rectangle.center(smallTestRectangle), unitSphereEllipsoid); var enuMatrix = Transforms.eastNorthUpToFixedFrame(smallRectangleCenter, unitSphereEllipsoid); var inverseEnu = Matrix4.inverse(enuMatrix, new Matrix4()); - var eastwardENU = Matrix4.multiplyByPointAsVector(inverseEnu, Cartesian3.fromArray(eastward.value), new Cartesian3()); + var eastwardENU = Matrix4.multiplyByPointAsVector(inverseEnu, Cartesian3.fromArray(eastward), new Cartesian3()); eastwardENU = Cartesian3.normalize(eastwardENU, eastwardENU); - expect(Cartesian3.equalsEpsilon(eastwardENU, Cartesian3.UNIT_X, CesiumMath.EPSILON7)).toBe(true); + expect(Cartesian3.equalsEpsilon(eastwardENU, Cartesian3.UNIT_X, CesiumMath.EPSILON2)).toBe(true); - var northwardENU = Matrix4.multiplyByPointAsVector(inverseEnu, Cartesian3.fromArray(northward.value), new Cartesian3()); + var northwardENU = Matrix4.multiplyByPointAsVector(inverseEnu, Cartesian3.fromArray(northward), new Cartesian3()); northwardENU = Cartesian3.normalize(northwardENU, northwardENU); - expect(Cartesian3.equalsEpsilon(northwardENU, Cartesian3.UNIT_Y, CesiumMath.EPSILON7)).toBe(true); + expect(Cartesian3.equalsEpsilon(northwardENU, Cartesian3.UNIT_Y, CesiumMath.EPSILON2)).toBe(true); }); it('provides attributes for computing planes in 2D and Columbus View', function() { - var planes2D_HIGH = largeRectangleAttributes.planes2D_HIGH; - var planes2D_LOW = largeRectangleAttributes.planes2D_LOW; - - expect(planes2D_HIGH.componentDatatype).toEqual(ComponentDatatype.FLOAT); - expect(planes2D_HIGH.componentsPerAttribute).toEqual(4); - expect(planes2D_HIGH.normalize).toEqual(false); + var highValue = [0, 0, 0, 0]; + highValue[0] = unpackHighMagLessThan100Million(largeRectangleAttributes.planes2D_HIGH_x); + highValue[1] = unpackHighMagLessThan100Million(largeRectangleAttributes.planes2D_HIGH_y); + highValue[2] = unpackHighMagLessThan100Million(largeRectangleAttributes.planes2D_HIGH_z); + highValue[3] = unpackHighMagLessThan100Million(largeRectangleAttributes.planes2D_HIGH_w); + + var lowValue = [0, 0, 0, 0]; + lowValue[0] = unpackLowLessThan100k(largeRectangleAttributes.planes2D_LOW_x); + lowValue[1] = unpackLowLessThan100k(largeRectangleAttributes.planes2D_LOW_y); + lowValue[2] = unpackLowLessThan100k(largeRectangleAttributes.planes2D_LOW_z); + lowValue[3] = unpackLowLessThan100k(largeRectangleAttributes.planes2D_LOW_w); // Because using a unit sphere expect all HIGH values to be basically 0 - var highValue = planes2D_HIGH.value; - expect(highValue[0]).toEqualEpsilon(0.0, CesiumMath.EPSILON7); - expect(highValue[1]).toEqualEpsilon(0.0, CesiumMath.EPSILON7); - expect(highValue[2]).toEqualEpsilon(0.0, CesiumMath.EPSILON7); - expect(highValue[3]).toEqualEpsilon(0.0, CesiumMath.EPSILON7); - - expect(planes2D_LOW.componentDatatype).toEqual(ComponentDatatype.FLOAT); - expect(planes2D_LOW.componentsPerAttribute).toEqual(4); - expect(planes2D_LOW.normalize).toEqual(false); + expect(highValue[0]).toEqualEpsilon(0.0, CesiumMath.EPSILON2); + expect(highValue[1]).toEqualEpsilon(0.0, CesiumMath.EPSILON2); + expect(highValue[2]).toEqualEpsilon(0.0, CesiumMath.EPSILON2); + expect(highValue[3]).toEqualEpsilon(0.0, CesiumMath.EPSILON2); var cartographic = Cartographic.fromDegrees(-45, -45, 0.0); // southwest corner var southwestCartesian = projection.project(cartographic); - var lowValue = planes2D_LOW.value; - expect(lowValue[0]).toEqualEpsilon(southwestCartesian.x, CesiumMath.EPSILON7); - expect(lowValue[1]).toEqualEpsilon(southwestCartesian.y, CesiumMath.EPSILON7); - expect(lowValue[2]).toEqualEpsilon(-southwestCartesian.y, CesiumMath.EPSILON7); - expect(lowValue[3]).toEqualEpsilon(-southwestCartesian.x, CesiumMath.EPSILON7); + expect(lowValue[0]).toEqualEpsilon(southwestCartesian.x, CesiumMath.EPSILON2); + expect(lowValue[1]).toEqualEpsilon(southwestCartesian.y, CesiumMath.EPSILON2); + expect(lowValue[2]).toEqualEpsilon(-southwestCartesian.y, CesiumMath.EPSILON2); + expect(lowValue[3]).toEqualEpsilon(-southwestCartesian.x, CesiumMath.EPSILON2); // Small case // Because using a unit sphere expect all HIGH values to be basically 0 - highValue = smallRectangleAttributes.planes2D_HIGH.value; - expect(highValue[0]).toEqualEpsilon(0.0, CesiumMath.EPSILON7); - expect(highValue[1]).toEqualEpsilon(0.0, CesiumMath.EPSILON7); - expect(highValue[2]).toEqualEpsilon(0.0, CesiumMath.EPSILON7); - expect(highValue[3]).toEqualEpsilon(0.0, CesiumMath.EPSILON7); + highValue[0] = unpackHighMagLessThan100Million(smallRectangleAttributes.planes2D_HIGH_x); + highValue[1] = unpackHighMagLessThan100Million(smallRectangleAttributes.planes2D_HIGH_y); + highValue[2] = unpackHighMagLessThan100Million(smallRectangleAttributes.planes2D_HIGH_z); + highValue[3] = unpackHighMagLessThan100Million(smallRectangleAttributes.planes2D_HIGH_w); + + expect(highValue[0]).toEqualEpsilon(0.0, CesiumMath.EPSILON2); + expect(highValue[1]).toEqualEpsilon(0.0, CesiumMath.EPSILON2); + expect(highValue[2]).toEqualEpsilon(0.0, CesiumMath.EPSILON2); + expect(highValue[3]).toEqualEpsilon(0.0, CesiumMath.EPSILON2); cartographic = Cartographic.fromDegrees(-0.1, -0.1, 0.0); // southwest corner southwestCartesian = projection.project(cartographic); - lowValue = smallRectangleAttributes.planes2D_LOW.value; - expect(lowValue[0]).toEqualEpsilon(southwestCartesian.x, CesiumMath.EPSILON7); - expect(lowValue[1]).toEqualEpsilon(southwestCartesian.y, CesiumMath.EPSILON7); - expect(lowValue[2]).toEqualEpsilon(-southwestCartesian.y, CesiumMath.EPSILON7); - expect(lowValue[3]).toEqualEpsilon(-southwestCartesian.x, CesiumMath.EPSILON7); + lowValue[0] = unpackLowLessThan100k(smallRectangleAttributes.planes2D_LOW_x); + lowValue[1] = unpackLowLessThan100k(smallRectangleAttributes.planes2D_LOW_y); + lowValue[2] = unpackLowLessThan100k(smallRectangleAttributes.planes2D_LOW_z); + lowValue[3] = unpackLowLessThan100k(smallRectangleAttributes.planes2D_LOW_w); + + expect(lowValue[0]).toEqualEpsilon(southwestCartesian.x, CesiumMath.EPSILON2); + expect(lowValue[1]).toEqualEpsilon(southwestCartesian.y, CesiumMath.EPSILON2); + expect(lowValue[2]).toEqualEpsilon(-southwestCartesian.y, CesiumMath.EPSILON2); + expect(lowValue[3]).toEqualEpsilon(-southwestCartesian.x, CesiumMath.EPSILON2); }); it('provides attributes for rotating texture coordinates', function() { From 5e2e084c538fe61ce752a1ed154743d64599289e Mon Sep 17 00:00:00 2001 From: Kangning Li Date: Mon, 17 Dec 2018 13:19:47 -0500 Subject: [PATCH 2/7] update CHANGES.md --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index 74362f54e877..1fa16eb14bfd 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -22,6 +22,7 @@ Change Log ##### Fixes :wrench: * Fixed issue causing polyline to look wavy depending on the position of the camera [#7209](https://github.com/AnalyticalGraphicsInc/cesium/pull/7209) * Fixed translucency issues for dynamic geometry entities. [#7364](https://github.com/AnalyticalGraphicsInc/cesium/issues/7364) +* Fixed an issue where polygons, corridors, rectangles, and ellipses on terrain would not render on some mobile devices. [#6739](https://github.com/AnalyticalGraphicsInc/cesium/issues/6739) ### 1.51 - 2018-11-01 From fe4624bb915bf5a14d2b54ded1dce163b6a0f327 Mon Sep 17 00:00:00 2001 From: likangning93 Date: Wed, 18 Sep 2019 14:04:21 -0400 Subject: [PATCH 3/7] update CHANGES.md --- CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index a9d048c774a1..ef1cba459be8 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -9,6 +9,7 @@ Change Log ##### Fixes :wrench: * `Camera.flyTo` flies to the correct location in 2D when the destination crosses the international date line [#7909](https://github.com/AnalyticalGraphicsInc/cesium/pull/7909) * Improved display of tile coordinates for `TileCoordinatesImageryProvider` [#8131](https://github.com/AnalyticalGraphicsInc/cesium/pull/8131) +* Fixed an issue where polygons, corridors, rectangles, and ellipses on terrain would not render on some mobile devices. [#6739](https://github.com/AnalyticalGraphicsInc/cesium/issues/6739) ### 1.61 - 2019-09-03 @@ -247,7 +248,6 @@ _This is an npm-only release to fix a publishing issue_. ##### Fixes :wrench: * Fixed issue causing polyline to look wavy depending on the position of the camera [#7209](https://github.com/AnalyticalGraphicsInc/cesium/pull/7209) * Fixed translucency issues for dynamic geometry entities. [#7364](https://github.com/AnalyticalGraphicsInc/cesium/issues/7364) -* Fixed an issue where polygons, corridors, rectangles, and ellipses on terrain would not render on some mobile devices. [#6739](https://github.com/AnalyticalGraphicsInc/cesium/issues/6739) ### 1.51 - 2018-11-01 From 0cb5046813483421f7541fcf439da25aa8ba69eb Mon Sep 17 00:00:00 2001 From: likangning93 Date: Thu, 19 Sep 2019 17:04:23 -0400 Subject: [PATCH 4/7] add test for float texture precision to context construction --- Source/Renderer/ComputeCommand.js | 2 +- Source/Renderer/Context.js | 16 +++ Source/Renderer/checkFloatTexturePrecision.js | 101 ++++++++++++++++++ .../Shaders/CheckFloatTexturePrecisionFS.glsl | 7 ++ Specs/Renderer/ContextSpec.js | 4 + .../checkFloatTexturePrecisionSpec.js | 42 ++++++++ 6 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 Source/Renderer/checkFloatTexturePrecision.js create mode 100644 Source/Shaders/CheckFloatTexturePrecisionFS.glsl create mode 100644 Specs/Renderer/checkFloatTexturePrecisionSpec.js diff --git a/Source/Renderer/ComputeCommand.js b/Source/Renderer/ComputeCommand.js index 0ed531cdd1bb..071fac2a5eaa 100644 --- a/Source/Renderer/ComputeCommand.js +++ b/Source/Renderer/ComputeCommand.js @@ -107,7 +107,7 @@ define([ /** * Executes the compute command. * - * @param {Context} computeEngine The context that processes the compute command. + * @param {ComputeEngine} computeEngine The context that processes the compute command. */ ComputeCommand.prototype.execute = function(computeEngine) { computeEngine.execute(this); diff --git a/Source/Renderer/Context.js b/Source/Renderer/Context.js index de2ea5cfae57..3270051e9ba4 100644 --- a/Source/Renderer/Context.js +++ b/Source/Renderer/Context.js @@ -18,6 +18,7 @@ define([ '../Core/WebGLConstants', '../Shaders/ViewportQuadVS', './BufferUsage', + './checkFloatTexturePrecision', './ClearCommand', './ContextLimits', './CubeMap', @@ -51,6 +52,7 @@ define([ WebGLConstants, ViewportQuadVS, BufferUsage, + checkFloatTexturePrecision, ClearCommand, ContextLimits, CubeMap, @@ -448,6 +450,8 @@ define([ this.cache = {}; RenderState.apply(gl, rs, ps); + + this._floatTexSixPlaces = checkFloatTexturePrecision(this); } var defaultFramebufferMarker = {}; @@ -589,6 +593,18 @@ define([ } }, + /** + * true returns if the context's floating point textures support 6 decimal places of precision. + * @memberof Context.prototype + * @type {Boolean} + * @see {@link https://www.khronos.org/registry/webgl/extensions/OES_texture_float/} + */ + floatTextureSixPlaces : { + get : function() { + return this._floatTexSixPlaces; + } + }, + /** * true if OES_texture_half_float is supported. This extension provides * access to floating point textures that, for example, can be attached to framebuffers for high dynamic range. diff --git a/Source/Renderer/checkFloatTexturePrecision.js b/Source/Renderer/checkFloatTexturePrecision.js new file mode 100644 index 000000000000..c30ec61a40fb --- /dev/null +++ b/Source/Renderer/checkFloatTexturePrecision.js @@ -0,0 +1,101 @@ +define([ + '../Core/PixelFormat', + '../Shaders/CheckFloatTexturePrecisionFS', + './ComputeCommand', + './ComputeEngine', + './Framebuffer', + './PixelDatatype', + './Texture' +], function( + PixelFormat, + CheckFloatTexturePrecisionFS, + ComputeCommand, + ComputeEngine, + Framebuffer, + PixelDatatype, + Texture +) { + 'use strict'; + + /** + * Checks if the context's floating point textures support 6 decimal places of precision. + * + * @param {Context} context A context wrapping a gl implementation. + * @returns {Boolean} whether or not the context's floating point textures support 6 decimal places of precision + * + * @private + */ + function checkFloatTexturePrecision(context) { + if (!context.floatingPointTexture) { + return false; + } + + var computeEngine = new ComputeEngine(context); + var outputTexture = new Texture({ + context : context, + width : 1, + height : 1, + pixelFormat : PixelFormat.RGBA + }); + + var floatTexture = new Texture({ + context : context, + width : 1, + height : 1, + pixelFormat : PixelFormat.RGBA, + pixelDatatype : checkFloatTexturePrecision._getFloatPixelType(), + source : { + width : 1, + height : 1, + arrayBufferView : checkFloatTexturePrecision._getArray([123456, 0, 0, 0]) + } + }); + + var framebuffer = new Framebuffer({ + context : context, + colorTextures : [outputTexture], + destroyAttachments : false + }); + + var readState = { + framebuffer : framebuffer, + x : 0, + y : 0, + width : 1, + height : 1 + }; + + var sixPlaces = false; + var computeCommand = new ComputeCommand({ + fragmentShaderSource : CheckFloatTexturePrecisionFS, + outputTexture : outputTexture, + uniformMap : { + u_floatTexture : function() { + return floatTexture; + } + }, + persists : false, + postExecute : function() { + var pixel = context.readPixels(readState); + sixPlaces = pixel[0] === 0; + } + }); + + computeCommand.execute(computeEngine); + + computeEngine.destroy(); + framebuffer.destroy(); + + return sixPlaces; + } + + checkFloatTexturePrecision._getFloatPixelType = function() { + return PixelDatatype.FLOAT; + }; + + checkFloatTexturePrecision._getArray = function(array) { + return new Float32Array(array); + }; + + return checkFloatTexturePrecision; +}); diff --git a/Source/Shaders/CheckFloatTexturePrecisionFS.glsl b/Source/Shaders/CheckFloatTexturePrecisionFS.glsl new file mode 100644 index 000000000000..a2eadb4bd827 --- /dev/null +++ b/Source/Shaders/CheckFloatTexturePrecisionFS.glsl @@ -0,0 +1,7 @@ +uniform sampler2D u_floatTexture; + +void main() { + float actual = texture2D(u_floatTexture, vec2(0.5, 0.5)).r; + float expected = 123456.0; + gl_FragColor = vec4(abs(actual - expected), 0.0, 0.0, 1.0); +} diff --git a/Specs/Renderer/ContextSpec.js b/Specs/Renderer/ContextSpec.js index d395ca7a7daf..273967a07865 100644 --- a/Specs/Renderer/ContextSpec.js +++ b/Specs/Renderer/ContextSpec.js @@ -173,6 +173,10 @@ describe('Renderer/Context', function() { expect(context.floatingPointTexture).toBeDefined(); }); + it('gets whether the texture float has 6 places of precision', function() { + expect(context.floatTextureSixPlaces).toBeDefined(); + }); + it('gets texture filter anisotropic extension', function() { expect(context.textureFilterAnisotropic).toBeDefined(); }); diff --git a/Specs/Renderer/checkFloatTexturePrecisionSpec.js b/Specs/Renderer/checkFloatTexturePrecisionSpec.js new file mode 100644 index 000000000000..c9224ed87f99 --- /dev/null +++ b/Specs/Renderer/checkFloatTexturePrecisionSpec.js @@ -0,0 +1,42 @@ +define([ + 'Renderer/checkFloatTexturePrecision', + 'Renderer/PixelDatatype', + 'Specs/createContext' + ], function( + checkFloatTexturePrecision, + PixelDatatype, + createContext) { + 'use strict'; + +describe('Renderer/checkFloatTexturePrecision', function() { + + var context; + + beforeAll(function() { + context = createContext(); + }); + + afterAll(function() { + context.destroyForSpecs(); + }); + + it('returns false when float textures are not available', function() { + expect(checkFloatTexturePrecision({ floatingPointTexture : false })).toBe(false); + }); + + it('returns false when float textures are of insufficient precision', function() { + if (!context.floatingPointTexture) { + return; + } + + spyOn(checkFloatTexturePrecision, '_getFloatPixelType').and.callFake(function() { + return PixelDatatype.HALF_FLOAT; + }); + spyOn(checkFloatTexturePrecision, '_getArray').and.callFake(function(array) { + return new Uint16Array(array); + }); + + expect(checkFloatTexturePrecision(context)).toBe(false); + }); +}, 'WebGL'); +}); From c5c7078e7139a622d633a2e34968b6b357ceaaa6 Mon Sep 17 00:00:00 2001 From: likangning93 Date: Fri, 20 Sep 2019 10:22:53 -0400 Subject: [PATCH 5/7] use float batch table or uint8 packing for positions in ground primitive materials depending on tested precision --- Source/Scene/ClassificationPrimitive.js | 2 +- Source/Scene/GroundPrimitive.js | 5 +- Source/Scene/ShadowVolumeAppearance.js | 173 +++++++--- Source/Shaders/ShadowVolumeAppearanceVS.glsl | 13 +- Specs/Scene/ShadowVolumeAppearanceSpec.js | 334 +++++++++++++------ 5 files changed, 379 insertions(+), 148 deletions(-) diff --git a/Source/Scene/ClassificationPrimitive.js b/Source/Scene/ClassificationPrimitive.js index 0d9be7b8880a..7218167cade9 100644 --- a/Source/Scene/ClassificationPrimitive.js +++ b/Source/Scene/ClassificationPrimitive.js @@ -578,7 +578,7 @@ define([ }); var attributeLocations = classificationPrimitive._primitive._attributeLocations; - var shadowVolumeAppearance = new ShadowVolumeAppearance(cullFragmentsUsingExtents, planarExtents, classificationPrimitive.appearance); + var shadowVolumeAppearance = new ShadowVolumeAppearance(cullFragmentsUsingExtents, planarExtents, classificationPrimitive.appearance, context.floatTextureSixPlaces); classificationPrimitive._spStencil = ShaderProgram.replaceCache({ context : context, diff --git a/Source/Scene/GroundPrimitive.js b/Source/Scene/GroundPrimitive.js index 905ea01005bb..eb09ab4561d1 100644 --- a/Source/Scene/GroundPrimitive.js +++ b/Source/Scene/GroundPrimitive.js @@ -730,10 +730,11 @@ define([ var boundingRectangle = getRectangle(frameState, geometry); var textureCoordinateRotationPoints = geometry.textureCoordinateRotationPoints; + var useFloatBatchTable = frameState.context.floatTextureSixPlaces; if (usePlanarExtents) { - attributes = ShadowVolumeAppearance.getPlanarTextureCoordinateAttributes(boundingRectangle, textureCoordinateRotationPoints, ellipsoid, frameState.mapProjection, this._maxHeight); + attributes = ShadowVolumeAppearance.getPlanarTextureCoordinateAttributes(boundingRectangle, textureCoordinateRotationPoints, ellipsoid, frameState.mapProjection, useFloatBatchTable, this._maxHeight); } else { - attributes = ShadowVolumeAppearance.getSphericalExtentGeometryInstanceAttributes(boundingRectangle, textureCoordinateRotationPoints, ellipsoid, frameState.mapProjection); + attributes = ShadowVolumeAppearance.getSphericalExtentGeometryInstanceAttributes(boundingRectangle, textureCoordinateRotationPoints, ellipsoid, frameState.mapProjection, useFloatBatchTable); } var instanceAttributes = instance.attributes; diff --git a/Source/Scene/ShadowVolumeAppearance.js b/Source/Scene/ShadowVolumeAppearance.js index ff810d1d5546..3bf2997ec2e7 100644 --- a/Source/Scene/ShadowVolumeAppearance.js +++ b/Source/Scene/ShadowVolumeAppearance.js @@ -49,15 +49,19 @@ define([ * @param {Boolean} extentsCulling Discard fragments outside the instance's texture coordinate extents. * @param {Boolean} planarExtents If true, texture coordinates will be computed using planes instead of spherical coordinates. * @param {Appearance} appearance An Appearance to be used with a ClassificationPrimitive via GroundPrimitive. + * @param {Boolean} useFloatBatchTable Whether or not the ShadowVolumeAppearance should use floating point batch table values. * @private */ - function ShadowVolumeAppearance(extentsCulling, planarExtents, appearance) { + function ShadowVolumeAppearance(extentsCulling, planarExtents, appearance, useFloatBatchTable) { //>>includeStart('debug', pragmas.debug); Check.typeOf.bool('extentsCulling', extentsCulling); Check.typeOf.bool('planarExtents', planarExtents); Check.typeOf.object('appearance', appearance); + Check.typeOf.bool('useFloatBatchTable', useFloatBatchTable); //>>includeEnd('debug'); + this._useFloatBatchTable = useFloatBatchTable; + // Compute shader dependencies var colorShaderDependencies = new ShaderDependencies(); colorShaderDependencies.requiresTextureCoordinates = extentsCulling; @@ -200,7 +204,7 @@ define([ Check.typeOf.bool('columbusView2D', columbusView2D); Check.defined('mapProjection', mapProjection); //>>includeEnd('debug'); - return createShadowVolumeAppearanceVS(this._colorShaderDependencies, this._planarExtents, columbusView2D, defines, vertexShaderSource, this._appearance, mapProjection); + return createShadowVolumeAppearanceVS(this._colorShaderDependencies, this._planarExtents, columbusView2D, defines, vertexShaderSource, this._appearance, mapProjection, this._useFloatBatchTable); }; /** @@ -219,7 +223,7 @@ define([ Check.typeOf.bool('columbusView2D', columbusView2D); Check.defined('mapProjection', mapProjection); //>>includeEnd('debug'); - return createShadowVolumeAppearanceVS(this._pickShaderDependencies, this._planarExtents, columbusView2D, defines, vertexShaderSource, undefined, mapProjection); + return createShadowVolumeAppearanceVS(this._pickShaderDependencies, this._planarExtents, columbusView2D, defines, vertexShaderSource, undefined, mapProjection, this._useFloatBatchTable); }; var longitudeExtentsCartesianScratch = new Cartesian3(); @@ -228,7 +232,7 @@ define([ high : 0.0, low : 0.0 }; - function createShadowVolumeAppearanceVS(shaderDependencies, planarExtents, columbusView2D, defines, vertexShaderSource, appearance, mapProjection) { + function createShadowVolumeAppearanceVS(shaderDependencies, planarExtents, columbusView2D, defines, vertexShaderSource, appearance, mapProjection, useFloatBatchTable) { var allDefines = defines.slice(); if (projectionExtentDefines.eastMostYhighDefine === '') { @@ -271,6 +275,10 @@ define([ } } + if (!useFloatBatchTable) { + allDefines.push('UINT8_PACKING'); + } + return new ShaderSource({ defines : allDefines, sources : [vertexShaderSource] @@ -477,7 +485,7 @@ define([ var northWestScratch = new Cartesian3(); var southEastScratch = new Cartesian3(); var highLowScratch = {high : 0.0, low : 0.0}; - function add2DTextureCoordinateAttributes(rectangle, projection, attributes) { + function add2DTextureCoordinateAttributes(rectangle, projection, attributes, useFloatBatchTable) { // Compute corner positions in double precision var carto = cartographicScratch; carto.height = 0.0; @@ -502,21 +510,57 @@ define([ // z: y value for northWest // w: x value for southEast - var encoded = EncodedCartesian3.encode(southWestCorner.x, highLowScratch); - encodeHighLessThan100Million(encoded.high, 'planes2D_HIGH_x', attributes); - encodeLowLessThan100k(encoded.low, 'planes2D_LOW_x', attributes); + var encoded; + if (!useFloatBatchTable) { + encoded = EncodedCartesian3.encode(southWestCorner.x, highLowScratch); + encodeHighLessThan100Million(encoded.high, 'planes2D_HIGH_x', attributes); + encodeLowLessThan100k(encoded.low, 'planes2D_LOW_x', attributes); + + encoded = EncodedCartesian3.encode(southWestCorner.y, highLowScratch); + encodeHighLessThan100Million(encoded.high, 'planes2D_HIGH_y', attributes); + encodeLowLessThan100k(encoded.low, 'planes2D_LOW_y', attributes); + + encoded = EncodedCartesian3.encode(northWest.y, highLowScratch); + encodeHighLessThan100Million(encoded.high, 'planes2D_HIGH_z', attributes); + encodeLowLessThan100k(encoded.low, 'planes2D_LOW_z', attributes); + + encoded = EncodedCartesian3.encode(southEast.x, highLowScratch); + encodeHighLessThan100Million(encoded.high, 'planes2D_HIGH_w', attributes); + encodeLowLessThan100k(encoded.low, 'planes2D_LOW_w', attributes); + return; + } + + var valuesHigh = [0, 0, 0, 0]; + var valuesLow = [0, 0, 0, 0]; + encoded = EncodedCartesian3.encode(southWestCorner.x, highLowScratch); + valuesHigh[0] = encoded.high; + valuesLow[0] = encoded.low; encoded = EncodedCartesian3.encode(southWestCorner.y, highLowScratch); - encodeHighLessThan100Million(encoded.high, 'planes2D_HIGH_y', attributes); - encodeLowLessThan100k(encoded.low, 'planes2D_LOW_y', attributes); + valuesHigh[1] = encoded.high; + valuesLow[1] = encoded.low; encoded = EncodedCartesian3.encode(northWest.y, highLowScratch); - encodeHighLessThan100Million(encoded.high, 'planes2D_HIGH_z', attributes); - encodeLowLessThan100k(encoded.low, 'planes2D_LOW_z', attributes); + valuesHigh[2] = encoded.high; + valuesLow[2] = encoded.low; encoded = EncodedCartesian3.encode(southEast.x, highLowScratch); - encodeHighLessThan100Million(encoded.high, 'planes2D_HIGH_w', attributes); - encodeLowLessThan100k(encoded.low, 'planes2D_LOW_w', attributes); + valuesHigh[3] = encoded.high; + valuesLow[3] = encoded.low; + + attributes.planes2D_HIGH = new GeometryInstanceAttribute({ + componentDatatype: ComponentDatatype.FLOAT, + componentsPerAttribute: 4, + normalize: false, + value : valuesHigh + }); + + attributes.planes2D_LOW = new GeometryInstanceAttribute({ + componentDatatype: ComponentDatatype.FLOAT, + componentsPerAttribute: 4, + normalize: false, + value : valuesLow + }); } var enuMatrixScratch = new Matrix4(); @@ -632,15 +676,17 @@ define([ * @param {Number[]} textureCoordinateRotationPoints Points in the computed texture coordinate system for remapping texture coordinates * @param {Ellipsoid} ellipsoid Ellipsoid for converting Rectangle points to world coordinates * @param {MapProjection} projection The MapProjection used for 2D and Columbus View. + * @param {Boolean} useFloatBatchTable Whether or not the ShadowVolumeAppearance should use floating point batch table values. * @param {Number} [height=0] The maximum height for the shadow volume. * @returns {Object} An attributes dictionary containing planar texture coordinate attributes. */ - ShadowVolumeAppearance.getPlanarTextureCoordinateAttributes = function(boundingRectangle, textureCoordinateRotationPoints, ellipsoid, projection, height) { + ShadowVolumeAppearance.getPlanarTextureCoordinateAttributes = function(boundingRectangle, textureCoordinateRotationPoints, ellipsoid, projection, useFloatBatchTable, height) { //>>includeStart('debug', pragmas.debug); Check.typeOf.object('boundingRectangle', boundingRectangle); Check.defined('textureCoordinateRotationPoints', textureCoordinateRotationPoints); Check.typeOf.object('ellipsoid', ellipsoid); Check.typeOf.object('projection', projection); + Check.typeOf.bool('useFloatBatchTable', useFloatBatchTable); //>>includeEnd('debug'); var corner = cornerScratch; @@ -653,25 +699,55 @@ define([ var encoded = EncodedCartesian3.fromCartesian(corner, encodeScratch); - var high = encoded.high; - encodeHighLessThan100Million(high.x, 'southWest_HIGH_x', attributes); - encodeHighLessThan100Million(high.y, 'southWest_HIGH_y', attributes); - encodeHighLessThan100Million(high.z, 'southWest_HIGH_z', attributes); + if (!useFloatBatchTable) { + var high = encoded.high; + encodeHighLessThan100Million(high.x, 'southWest_HIGH_x', attributes); + encodeHighLessThan100Million(high.y, 'southWest_HIGH_y', attributes); + encodeHighLessThan100Million(high.z, 'southWest_HIGH_z', attributes); + + var low = encoded.low; + encodeLowLessThan100k(low.x, 'southWest_LOW_x', attributes); + encodeLowLessThan100k(low.y, 'southWest_LOW_y', attributes); + encodeLowLessThan100k(low.z, 'southWest_LOW_z', attributes); - var low = encoded.low; - encodeLowLessThan100k(low.x, 'southWest_LOW_x', attributes); - encodeLowLessThan100k(low.y, 'southWest_LOW_y', attributes); - encodeLowLessThan100k(low.z, 'southWest_LOW_z', attributes); + encodeLessThan1000k(eastward.x, 'eastward_x', attributes); + encodeLessThan1000k(eastward.y, 'eastward_y', attributes); + encodeLessThan1000k(eastward.z, 'eastward_z', attributes); - encodeLessThan1000k(eastward.x, 'eastward_x', attributes); - encodeLessThan1000k(eastward.y, 'eastward_y', attributes); - encodeLessThan1000k(eastward.z, 'eastward_z', attributes); + encodeLessThan1000k(northward.x, 'northward_x', attributes); + encodeLessThan1000k(northward.y, 'northward_y', attributes); + encodeLessThan1000k(northward.z, 'northward_z', attributes); - encodeLessThan1000k(northward.x, 'northward_x', attributes); - encodeLessThan1000k(northward.y, 'northward_y', attributes); - encodeLessThan1000k(northward.z, 'northward_z', attributes); + add2DTextureCoordinateAttributes(boundingRectangle, projection, attributes, false); + return attributes; + } + + attributes.southWest_HIGH = new GeometryInstanceAttribute({ + componentDatatype: ComponentDatatype.FLOAT, + componentsPerAttribute: 3, + normalize: false, + value : Cartesian3.pack(encoded.high, [0, 0, 0]) + }); + attributes.southWest_LOW = new GeometryInstanceAttribute({ + componentDatatype: ComponentDatatype.FLOAT, + componentsPerAttribute: 3, + normalize: false, + value : Cartesian3.pack(encoded.low, [0, 0, 0]) + }); + attributes.eastward = new GeometryInstanceAttribute({ + componentDatatype: ComponentDatatype.FLOAT, + componentsPerAttribute: 3, + normalize: false, + value : Cartesian3.pack(eastward, [0, 0, 0]) + }); + attributes.northward = new GeometryInstanceAttribute({ + componentDatatype: ComponentDatatype.FLOAT, + componentsPerAttribute: 3, + normalize: false, + value : Cartesian3.pack(northward, [0, 0, 0]) + }); - add2DTextureCoordinateAttributes(boundingRectangle, projection, attributes); + add2DTextureCoordinateAttributes(boundingRectangle, projection, attributes, true); return attributes; }; @@ -715,14 +791,16 @@ define([ * @param {Number[]} textureCoordinateRotationPoints Points in the computed texture coordinate system for remapping texture coordinates * @param {Ellipsoid} ellipsoid Ellipsoid for converting Rectangle points to world coordinates * @param {MapProjection} projection The MapProjection used for 2D and Columbus View. + * @param {Boolean} useFloatBatchTable Whether or not the ShadowVolumeAppearance should use floating point batch table values. * @returns {Object} An attributes dictionary containing spherical texture coordinate attributes. */ - ShadowVolumeAppearance.getSphericalExtentGeometryInstanceAttributes = function(boundingRectangle, textureCoordinateRotationPoints, ellipsoid, projection) { + ShadowVolumeAppearance.getSphericalExtentGeometryInstanceAttributes = function(boundingRectangle, textureCoordinateRotationPoints, ellipsoid, projection, useFloatBatchTable) { //>>includeStart('debug', pragmas.debug); Check.typeOf.object('boundingRectangle', boundingRectangle); Check.defined('textureCoordinateRotationPoints', textureCoordinateRotationPoints); Check.typeOf.object('ellipsoid', ellipsoid); Check.typeOf.object('projection', projection); + Check.typeOf.bool('useFloatBatchTable', useFloatBatchTable); //>>includeEnd('debug'); // rectangle cartographic coords !== spherical because it's on an ellipsoid @@ -769,12 +847,19 @@ define([ }; addTextureCoordinateRotationAttributes(attributes, textureCoordinateRotationPoints); - add2DTextureCoordinateAttributes(boundingRectangle, projection, attributes); + add2DTextureCoordinateAttributes(boundingRectangle, projection, attributes, useFloatBatchTable); return attributes; }; ShadowVolumeAppearance.hasAttributesForTextureCoordinatePlanes = function(attributes) { - return defined(attributes.southWest_HIGH_x) && defined(attributes.southWest_LOW_x) && + var hasFloatAttributes = + defined(attributes.southWest_HIGH) && defined(attributes.southWest_LOW) && + defined(attributes.northward) && defined(attributes.eastward) && + defined(attributes.planes2D_HIGH) && defined(attributes.planes2D_LOW) && + defined(attributes.uMaxVmax) && defined(attributes.uvMinAndExtents); + + var hasUint8Attributes = + defined(attributes.southWest_HIGH_x) && defined(attributes.southWest_LOW_x) && defined(attributes.southWest_HIGH_y) && defined(attributes.southWest_LOW_y) && defined(attributes.southWest_HIGH_z) && defined(attributes.southWest_LOW_z) && defined(attributes.northward_x) && defined(attributes.eastward_x) && @@ -785,15 +870,25 @@ define([ defined(attributes.planes2D_HIGH_z) && defined(attributes.planes2D_LOW_z) && defined(attributes.planes2D_HIGH_w) && defined(attributes.planes2D_LOW_w) && defined(attributes.uMaxVmax) && defined(attributes.uvMinAndExtents); + + return hasFloatAttributes || hasUint8Attributes; }; ShadowVolumeAppearance.hasAttributesForSphericalExtents = function(attributes) { - return defined(attributes.sphericalExtents) && defined(attributes.longitudeRotation) && - defined(attributes.planes2D_HIGH_x) && defined(attributes.planes2D_LOW_x) && - defined(attributes.planes2D_HIGH_y) && defined(attributes.planes2D_LOW_y) && - defined(attributes.planes2D_HIGH_z) && defined(attributes.planes2D_LOW_z) && - defined(attributes.planes2D_HIGH_w) && defined(attributes.planes2D_LOW_w) && - defined(attributes.uMaxVmax) && defined(attributes.uvMinAndExtents); + var hasFloatAttributes = + defined(attributes.sphericalExtents) && defined(attributes.longitudeRotation) && + defined(attributes.planes2D_HIGH) && defined(attributes.planes2D_LOW) && + defined(attributes.uMaxVmax) && defined(attributes.uvMinAndExtents); + + var hasUint8Attributes = + defined(attributes.sphericalExtents) && defined(attributes.longitudeRotation) && + defined(attributes.planes2D_HIGH_x) && defined(attributes.planes2D_LOW_x) && + defined(attributes.planes2D_HIGH_y) && defined(attributes.planes2D_LOW_y) && + defined(attributes.planes2D_HIGH_z) && defined(attributes.planes2D_LOW_z) && + defined(attributes.planes2D_HIGH_w) && defined(attributes.planes2D_LOW_w) && + defined(attributes.uMaxVmax) && defined(attributes.uvMinAndExtents); + + return hasFloatAttributes || hasUint8Attributes; }; function shouldUseSpherical(rectangle) { diff --git a/Source/Shaders/ShadowVolumeAppearanceVS.glsl b/Source/Shaders/ShadowVolumeAppearanceVS.glsl index 5cd0d118b42e..f1e2e6b0c2e0 100644 --- a/Source/Shaders/ShadowVolumeAppearanceVS.glsl +++ b/Source/Shaders/ShadowVolumeAppearanceVS.glsl @@ -25,7 +25,7 @@ varying vec3 v_uMaxAndInverseDistance; varying vec3 v_vMaxAndInverseDistance; #endif // TEXTURE_COORDINATES -#if defined(TEXTURE_COORDINATES) && !defined(SPHERICAL) +#if defined(TEXTURE_COORDINATES) && !defined(SPHERICAL) && defined(UINT8_PACKING) vec4 clampAndMagnitude(vec4 sd) { vec4 d = sd; d.x = czm_branchFreeTernary(sd.x < 128.0, d.x, (255.0 - sd.x)); @@ -115,6 +115,7 @@ void main() v_uvMinAndSphericalLongitudeRotation.z = czm_batchTable_longitudeRotation(batchId); #else // SPHERICAL #ifdef COLUMBUS_VIEW_2D +#ifdef UINT8_PACKING vec4 planes2D_high = unpackPlanes2D_HIGH(czm_batchTable_planes2D_HIGH_x(batchId), czm_batchTable_planes2D_HIGH_y(batchId), czm_batchTable_planes2D_HIGH_z(batchId), @@ -123,6 +124,10 @@ void main() czm_batchTable_planes2D_LOW_y(batchId), czm_batchTable_planes2D_LOW_z(batchId), czm_batchTable_planes2D_LOW_w(batchId)); +#else // UINT8_PACKING + vec4 planes2D_high = czm_batchTable_planes2D_HIGH(batchId); + vec4 planes2D_low = czm_batchTable_planes2D_LOW(batchId); +#endif // UINT8_PACKING // If the primitive is split across the IDL (planes2D_high.x > planes2D_high.w): // - If this vertex is on the east side of the IDL (position3DLow.y > 0.0, comparison with position3DHigh may produce artifacts) @@ -146,6 +151,7 @@ void main() vec3 southEastCorner = (czm_modelViewRelativeToEye * czm_translateRelativeToEye(vec3(0.0, planes2D_high.w, planes2D_high.y), vec3(0.0, planes2D_low.w, planes2D_low.y))).xyz; #else // COLUMBUS_VIEW_2D // 3D case has smaller "plane extents," so planes encoded as a 64 bit position and 2 vec3s for distances/direction +#ifdef UINT8_PACKING vec3 low = southwest_LOW(czm_batchTable_southWest_LOW_x(batchId), czm_batchTable_southWest_LOW_y(batchId), czm_batchTable_southWest_LOW_z(batchId)); vec3 high = southwest_HIGH(czm_batchTable_southWest_HIGH_x(batchId), czm_batchTable_southWest_HIGH_y(batchId), czm_batchTable_southWest_HIGH_z(batchId)); vec3 southWestCorner = (czm_modelViewRelativeToEye * czm_translateRelativeToEye(high, low)).xyz; @@ -158,6 +164,11 @@ void main() czm_batchTable_eastward_x(batchId), czm_batchTable_eastward_y(batchId), czm_batchTable_eastward_z(batchId)) + southWestCorner; +#else // UINT8_PACKING + vec3 southWestCorner = (czm_modelViewRelativeToEye * czm_translateRelativeToEye(czm_batchTable_southWest_HIGH(batchId), czm_batchTable_southWest_LOW(batchId))).xyz; + vec3 northWestCorner = czm_normal * czm_batchTable_northward(batchId) + southWestCorner; + vec3 southEastCorner = czm_normal * czm_batchTable_eastward(batchId) + southWestCorner; +#endif // UINT8_PACKING #endif // COLUMBUS_VIEW_2D vec3 eastWard = southEastCorner - southWestCorner; diff --git a/Specs/Scene/ShadowVolumeAppearanceSpec.js b/Specs/Scene/ShadowVolumeAppearanceSpec.js index 3b2bdf2ed014..3b261cf41e2c 100644 --- a/Specs/Scene/ShadowVolumeAppearanceSpec.js +++ b/Specs/Scene/ShadowVolumeAppearanceSpec.js @@ -47,8 +47,10 @@ describe('Scene/ShadowVolumeAppearance', function() { var largeTestRectangle = Rectangle.fromDegrees(-45.0, -45.0, 45.0, 45.0); var smallTestRectangle = Rectangle.fromDegrees(-0.1, -0.1, 0.1, 0.1); - var largeRectangleAttributes = ShadowVolumeAppearance.getSphericalExtentGeometryInstanceAttributes(largeTestRectangle, [0, 0, 0, 1, 1, 0], unitSphereEllipsoid, projection); - var smallRectangleAttributes = ShadowVolumeAppearance.getPlanarTextureCoordinateAttributes(smallTestRectangle, [0, 0, 0, 1, 1, 0], unitSphereEllipsoid, projection); + var largeRectangleAttributes = ShadowVolumeAppearance.getSphericalExtentGeometryInstanceAttributes(largeTestRectangle, [0, 0, 0, 1, 1, 0], unitSphereEllipsoid, projection, true); + var smallRectangleAttributes = ShadowVolumeAppearance.getPlanarTextureCoordinateAttributes(smallTestRectangle, [0, 0, 0, 1, 1, 0], unitSphereEllipsoid, projection, true); + var largeRectangleAttributesBadFloats = ShadowVolumeAppearance.getSphericalExtentGeometryInstanceAttributes(largeTestRectangle, [0, 0, 0, 1, 1, 0], unitSphereEllipsoid, projection, false); + var smallRectangleAttributesBadFloats = ShadowVolumeAppearance.getPlanarTextureCoordinateAttributes(smallTestRectangle, [0, 0, 0, 1, 1, 0], unitSphereEllipsoid, projection, false); var perInstanceColorMaterialAppearance = new PerInstanceColorAppearance(); var flatPerInstanceColorMaterialAppearance = new PerInstanceColorAppearance({ @@ -117,6 +119,12 @@ describe('Scene/ShadowVolumeAppearance', function() { expect(value[0]).toEqualEpsilon(0.0, CesiumMath.EPSILON4); }); + function checkGeometryInstanceAttributeVec3(attribute) { + expect(attribute.componentDatatype).toEqual(ComponentDatatype.FLOAT); + expect(attribute.componentsPerAttribute).toEqual(3); + expect(attribute.normalize).toEqual(false); + } + function clampAndMagnitude(signedVec4Attribute) { var signedVec4 = signedVec4Attribute.value; var unsigned = signedVec4.slice(); @@ -146,105 +154,190 @@ describe('Scene/ShadowVolumeAppearance', function() { return (10000.0 * unsigned[0] + 100.0 * unsigned[1] + unsigned[2] + 0.01 * unsigned[3]) * (signed[0] < 128.0 ? 1.0 : -1.0); } - it('provides attributes for computing texture coordinates using planes in 3D', function() { - var attributes = smallRectangleAttributes; - - var southWest_LOW = [0, 0, 0]; - southWest_LOW[0] = unpackLowLessThan100k(attributes.southWest_LOW_x); - southWest_LOW[1] = unpackLowLessThan100k(attributes.southWest_LOW_y); - southWest_LOW[2] = unpackLowLessThan100k(attributes.southWest_LOW_z); - - var southWest_HIGH = [0, 0, 0]; - southWest_HIGH[0] = unpackHighMagLessThan100Million(attributes.southWest_HIGH_x); - southWest_HIGH[1] = unpackHighMagLessThan100Million(attributes.southWest_HIGH_y); - southWest_HIGH[2] = unpackHighMagLessThan100Million(attributes.southWest_HIGH_z); - - var eastward = [0, 0, 0]; - eastward[0] = unpackLowLessThan1000k(attributes.eastward_x); - eastward[1] = unpackLowLessThan1000k(attributes.eastward_y); - eastward[2] = unpackLowLessThan1000k(attributes.eastward_z); - - var northward = [0, 0, 0]; - northward[0] = unpackLowLessThan1000k(attributes.northward_x); - northward[1] = unpackLowLessThan1000k(attributes.northward_y); - northward[2] = unpackLowLessThan1000k(attributes.northward_z); - - // We're using a unit sphere, so expect all HIGH values to be basically 0 - // and LOW value to be within a small cone around UNIT_X - expect(southWest_HIGH[0]).toEqualEpsilon(0.0, CesiumMath.EPSILON2); - expect(southWest_HIGH[1]).toEqualEpsilon(0.0, CesiumMath.EPSILON2); - expect(southWest_HIGH[2]).toEqualEpsilon(0.0, CesiumMath.EPSILON2); - - expect(southWest_LOW[0]).toBeGreaterThan(Math.cos(CesiumMath.toRadians(0.2))); - - // Expect eastward and northward to be unit-direction vectors in the ENU coordinate system at the rectangle center - var smallRectangleCenter = Cartographic.toCartesian(Rectangle.center(smallTestRectangle), unitSphereEllipsoid); - var enuMatrix = Transforms.eastNorthUpToFixedFrame(smallRectangleCenter, unitSphereEllipsoid); - var inverseEnu = Matrix4.inverse(enuMatrix, new Matrix4()); - - var eastwardENU = Matrix4.multiplyByPointAsVector(inverseEnu, Cartesian3.fromArray(eastward), new Cartesian3()); - eastwardENU = Cartesian3.normalize(eastwardENU, eastwardENU); - expect(Cartesian3.equalsEpsilon(eastwardENU, Cartesian3.UNIT_X, CesiumMath.EPSILON2)).toBe(true); - - var northwardENU = Matrix4.multiplyByPointAsVector(inverseEnu, Cartesian3.fromArray(northward), new Cartesian3()); - northwardENU = Cartesian3.normalize(northwardENU, northwardENU); - expect(Cartesian3.equalsEpsilon(northwardENU, Cartesian3.UNIT_Y, CesiumMath.EPSILON2)).toBe(true); + describe('floating point textures reliable', function () { + it('provides attributes for computing texture coordinates using planes in 3D', function() { + var attributes = smallRectangleAttributes; + + var southWest_LOW = attributes.southWest_LOW; + var southWest_HIGH = attributes.southWest_HIGH; + var eastward = attributes.eastward; + var northward = attributes.northward; + + checkGeometryInstanceAttributeVec3(southWest_LOW); + checkGeometryInstanceAttributeVec3(southWest_HIGH); + checkGeometryInstanceAttributeVec3(eastward); + checkGeometryInstanceAttributeVec3(northward); + + // We're using a unit sphere, so expect all HIGH values to be basically 0 + // and LOW value to be within a small cone around UNIT_X + expect(southWest_HIGH.value[0]).toEqualEpsilon(0.0, CesiumMath.EPSILON7); + expect(southWest_HIGH.value[1]).toEqualEpsilon(0.0, CesiumMath.EPSILON7); + expect(southWest_HIGH.value[2]).toEqualEpsilon(0.0, CesiumMath.EPSILON7); + + expect(southWest_LOW.value[0]).toBeGreaterThan(Math.cos(CesiumMath.toRadians(0.2))); + + // Expect eastward and northward to be unit-direction vectors in the ENU coordinate system at the rectangle center + var smallRectangleCenter = Cartographic.toCartesian(Rectangle.center(smallTestRectangle), unitSphereEllipsoid); + var enuMatrix = Transforms.eastNorthUpToFixedFrame(smallRectangleCenter, unitSphereEllipsoid); + var inverseEnu = Matrix4.inverse(enuMatrix, new Matrix4()); + + var eastwardENU = Matrix4.multiplyByPointAsVector(inverseEnu, Cartesian3.fromArray(eastward.value), new Cartesian3()); + eastwardENU = Cartesian3.normalize(eastwardENU, eastwardENU); + expect(Cartesian3.equalsEpsilon(eastwardENU, Cartesian3.UNIT_X, CesiumMath.EPSILON7)).toBe(true); + + var northwardENU = Matrix4.multiplyByPointAsVector(inverseEnu, Cartesian3.fromArray(northward.value), new Cartesian3()); + northwardENU = Cartesian3.normalize(northwardENU, northwardENU); + expect(Cartesian3.equalsEpsilon(northwardENU, Cartesian3.UNIT_Y, CesiumMath.EPSILON7)).toBe(true); + }); + + it('provides attributes for computing planes in 2D and Columbus View', function() { + var planes2D_HIGH = largeRectangleAttributes.planes2D_HIGH; + var planes2D_LOW = largeRectangleAttributes.planes2D_LOW; + + expect(planes2D_HIGH.componentDatatype).toEqual(ComponentDatatype.FLOAT); + expect(planes2D_HIGH.componentsPerAttribute).toEqual(4); + expect(planes2D_HIGH.normalize).toEqual(false); + + // Because using a unit sphere expect all HIGH values to be basically 0 + var highValue = planes2D_HIGH.value; + expect(highValue[0]).toEqualEpsilon(0.0, CesiumMath.EPSILON7); + expect(highValue[1]).toEqualEpsilon(0.0, CesiumMath.EPSILON7); + expect(highValue[2]).toEqualEpsilon(0.0, CesiumMath.EPSILON7); + expect(highValue[3]).toEqualEpsilon(0.0, CesiumMath.EPSILON7); + + expect(planes2D_LOW.componentDatatype).toEqual(ComponentDatatype.FLOAT); + expect(planes2D_LOW.componentsPerAttribute).toEqual(4); + expect(planes2D_LOW.normalize).toEqual(false); + + var cartographic = Cartographic.fromDegrees(-45, -45, 0.0); // southwest corner + var southwestCartesian = projection.project(cartographic); + var lowValue = planes2D_LOW.value; + expect(lowValue[0]).toEqualEpsilon(southwestCartesian.x, CesiumMath.EPSILON7); + expect(lowValue[1]).toEqualEpsilon(southwestCartesian.y, CesiumMath.EPSILON7); + expect(lowValue[2]).toEqualEpsilon(-southwestCartesian.y, CesiumMath.EPSILON7); + expect(lowValue[3]).toEqualEpsilon(-southwestCartesian.x, CesiumMath.EPSILON7); + + // Small case + // Because using a unit sphere expect all HIGH values to be basically 0 + highValue = smallRectangleAttributes.planes2D_HIGH.value; + expect(highValue[0]).toEqualEpsilon(0.0, CesiumMath.EPSILON7); + expect(highValue[1]).toEqualEpsilon(0.0, CesiumMath.EPSILON7); + expect(highValue[2]).toEqualEpsilon(0.0, CesiumMath.EPSILON7); + expect(highValue[3]).toEqualEpsilon(0.0, CesiumMath.EPSILON7); + + cartographic = Cartographic.fromDegrees(-0.1, -0.1, 0.0); // southwest corner + southwestCartesian = projection.project(cartographic); + lowValue = smallRectangleAttributes.planes2D_LOW.value; + expect(lowValue[0]).toEqualEpsilon(southwestCartesian.x, CesiumMath.EPSILON7); + expect(lowValue[1]).toEqualEpsilon(southwestCartesian.y, CesiumMath.EPSILON7); + expect(lowValue[2]).toEqualEpsilon(-southwestCartesian.y, CesiumMath.EPSILON7); + expect(lowValue[3]).toEqualEpsilon(-southwestCartesian.x, CesiumMath.EPSILON7); + }); }); - it('provides attributes for computing planes in 2D and Columbus View', function() { - var highValue = [0, 0, 0, 0]; - highValue[0] = unpackHighMagLessThan100Million(largeRectangleAttributes.planes2D_HIGH_x); - highValue[1] = unpackHighMagLessThan100Million(largeRectangleAttributes.planes2D_HIGH_y); - highValue[2] = unpackHighMagLessThan100Million(largeRectangleAttributes.planes2D_HIGH_z); - highValue[3] = unpackHighMagLessThan100Million(largeRectangleAttributes.planes2D_HIGH_w); - - var lowValue = [0, 0, 0, 0]; - lowValue[0] = unpackLowLessThan100k(largeRectangleAttributes.planes2D_LOW_x); - lowValue[1] = unpackLowLessThan100k(largeRectangleAttributes.planes2D_LOW_y); - lowValue[2] = unpackLowLessThan100k(largeRectangleAttributes.planes2D_LOW_z); - lowValue[3] = unpackLowLessThan100k(largeRectangleAttributes.planes2D_LOW_w); - - // Because using a unit sphere expect all HIGH values to be basically 0 - expect(highValue[0]).toEqualEpsilon(0.0, CesiumMath.EPSILON2); - expect(highValue[1]).toEqualEpsilon(0.0, CesiumMath.EPSILON2); - expect(highValue[2]).toEqualEpsilon(0.0, CesiumMath.EPSILON2); - expect(highValue[3]).toEqualEpsilon(0.0, CesiumMath.EPSILON2); - - var cartographic = Cartographic.fromDegrees(-45, -45, 0.0); // southwest corner - var southwestCartesian = projection.project(cartographic); - expect(lowValue[0]).toEqualEpsilon(southwestCartesian.x, CesiumMath.EPSILON2); - expect(lowValue[1]).toEqualEpsilon(southwestCartesian.y, CesiumMath.EPSILON2); - expect(lowValue[2]).toEqualEpsilon(-southwestCartesian.y, CesiumMath.EPSILON2); - expect(lowValue[3]).toEqualEpsilon(-southwestCartesian.x, CesiumMath.EPSILON2); - - // Small case - // Because using a unit sphere expect all HIGH values to be basically 0 - highValue[0] = unpackHighMagLessThan100Million(smallRectangleAttributes.planes2D_HIGH_x); - highValue[1] = unpackHighMagLessThan100Million(smallRectangleAttributes.planes2D_HIGH_y); - highValue[2] = unpackHighMagLessThan100Million(smallRectangleAttributes.planes2D_HIGH_z); - highValue[3] = unpackHighMagLessThan100Million(smallRectangleAttributes.planes2D_HIGH_w); - - expect(highValue[0]).toEqualEpsilon(0.0, CesiumMath.EPSILON2); - expect(highValue[1]).toEqualEpsilon(0.0, CesiumMath.EPSILON2); - expect(highValue[2]).toEqualEpsilon(0.0, CesiumMath.EPSILON2); - expect(highValue[3]).toEqualEpsilon(0.0, CesiumMath.EPSILON2); - - cartographic = Cartographic.fromDegrees(-0.1, -0.1, 0.0); // southwest corner - southwestCartesian = projection.project(cartographic); - lowValue[0] = unpackLowLessThan100k(smallRectangleAttributes.planes2D_LOW_x); - lowValue[1] = unpackLowLessThan100k(smallRectangleAttributes.planes2D_LOW_y); - lowValue[2] = unpackLowLessThan100k(smallRectangleAttributes.planes2D_LOW_z); - lowValue[3] = unpackLowLessThan100k(smallRectangleAttributes.planes2D_LOW_w); - - expect(lowValue[0]).toEqualEpsilon(southwestCartesian.x, CesiumMath.EPSILON2); - expect(lowValue[1]).toEqualEpsilon(southwestCartesian.y, CesiumMath.EPSILON2); - expect(lowValue[2]).toEqualEpsilon(-southwestCartesian.y, CesiumMath.EPSILON2); - expect(lowValue[3]).toEqualEpsilon(-southwestCartesian.x, CesiumMath.EPSILON2); + describe('floating point textures unreliable', function () { + it('provides attributes for computing texture coordinates using planes in 3D', function() { + var attributes = smallRectangleAttributesBadFloats; + + var southWest_LOW = [0, 0, 0]; + southWest_LOW[0] = unpackLowLessThan100k(attributes.southWest_LOW_x); + southWest_LOW[1] = unpackLowLessThan100k(attributes.southWest_LOW_y); + southWest_LOW[2] = unpackLowLessThan100k(attributes.southWest_LOW_z); + + var southWest_HIGH = [0, 0, 0]; + southWest_HIGH[0] = unpackHighMagLessThan100Million(attributes.southWest_HIGH_x); + southWest_HIGH[1] = unpackHighMagLessThan100Million(attributes.southWest_HIGH_y); + southWest_HIGH[2] = unpackHighMagLessThan100Million(attributes.southWest_HIGH_z); + + var eastward = [0, 0, 0]; + eastward[0] = unpackLowLessThan1000k(attributes.eastward_x); + eastward[1] = unpackLowLessThan1000k(attributes.eastward_y); + eastward[2] = unpackLowLessThan1000k(attributes.eastward_z); + + var northward = [0, 0, 0]; + northward[0] = unpackLowLessThan1000k(attributes.northward_x); + northward[1] = unpackLowLessThan1000k(attributes.northward_y); + northward[2] = unpackLowLessThan1000k(attributes.northward_z); + + // We're using a unit sphere, so expect all HIGH values to be basically 0 + // and LOW value to be within a small cone around UNIT_X + expect(southWest_HIGH[0]).toEqualEpsilon(0.0, CesiumMath.EPSILON2); + expect(southWest_HIGH[1]).toEqualEpsilon(0.0, CesiumMath.EPSILON2); + expect(southWest_HIGH[2]).toEqualEpsilon(0.0, CesiumMath.EPSILON2); + + expect(southWest_LOW[0]).toBeGreaterThan(Math.cos(CesiumMath.toRadians(0.2))); + + // Expect eastward and northward to be unit-direction vectors in the ENU coordinate system at the rectangle center + var smallRectangleCenter = Cartographic.toCartesian(Rectangle.center(smallTestRectangle), unitSphereEllipsoid); + var enuMatrix = Transforms.eastNorthUpToFixedFrame(smallRectangleCenter, unitSphereEllipsoid); + var inverseEnu = Matrix4.inverse(enuMatrix, new Matrix4()); + + var eastwardENU = Matrix4.multiplyByPointAsVector(inverseEnu, Cartesian3.fromArray(eastward), new Cartesian3()); + eastwardENU = Cartesian3.normalize(eastwardENU, eastwardENU); + expect(Cartesian3.equalsEpsilon(eastwardENU, Cartesian3.UNIT_X, CesiumMath.EPSILON2)).toBe(true); + + var northwardENU = Matrix4.multiplyByPointAsVector(inverseEnu, Cartesian3.fromArray(northward), new Cartesian3()); + northwardENU = Cartesian3.normalize(northwardENU, northwardENU); + expect(Cartesian3.equalsEpsilon(northwardENU, Cartesian3.UNIT_Y, CesiumMath.EPSILON2)).toBe(true); + }); + + it('provides attributes for computing planes in 2D and Columbus View', function() { + var attributes = largeRectangleAttributesBadFloats; + var highValue = [0, 0, 0, 0]; + highValue[0] = unpackHighMagLessThan100Million(attributes.planes2D_HIGH_x); + highValue[1] = unpackHighMagLessThan100Million(attributes.planes2D_HIGH_y); + highValue[2] = unpackHighMagLessThan100Million(attributes.planes2D_HIGH_z); + highValue[3] = unpackHighMagLessThan100Million(attributes.planes2D_HIGH_w); + + var lowValue = [0, 0, 0, 0]; + lowValue[0] = unpackLowLessThan100k(attributes.planes2D_LOW_x); + lowValue[1] = unpackLowLessThan100k(attributes.planes2D_LOW_y); + lowValue[2] = unpackLowLessThan100k(attributes.planes2D_LOW_z); + lowValue[3] = unpackLowLessThan100k(attributes.planes2D_LOW_w); + + // Because using a unit sphere expect all HIGH values to be basically 0 + expect(highValue[0]).toEqualEpsilon(0.0, CesiumMath.EPSILON2); + expect(highValue[1]).toEqualEpsilon(0.0, CesiumMath.EPSILON2); + expect(highValue[2]).toEqualEpsilon(0.0, CesiumMath.EPSILON2); + expect(highValue[3]).toEqualEpsilon(0.0, CesiumMath.EPSILON2); + + var cartographic = Cartographic.fromDegrees(-45, -45, 0.0); // southwest corner + var southwestCartesian = projection.project(cartographic); + expect(lowValue[0]).toEqualEpsilon(southwestCartesian.x, CesiumMath.EPSILON2); + expect(lowValue[1]).toEqualEpsilon(southwestCartesian.y, CesiumMath.EPSILON2); + expect(lowValue[2]).toEqualEpsilon(-southwestCartesian.y, CesiumMath.EPSILON2); + expect(lowValue[3]).toEqualEpsilon(-southwestCartesian.x, CesiumMath.EPSILON2); + + // Small case + attributes = smallRectangleAttributesBadFloats; + // Because using a unit sphere expect all HIGH values to be basically 0 + highValue[0] = unpackHighMagLessThan100Million(attributes.planes2D_HIGH_x); + highValue[1] = unpackHighMagLessThan100Million(attributes.planes2D_HIGH_y); + highValue[2] = unpackHighMagLessThan100Million(attributes.planes2D_HIGH_z); + highValue[3] = unpackHighMagLessThan100Million(attributes.planes2D_HIGH_w); + + expect(highValue[0]).toEqualEpsilon(0.0, CesiumMath.EPSILON2); + expect(highValue[1]).toEqualEpsilon(0.0, CesiumMath.EPSILON2); + expect(highValue[2]).toEqualEpsilon(0.0, CesiumMath.EPSILON2); + expect(highValue[3]).toEqualEpsilon(0.0, CesiumMath.EPSILON2); + + cartographic = Cartographic.fromDegrees(-0.1, -0.1, 0.0); // southwest corner + southwestCartesian = projection.project(cartographic); + lowValue[0] = unpackLowLessThan100k(attributes.planes2D_LOW_x); + lowValue[1] = unpackLowLessThan100k(attributes.planes2D_LOW_y); + lowValue[2] = unpackLowLessThan100k(attributes.planes2D_LOW_z); + lowValue[3] = unpackLowLessThan100k(attributes.planes2D_LOW_w); + + expect(lowValue[0]).toEqualEpsilon(southwestCartesian.x, CesiumMath.EPSILON2); + expect(lowValue[1]).toEqualEpsilon(southwestCartesian.y, CesiumMath.EPSILON2); + expect(lowValue[2]).toEqualEpsilon(-southwestCartesian.y, CesiumMath.EPSILON2); + expect(lowValue[3]).toEqualEpsilon(-southwestCartesian.x, CesiumMath.EPSILON2); + }); }); it('provides attributes for rotating texture coordinates', function() { // 90 degree rotation of a square, so "max" in Y direction is (0,0), "max" in X direction is (1,1) - var attributes = ShadowVolumeAppearance.getPlanarTextureCoordinateAttributes(smallTestRectangle, [1, 0, 0, 0, 1, 1], unitSphereEllipsoid, projection, 0.0); + var attributes = ShadowVolumeAppearance.getPlanarTextureCoordinateAttributes(smallTestRectangle, [1, 0, 0, 0, 1, 1], unitSphereEllipsoid, projection, false, 0.0); var uMaxVmax = attributes.uMaxVmax; var uvMinAndExtents = attributes.uvMinAndExtents; @@ -273,11 +366,15 @@ describe('Scene/ShadowVolumeAppearance', function() { it('checks for spherical extent attributes', function() { expect(ShadowVolumeAppearance.hasAttributesForSphericalExtents(smallRectangleAttributes)).toBe(false); expect(ShadowVolumeAppearance.hasAttributesForSphericalExtents(largeRectangleAttributes)).toBe(true); + expect(ShadowVolumeAppearance.hasAttributesForSphericalExtents(smallRectangleAttributesBadFloats)).toBe(false); + expect(ShadowVolumeAppearance.hasAttributesForSphericalExtents(largeRectangleAttributesBadFloats)).toBe(true); }); it('checks for planar texture coordinate attributes', function() { expect(ShadowVolumeAppearance.hasAttributesForTextureCoordinatePlanes(smallRectangleAttributes)).toBe(true); expect(ShadowVolumeAppearance.hasAttributesForTextureCoordinatePlanes(largeRectangleAttributes)).toBe(false); + expect(ShadowVolumeAppearance.hasAttributesForTextureCoordinatePlanes(smallRectangleAttributesBadFloats)).toBe(true); + expect(ShadowVolumeAppearance.hasAttributesForTextureCoordinatePlanes(largeRectangleAttributesBadFloats)).toBe(false); }); it('checks if a rectangle should use spherical texture coordinates', function() { @@ -285,9 +382,36 @@ describe('Scene/ShadowVolumeAppearance', function() { expect(ShadowVolumeAppearance.shouldUseSphericalCoordinates(largeTestRectangle)).toBe(true); }); + it('creates vertex shaders based on whether or not float textures are used for high/low positions', function() { + // Check defines + var sphericalTexturedAppearanceUnsafe = new ShadowVolumeAppearance(true, false, textureMaterialAppearance, false); + var shaderSource = sphericalTexturedAppearanceUnsafe.createVertexShader([], testVs, false, projection); + var defines = shaderSource.defines; + expect(defines.length).toEqual(3); + expect(defines.indexOf('UINT8_PACKING')).not.toEqual(-1); + + // 2D variant + shaderSource = sphericalTexturedAppearanceUnsafe.createVertexShader([], testVs, true, projection); + defines = shaderSource.defines; + expect(defines.length).toEqual(7); + expect(defines.indexOf('UINT8_PACKING')).not.toEqual(-1); + + var sphericalTexturedAppearanceSafe = new ShadowVolumeAppearance(true, false, textureMaterialAppearance, true); + shaderSource = sphericalTexturedAppearanceSafe.createVertexShader([], testVs, false, projection); + defines = shaderSource.defines; + expect(defines.length).toEqual(2); + expect(defines.indexOf('UINT8_PACKING')).toEqual(-1); + + // 2D variant + shaderSource = sphericalTexturedAppearanceSafe.createVertexShader([], testVs, true, projection); + defines = shaderSource.defines; + expect(defines.length).toEqual(6); + expect(defines.indexOf('UINT8_PACKING')).toEqual(-1); + }); + it('creates vertex shaders for color', function() { // Check defines - var sphericalTexturedAppearance = new ShadowVolumeAppearance(true, false, textureMaterialAppearance); + var sphericalTexturedAppearance = new ShadowVolumeAppearance(true, false, textureMaterialAppearance, true); var shaderSource = sphericalTexturedAppearance.createVertexShader([], testVs, false, projection); var defines = shaderSource.defines; expect(defines.length).toEqual(2); @@ -307,7 +431,7 @@ describe('Scene/ShadowVolumeAppearance', function() { expect(defines.indexOf(westMostYlowDefine)).not.toEqual(-1); // Unculled color appearance - no texcoords at all - var sphericalUnculledColorAppearance = new ShadowVolumeAppearance(false, false, perInstanceColorMaterialAppearance); + var sphericalUnculledColorAppearance = new ShadowVolumeAppearance(false, false, perInstanceColorMaterialAppearance, true); shaderSource = sphericalUnculledColorAppearance.createVertexShader([], testVs, false, projection); defines = shaderSource.defines; expect(defines.length).toEqual(1); @@ -326,7 +450,7 @@ describe('Scene/ShadowVolumeAppearance', function() { expect(defines.indexOf('PER_INSTANCE_COLOR')).not.toEqual(-1); // Planar textured, without culling - var planarTexturedAppearance = new ShadowVolumeAppearance(false, true, textureMaterialAppearance); + var planarTexturedAppearance = new ShadowVolumeAppearance(false, true, textureMaterialAppearance, true); shaderSource = planarTexturedAppearance.createVertexShader([], testVs, false, projection); defines = shaderSource.defines; expect(defines.indexOf('TEXTURE_COORDINATES')).not.toEqual(-1); @@ -347,7 +471,7 @@ describe('Scene/ShadowVolumeAppearance', function() { it('creates vertex shaders for pick', function() { // Check defines - var sphericalTexturedAppearance = new ShadowVolumeAppearance(true, false, textureMaterialAppearance); + var sphericalTexturedAppearance = new ShadowVolumeAppearance(true, false, textureMaterialAppearance, true); var shaderSource = sphericalTexturedAppearance.createPickVertexShader([], testVs, false, projection); var defines = shaderSource.defines; expect(defines.length).toEqual(2); @@ -367,7 +491,7 @@ describe('Scene/ShadowVolumeAppearance', function() { expect(defines.indexOf(westMostYlowDefine)).not.toEqual(-1); // Unculled color appearance - no texcoords at all - var sphericalUnculledColorAppearance = new ShadowVolumeAppearance(false, false, perInstanceColorMaterialAppearance); + var sphericalUnculledColorAppearance = new ShadowVolumeAppearance(false, false, perInstanceColorMaterialAppearance, true); shaderSource = sphericalUnculledColorAppearance.createPickVertexShader([], testVs, false, projection); defines = shaderSource.defines; expect(defines.length).toEqual(0); @@ -384,7 +508,7 @@ describe('Scene/ShadowVolumeAppearance', function() { expect(defines.length).toEqual(4); // Planar textured, without culling - var planarTexturedAppearance = new ShadowVolumeAppearance(false, true, textureMaterialAppearance); + var planarTexturedAppearance = new ShadowVolumeAppearance(false, true, textureMaterialAppearance, true); shaderSource = planarTexturedAppearance.createPickVertexShader([], testVs, false, projection); defines = shaderSource.defines; expect(defines.length).toEqual(0); @@ -402,7 +526,7 @@ describe('Scene/ShadowVolumeAppearance', function() { it('creates fragment shaders for color and pick', function() { // Check defines - var sphericalTexturedAppearance = new ShadowVolumeAppearance(true, false, textureMaterialAppearance); + var sphericalTexturedAppearance = new ShadowVolumeAppearance(true, false, textureMaterialAppearance, true); var shaderSource = sphericalTexturedAppearance.createFragmentShader(false); var defines = shaderSource.defines; @@ -435,7 +559,7 @@ describe('Scene/ShadowVolumeAppearance', function() { expect(defines.length).toEqual(9); // Culling with planar texture coordinates on a per-color material - var planarColorAppearance = new ShadowVolumeAppearance(true, true, perInstanceColorMaterialAppearance); + var planarColorAppearance = new ShadowVolumeAppearance(true, true, perInstanceColorMaterialAppearance, true); shaderSource = planarColorAppearance.createFragmentShader(false); defines = shaderSource.defines; @@ -459,7 +583,7 @@ describe('Scene/ShadowVolumeAppearance', function() { expect(defines.length).toEqual(5); // Flat - var flatSphericalTexturedAppearance = new ShadowVolumeAppearance(true, false, flatTextureMaterialAppearance); + var flatSphericalTexturedAppearance = new ShadowVolumeAppearance(true, false, flatTextureMaterialAppearance, true); shaderSource = flatSphericalTexturedAppearance.createFragmentShader(false); defines = shaderSource.defines; expect(defines.indexOf('SPHERICAL')).not.toEqual(-1); @@ -474,7 +598,7 @@ describe('Scene/ShadowVolumeAppearance', function() { expect(defines.indexOf('FLAT')).not.toEqual(-1); expect(defines.length).toEqual(10); - var flatSphericalColorAppearance = new ShadowVolumeAppearance(false, false, flatPerInstanceColorMaterialAppearance); + var flatSphericalColorAppearance = new ShadowVolumeAppearance(false, false, flatPerInstanceColorMaterialAppearance, true); shaderSource = flatSphericalColorAppearance.createFragmentShader(false); defines = shaderSource.defines; expect(defines.indexOf('SPHERICAL')).not.toEqual(-1); From c283527f479a171dea9b1e1918eb13b8935db0fd Mon Sep 17 00:00:00 2001 From: likangning93 Date: Mon, 23 Sep 2019 11:18:38 -0400 Subject: [PATCH 6/7] PR comments --- Source/Renderer/Context.js | 2 +- Source/Renderer/checkFloatTexturePrecision.js | 2 +- .../Shaders/CheckFloatTexturePrecisionFS.glsl | 3 +- Source/Shaders/ShadowVolumeAppearanceFS.glsl | 12 +++++--- Source/Shaders/ShadowVolumeAppearanceVS.glsl | 28 +++++++++++++------ 5 files changed, 31 insertions(+), 16 deletions(-) diff --git a/Source/Renderer/Context.js b/Source/Renderer/Context.js index 77d26c021712..9dd5eba7c0ff 100644 --- a/Source/Renderer/Context.js +++ b/Source/Renderer/Context.js @@ -591,7 +591,7 @@ define([ }, /** - * true returns if the context's floating point textures support 6 decimal places of precision. + * Returns true if the context's floating point textures support 6 decimal places of precision. * @memberof Context.prototype * @type {Boolean} * @see {@link https://www.khronos.org/registry/webgl/extensions/OES_texture_float/} diff --git a/Source/Renderer/checkFloatTexturePrecision.js b/Source/Renderer/checkFloatTexturePrecision.js index c30ec61a40fb..3da3deb22aa6 100644 --- a/Source/Renderer/checkFloatTexturePrecision.js +++ b/Source/Renderer/checkFloatTexturePrecision.js @@ -21,7 +21,7 @@ define([ * Checks if the context's floating point textures support 6 decimal places of precision. * * @param {Context} context A context wrapping a gl implementation. - * @returns {Boolean} whether or not the context's floating point textures support 6 decimal places of precision + * @returns {Boolean} Whether or not the context's floating point textures support 6 decimal places of precision * * @private */ diff --git a/Source/Shaders/CheckFloatTexturePrecisionFS.glsl b/Source/Shaders/CheckFloatTexturePrecisionFS.glsl index a2eadb4bd827..8f77d167cef5 100644 --- a/Source/Shaders/CheckFloatTexturePrecisionFS.glsl +++ b/Source/Shaders/CheckFloatTexturePrecisionFS.glsl @@ -1,6 +1,7 @@ uniform sampler2D u_floatTexture; -void main() { +void main() +{ float actual = texture2D(u_floatTexture, vec2(0.5, 0.5)).r; float expected = 123456.0; gl_FragColor = vec4(abs(actual - expected), 0.0, 0.0, 1.0); diff --git a/Source/Shaders/ShadowVolumeAppearanceFS.glsl b/Source/Shaders/ShadowVolumeAppearanceFS.glsl index ab8903295863..d42c278e5111 100644 --- a/Source/Shaders/ShadowVolumeAppearanceFS.glsl +++ b/Source/Shaders/ShadowVolumeAppearanceFS.glsl @@ -20,12 +20,14 @@ varying vec4 v_color; #endif #ifdef NORMAL_EC -vec3 getEyeCoordinate3FromWindowCoordinate(vec2 fragCoord, float logDepthOrDepth) { +vec3 getEyeCoordinate3FromWindowCoordinate(vec2 fragCoord, float logDepthOrDepth) +{ vec4 eyeCoordinate = czm_windowToEyeCoordinates(fragCoord, logDepthOrDepth); return eyeCoordinate.xyz / eyeCoordinate.w; } -vec3 vectorFromOffset(vec4 eyeCoordinate, vec2 positiveOffset) { +vec3 vectorFromOffset(vec4 eyeCoordinate, vec2 positiveOffset) +{ vec2 glFragCoordXY = gl_FragCoord.xy; // Sample depths at both offset and negative offset float upOrRightLogDepth = czm_unpackDepth(texture2D(czm_globeDepthTexture, (glFragCoordXY + positiveOffset) / czm_viewport.zw)); @@ -71,7 +73,8 @@ void main(void) #ifdef PICK #ifdef CULL_FRAGMENTS - if (0.0 <= uv.x && uv.x <= 1.0 && 0.0 <= uv.y && uv.y <= 1.0) { + if (0.0 <= uv.x && uv.x <= 1.0 && 0.0 <= uv.y && uv.y <= 1.0) + { gl_FragColor.a = 1.0; // 0.0 alpha leads to discard from ShaderSource.createPickFragmentShaderSource czm_writeDepthClampedToFarPlane(); } @@ -81,7 +84,8 @@ void main(void) #else // PICK #ifdef CULL_FRAGMENTS - if (uv.x <= 0.0 || 1.0 <= uv.x || uv.y <= 0.0 || 1.0 <= uv.y) { + if (uv.x <= 0.0 || 1.0 <= uv.x || uv.y <= 0.0 || 1.0 <= uv.y) + { discard; } #endif diff --git a/Source/Shaders/ShadowVolumeAppearanceVS.glsl b/Source/Shaders/ShadowVolumeAppearanceVS.glsl index f1e2e6b0c2e0..b5d486c7de68 100644 --- a/Source/Shaders/ShadowVolumeAppearanceVS.glsl +++ b/Source/Shaders/ShadowVolumeAppearanceVS.glsl @@ -26,7 +26,8 @@ varying vec3 v_vMaxAndInverseDistance; #endif // TEXTURE_COORDINATES #if defined(TEXTURE_COORDINATES) && !defined(SPHERICAL) && defined(UINT8_PACKING) -vec4 clampAndMagnitude(vec4 sd) { +vec4 clampAndMagnitude(vec4 sd) +{ vec4 d = sd; d.x = czm_branchFreeTernary(sd.x < 128.0, d.x, (255.0 - sd.x)); d.x = floor(0.5 + d.x); @@ -36,12 +37,14 @@ vec4 clampAndMagnitude(vec4 sd) { return d; } -float unpackLowLessThan100k(vec4 sd) { +float unpackLowLessThan100k(vec4 sd) +{ vec4 d = clampAndMagnitude(sd); return (1000.0 * d.x + 10.0 * d.y + 0.1 * d.z + 0.001 * d.w) * czm_branchFreeTernary(sd.x < 128.0, 1.0, -1.0); } -vec3 southwest_LOW(vec4 x, vec4 y, vec4 z) { +vec3 southwest_LOW(vec4 x, vec4 y, vec4 z) +{ vec3 value; value.x = unpackLowLessThan100k(x); value.y = unpackLowLessThan100k(y); @@ -49,11 +52,14 @@ vec3 southwest_LOW(vec4 x, vec4 y, vec4 z) { return value; } -float unpackHighMagLessThan100Million(vec4 sd) { +float unpackHighMagLessThan100Million(vec4 sd) +{ vec4 d = clampAndMagnitude(sd); return (1000000.0 * d.x + 10000.0 * d.y + 100.0 * d.z + d.w) * czm_branchFreeTernary(sd.x < 128.0, 1.0, -1.0); } -vec3 southwest_HIGH(vec4 x, vec4 y, vec4 z) { + +vec3 southwest_HIGH(vec4 x, vec4 y, vec4 z) +{ vec3 value; value.x = unpackHighMagLessThan100Million(x); value.y = unpackHighMagLessThan100Million(y); @@ -62,7 +68,8 @@ vec3 southwest_HIGH(vec4 x, vec4 y, vec4 z) { } #ifdef COLUMBUS_VIEW_2D -vec4 unpackPlanes2D_HIGH(vec4 x, vec4 y, vec4 z, vec4 w) { +vec4 unpackPlanes2D_HIGH(vec4 x, vec4 y, vec4 z, vec4 w) +{ vec4 value; value.x = unpackHighMagLessThan100Million(x); value.y = unpackHighMagLessThan100Million(y); @@ -71,7 +78,8 @@ vec4 unpackPlanes2D_HIGH(vec4 x, vec4 y, vec4 z, vec4 w) { return value; } -vec4 unpackPlanes2D_LOW(vec4 x, vec4 y, vec4 z, vec4 w) { +vec4 unpackPlanes2D_LOW(vec4 x, vec4 y, vec4 z, vec4 w) +{ vec4 value; value.x = unpackLowLessThan100k(x); value.y = unpackLowLessThan100k(y); @@ -81,12 +89,14 @@ vec4 unpackPlanes2D_LOW(vec4 x, vec4 y, vec4 z, vec4 w) { } #else -float unpackLowLessThan1000k(vec4 sd) { +float unpackLowLessThan1000k(vec4 sd) +{ vec4 d = clampAndMagnitude(sd); return (10000.0 * d.x + 100.0 * d.y + d.z + 0.01 * d.w) * czm_branchFreeTernary(sd.x < 128.0, 1.0, -1.0); } -vec3 unpackExtent(vec4 x, vec4 y, vec4 z) { +vec3 unpackExtent(vec4 x, vec4 y, vec4 z) +{ vec3 value; value.x = unpackLowLessThan1000k(x); value.y = unpackLowLessThan1000k(y); From a3ac1da7c02db61c2106cf3d82eb9af0cc2f5f5d Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Mon, 23 Sep 2019 17:19:02 -0400 Subject: [PATCH 7/7] Formatting [skip ci] --- Source/Renderer/checkFloatTexturePrecision.js | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/Source/Renderer/checkFloatTexturePrecision.js b/Source/Renderer/checkFloatTexturePrecision.js index 3da3deb22aa6..2e00e1100a7c 100644 --- a/Source/Renderer/checkFloatTexturePrecision.js +++ b/Source/Renderer/checkFloatTexturePrecision.js @@ -1,20 +1,19 @@ define([ - '../Core/PixelFormat', - '../Shaders/CheckFloatTexturePrecisionFS', - './ComputeCommand', - './ComputeEngine', - './Framebuffer', - './PixelDatatype', - './Texture' -], function( - PixelFormat, - CheckFloatTexturePrecisionFS, - ComputeCommand, - ComputeEngine, - Framebuffer, - PixelDatatype, - Texture -) { + '../Core/PixelFormat', + '../Shaders/CheckFloatTexturePrecisionFS', + './ComputeCommand', + './ComputeEngine', + './Framebuffer', + './PixelDatatype', + './Texture' + ], function( + PixelFormat, + CheckFloatTexturePrecisionFS, + ComputeCommand, + ComputeEngine, + Framebuffer, + PixelDatatype, + Texture) { 'use strict'; /**