From bdf302eec8f00853e4e8015143a0620098eaa761 Mon Sep 17 00:00:00 2001
From: Kangning Li Loading...
Loading...
true
and componentDatatype
is an integer format,
+ * indicate that the components should be mapped to the range [0, 1] (unsigned)
+ * or [-1, 1] (signed) when they are accessed as floating-point for rendering.
+ *
+ * @memberof SphericalExtentsGeometryInstanceAttribute.prototype
+ *
+ * @type {Boolean}
+ * @readonly
+ *
+ * @default false
+ */
+ normalize : {
+ get : function() {
+ return false;
+ }
+ }
+ });
+
+ return SphericalExtentsGeometryInstanceAttribute;
+});
diff --git a/Source/DataSources/StaticGroundGeometryColorBatch.js b/Source/DataSources/StaticGroundGeometryColorBatch.js
index e0c22eb2a10..b0235c2b33e 100644
--- a/Source/DataSources/StaticGroundGeometryColorBatch.js
+++ b/Source/DataSources/StaticGroundGeometryColorBatch.js
@@ -259,7 +259,7 @@ define([
var instance = updater.createFillGeometryInstance(time);
var batches = this._batches;
// instance.attributes.color.value is a Uint8Array, so just read it as a Uint32 and make that the key
- var batchKey = new Uint32Array(instance.attributes.color.value.buffer)[0];
+ var batchKey = 1;//new Uint32Array(instance.attributes.color.value.buffer)[0];
var batch;
if (batches.contains(batchKey)) {
batch = batches.get(batchKey);
diff --git a/Source/Scene/ClassificationPrimitive.js b/Source/Scene/ClassificationPrimitive.js
index b53fb5ba5a9..2754e424919 100644
--- a/Source/Scene/ClassificationPrimitive.js
+++ b/Source/Scene/ClassificationPrimitive.js
@@ -858,9 +858,9 @@ define([
instance = instances[i];
var attributes = instance.attributes;
if (!defined(attributes) || !defined(attributes.color)) {
- throw new DeveloperError('Not all of the geometry instances have the same color attribute.');
+ //throw new DeveloperError('Not all of the geometry instances have the same color attribute.');
} else if (defined(color) && !ColorGeometryInstanceAttribute.equals(color, attributes.color)) {
- throw new DeveloperError('Not all of the geometry instances have the same color attribute.');
+ //throw new DeveloperError('Not all of the geometry instances have the same color attribute.');
} else if (!defined(color)) {
color = attributes.color;
}
@@ -936,7 +936,7 @@ define([
this._rsColorPass = RenderState.fromCache(getColorRenderState(true));
}
- this._primitive.debugShowBoundingVolume = this.debugShowBoundingVolume;
+ this._primitive.debugShowBoundingVolume = true;//this.debugShowBoundingVolume;
this._primitive.update(frameState);
};
diff --git a/Source/Scene/GroundPrimitive.js b/Source/Scene/GroundPrimitive.js
index 002056d4300..22db4e87f1c 100644
--- a/Source/Scene/GroundPrimitive.js
+++ b/Source/Scene/GroundPrimitive.js
@@ -17,6 +17,7 @@ define([
'../Core/OrientedBoundingBox',
'../Core/Rectangle',
'../Core/Resource',
+ '../Core/SphericalExtentsGeometryInstanceAttribute',
'../Renderer/Pass',
'../ThirdParty/when',
'./ClassificationPrimitive',
@@ -41,6 +42,7 @@ define([
OrientedBoundingBox,
Rectangle,
Resource,
+ SphericalExtentsGeometryInstanceAttribute,
Pass,
when,
ClassificationPrimitive,
@@ -209,16 +211,11 @@ define([
this._boundingSpheresKeys = [];
this._boundingSpheres = [];
- var sphericalExtents = new Cartesian4();
var uniformMap = {
u_globeMinimumAltitude: function() {
return 55000.0;
- },
- u_sphericalExtents: function() {
- return sphericalExtents;
}
};
- this._sphericalExtents = sphericalExtents;
this._uniformMap = uniformMap;
var that = this;
@@ -728,7 +725,7 @@ define([
geometry = instance.geometry;
var instanceRectangle = getRectangle(frameState, geometry);
if (!defined(rectangle)) {
- rectangle = instanceRectangle;
+ rectangle = Rectangle.clone(instanceRectangle);
} else if (defined(instanceRectangle)) {
Rectangle.union(rectangle, instanceRectangle, rectangle);
}
@@ -758,10 +755,22 @@ define([
instance = instances[i];
geometry = instance.geometry;
instanceType = geometry.constructor;
+
+ // TODO: what to do if not all the geometryInstances are polygonHierarchies? TODO: does this even happen here?
+ var attributes = {
+ sphericalExtents : new SphericalExtentsGeometryInstanceAttribute(geometry._rectangle)
+ };
+ var instanceAttributes = instance.attributes;
+ for (var attributeKey in instanceAttributes) {
+ if (instanceAttributes.hasOwnProperty(attributeKey)) {
+ attributes[attributeKey] = instanceAttributes[attributeKey];
+ }
+ }
+
groundInstances[i] = new GeometryInstance({
geometry : instanceType.createShadowVolume(geometry, getComputeMinimumHeightFunction(this),
getComputeMaximumHeightFunction(this)),
- attributes : instance.attributes,
+ attributes : attributes,
id : instance.id
});
}
@@ -775,26 +784,6 @@ define([
updateAndQueueCommands(that, frameState, colorCommands, pickCommands, modelMatrix, cull, debugShowBoundingVolume, twoPasses);
};
- // grab spherical extents. TODO: what to do if not all the geometryInstances are polygonHierarchies? TODO: does this even happen here?
- var rectangleSphericalExtents = undefined;
- for (i = 0; i < length; i++) {
- var geometry = groundInstances[i].geometry;
- if (defined(geometry._rectangle)) {
- if (!defined(rectangleSphericalExtents)) {
- rectangleSphericalExtents = Rectangle.clone(geometry._rectangle);
- } else {
- Rectangle.union(rectangleSphericalExtents, geometry._rectangle, rectangleSphericalExtents);
- }
- }
- }
- console.log(rectangleSphericalExtents);
- var sphericalExtentsVec4 = this._sphericalExtents;
- sphericalExtentsVec4.x = rectangleSphericalExtents.west;
- sphericalExtentsVec4.y = rectangleSphericalExtents.south;
- sphericalExtentsVec4.z = 1.0 / (rectangleSphericalExtents.east - rectangleSphericalExtents.west);
- sphericalExtentsVec4.w = 1.0 / (rectangleSphericalExtents.north - rectangleSphericalExtents.south);
- console.log(sphericalExtentsVec4);
-
this._primitive = new ClassificationPrimitive(primitiveOptions);
this._primitive.readyPromise.then(function(primitive) {
that._ready = true;
diff --git a/Source/Scene/Scene.js b/Source/Scene/Scene.js
index d2e375709d5..3fb0d50ffbd 100644
--- a/Source/Scene/Scene.js
+++ b/Source/Scene/Scene.js
@@ -624,10 +624,10 @@ define([
/**
* Set to true to copy the depth texture after rendering the globe. Makes czm_globeDepthTexture valid.
* @type {Boolean}
- * @default false
+ * @default true
* @private
*/
- this.copyGlobeDepth = false;
+ this.copyGlobeDepth = true;
/**
* Blends the atmosphere to geometry far from the camera for horizon views. Allows for additional
diff --git a/Source/Shaders/ShadowVolumeFS.glsl b/Source/Shaders/ShadowVolumeFS.glsl
index b8e80513008..aca635fc219 100644
--- a/Source/Shaders/ShadowVolumeFS.glsl
+++ b/Source/Shaders/ShadowVolumeFS.glsl
@@ -6,10 +6,52 @@
uniform vec4 u_highlightColor;
#else
varying vec4 v_color;
-uniform vec4 u_sphericalExtents;
-
+varying vec4 v_sphericalExtents;
#endif
+float rez = 0.1;
+
+float asinRef(float x) {
+ float negate = x < 0.0 ? -1.0 : 1.0;
+ x = abs(x);
+ float ret = -0.0187293;
+ ret *= x;
+ ret += 0.0742610;
+ ret *= x;
+ ret -= 0.2121144;
+ ret *= x;
+ ret += 1.5707288;
+ ret = 3.14159265358979 * 0.5 - sqrt(1.0 - x) * ret;
+ return ret - 2.0 * negate * ret;
+}
+
+float atan2Ref(float y, float x)
+{
+ float t0, t1, t2, t3, t4;
+
+ t3 = abs(x);
+ t1 = abs(y);
+ t0 = max(t3, t1);
+ t1 = min(t3, t1);
+ t3 = 1.0 / t0;
+ t3 = t1 * t3;
+
+ t4 = t3 * t3;
+ t0 = - 0.013480470;
+ t0 = t0 * t4 + 0.057477314;
+ t0 = t0 * t4 - 0.121239071;
+ t0 = t0 * t4 + 0.195635925;
+ t0 = t0 * t4 - 0.332994597;
+ t0 = t0 * t4 + 0.999995630;
+ t3 = t0 * t3;
+
+ t3 = (abs(y) > abs(x)) ? 1.570796327 - t3 : t3;
+ t3 = (x < 0.0) ? 3.141592654 - t3 : t3;
+ t3 = (y < 0.0) ? -t3 : t3;
+
+ return t3;
+}
+
void main(void)
{
#ifdef VECTOR_TILE
@@ -23,24 +65,55 @@ void main(void)
vec4 worldCoord4 = czm_inverseView * eyeCoord;
vec3 worldCoord = worldCoord4.xyz / worldCoord4.w;
- float height = length(worldCoord);
+ //float height = length(worldCoord);
vec3 sphereNormal = normalize(worldCoord);
- float longitude = asin(sphereNormal.z); // find a dress for the ball Sinderella
- float latitude = atan(sphereNormal.y, sphereNormal.x); // the kitTans weep
+ float latitude = asinRef(sphereNormal.z); // find a dress for the ball Sinderella
+ float longitude = atan2Ref(sphereNormal.y, sphereNormal.x); // the kitTans weep
+
+ float u = (latitude - v_sphericalExtents.y) * v_sphericalExtents.w;
+ float v = (longitude - v_sphericalExtents.x) * v_sphericalExtents.z;
- float u = (latitude - u_sphericalExtents.x) * u_sphericalExtents.z;
- float v = (longitude - u_sphericalExtents.y) * u_sphericalExtents.w;
+ /*
+ // Snippet that made me realize spherical !== cartographic
+ float alpha = 1.0;
+ if (v < 0.5) {
+ alpha = 0.5;
+ }
+ if (u < 0.5) {
+ gl_FragColor = vec4(1.0, 0.0, 0.0, alpha);
+ } else {
+ gl_FragColor = vec4(0.0, 1.0, 0.0, alpha);
+ }
+ */
- float colorHeight = (height - 6370000.0) / 10000.0;
- //gl_FragColor = vec4(vec2(u, v), 0.0, 0.5);
- // UV checkerboard
- if (((mod(floor(u / 0.1), 2.0) == 1.0) && (mod(floor(v / 0.1), 2.0) == 0.0)) || ((mod(floor(u / 0.1), 2.0) == 0.0) && (mod(floor(v / 0.1), 2.0) == 1.0))) {
- gl_FragColor = vec4(vec2(u, v), 0.0, 0.5);
+ // snippet that I used to figure out that inverse trig functions on CPU and GPU have pretty noticeable differences
+ if (u < 0.0) {
+ gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
+ }
+ else if (1.0 < u) {
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ }
+ else if (v < 0.0) {
+ gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
+ }
+ else if (1.0 < v) {
+ gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
} else {
- gl_FragColor = vec4(0.0, vec2(u, v), 0.5);
+ // UV checkerboard
+ if (((mod(floor(u / rez), 2.0) == 1.0) && (mod(floor(v / rez), 2.0) == 0.0)) || ((mod(floor(u / rez), 2.0) == 0.0) && (mod(floor(v / rez), 2.0) == 1.0))) {
+ gl_FragColor = vec4(u, v, 0.0, 1.0);
+ } else {
+ gl_FragColor = v_color;
+ }
}
+/*
+ if (u < 0.0 || 1.0 < u || v < 0.0 || 1.0 < v) {
+ discard;
+ } else {
+ gl_FragColor = v_color;
+ }*/
#endif
czm_writeDepthClampedToFarPlane();
diff --git a/Source/Shaders/ShadowVolumeVS.glsl b/Source/Shaders/ShadowVolumeVS.glsl
index 9d83f1a2958..bb7721936ed 100644
--- a/Source/Shaders/ShadowVolumeVS.glsl
+++ b/Source/Shaders/ShadowVolumeVS.glsl
@@ -18,6 +18,7 @@ uniform float u_globeMinimumAltitude;
#ifndef VECTOR_TILE
varying vec4 v_color;
+varying vec4 v_sphericalExtents;
#endif
void main()
@@ -26,6 +27,7 @@ void main()
gl_Position = czm_depthClampFarPlane(u_modifiedModelViewProjection * vec4(position, 1.0));
#else
v_color = color;
+ v_sphericalExtents = czm_batchTable_sphericalExtents(batchId);
vec4 position = czm_computePosition();
diff --git a/Specs/Scene/GroundPrimitiveSpec.js b/Specs/Scene/GroundPrimitiveSpec.js
index a17aab5a121..808a0830ecd 100644
--- a/Specs/Scene/GroundPrimitiveSpec.js
+++ b/Specs/Scene/GroundPrimitiveSpec.js
@@ -619,7 +619,7 @@ defineSuite([
attributes : {
color : rectColorAttribute,
distanceDisplayCondition : new DistanceDisplayConditionGeometryInstanceAttribute(near, far)
- }
+ } // Dan: attributes added here "automagically" show up in the shader in the batch table. Look at DistanceDisplayConditionGeometryInstanceAttribute
});
primitive = new GroundPrimitive({
From 529b5ab55a4a6161e9fc5a1a1c71075cdf892681 Mon Sep 17 00:00:00 2001
From: Kangning Li
* For correct rendering, this feature requires the EXT_frag_depth WebGL extension. For hardware that do not support this extension, there
@@ -85,6 +90,7 @@ define([
*
* @param {Object} [options] Object with the following properties:
* @param {Array|GeometryInstance} [options.geometryInstances] The geometry instances to render. This can either be a single instance or an array of length one.
+ * @param {Appearance} [options.appearance] The appearance used to render the primitive.
* @param {Boolean} [options.show=true] Determines if this primitive will be shown.
* @param {Boolean} [options.vertexCacheOptimize=false] When true
, geometry vertices are optimized for the pre and post-vertex-shader caches.
* @param {Boolean} [options.interleave=false] When true
, geometry vertex attributes are interleaved, which can slightly improve rendering performance but increases load time.
@@ -104,6 +110,7 @@ define([
*/
function ClassificationPrimitive(options) {
options = defaultValue(options, defaultValue.EMPTY_OBJECT);
+ var geometryInstances = options.geometryInstances;
/**
* The geometry instance rendered with this primitive. This may
@@ -123,7 +130,7 @@ define([
*
* @default undefined
*/
- this.geometryInstances = options.geometryInstances;
+ this.geometryInstances = geometryInstances;
/**
* Determines if the primitive will be shown. This affects all geometry
* instances in the primitive.
@@ -187,12 +194,38 @@ define([
this._primitive = undefined;
this._pickPrimitive = options._pickPrimitive;
- var appearance = new PerInstanceColorAppearance({
- flat : true
- });
+ var appearance = options.appearance;
+
+ // Require SphericalExtents attribute on all geometries if material isn't PerInstanceColor
+ if (defined(appearance) && defined(appearance.material) && defined(geometryInstances)) {
+ var geometryInstancesArray = isArray(geometryInstances) ? geometryInstances : [geometryInstances];
+ var geometryInstanceCount = geometryInstances.length;
+ for (var i = 0; i < geometryInstanceCount; i++) {
+ var attributes = geometryInstances[i].attributes;
+ if (!defined(attributes) || !defined(attributes.sphericalExtents)) {
+ throw new DeveloperError('Materials on ClassificationPrimitives require sphericalExtents attribute');
+ }
+ }
+ }
+
+ // If attributes include color and appearance is undefined, then default to a color appearance
+ if (!defined(appearance)) {
+ var geometryInstancesArray = isArray(geometryInstances) ? geometryInstances : [geometryInstances];
+ var geometryInstanceCount = geometryInstances.length;
+ for (var i = 0; i < geometryInstanceCount; i++) {
+ var attributes = geometryInstances[i].attributes;
+ if (defined(attributes) && defined(attributes.color)) {
+ appearance = new PerInstanceColorAppearance({
+ flat : true
+ });
+ break;
+ }
+ }
+ }
+ this.appearance = appearance;
var readOnlyAttributes;
- if (defined(this.geometryInstances) && isArray(this.geometryInstances) && this.geometryInstances.length > 1) {
+ if (defined(geometryInstances) && isArray(geometryInstances) && geometryInstances.length > 1) {
readOnlyAttributes = ClassificationPrimitiveReadOnlyInstanceAttributes;
}
@@ -517,10 +550,6 @@ define([
}
function createShaderProgram(classificationPrimitive, frameState, appearance) {
- if (defined(classificationPrimitive._sp)) {
- return;
- }
-
var context = frameState.context;
var primitive = classificationPrimitive._primitive;
var vs = ShadowVolumeVS;
@@ -597,14 +626,33 @@ define([
attributeLocations : attributeLocations
});
+ var appearance = classificationPrimitive.appearance;
+ var isPerInstanceColor = appearance instanceof PerInstanceColorAppearance;
+
+ var vsColorSource = new ShaderSource({
+ defines : isPerInstanceColor ? ['PER_INSTANCE_COLOR'] : [],
+ sources : [vs]
+ });
+
+ var parts;
+ if (isPerInstanceColor) {
+ parts = [ShadowVolumeColorFS];
+ } else {
+ // Modify fsColorSource for material (yay!)
+ // Only have to modify the FS b/c all material hookups happen in there b/c lol VS
+ // TODO: scan shaderSource to determine what material inputs are needed for ShadowVolumeColorFS?
+ parts = [appearance.material.shaderSource, ShadowVolumeColorFS];
+ }
+
var fsColorSource = new ShaderSource({
- sources : [ShadowVolumeColorFS]
+ defines : isPerInstanceColor ? ['PER_INSTANCE_COLOR'] : [],
+ sources : [parts.join('\n')]
});
classificationPrimitive._spColor = ShaderProgram.replaceCache({
context : context,
shaderProgram : classificationPrimitive._spColor,
- vertexShaderSource : vsSource,
+ vertexShaderSource : vsColorSource,
fragmentShaderSource : fsColorSource,
attributeLocations : attributeLocations
});
@@ -663,6 +711,13 @@ define([
command.vertexArray = vertexArray;
command.renderState = classificationPrimitive._rsColorPass;
command.shaderProgram = classificationPrimitive._spColor;
+
+ var appearance = classificationPrimitive.appearance;
+ var material = appearance.material;
+ if (defined(material)) {
+ uniformMap = combine(uniformMap, material._uniforms)
+ }
+
command.uniformMap = uniformMap;
}
@@ -857,6 +912,11 @@ define([
return;
}
+ var appearance = this.appearance;
+ if (defined(appearance) && defined(appearance.material)) {
+ appearance.material.update(frameState.context);
+ }
+
var that = this;
var primitiveOptions = this._primitiveOptions;
@@ -949,6 +1009,8 @@ define([
this._rsStencilDepthPass = RenderState.fromCache(getStencilDepthRenderState(true));
this._rsColorPass = RenderState.fromCache(getColorRenderState(true));
}
+ // Update primitive appearance
+ this._primitive.appearance = appearance;
this._primitive.debugShowBoundingVolume = this.debugShowBoundingVolume;
this._primitive.update(frameState);
diff --git a/Source/Scene/GroundPrimitive.js b/Source/Scene/GroundPrimitive.js
index 22db4e87f1c..821169e3dfd 100644
--- a/Source/Scene/GroundPrimitive.js
+++ b/Source/Scene/GroundPrimitive.js
@@ -57,8 +57,7 @@ define([
* A primitive combines the geometry instance with an {@link Appearance} that describes the full shading, including
* {@link Material} and {@link RenderState}. Roughly, the geometry instance defines the structure and placement,
* and the appearance defines the visual characteristics. Decoupling geometry and appearance allows us to mix
- * and match most of them and add a new geometry or appearance independently of each other. Only the {@link PerInstanceColorAppearance}
- * is supported at this time.
+ * and match most of them and add a new geometry or appearance independently of each other.
*
* For correct rendering, this feature requires the EXT_frag_depth WebGL extension. For hardware that do not support this extension, there
@@ -73,6 +72,7 @@ define([
*
* @param {Object} [options] Object with the following properties:
* @param {Array|GeometryInstance} [options.geometryInstances] The geometry instances to render.
+ * @param {Appearance} [options.appearance] The appearance used to render the primitive.
* @param {Boolean} [options.show=true] Determines if this primitive will be shown.
* @param {Boolean} [options.vertexCacheOptimize=false] When
- * A primitive combines the geometry instance with an {@link Appearance} that describes the full shading, including
+ * A primitive combines geometry instances with an {@link Appearance} that describes the full shading, including
* {@link Material} and {@link RenderState}. Roughly, the geometry instance defines the structure and placement,
* and the appearance defines the visual characteristics. Decoupling geometry and appearance allows us to mix
* and match most of them and add a new geometry or appearance independently of each other.
@@ -217,26 +230,25 @@ define([
} else if (hasSphericalExtentsAttribute) {
throw new DeveloperError('All GeometryInstances must have the same attributes.');
}
- if (ReferencePointGeometryInstanceAttribute.hasAttributesForPlanes(attributes)) {
+ if (hasAttributesForTextureCoordinatePlanes(attributes)) {
hasPlanarExtentsAttributes = true;
} else if (hasPlanarExtentsAttributes) {
throw new DeveloperError('All GeometryInstances must have the same attributes.');
}
-
} else if (hasPerColorAttribute || hasSphericalExtentsAttribute) {
throw new DeveloperError('All GeometryInstances must have the same attributes.');
- }
+ }
}
// If attributes include color and appearance is undefined, default to a color appearance
if (!defined(appearance) && hasPerColorAttribute) {
- appearance = new PerInstanceColorAppearance({
- flat : true
- });
- }
+ appearance = new PerInstanceColorAppearance({
+ flat : true
+ });
+ }
if (!hasPerColorAttribute && appearance instanceof PerInstanceColorAppearance) {
throw new DeveloperError('PerInstanceColorAppearance requires color GeometryInstanceAttribute');
- }
+ }
// TODO: SphericalExtents or PlanarExtents needed if PerInstanceColor isn't all the same
if (defined(appearance.material) && !hasSphericalExtentsAttribute && !hasPlanarExtentsAttributes) {
@@ -667,7 +679,7 @@ define([
}
var colorVSDefines = isPerInstanceColor ? ['PER_INSTANCE_COLOR'] : [];
- if (shadowVolumeAppearanceShader.usesTexcoords) {
+ if (shadowVolumeAppearanceShader.usesTextureCoordinates) {
if (shadowVolumeAppearanceShader.planarExtents) {
colorVSDefines.push('PLANAR_EXTENTS');
} else {
@@ -1120,5 +1132,134 @@ define([
return destroyObject(this);
};
+ function hasAttributesForTextureCoordinatePlanes(attributes) {
+ return defined(attributes.southWest_HIGH) && defined(attributes.southWest_LOW) &&
+ defined(attributes.northWest_HIGH) && defined(attributes.northWest_LOW) &&
+ defined(attributes.southEast_HIGH) && defined(attributes.southEast_LOW);
+ }
+
+ var encodeScratch = new EncodedCartesian3();
+ function addAttributesForPoint(point, name, attributes) {
+ var encoded = EncodedCartesian3.fromCartesian(point, encodeScratch);
+
+ attributes[name + '_HIGH'] = new GeometryInstanceAttribute({
+ componentDatatype: ComponentDatatype.FLOAT,
+ componentsPerAttribute: 3,
+ normalize: false,
+ value : Cartesian3.pack(encoded.high, [0, 0, 0])
+ });
+
+ attributes[name + '_LOW'] = new GeometryInstanceAttribute({
+ componentDatatype: ComponentDatatype.FLOAT,
+ componentsPerAttribute: 3,
+ normalize: false,
+ value : Cartesian3.pack(encoded.low, [0, 0, 0])
+ });
+ }
+
+ var cartographicScratch = new Cartographic();
+ var cornerScratch = new Cartesian3();
+ var northWestScratch = new Cartesian3();
+ var southEastScratch = new Cartesian3();
+ /**
+ * Gets an attributes object containing 3 high-precision points as 6 GeometryInstanceAttributes.
+ * These points are used to compute eye-space planes, which are then used to compute texture
+ * coordinates for small-area ClassificationPrimitives with materials or multiple non-overlapping instances.
+ * @see ShadowVolumeAppearanceShader
+ * @private
+ *
+ * @param {Rectangle} rectangle Rectangle object that the points will approximately bound
+ * @param {Ellipsoid} ellipsoid Ellipsoid for converting Rectangle points to world coordinates
+ */
+ ClassificationPrimitive.getAttributesForTextureCoordinatePlanes = function(rectangle, ellipsoid) {
+ //>>includeStart('debug', pragmas.debug);
+ Check.typeOf.object('rectangle', rectangle);
+ Check.typeOf.object('ellipsoid', ellipsoid);
+ //>>includeEnd('debug');
+
+ // Compute corner positions in double precision
+ var carto = cartographicScratch;
+ carto.longitude = rectangle.west;
+ carto.latitude = rectangle.south;
+
+ var corner = Cartographic.toCartesian(carto, ellipsoid, cornerScratch);
+
+ carto.latitude = rectangle.north;
+ var northWest = Cartographic.toCartesian(carto, ellipsoid, northWestScratch);
+
+ carto.longitude = rectangle.east;
+ carto.latitude = rectangle.south;
+ var southEast = Cartographic.toCartesian(carto, ellipsoid, southEastScratch);
+
+ var attributes = {};
+ addAttributesForPoint(corner, 'southWest', attributes);
+ addAttributesForPoint(northWest, 'northWest', attributes);
+ addAttributesForPoint(southEast, 'southEast', attributes);
+ return attributes;
+ };
+
+ var spherePointScratch = new Cartesian3();
+ function latLongToSpherical(latitude, longitude, ellipsoid, result) {
+ var cartographic = cartographicScratch;
+ cartographic.latitude = latitude;
+ cartographic.longitude = longitude;
+ cartographic.height = 0.0;
+
+ var spherePoint = Cartographic.toCartesian(cartographic, ellipsoid, spherePointScratch);
+
+ // Project into plane with vertical for latitude
+ var magXY = Math.sqrt(spherePoint.x * spherePoint.x + spherePoint.y * spherePoint.y);
+
+ // Use fastApproximateAtan2 for alignment with shader
+ var sphereLatitude = CesiumMath.fastApproximateAtan2(magXY, spherePoint.z);
+ var sphereLongitude = CesiumMath.fastApproximateAtan2(spherePoint.x, spherePoint.y);
+
+ result.x = sphereLatitude;
+ result.y = sphereLongitude;
+
+ return result;
+ }
+
+ var sphericalScratch = new Cartesian2();
+ /**
+ * Gets an attributes object containing the southwest corner of a rectangular area in spherical coordinates,
+ * as well as the inverse of the latitude/longitude range.
+ * These are computed using the same atan2 approximation used in the shader.
+ * Used when computing texture coordinates for large-area ClassificationPrimitives with materials or
+ * multiple non-overlapping instances.
+ * @see ShadowVolumeAppearanceShader
+ * @private
+ *
+ * @param {Rectangle} rectangle Rectangle object that the spherical extents will approximately bound
+ * @param {Ellipsoid} ellipsoid Ellipsoid for converting Rectangle points to world coordinates
+ */
+ ClassificationPrimitive.getSphericalExtentsGeometryInstanceAttribute = function(rectangle, ellipsoid) {
+ //>>includeStart('debug', pragmas.debug);
+ Check.typeOf.object('rectangle', rectangle);
+ Check.typeOf.object('ellipsoid', ellipsoid);
+ //>>includeEnd('debug');
+
+ // rectangle cartographic coords !== spherical because it's on an ellipsoid
+ var southWestExtents = latLongToSpherical(rectangle.south, rectangle.west, ellipsoid, sphericalScratch);
+
+ // Slightly pad extents to avoid floating point error when fragment culling at edges.
+ var south = southWestExtents.x - CesiumMath.EPSILON5;
+ var west = southWestExtents.y - CesiumMath.EPSILON5;
+
+ var northEastExtents = latLongToSpherical(rectangle.north, rectangle.east, ellipsoid, sphericalScratch);
+ var north = northEastExtents.x + CesiumMath.EPSILON5;
+ var east = northEastExtents.y + CesiumMath.EPSILON5;
+
+ var longitudeRangeInverse = 1.0 / (east - west);
+ var latitudeRangeInverse = 1.0 / (north - south);
+
+ return new GeometryInstanceAttribute({
+ componentDatatype: ComponentDatatype.FLOAT,
+ componentsPerAttribute: 4,
+ normalize: false,
+ value : [south, west, latitudeRangeInverse, longitudeRangeInverse]
+ });
+ };
+
return ClassificationPrimitive;
});
diff --git a/Source/Scene/GroundPrimitive.js b/Source/Scene/GroundPrimitive.js
index 86fa9fcd16c..31151d92590 100644
--- a/Source/Scene/GroundPrimitive.js
+++ b/Source/Scene/GroundPrimitive.js
@@ -17,9 +17,7 @@ define([
'../Core/Math',
'../Core/OrientedBoundingBox',
'../Core/Rectangle',
- '../Core/ReferencePointGeometryInstanceAttribute',
'../Core/Resource',
- '../Core/SphericalExtentsGeometryInstanceAttribute',
'../Renderer/Pass',
'../ThirdParty/when',
'./ClassificationPrimitive',
@@ -45,9 +43,7 @@ define([
CesiumMath,
OrientedBoundingBox,
Rectangle,
- ReferencePointGeometryInstanceAttribute,
Resource,
- SphericalExtentsGeometryInstanceAttribute,
Pass,
when,
ClassificationPrimitive,
@@ -57,13 +53,13 @@ define([
'use strict';
/**
- * A ground primitive represents geometry draped over the terrain in the {@link Scene}. The geometry must be from a single {@link GeometryInstance}.
- * Batching multiple geometries is not yet supported.
+ * A ground primitive represents geometry draped over the terrain in the {@link Scene}.
*
- * A primitive combines the geometry instance with an {@link Appearance} that describes the full shading, including
+ * A primitive combines geometry instances with an {@link Appearance} that describes the full shading, including
* {@link Material} and {@link RenderState}. Roughly, the geometry instance defines the structure and placement,
* and the appearance defines the visual characteristics. Decoupling geometry and appearance allows us to mix
* and match most of them and add a new geometry or appearance independently of each other.
+ * // TODO add note that textures on ground should use single imagery provider for high precision
*
* For correct rendering, this feature requires the EXT_frag_depth WebGL extension. For hardware that do not support this extension, there
@@ -797,10 +793,10 @@ define([
var attributes;
if (usePlanarExtents) {
- attributes = ReferencePointGeometryInstanceAttribute.getAttributesForPlanes(rectangle, ellipsoid, attributes);
+ attributes = ClassificationPrimitive.getAttributesForTextureCoordinatePlanes(rectangle, ellipsoid, attributes);
} else {
attributes = {
- sphericalExtents : new SphericalExtentsGeometryInstanceAttribute(rectangle)
+ sphericalExtents : ClassificationPrimitive.getSphericalExtentsGeometryInstanceAttribute(rectangle, ellipsoid)
};
}
diff --git a/Source/Scene/ShadowVolumeAppearanceShader.js b/Source/Scene/ShadowVolumeAppearanceShader.js
index db8ffb9115f..455dbca0e44 100644
--- a/Source/Scene/ShadowVolumeAppearanceShader.js
+++ b/Source/Scene/ShadowVolumeAppearanceShader.js
@@ -29,7 +29,7 @@ define([
this._extentsCulling = defaultValue(extentsCulling, false);
this._planarExtents = defaultValue(planarExtents, false);
this._shaderSource = createShadowVolumeAppearanceShader(appearance, this._extentsCulling, this._planarExtents);
- this._usesTexcoords = shaderDependenciesScratch._requiresTexcoords;
+ this._usesTextureCoordinates = shaderDependenciesScratch._requiresTextureCoordinates;
}
defineProperties(ShadowVolumeAppearanceShader.prototype, {
@@ -40,9 +40,9 @@ define([
* @type {Boolean}
* @readonly
*/
- usesTexcoords : {
+ usesTextureCoordinates : {
get : function() {
- return this._usesTexcoords;
+ return this._usesTextureCoordinates;
}
},
/**
@@ -76,8 +76,8 @@ define([
return getPerInstanceColorShader(extentsCull, appearance.flat, planarExtents);
}
- shaderDependencies.requiresTexcoords = extentsCull;
- shaderDependencies.requiresEyeCoord = !appearance.flat;
+ shaderDependencies.requiresTextureCoordinates = extentsCull;
+ shaderDependencies.requiresEC = !appearance.flat;
// Scan material source for what hookups are needed. Assume czm_materialInput materialInput.
var materialShaderSource = appearance.material.shaderSource;
@@ -113,10 +113,10 @@ define([
glsl += ' materialInput.normalEC = normalEC;\n';
}
if (usesPositionToEyeEC) {
- glsl += ' materialInput.positionToEyeEC = -eyeCoord.xyz;\n';
+ glsl += ' materialInput.positionToEyeEC = -eyeCoordinate.xyz;\n';
}
if (usesTangentToEyeMat) {
- glsl += ' materialInput.tangentToEyeMatrix = czm_eastNorthUpToEyeCoordinates(worldCoord, normalEC);\n';
+ glsl += ' materialInput.tangentToEyeMatrix = czm_eastNorthUpToEyeCoordinates(worldCoordinate, normalEC);\n';
}
if (usesSt) {
glsl += ' materialInput.st = vec2(v, u);\n';
@@ -126,7 +126,7 @@ define([
if (appearance.flat) {
glsl += ' gl_FragColor = vec4(material.diffuse + material.emission, material.alpha);\n';
} else {
- glsl += ' gl_FragColor = czm_phong(normalize(-eyeCoord.xyz), material);\n';
+ glsl += ' gl_FragColor = czm_phong(normalize(-eyeCoordinate.xyz), material);\n';
}
glsl += '}\n';
@@ -148,7 +148,7 @@ define([
'varying vec4 v_sphericalExtents;\n';
}
var shaderDependencies = shaderDependenciesScratch;
- shaderDependencies.requiresTexcoords = extentsCulling;
+ shaderDependencies.requiresTextureCoordinates = extentsCulling;
shaderDependencies.requiresNormalEC = !flatShading;
glsl += getLocalFunctions(shaderDependencies, planarExtents);
@@ -165,12 +165,12 @@ define([
glsl +=
' czm_materialInput materialInput;\n' +
' materialInput.normalEC = normalEC;\n' +
- ' materialInput.positionToEyeEC = -eyeCoord.xyz;\n' +
+ ' materialInput.positionToEyeEC = -eyeCoordinate.xyz;\n' +
' czm_material material = czm_getDefaultMaterial(materialInput);\n' +
' material.diffuse = v_color.rgb;\n' +
' material.alpha = v_color.a;\n' +
- ' gl_FragColor = czm_phong(normalize(-eyeCoord.xyz), material);\n';
+ ' gl_FragColor = czm_phong(normalize(-eyeCoordinate.xyz), material);\n';
}
glsl += '}\n';
return glsl;
@@ -178,32 +178,32 @@ define([
function getDependenciesAndCulling(shaderDependencies, extentsCulling, planarExtents) {
var glsl = '';
- if (shaderDependencies.requiresEyeCoord) {
+ if (shaderDependencies.requiresEC) {
glsl +=
- ' vec4 eyeCoord = getEyeCoord(gl_FragCoord.xy);\n';
+ ' vec4 eyeCoordinate = getEyeCoordinate(gl_FragCoord.xy);\n';
}
- if (shaderDependencies.requiresWorldCoord) {
+ if (shaderDependencies.requiresWC) {
glsl +=
- ' vec4 worldCoord4 = czm_inverseView * eyeCoord;\n' +
- ' vec3 worldCoord = worldCoord4.xyz / worldCoord4.w;\n';
+ ' vec4 worldCoordinate4 = czm_inverseView * eyeCoordinate;\n' +
+ ' vec3 worldCoordinate = worldCoordinate4.xyz / worldCoordinate4.w;\n';
}
- if (shaderDependencies.requiresTexcoords) {
- if (planarExtents) { // TODO: add ability to do long-and-narrows?
+ if (shaderDependencies.requiresTextureCoordinates) {
+ if (planarExtents) {
glsl +=
' // Unpack planes and transform to eye space\n' +
- ' float u = computePlanarTexcoord(v_southPlane, eyeCoord.xyz / eyeCoord.w, v_inversePlaneExtents.y);\n' +
- ' float v = computePlanarTexcoord(v_westPlane, eyeCoord.xyz / eyeCoord.w, v_inversePlaneExtents.x);\n';
+ ' float u = computePlanarTextureCoordinates(v_southPlane, eyeCoordinate.xyz / eyeCoordinate.w, v_inversePlaneExtents.y);\n' +
+ ' float v = computePlanarTextureCoordinates(v_westPlane, eyeCoordinate.xyz / eyeCoordinate.w, v_inversePlaneExtents.x);\n';
} else {
glsl +=
' // Treat world coords as a sphere normal for spherical coordinates\n' +
- ' vec2 sphericalLatLong = czm_approximateSphericalCoordinates(worldCoord);\n' +
- ' float u = (sphericalLatLong.x - v_sphericalExtents.y) * v_sphericalExtents.w;\n' +
- ' float v = (sphericalLatLong.y - v_sphericalExtents.x) * v_sphericalExtents.z;\n'; // TODO: clean up...
+ ' vec2 sphericalLatLong = czm_approximateSphericalCoordinates(worldCoordinate);\n' +
+ ' float u = (sphericalLatLong.x - v_sphericalExtents.x) * v_sphericalExtents.z;\n' +
+ ' float v = (sphericalLatLong.y - v_sphericalExtents.y) * v_sphericalExtents.w;\n';
}
}
if (extentsCulling) {
glsl +=
- ' if (u <= 0.0 || 1.0 <= u || v <= 0.0 || 1.0 <= v) {\n' + // TODO: there's floating point problems at the edges of rectangles. Use remapping.
+ ' if (u <= 0.0 || 1.0 <= u || v <= 0.0 || 1.0 <= v) {\n' +
' discard;\n' +
' }\n';
}
@@ -211,8 +211,8 @@ define([
if (shaderDependencies.requiresNormalEC) {
glsl +=
' // compute normal. sample adjacent pixels in 2x2 block in screen space\n' +
- ' vec3 downUp = getVectorFromOffset(eyeCoord, gl_FragCoord.xy, vec2(0.0, 1.0));\n' +
- ' vec3 leftRight = getVectorFromOffset(eyeCoord, gl_FragCoord.xy, vec2(1.0, 0.0));\n' +
+ ' vec3 downUp = getVectorFromOffset(eyeCoordinate, gl_FragCoord.xy, vec2(0.0, 1.0));\n' +
+ ' vec3 leftRight = getVectorFromOffset(eyeCoordinate, gl_FragCoord.xy, vec2(1.0, 0.0));\n' +
' vec3 normalEC = normalize(cross(leftRight, downUp));\n' +
'\n';
}
@@ -221,43 +221,43 @@ define([
function getLocalFunctions(shaderDependencies, planarExtents) {
var glsl = '';
- if (shaderDependencies.requiresEyeCoord) {
+ if (shaderDependencies.requiresEC) {
glsl +=
- 'vec4 getEyeCoord(vec2 fragCoord) {\n' +
+ 'vec4 getEyeCoordinate(vec2 fragCoord) {\n' +
' vec2 coords = fragCoord / czm_viewport.zw;\n' +
' float depth = czm_unpackDepth(texture2D(czm_globeDepthTexture, coords));\n' +
' vec4 windowCoord = vec4(fragCoord, depth, 1.0);\n' +
- ' vec4 eyeCoord = czm_windowToEyeCoordinates(windowCoord);\n' +
- ' return eyeCoord;\n' +
+ ' vec4 eyeCoordinate = czm_windowToEyeCoordinates(windowCoord);\n' +
+ ' return eyeCoordinate;\n' +
'}\n';
}
if (shaderDependencies.requiresNormalEC) {
glsl +=
- 'vec3 getEyeCoord3FromWindowCoord(vec2 fragCoord, float depth) {\n' +
+ 'vec3 getEyeCoordinate3FromWindowCoordordinate(vec2 fragCoord, float depth) {\n' +
' vec4 windowCoord = vec4(fragCoord, depth, 1.0);\n' +
- ' vec4 eyeCoord = czm_windowToEyeCoordinates(windowCoord);\n' +
- ' return eyeCoord.xyz / eyeCoord.w;\n' +
+ ' vec4 eyeCoordinate = czm_windowToEyeCoordinates(windowCoord);\n' +
+ ' return eyeCoordinate.xyz / eyeCoordinate.w;\n' +
'}\n' +
- 'vec3 getVectorFromOffset(vec4 eyeCoord, vec2 fragCoord2, vec2 positiveOffset) {\n' +
+ 'vec3 getVectorFromOffset(vec4 eyeCoordinate, vec2 glFragCoordXY, vec2 positiveOffset) {\n' +
' // Sample depths at both offset and negative offset\n' +
- ' float upOrRightDepth = czm_unpackDepth(texture2D(czm_globeDepthTexture, (fragCoord2 + positiveOffset) / czm_viewport.zw));\n' +
- ' float downOrLeftDepth = czm_unpackDepth(texture2D(czm_globeDepthTexture, (fragCoord2 - positiveOffset) / czm_viewport.zw));\n' +
+ ' float upOrRightDepth = czm_unpackDepth(texture2D(czm_globeDepthTexture, (glFragCoordXY + positiveOffset) / czm_viewport.zw));\n' +
+ ' float downOrLeftDepth = czm_unpackDepth(texture2D(czm_globeDepthTexture, (glFragCoordXY - positiveOffset) / czm_viewport.zw));\n' +
' // Explicitly evaluate both paths\n' +
- ' bvec2 upOrRightInBounds = lessThan(fragCoord2 + positiveOffset, czm_viewport.zw);\n' +
+ ' bvec2 upOrRightInBounds = lessThan(glFragCoordXY + positiveOffset, czm_viewport.zw);\n' +
' float useUpOrRight = float(upOrRightDepth > 0.0 && upOrRightInBounds.x && upOrRightInBounds.y);\n' +
' float useDownOrLeft = float(useUpOrRight == 0.0);\n' +
- ' vec3 upOrRightEC = getEyeCoord3FromWindowCoord(fragCoord2 + positiveOffset, upOrRightDepth);\n' +
- ' vec3 downOrLeftEC = getEyeCoord3FromWindowCoord(fragCoord2 - positiveOffset, downOrLeftDepth);\n' +
+ ' vec3 upOrRightEC = getEyeCoordinate3FromWindowCoordordinate(glFragCoordXY + positiveOffset, upOrRightDepth);\n' +
+ ' vec3 downOrLeftEC = getEyeCoordinate3FromWindowCoordordinate(glFragCoordXY - positiveOffset, downOrLeftDepth);\n' +
- ' return (upOrRightEC - (eyeCoord.xyz / eyeCoord.w)) * useUpOrRight + ((eyeCoord.xyz / eyeCoord.w) - downOrLeftEC) * useDownOrLeft;\n' +
+ ' return (upOrRightEC - (eyeCoordinate.xyz / eyeCoordinate.w)) * useUpOrRight + ((eyeCoordinate.xyz / eyeCoordinate.w) - downOrLeftEC) * useDownOrLeft;\n' +
'}\n';
}
- if (shaderDependencies.requiresTexcoords && planarExtents) {
+ if (shaderDependencies.requiresTextureCoordinates && planarExtents) {
glsl +=
- 'float computePlanarTexcoord(vec4 plane, vec3 eyeCoords, float inverseExtent) {\n' +
- ' return (dot(plane.xyz, eyeCoords) + plane.w) * inverseExtent;\n' +
+ 'float computePlanarTextureCoordinates(vec4 plane, vec3 eyeCoordinates, float inverseExtent) {\n' +
+ ' return (dot(plane.xyz, eyeCoordinates) + plane.w) * inverseExtent;\n' +
'}\n';
}
return glsl;
@@ -268,37 +268,37 @@ define([
* @private
*/
function ShaderDependencies() {
- this._requiresEyeCoord = false;
- this._requiresWorldCoord = false; // depends on eyeCoord, needed for material and for phong
- this._requiresNormalEC = false; // depends on eyeCoord, needed for material
- this._requiresTexcoords = false; // depends on worldCoord, needed for material and for culling
+ this._requiresEC = false;
+ this._requiresWC = false; // depends on eye coordinates, needed for material and for phong
+ this._requiresNormalEC = false; // depends on eye coordinates, needed for material
+ this._requiresTextureCoordinates = false; // depends on world coordinates, needed for material and for culling
}
ShaderDependencies.prototype.reset = function() {
- this._requiresEyeCoord = false;
- this._requiresWorldCoord = false;
+ this._requiresEC = false;
+ this._requiresWC = false;
this._requiresNormalEC = false;
- this._requiresTexcoords = false;
+ this._requiresTextureCoordinates = false;
return this;
};
defineProperties(ShaderDependencies.prototype, {
- // Set when assessing final shading (flat vs. phong) and spherical extent culling
- requiresEyeCoord : {
+ // Set when assessing final shading (flat vs. phong) and culling using computed texture coordinates
+ requiresEC : {
get : function() {
- return this._requiresEyeCoord;
+ return this._requiresEC;
},
set : function(value) {
- this._requiresEyeCoord = value || this._requiresEyeCoord;
+ this._requiresEC = value || this._requiresEC;
}
},
- requiresWorldCoord : {
+ requiresWC : {
get : function() {
- return this._requiresWorldCoord;
+ return this._requiresWC;
},
set : function(value) {
- this._requiresWorldCoord = value || this._requiresWorldCoord;
- this.requiresEyeCoord = this._requiresWorldCoord;
+ this._requiresWC = value || this._requiresWC;
+ this.requiresEC = this._requiresWC;
}
},
requiresNormalEC : {
@@ -307,16 +307,16 @@ define([
},
set : function(value) {
this._requiresNormalEC = value || this._requiresNormalEC;
- this.requiresEyeCoord = this._requiresNormalEC;
+ this.requiresEC = this._requiresNormalEC;
}
},
- requiresTexcoords : {
+ requiresTextureCoordinates : {
get : function() {
- return this._requiresTexcoords;
+ return this._requiresTextureCoordinates;
},
set : function(value) {
- this._requiresTexcoords = value || this._requiresTexcoords;
- this.requiresWorldCoord = this._requiresTexcoords;
+ this._requiresTextureCoordinates = value || this._requiresTextureCoordinates;
+ this.requiresWC = this._requiresTextureCoordinates;
}
},
// Set when assessing material hookups
@@ -327,18 +327,18 @@ define([
},
tangentToEyeMatrix : {
set : function(value) {
- this.requiresWorldCoord = value;
+ this.requiresWC = value;
this.requiresNormalEC = value;
}
},
positionToEyeEC : {
set : function(value) {
- this.requiresEyeCoord = value;
+ this.requiresEC = value;
}
},
st : {
set : function(value) {
- this.requiresTexcoords = value;
+ this.requiresTextureCoordinates = value;
}
}
});
diff --git a/Source/Shaders/Builtin/Functions/approximateSphericalCoordinates.glsl b/Source/Shaders/Builtin/Functions/approximateSphericalCoordinates.glsl
index ace9edae9f0..90fe79393a3 100644
--- a/Source/Shaders/Builtin/Functions/approximateSphericalCoordinates.glsl
+++ b/Source/Shaders/Builtin/Functions/approximateSphericalCoordinates.glsl
@@ -12,29 +12,22 @@ float fastApproximateAtan01(float x) {
return x * (-0.1784 * x - 0.0663 * x * x + 1.0301);
}
-// Used in place of ternaries to trade some math for branching
-float branchFree(bool comparison, float a, float b) {
- float useA = float(comparison);
- return a * useA + b * (1.0 - useA);
-}
-
// Range reduction math based on nvidia's cg reference implementation for atan2: http://developer.download.nvidia.com/cg/atan2.html
// However, we replaced their atan curve with Michael Drobot's.
float fastApproximateAtan2(float x, float y) {
// atan approximations are usually only reliable over [-1, 1], or, in our case, [0, 1] due to modifications.
// So range-reduce using abs and by flipping whether x or y is on top.
- float opposite, adjacent, t; // t used as swap and atan result.
- t = abs(x);
- opposite = abs(y);
- adjacent = max(t, opposite);
+ float t = abs(x); // t used as swap and atan result.
+ float opposite = abs(y);
+ float adjacent = max(t, opposite);
opposite = min(t, opposite);
t = fastApproximateAtan01(opposite / adjacent);
// Undo range reduction
- t = branchFree(abs(y) > abs(x), czm_piOverTwo - t, t);
- t = branchFree(x < 0.0, czm_pi - t, t);
- t = branchFree(y < 0.0, -t, t);
+ t = czm_branchFreeTernaryFloat(abs(y) > abs(x), czm_piOverTwo - t, t);
+ t = czm_branchFreeTernaryFloat(x < 0.0, czm_pi - t, t);
+ t = czm_branchFreeTernaryFloat(y < 0.0, -t, t);
return t;
}
diff --git a/Source/Shaders/Builtin/Functions/branchFreeTernaryFloat.glsl b/Source/Shaders/Builtin/Functions/branchFreeTernaryFloat.glsl
new file mode 100644
index 00000000000..951f2b155ce
--- /dev/null
+++ b/Source/Shaders/Builtin/Functions/branchFreeTernaryFloat.glsl
@@ -0,0 +1,17 @@
+/**
+ * Branchless ternary operator to be used when it's inexpensive to explicitly
+ * evaluate both possibilities for a float expression.
+ *
+ * @name czm_branchFreeTernaryFloat
+ * @glslFunction
+ *
+ * @param {bool} comparison A comparison statement
+ * @param {float} a Value to return if the comparison is true.
+ * @param {float} b Value to return if the comparison is false.
+ *
+ * @returns {float} equivalent of comparison ? a : b
+ */
+float czm_branchFreeTernaryFloat(bool comparison, float a, float b) {
+ float useA = float(comparison);
+ return a * useA + b * (1.0 - useA);
+}
diff --git a/Specs/Renderer/BuiltinFunctionsSpec.js b/Specs/Renderer/BuiltinFunctionsSpec.js
index 42f97f5bca9..4138cbfd93b 100644
--- a/Specs/Renderer/BuiltinFunctionsSpec.js
+++ b/Specs/Renderer/BuiltinFunctionsSpec.js
@@ -408,4 +408,14 @@ defineSuite([
}).contextToRender();
});
+ it('has czm_branchFreeTernaryFloat', function() {
+ var fs =
+ 'void main() { ' +
+ ' gl_FragColor = vec4(czm_branchFreeTernaryFloat(true, 1.0, 0.0));' +
+ '}';
+ expect({
+ context : context,
+ fragmentShader : fs
+ }).contextToRender();
+ });
}, 'WebGL');
From 8e59e2d93ca5e21d0c7785605a831ec85baafc39 Mon Sep 17 00:00:00 2001
From: Kangning Li
* For correct rendering, this feature requires the EXT_frag_depth WebGL extension. For hardware that do not support this extension, there
@@ -229,12 +206,12 @@ define([
} else if (hasPerColorAttribute) {
throw new DeveloperError('All GeometryInstances must have the same attributes.');
}
- if (defined(attributes.sphericalExtents)) {
+ if (ShadowVolumeAppearance.hasAttributesForSphericalExtents) {
hasSphericalExtentsAttribute = true;
} else if (hasSphericalExtentsAttribute) {
throw new DeveloperError('All GeometryInstances must have the same attributes.');
}
- if (hasAttributesForTextureCoordinatePlanes(attributes)) {
+ if (ShadowVolumeAppearance.hasAttributesForTextureCoordinatePlanes(attributes)) {
hasPlanarExtentsAttributes = true;
} else if (hasPlanarExtentsAttributes) {
throw new DeveloperError('All GeometryInstances must have the same attributes.');
@@ -250,11 +227,11 @@ define([
flat : true
});
}
+
if (!hasPerColorAttribute && appearance instanceof PerInstanceColorAppearance) {
throw new DeveloperError('PerInstanceColorAppearance requires color GeometryInstanceAttribute');
}
- // TODO: SphericalExtents or PlanarExtents needed if PerInstanceColor isn't all the same
if (defined(appearance.material) && !hasSphericalExtentsAttribute && !hasPlanarExtentsAttributes) {
throw new DeveloperError('Materials on ClassificationPrimitives requires sphericalExtents GeometryInstanceAttribute or GeometryInstanceAttributes for computing planes');
}
@@ -598,8 +575,8 @@ define([
vs = Primitive._modifyShaderPosition(classificationPrimitive, vs, frameState.scene3DOnly);
vs = Primitive._updateColorAttribute(primitive, vs);
- var usePlanarExtents = classificationPrimitive._hasPlanarExtentsAttributes;
- var cullUsingExtents = classificationPrimitive._hasPlanarExtentsAttributes || classificationPrimitive._hasSphericalExtentsAttribute;
+ var planarExtents = classificationPrimitive._hasPlanarExtentsAttributes;
+ var cullUsingExtents = planarExtents || classificationPrimitive._hasSphericalExtentsAttribute;
if (classificationPrimitive._extruded) {
vs = modifyForEncodedNormals(primitive, vs);
@@ -620,6 +597,8 @@ define([
});
var attributeLocations = classificationPrimitive._primitive._attributeLocations;
+ var shadowVolumeAppearance = new ShadowVolumeAppearance(cullUsingExtents, planarExtents, classificationPrimitive.appearance);
+
classificationPrimitive._spStencil = ShaderProgram.replaceCache({
context : context,
shaderProgram : classificationPrimitive._spStencil,
@@ -633,15 +612,14 @@ define([
vsPick = Primitive._appendShowToShader(primitive, vsPick);
vsPick = Primitive._updatePickColorAttribute(vsPick);
- var pick3DShadowVolumeAppearanceShader = new ShadowVolumeAppearanceShader(cullUsingExtents, usePlanarExtents, false, vsPick);
var pickFS3D = new ShaderSource({
- sources : [pick3DShadowVolumeAppearanceShader.fragmentShaderSource],
+ sources : [shadowVolumeAppearance.createPickingFragmentShader(false)],
pickColorQualifier : 'varying'
});
var pickVS3D = new ShaderSource({
defines : [extrudedDefine, disableGlPositionLogDepth],
- sources : [pick3DShadowVolumeAppearanceShader.vertexShaderSource]
+ sources : [shadowVolumeAppearance.createVertexShader(vsPick, false)]
});
classificationPrimitive._spPick = ShaderProgram.replaceCache({
@@ -652,15 +630,14 @@ define([
attributeLocations : attributeLocations
});
- var pick2DShadowVolumeAppearanceShader = new ShadowVolumeAppearanceShader(cullUsingExtents, true, true, vsPick);
var pickFS2D = new ShaderSource({
- sources : [pick2DShadowVolumeAppearanceShader.fragmentShaderSource],
+ sources : [shadowVolumeAppearance.createPickingFragmentShader(true)],
pickColorQualifier : 'varying'
});
var pickVS2D = new ShaderSource({
defines : [extrudedDefine, disableGlPositionLogDepth],
- sources : [pick2DShadowVolumeAppearanceShader.vertexShaderSource]
+ sources : [shadowVolumeAppearance.createVertexShader(vsPick, true)]
});
classificationPrimitive._spPick2D = ShaderProgram.replaceCache({
@@ -693,27 +670,14 @@ define([
attributeLocations : attributeLocations
});
- var appearance = classificationPrimitive.appearance;
- var isPerInstanceColor = appearance instanceof PerInstanceColorAppearance;
-
- var parts;
-
// Create a fragment shader that computes only required material hookups using screen space techniques
- var shadowVolumeAppearanceShader = new ShadowVolumeAppearanceShader(cullUsingExtents, usePlanarExtents, false, vs, appearance);
- var shadowVolumeAppearanceFS = shadowVolumeAppearanceShader.fragmentShaderSource;
- if (isPerInstanceColor) {
- parts = [shadowVolumeAppearanceFS];
- } else {
- parts = [appearance.material.shaderSource, shadowVolumeAppearanceFS];
- }
-
var fsColorSource = new ShaderSource({
- sources : [parts.join('\n')]
+ sources : [shadowVolumeAppearance.createAppearanceFragmentShader(false)]
});
var vsColorSource = new ShaderSource({
defines : [extrudedDefine, disableGlPositionLogDepth],
- sources : [shadowVolumeAppearanceShader.vertexShaderSource]
+ sources : [shadowVolumeAppearance.createVertexShader(vs, false)]
});
classificationPrimitive._spColor = ShaderProgram.replaceCache({
@@ -725,21 +689,13 @@ define([
});
// Create a similar fragment shader for 2D, forcing planar extents
- var shadowVolumeAppearanceShader2D = new ShadowVolumeAppearanceShader(cullUsingExtents, true, true, vs, appearance);
- var shadowVolumeAppearanceFS2D = shadowVolumeAppearanceShader2D.fragmentShaderSource;
- if (isPerInstanceColor) {
- parts = [shadowVolumeAppearanceFS2D];
- } else {
- parts = [appearance.material.shaderSource, shadowVolumeAppearanceFS2D];
- }
-
var fsColorSource2D = new ShaderSource({
- sources : [parts.join('\n')]
+ sources : [shadowVolumeAppearance.createAppearanceFragmentShader(true)]
});
var vsColorSource2D = new ShaderSource({
defines : [extrudedDefine, disableGlPositionLogDepth],
- sources : [shadowVolumeAppearanceShader2D.vertexShaderSource]
+ sources : [shadowVolumeAppearance.createVertexShader(vs, true)]
});
classificationPrimitive._spColor2D = ShaderProgram.replaceCache({
@@ -1171,310 +1127,5 @@ define([
return destroyObject(this);
};
- function hasAttributesForTextureCoordinatePlanes(attributes) {
- return defined(attributes.southWest_HIGH) && defined(attributes.southWest_LOW) &&
- defined(attributes.northWest_HIGH) && defined(attributes.northWest_LOW) &&
- defined(attributes.southEast_HIGH) && defined(attributes.southEast_LOW);
- }
-
- var encodeScratch = new EncodedCartesian3();
- function addAttributesForPoint(point, name, attributes) {
- var encoded = EncodedCartesian3.fromCartesian(point, encodeScratch);
-
- attributes[name + '_HIGH'] = new GeometryInstanceAttribute({
- componentDatatype: ComponentDatatype.FLOAT,
- componentsPerAttribute: 3,
- normalize: false,
- value : Cartesian3.pack(encoded.high, [0, 0, 0])
- });
-
- attributes[name + '_LOW'] = new GeometryInstanceAttribute({
- componentDatatype: ComponentDatatype.FLOAT,
- componentsPerAttribute: 3,
- normalize: false,
- value : Cartesian3.pack(encoded.low, [0, 0, 0])
- });
- }
-
- var cartographicScratch = new Cartographic();
- var rectangleCenterScratch = new Cartographic();
- var northCenterScratch = new Cartesian3();
- var southCenterScratch = new Cartesian3();
- var eastCenterScratch = new Cartesian3();
- var westCenterScratch = new Cartesian3();
- var points2DScratch = [new Cartesian2(), new Cartesian2(), new Cartesian2(), new Cartesian2()];
- var rotation2DScratch = new Matrix2();
- var min2DScratch = new Cartesian2();
- var max2DScratch = new Cartesian2();
- function getTextureCoordinateRotationAttribute(rectangle, ellipsoid, textureCoordinateRotation) {
- var theta = defaultValue(textureCoordinateRotation, 0.0);
-
- // Approximate scale such that the rectangle, if scaled and rotated, will completely enclose
- // the unrotated/unscaled rectangle.
- var cosTheta = Math.cos(theta);
- var sinTheta = Math.sin(theta);
-
- // Build a rectangle centered in 2D space approximating the bounding rectangle's dimensions
- var cartoCenter = Rectangle.center(rectangle, rectangleCenterScratch);
-
- var carto = cartographicScratch;
- carto.latitude = cartoCenter.latitude;
-
- carto.longitude = rectangle.west;
- var westCenter = Cartographic.toCartesian(carto, ellipsoid, westCenterScratch);
-
- carto.longitude = rectangle.east;
- var eastCenter = Cartographic.toCartesian(carto, ellipsoid, eastCenterScratch);
-
- carto.longitude = cartoCenter.longitude;
- carto.latitude = rectangle.north;
- var northCenter = Cartographic.toCartesian(carto, ellipsoid, northCenterScratch);
-
- carto.latitude = rectangle.south;
- var southCenter = Cartographic.toCartesian(carto, ellipsoid, southCenterScratch);
-
- var northSouthHalfDistance = Cartesian3.distance(northCenter, southCenter) * 0.5;
- var eastWestHalfDistance = Cartesian3.distance(eastCenter, westCenter) * 0.5;
-
- var points2D = points2DScratch;
- points2D[0].x = eastWestHalfDistance;
- points2D[0].y = northSouthHalfDistance;
-
- points2D[1].x = -eastWestHalfDistance;
- points2D[1].y = northSouthHalfDistance;
-
- points2D[2].x = eastWestHalfDistance;
- points2D[2].y = -northSouthHalfDistance;
-
- points2D[3].x = -eastWestHalfDistance;
- points2D[3].y = -northSouthHalfDistance;
-
- // Rotate the dimensions rectangle and compute min/max in rotated space
- var min2D = min2DScratch;
- min2D.x = Number.POSITIVE_INFINITY;
- min2D.y = Number.POSITIVE_INFINITY;
- var max2D = max2DScratch;
- max2D.x = Number.NEGATIVE_INFINITY;
- max2D.y = Number.NEGATIVE_INFINITY;
-
- var rotation2D = Matrix2.fromRotation(-theta, rotation2DScratch);
- for (var i = 0; i < 4; ++i) {
- var point2D = points2D[i];
- Matrix2.multiplyByVector(rotation2D, point2D, point2D);
- Cartesian2.minimumByComponent(point2D, min2D, min2D);
- Cartesian2.maximumByComponent(point2D, max2D, max2D);
- }
-
- // Depending on the rotation, east/west may be more appropriate for vertical scale than horizontal
- var scaleU, scaleV;
- if (Math.abs(sinTheta) < Math.abs(cosTheta)) {
- scaleU = eastWestHalfDistance / ((max2D.x - min2D.x) * 0.5);
- scaleV = northSouthHalfDistance / ((max2D.y - min2D.y) * 0.5);
- } else {
- scaleU = eastWestHalfDistance / ((max2D.y - min2D.y) * 0.5);
- scaleV = northSouthHalfDistance / ((max2D.x - min2D.x) * 0.5);
- }
-
- return new GeometryInstanceAttribute({
- componentDatatype: ComponentDatatype.FLOAT,
- componentsPerAttribute: 4,
- normalize: false,
- value : [sinTheta, cosTheta, scaleU, scaleV] // Precompute trigonometry for rotation and inverse of scale
- });
- }
-
- // Swizzle to 2D/CV projected space. This produces positions that
- // can directly be used in the VS for 2D/CV, but in practice there's
- // a lot of duplicated and zero values (see below).
- var swizzleScratch = new Cartesian3();
- function swizzle(cartesian) {
- Cartesian3.clone(cartesian, swizzleScratch);
- cartesian.x = swizzleScratch.z;
- cartesian.y = swizzleScratch.x;
- cartesian.z = swizzleScratch.y;
- return cartesian;
- }
-
- var cornerScratch = new Cartesian3();
- var northWestScratch = new Cartesian3();
- var southEastScratch = new Cartesian3();
- var highLowScratch = {high : 0.0, low : 0.0};
- function add2DTextureCoordinateAttributes(rectangle, frameState, attributes) {
- var projection = frameState.mapProjection;
-
- // Compute corner positions in double precision
- var carto = cartographicScratch;
- carto.height = 0.0;
-
- carto.longitude = rectangle.west;
- carto.latitude = rectangle.south;
-
- var southWestCorner = swizzle(projection.project(carto, cornerScratch));
-
- carto.latitude = rectangle.north;
- var northWest = swizzle(projection.project(carto, northWestScratch));
-
- carto.longitude = rectangle.east;
- carto.latitude = rectangle.south;
- var southEast = swizzle(projection.project(carto, southEastScratch));
-
- // Since these positions are all in the 2D plane, there's a lot of zeros
- // and a lot of repetition. So we only need to encode 4 values.
- // Encode:
- // x: y value for southWestCorner
- // y: z value for southWestCorner
- // z: z value for northWest
- // w: y value for southEast
- var valuesHigh = [0, 0, 0, 0];
- var valuesLow = [0, 0, 0, 0];
- var encoded = EncodedCartesian3.encode(southWestCorner.y, highLowScratch);
- valuesHigh[0] = encoded.high;
- valuesLow[0] = encoded.low;
-
- encoded = EncodedCartesian3.encode(southWestCorner.z, highLowScratch);
- valuesHigh[1] = encoded.high;
- valuesLow[1] = encoded.low;
-
- encoded = EncodedCartesian3.encode(northWest.z, highLowScratch);
- valuesHigh[2] = encoded.high;
- valuesLow[2] = encoded.low;
-
- encoded = EncodedCartesian3.encode(southEast.y, 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
- });
- }
-
- /**
- * Gets an attributes object containing 3 high-precision points as 6 GeometryInstanceAttributes.
- * These points are used to compute eye-space planes, which are then used to compute texture
- * coordinates for small-area ClassificationPrimitives with materials or multiple non-overlapping instances.
- * @see ShadowVolumeAppearanceShader
- * @private
- *
- * @param {Rectangle} rectangle Rectangle object that the points will approximately bound
- * @param {Ellipsoid} ellipsoid Ellipsoid for converting Rectangle points to world coordinates
- * @param {Number} [textureCoordinateRotation=0] Texture coordinate rotation
- * @return {Object} An attributes dictionary containing planar texture coordinate attributes.
- */
- ClassificationPrimitive.getPlanarTextureCoordinateAttributes = function(rectangle, ellipsoid, frameState, textureCoordinateRotation) {
- //>>includeStart('debug', pragmas.debug);
- Check.typeOf.object('rectangle', rectangle);
- Check.typeOf.object('ellipsoid', ellipsoid);
- Check.typeOf.object('frameState', frameState);
- //>>includeEnd('debug');
-
- // Compute corner positions in double precision
- var carto = cartographicScratch;
- carto.height = 0.0;
-
- carto.longitude = rectangle.west;
- carto.latitude = rectangle.south;
-
- var corner = Cartographic.toCartesian(carto, ellipsoid, cornerScratch);
-
- carto.latitude = rectangle.north;
- var northWest = Cartographic.toCartesian(carto, ellipsoid, northWestScratch);
-
- carto.longitude = rectangle.east;
- carto.latitude = rectangle.south;
- var southEast = Cartographic.toCartesian(carto, ellipsoid, southEastScratch);
-
- var attributes = {
- stSineCosineUVScale : getTextureCoordinateRotationAttribute(rectangle, ellipsoid, textureCoordinateRotation)
- };
- addAttributesForPoint(corner, 'southWest', attributes);
- addAttributesForPoint(northWest, 'northWest', attributes);
- addAttributesForPoint(southEast, 'southEast', attributes);
-
- add2DTextureCoordinateAttributes(rectangle, frameState, attributes);
- return attributes;
- };
-
- var spherePointScratch = new Cartesian3();
- function latLongToSpherical(latitude, longitude, ellipsoid, result) {
- var cartographic = cartographicScratch;
- cartographic.latitude = latitude;
- cartographic.longitude = longitude;
- cartographic.height = 0.0;
-
- var spherePoint = Cartographic.toCartesian(cartographic, ellipsoid, spherePointScratch);
-
- // Project into plane with vertical for latitude
- var magXY = Math.sqrt(spherePoint.x * spherePoint.x + spherePoint.y * spherePoint.y);
-
- // Use fastApproximateAtan2 for alignment with shader
- var sphereLatitude = CesiumMath.fastApproximateAtan2(magXY, spherePoint.z);
- var sphereLongitude = CesiumMath.fastApproximateAtan2(spherePoint.x, spherePoint.y);
-
- result.x = sphereLatitude;
- result.y = sphereLongitude;
-
- return result;
- }
-
- var sphericalScratch = new Cartesian2();
- /**
- * Gets an attributes object containing the southwest corner of a rectangular area in spherical coordinates,
- * as well as the inverse of the latitude/longitude range.
- * These are computed using the same atan2 approximation used in the shader.
- * Used when computing texture coordinates for large-area ClassificationPrimitives with materials or
- * multiple non-overlapping instances.
- * @see ShadowVolumeAppearanceShader
- * @private
- *
- * @param {Rectangle} rectangle Rectangle object that the spherical extents will approximately bound
- * @param {Ellipsoid} ellipsoid Ellipsoid for converting Rectangle points to world coordinates
- * @param {Number} [textureCoordinateRotation=0] Texture coordinate rotation
- * @return An attributes dictionary containing spherical texture coordinate attributes.
- */
- ClassificationPrimitive.getSphericalExtentGeometryInstanceAttributes = function(rectangle, ellipsoid, frameState, textureCoordinateRotation) {
- //>>includeStart('debug', pragmas.debug);
- Check.typeOf.object('rectangle', rectangle);
- Check.typeOf.object('ellipsoid', ellipsoid);
- Check.typeOf.object('frameState', frameState);
- //>>includeEnd('debug');
-
- // rectangle cartographic coords !== spherical because it's on an ellipsoid
- var southWestExtents = latLongToSpherical(rectangle.south, rectangle.west, ellipsoid, sphericalScratch);
-
- // Slightly pad extents to avoid floating point error when fragment culling at edges.
- var south = southWestExtents.x - CesiumMath.EPSILON5;
- var west = southWestExtents.y - CesiumMath.EPSILON5;
-
- var northEastExtents = latLongToSpherical(rectangle.north, rectangle.east, ellipsoid, sphericalScratch);
- var north = northEastExtents.x + CesiumMath.EPSILON5;
- var east = northEastExtents.y + CesiumMath.EPSILON5;
-
- var longitudeRangeInverse = 1.0 / (east - west);
- var latitudeRangeInverse = 1.0 / (north - south);
-
- var attributes = {
- sphericalExtents : new GeometryInstanceAttribute({
- componentDatatype: ComponentDatatype.FLOAT,
- componentsPerAttribute: 4,
- normalize: false,
- value : [south, west, latitudeRangeInverse, longitudeRangeInverse]
- }),
- stSineCosineUVScale : getTextureCoordinateRotationAttribute(rectangle, ellipsoid, textureCoordinateRotation)
- };
-
- add2DTextureCoordinateAttributes(rectangle, frameState, attributes);
- return attributes;
- };
-
return ClassificationPrimitive;
});
diff --git a/Source/Scene/GroundPrimitive.js b/Source/Scene/GroundPrimitive.js
index f4143fc4d69..5c0fbaaab9c 100644
--- a/Source/Scene/GroundPrimitive.js
+++ b/Source/Scene/GroundPrimitive.js
@@ -3,9 +3,7 @@ define([
'../Core/buildModuleUrl',
'../Core/Cartesian2',
'../Core/Cartesian3',
- '../Core/Cartesian4',
'../Core/Cartographic',
- '../Core/Check',
'../Core/defaultValue',
'../Core/defined',
'../Core/defineProperties',
@@ -24,15 +22,14 @@ define([
'./ClassificationPrimitive',
'./ClassificationType',
'./PerInstanceColorAppearance',
- './SceneMode'
+ './SceneMode',
+ './ShadowVolumeAppearance'
], function(
BoundingSphere,
buildModuleUrl,
Cartesian2,
Cartesian3,
- Cartesian4,
Cartographic,
- Check,
defaultValue,
defined,
defineProperties,
@@ -51,7 +48,8 @@ define([
ClassificationPrimitive,
ClassificationType,
PerInstanceColorAppearance,
- SceneMode) {
+ SceneMode,
+ ShadowVolumeAppearance) {
'use strict';
/**
@@ -61,7 +59,10 @@ define([
* {@link Material} and {@link RenderState}. Roughly, the geometry instance defines the structure and placement,
* and the appearance defines the visual characteristics. Decoupling geometry and appearance allows us to mix
* and match most of them and add a new geometry or appearance independently of each other.
- * // TODO add note that textures on ground should use single imagery provider for high precision
+ *
+ * Textured GroundPrimitives were designed for notional patterns and are not meant for precisely mapping
+ * textures to terrain - for that use case, use {@link SingleTileImageryProvider}.
+ *
*
* For correct rendering, this feature requires the EXT_frag_depth WebGL extension. For hardware that do not support this extension, there
@@ -800,7 +801,7 @@ define([
instance = instances[i];
geometry = instance.geometry;
rectangle = getRectangle(frameState, geometry);
- if (shouldUseSpherical(rectangle)) {
+ if (ShadowVolumeAppearance.shouldUseSphericalCoordinates(rectangle)) {
usePlanarExtents = false;
break;
}
@@ -815,9 +816,9 @@ define([
var attributes;
if (usePlanarExtents) {
- attributes = ClassificationPrimitive.getPlanarTextureCoordinateAttributes(rectangle, ellipsoid, frameState, geometry._stRotation);
+ attributes = ShadowVolumeAppearance.getPlanarTextureCoordinateAttributes(rectangle, ellipsoid, frameState.mapProjection, geometry._stRotation);
} else {
- attributes = ClassificationPrimitive.getSphericalExtentGeometryInstanceAttributes(rectangle, ellipsoid, frameState, geometry._stRotation);
+ attributes = ShadowVolumeAppearance.getSphericalExtentGeometryInstanceAttributes(rectangle, ellipsoid, frameState.mapProjection, geometry._stRotation);
}
var instanceAttributes = instance.attributes;
@@ -869,10 +870,6 @@ define([
this._primitive.update(frameState);
};
- function shouldUseSpherical(rectangle) {
- return Math.max(rectangle.width, rectangle.height) > GroundPrimitive.MAX_WIDTH_FOR_PLANAR_EXTENTS;
- }
-
/**
* @private
*/
@@ -943,30 +940,5 @@ define([
return destroyObject(this);
};
- /**
- * Computes whether the given rectangle is wide enough that texture coordinates
- * over its area should be computed using spherical extents instead of distance to planes.
- *
- * @param {Rectangle} rectangle A rectangle
- * @private
- */
- GroundPrimitive.shouldUseSphericalCoordinates = function(rectangle) {
- //>>includeStart('debug', pragmas.debug);
- Check.typeOf.object('rectangle', rectangle);
- //>>includeEnd('debug');
-
- return shouldUseSpherical(rectangle);
- };
-
- /**
- * Texture coordinates for ground primitives are computed either using spherical coordinates for large areas or
- * using distance from planes for small areas.
- *
- * @type {Number}
- * @constant
- * @private
- */
- GroundPrimitive.MAX_WIDTH_FOR_PLANAR_EXTENTS = CesiumMath.toRadians(1.0);
-
return GroundPrimitive;
});
diff --git a/Source/Scene/ShadowVolumeAppearance.js b/Source/Scene/ShadowVolumeAppearance.js
new file mode 100644
index 00000000000..d2ab636160d
--- /dev/null
+++ b/Source/Scene/ShadowVolumeAppearance.js
@@ -0,0 +1,900 @@
+define([
+ '../Core/Cartographic',
+ '../Core/Cartesian2',
+ '../Core/Cartesian3',
+ '../Core/Math',
+ '../Core/Check',
+ '../Core/ComponentDatatype',
+ '../Core/defaultValue',
+ '../Core/defined',
+ '../Core/defineProperties',
+ '../Core/EncodedCartesian3',
+ '../Core/GeometryInstanceAttribute',
+ '../Core/Matrix2',
+ '../Core/Rectangle',
+ '../Renderer/ShaderSource',
+ '../Scene/PerInstanceColorAppearance'
+], function(
+ Cartographic,
+ Cartesian2,
+ Cartesian3,
+ CesiumMath,
+ Check,
+ ComponentDatatype,
+ defaultValue,
+ defined,
+ defineProperties,
+ EncodedCartesian3,
+ GeometryInstanceAttribute,
+ Matrix2,
+ Rectangle,
+ ShaderSource,
+ PerInstanceColorAppearance) {
+ 'use strict';
+
+ /**
+ * Creates shaders for a ClassificationPrimitive to use a given Appearance, as well as for picking.
+ *
+ * @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.
+ * @private
+ */
+ function ShadowVolumeAppearance(extentsCulling, planarExtents, appearance) {
+ //>>includeStart('debug', pragmas.debug);
+ Check.typeOf.bool('extentsCulling', extentsCulling);
+ Check.typeOf.bool('planarExtents', planarExtents);
+ Check.typeOf.object('appearance', appearance);
+ //>>includeEnd('debug');
+
+ // Compute shader dependencies
+ var shaderDependencies = new ShaderDependencies();
+ shaderDependencies.requiresTextureCoordinates = extentsCulling;
+ shaderDependencies.requiresEC = !appearance.flat;
+
+ if (appearance instanceof PerInstanceColorAppearance) {
+ // PerInstanceColorAppearance doesn't have material.shaderSource, instead it has its own vertex and fragment shaders
+ shaderDependencies.requiresNormalEC = !appearance.flat;
+ } else {
+ // Scan material source for what hookups are needed. Assume czm_materialInput materialInput.
+ var materialShaderSource = appearance.material.shaderSource;
+
+ shaderDependencies.normalEC = materialShaderSource.includes('materialInput.normalEC') || materialShaderSource.includes('czm_getDefaultMaterial');
+ shaderDependencies.positionToEyeEC = materialShaderSource.includes('materialInput.positionToEyeEC');
+ shaderDependencies.tangentToEyeMatrix = materialShaderSource.includes('materialInput.tangentToEyeMatrix');
+ shaderDependencies.st = materialShaderSource.includes('materialInput.st');
+ }
+
+ this._shaderDependencies = shaderDependencies;
+ this._appearance = appearance;
+ this._extentsCulling = extentsCulling;
+ this._planarExtents = planarExtents;
+ }
+
+ /**
+ * Create the fragment shader for a ClassificationPrimitive's color pass when rendering for color.
+ *
+ * @param {Boolean} columbusView2D Whether the shader will be used for Columbus View or 2D.
+ * @returns {String} Shader source for the fragment shader including its material.
+ */
+ ShadowVolumeAppearance.prototype.createAppearanceFragmentShader = function(columbusView2D) {
+ //>>includeStart('debug', pragmas.debug);
+ Check.typeOf.bool('columbusView2D', columbusView2D);
+ //>>includeEnd('debug');
+
+ var appearance = this._appearance;
+ var materialHookups = createShadowVolumeAppearanceFS(this._shaderDependencies, appearance, this._extentsCulling, this._planarExtents || columbusView2D);
+ if (appearance instanceof PerInstanceColorAppearance) {
+ return materialHookups;
+ }
+ return appearance.material.shaderSource + '\n' + materialHookups;
+ };
+
+ /**
+ * Create the fragment shader for a ClassificationPrimitive's color pass when rendering for pick.
+ *
+ * @param {Boolean} columbusView2D Whether the shader will be used for Columbus View or 2D.
+ * @returns {String} Shader source for the fragment shader.
+ */
+ ShadowVolumeAppearance.prototype.createPickingFragmentShader = function(columbusView2D) {
+ //>>includeStart('debug', pragmas.debug);
+ Check.typeOf.bool('columbusView2D', columbusView2D);
+ //>>includeEnd('debug');
+
+ return getPickShaderFS(this._extentsCulling, this._planarExtents || columbusView2D);
+ };
+
+ /**
+ * Create the vertex shader for a ClassificationPrimitive's color pass, both when rendering for color and for pick.
+ *
+ * @param {String} vertexShaderSource Vertex shader source.
+ * @param {Boolean} columbusView2D Whether the shader will be used for Columbus View or 2D.
+ * @returns {String} Shader source for the vertex shader.
+ */
+ ShadowVolumeAppearance.prototype.createVertexShader = function(vertexShaderSource, columbusView2D) {
+ //>>includeStart('debug', pragmas.debug);
+ Check.typeOf.string('vertexShaderSource', vertexShaderSource);
+ Check.typeOf.bool('columbusView2D', columbusView2D);
+ //>>includeEnd('debug');
+
+ return createShadowVolumeAppearanceVS(this._shaderDependencies, this._appearance, this._planarExtents, columbusView2D, vertexShaderSource);
+ };
+
+ function createShadowVolumeAppearanceFS(shaderDependencies, appearance, extentsCull, planarExtents) {
+ if (appearance instanceof PerInstanceColorAppearance) {
+ return getPerInstanceColorShaderFS(shaderDependencies, extentsCull, appearance.flat, planarExtents);
+ }
+
+ var usesNormalEC = shaderDependencies.normalEC;
+ var usesPositionToEyeEC = shaderDependencies.positionToEyeEC;
+ var usesTangentToEyeMat = shaderDependencies.tangentToEyeMatrix;
+ var usesSt = shaderDependencies.st;
+
+ var glsl =
+ '#ifdef GL_EXT_frag_depth\n' +
+ '#extension GL_EXT_frag_depth : enable\n' +
+ '#endif\n';
+ if (extentsCull || usesSt) {
+ glsl += planarExtents ?
+ 'varying vec2 v_inversePlaneExtents;\n' +
+ 'varying vec4 v_westPlane;\n' +
+ 'varying vec4 v_southPlane;\n' :
+
+ 'varying vec4 v_sphericalExtents;\n';
+ }
+ if (usesSt) {
+ glsl +=
+ 'varying vec4 v_stSineCosineUVScale;\n';
+ }
+
+ // Get local functions
+ glsl += getLocalFunctionsFS(shaderDependencies, planarExtents);
+
+ glsl +=
+ 'void main(void)\n' +
+ '{\n';
+
+ // Compute material input stuff and cull if outside texture coordinate extents
+ glsl += getDependenciesAndCullingFS(shaderDependencies, extentsCull, planarExtents);
+
+ glsl += ' czm_materialInput materialInput;\n';
+ if (usesNormalEC) {
+ glsl += ' materialInput.normalEC = normalEC;\n';
+ }
+ if (usesPositionToEyeEC) {
+ glsl += ' materialInput.positionToEyeEC = -eyeCoordinate.xyz;\n';
+ }
+ if (usesTangentToEyeMat) {
+ glsl += ' materialInput.tangentToEyeMatrix = czm_eastNorthUpToEyeCoordinates(worldCoordinate, normalEC);\n';
+ }
+ if (usesSt) {
+ // Scale texture coordinates and rotate around 0.5, 0.5
+ glsl +=
+ ' materialInput.st.x = v_stSineCosineUVScale.y * (v - 0.5) * v_stSineCosineUVScale.z + v_stSineCosineUVScale.x * (u - 0.5) * v_stSineCosineUVScale.w + 0.5;\n' +
+ ' materialInput.st.y = v_stSineCosineUVScale.y * (u - 0.5) * v_stSineCosineUVScale.w - v_stSineCosineUVScale.x * (v - 0.5) * v_stSineCosineUVScale.z + 0.5;\n';
+ }
+ glsl += ' czm_material material = czm_getMaterial(materialInput);\n';
+
+ if (appearance.flat) {
+ glsl += ' gl_FragColor = vec4(material.diffuse + material.emission, material.alpha);\n';
+ } else {
+ glsl += ' gl_FragColor = czm_phong(normalize(-eyeCoordinate.xyz), material);\n';
+ }
+ glsl += ' czm_writeDepthClampedToFarPlane();\n';
+ glsl += '}\n';
+ return glsl;
+ }
+
+ var pickingShaderDependenciesScratch = new ShaderDependencies();
+ function getPickShaderFS(extentsCulling, planarExtents) {
+ var glsl =
+ '#ifdef GL_EXT_frag_depth\n' +
+ '#extension GL_EXT_frag_depth : enable\n' +
+ '#endif\n';
+ if (extentsCulling) {
+ glsl += planarExtents ?
+ 'varying vec2 v_inversePlaneExtents;\n' +
+ 'varying vec4 v_westPlane;\n' +
+ 'varying vec4 v_southPlane;\n' :
+
+ 'varying vec4 v_sphericalExtents;\n';
+ }
+ var shaderDependencies = pickingShaderDependenciesScratch;
+ shaderDependencies.reset();
+ shaderDependencies.requiresTextureCoordinates = extentsCulling;
+ shaderDependencies.requiresNormalEC = false;
+
+ glsl += getLocalFunctionsFS(shaderDependencies, planarExtents);
+
+ glsl += 'void main(void)\n' +
+ '{\n';
+ glsl += ' bool culled = false;\n';
+ var outOfBoundsSnippet =
+ ' culled = true;\n';
+ glsl += getDependenciesAndCullingFS(shaderDependencies, extentsCulling, planarExtents, outOfBoundsSnippet);
+ glsl += ' if (!culled) {\n' +
+ ' gl_FragColor.a = 1.0;\n' + // 0.0 alpha leads to discard from ShaderSource.createPickFragmentShaderSource
+ ' czm_writeDepthClampedToFarPlane();\n' +
+ ' }\n' +
+ '}\n';
+ return glsl;
+ }
+
+ function getPerInstanceColorShaderFS(shaderDependencies, extentsCulling, flatShading, planarExtents) {
+ var glsl =
+ '#ifdef GL_EXT_frag_depth\n' +
+ '#extension GL_EXT_frag_depth : enable\n' +
+ '#endif\n' +
+ 'varying vec4 v_color;\n';
+ if (extentsCulling) {
+ glsl += planarExtents ?
+ 'varying vec2 v_inversePlaneExtents;\n' +
+ 'varying vec4 v_westPlane;\n' +
+ 'varying vec4 v_southPlane;\n' :
+
+ 'varying vec4 v_sphericalExtents;\n';
+ }
+
+ glsl += getLocalFunctionsFS(shaderDependencies, planarExtents);
+
+ glsl += 'void main(void)\n' +
+ '{\n';
+
+ glsl += getDependenciesAndCullingFS(shaderDependencies, extentsCulling, planarExtents);
+
+ if (flatShading) {
+ glsl +=
+ ' gl_FragColor = v_color;\n';
+ } else {
+ glsl +=
+ ' czm_materialInput materialInput;\n' +
+ ' materialInput.normalEC = normalEC;\n' +
+ ' materialInput.positionToEyeEC = -eyeCoordinate.xyz;\n' +
+ ' czm_material material = czm_getDefaultMaterial(materialInput);\n' +
+ ' material.diffuse = v_color.rgb;\n' +
+ ' material.alpha = v_color.a;\n' +
+
+ ' gl_FragColor = czm_phong(normalize(-eyeCoordinate.xyz), material);\n';
+ }
+ glsl += ' czm_writeDepthClampedToFarPlane();\n';
+ glsl += '}\n';
+ return glsl;
+ }
+
+ function getDependenciesAndCullingFS(shaderDependencies, extentsCulling, planarExtents, outOfBoundsSnippet) {
+ var glsl = '';
+ if (shaderDependencies.requiresEC) {
+ glsl +=
+ ' vec4 eyeCoordinate = getEyeCoordinate(gl_FragCoord.xy);\n';
+ }
+ if (shaderDependencies.requiresWC) {
+ glsl +=
+ ' vec4 worldCoordinate4 = czm_inverseView * eyeCoordinate;\n' +
+ ' vec3 worldCoordinate = worldCoordinate4.xyz / worldCoordinate4.w;\n';
+ }
+ if (shaderDependencies.requiresTextureCoordinates) {
+ if (planarExtents) {
+ glsl +=
+ ' // Unpack planes and transform to eye space\n' +
+ ' float u = computePlanarTextureCoordinates(v_southPlane, eyeCoordinate.xyz / eyeCoordinate.w, v_inversePlaneExtents.y);\n' +
+ ' float v = computePlanarTextureCoordinates(v_westPlane, eyeCoordinate.xyz / eyeCoordinate.w, v_inversePlaneExtents.x);\n';
+ } else {
+ glsl +=
+ ' // Treat world coords as a sphere normal for spherical coordinates\n' +
+ ' vec2 sphericalLatLong = czm_approximateSphericalCoordinates(worldCoordinate);\n' +
+ ' float u = (sphericalLatLong.x - v_sphericalExtents.x) * v_sphericalExtents.z;\n' +
+ ' float v = (sphericalLatLong.y - v_sphericalExtents.y) * v_sphericalExtents.w;\n';
+ }
+ }
+ if (extentsCulling) {
+ if (!defined(outOfBoundsSnippet)) {
+ outOfBoundsSnippet =
+ ' discard;\n';
+ }
+ glsl +=
+ ' if (u <= 0.0 || 1.0 <= u || v <= 0.0 || 1.0 <= v) {\n' +
+ outOfBoundsSnippet +
+ ' }\n';
+ }
+ // Lots of texture access, so lookup after discard check
+ if (shaderDependencies.requiresNormalEC) {
+ glsl +=
+ ' // compute normal. sample adjacent pixels in 2x2 block in screen space\n' +
+ ' vec3 downUp = getVectorFromOffset(eyeCoordinate, gl_FragCoord.xy, vec2(0.0, 1.0));\n' +
+ ' vec3 leftRight = getVectorFromOffset(eyeCoordinate, gl_FragCoord.xy, vec2(1.0, 0.0));\n' +
+ ' vec3 normalEC = normalize(cross(leftRight, downUp));\n' +
+ '\n';
+ }
+ return glsl;
+ }
+
+ function getLocalFunctionsFS(shaderDependencies, planarExtents) {
+ var glsl = '';
+ if (shaderDependencies.requiresEC || shaderDependencies.requiresNormalEC) {
+ glsl +=
+ 'vec4 windowToEyeCoordinates(vec2 xy, float depthOrLogDepth) {\n' +
+ // See reverseLogDepth.glsl. This is separate to re-use the pow.
+ '#ifdef LOG_DEPTH\n' +
+ ' float near = czm_currentFrustum.x;\n' +
+ ' float far = czm_currentFrustum.y;\n' +
+ ' float unscaledDepth = pow(2.0, depthOrLogDepth * czm_log2FarPlusOne) - 1.0;\n' +
+ ' vec4 windowCoord = vec4(xy, far * (1.0 - near / unscaledDepth) / (far - near), 1.0);\n' +
+ ' vec4 eyeCoordinate = czm_windowToEyeCoordinates(windowCoord);\n' +
+ ' eyeCoordinate.w = 1.0 / unscaledDepth;\n' + // Better precision
+ '#else\n' +
+ ' vec4 windowCoord = vec4(xy, depthOrLogDepth, 1.0);\n' +
+ ' vec4 eyeCoordinate = czm_windowToEyeCoordinates(windowCoord);\n' +
+ '#endif\n' +
+ ' return eyeCoordinate;\n' +
+ '}\n';
+ }
+ if (shaderDependencies.requiresEC) {
+ glsl +=
+ 'vec4 getEyeCoordinate(vec2 fragCoord) {\n' +
+ ' vec2 coords = fragCoord / czm_viewport.zw;\n' +
+ ' float logDepthOrDepth = czm_unpackDepth(texture2D(czm_globeDepthTexture, coords));\n' +
+ ' return windowToEyeCoordinates(fragCoord, logDepthOrDepth);\n' +
+ '}\n';
+ }
+ if (shaderDependencies.requiresNormalEC) {
+ glsl +=
+ 'vec3 getEyeCoordinate3FromWindowCoordinate(vec2 fragCoord, float logDepthOrDepth) {\n' +
+ ' vec4 eyeCoordinate = windowToEyeCoordinates(fragCoord, logDepthOrDepth);\n' +
+ ' return eyeCoordinate.xyz / eyeCoordinate.w;\n' +
+ '}\n' +
+
+ 'vec3 getVectorFromOffset(vec4 eyeCoordinate, vec2 glFragCoordXY, vec2 positiveOffset) {\n' +
+ ' // Sample depths at both offset and negative offset\n' +
+ ' float upOrRightLogDepth = czm_unpackDepth(texture2D(czm_globeDepthTexture, (glFragCoordXY + positiveOffset) / czm_viewport.zw));\n' +
+ ' float downOrLeftLogDepth = czm_unpackDepth(texture2D(czm_globeDepthTexture, (glFragCoordXY - positiveOffset) / czm_viewport.zw));\n' +
+ ' // Explicitly evaluate both paths\n' + // Necessary for multifrustum and for GroundPrimitives at the edges of the screen
+ ' bvec2 upOrRightInBounds = lessThan(glFragCoordXY + positiveOffset, czm_viewport.zw);\n' +
+ ' float useUpOrRight = float(upOrRightLogDepth > 0.0 && upOrRightInBounds.x && upOrRightInBounds.y);\n' +
+ ' float useDownOrLeft = float(useUpOrRight == 0.0);\n' +
+ ' vec3 upOrRightEC = getEyeCoordinate3FromWindowCoordinate(glFragCoordXY + positiveOffset, upOrRightLogDepth);\n' +
+ ' vec3 downOrLeftEC = getEyeCoordinate3FromWindowCoordinate(glFragCoordXY - positiveOffset, downOrLeftLogDepth);\n' +
+
+ ' return (upOrRightEC - (eyeCoordinate.xyz / eyeCoordinate.w)) * useUpOrRight + ((eyeCoordinate.xyz / eyeCoordinate.w) - downOrLeftEC) * useDownOrLeft;\n' +
+ '}\n';
+ }
+ if (shaderDependencies.requiresTextureCoordinates && planarExtents) {
+ glsl +=
+ 'float computePlanarTextureCoordinates(vec4 plane, vec3 eyeCoordinates, float inverseExtent) {\n' +
+ ' return (dot(plane.xyz, eyeCoordinates) + plane.w) * inverseExtent;\n' +
+ '}\n';
+ }
+ return glsl;
+ }
+
+ function createShadowVolumeAppearanceVS(shaderDependencies, appearance, planarExtents, columbusView2D, shadowVolumeVS) {
+ var glsl = ShaderSource.replaceMain(shadowVolumeVS, 'computePosition');
+
+ var isPerInstanceColor = defined(appearance) && appearance instanceof PerInstanceColorAppearance;
+ if (isPerInstanceColor) {
+ glsl += 'varying vec4 v_color;\n';
+ }
+
+ var spherical = !(planarExtents || columbusView2D);
+ if (shaderDependencies.requiresTextureCoordinates) {
+ if (spherical) {
+ glsl +=
+ 'varying vec4 v_sphericalExtents;\n' +
+ 'varying vec4 v_stSineCosineUVScale;\n';
+ } else {
+ glsl +=
+ 'varying vec2 v_inversePlaneExtents;\n' +
+ 'varying vec4 v_westPlane;\n' +
+ 'varying vec4 v_southPlane;\n' +
+ 'varying vec4 v_stSineCosineUVScale;\n';
+ }
+ }
+
+ glsl +=
+ 'void main()\n' +
+ '{\n' +
+ ' computePosition();\n';
+ if (isPerInstanceColor) {
+ glsl += 'v_color = czm_batchTable_color(batchId);\n';
+ }
+
+ // Add code for computing texture coordinate dependencies
+ if (shaderDependencies.requiresTextureCoordinates) {
+ if (spherical) {
+ glsl +=
+ 'v_sphericalExtents = czm_batchTable_sphericalExtents(batchId);\n' +
+ 'v_stSineCosineUVScale = czm_batchTable_stSineCosineUVScale(batchId);\n';
+ } else {
+ // Two varieties of planar texcoords. 2D/CV case is "compressed" to fewer attributes
+ if (columbusView2D) {
+ glsl +=
+ 'vec4 planes2D_high = czm_batchTable_planes2D_HIGH(batchId);\n' +
+ 'vec4 planes2D_low = czm_batchTable_planes2D_LOW(batchId);\n' +
+ 'vec3 southWestCorner = (czm_modelViewRelativeToEye * czm_translateRelativeToEye(vec3(0.0, planes2D_high.xy), vec3(0.0, planes2D_low.xy))).xyz;\n' +
+ 'vec3 northWestCorner = (czm_modelViewRelativeToEye * czm_translateRelativeToEye(vec3(0.0, planes2D_high.x, planes2D_high.z), vec3(0.0, planes2D_low.x, planes2D_low.z))).xyz;\n' +
+ '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;\n';
+ } else {
+ glsl +=
+ 'vec3 southWestCorner = (czm_modelViewRelativeToEye * czm_translateRelativeToEye(czm_batchTable_southWest_HIGH(batchId), czm_batchTable_southWest_LOW(batchId))).xyz;\n' +
+ 'vec3 northWestCorner = (czm_modelViewRelativeToEye * czm_translateRelativeToEye(czm_batchTable_northWest_HIGH(batchId), czm_batchTable_northWest_LOW(batchId))).xyz;\n' +
+ 'vec3 southEastCorner = (czm_modelViewRelativeToEye * czm_translateRelativeToEye(czm_batchTable_southEast_HIGH(batchId), czm_batchTable_southEast_LOW(batchId))).xyz;\n';
+ }
+ glsl +=
+ 'vec3 eastWard = southEastCorner - southWestCorner;\n' +
+ 'float eastExtent = length(eastWard);\n' +
+ 'eastWard /= eastExtent;\n' +
+
+ 'vec3 northWard = northWestCorner - southWestCorner;\n' +
+ 'float northExtent = length(northWard);\n' +
+ 'northWard /= northExtent;\n' +
+
+ 'v_westPlane = vec4(eastWard, -dot(eastWard, southWestCorner));\n' +
+ 'v_southPlane = vec4(northWard, -dot(northWard, southWestCorner));\n' +
+ 'v_inversePlaneExtents = vec2(1.0 / eastExtent, 1.0 / northExtent);\n' +
+ 'v_stSineCosineUVScale = czm_batchTable_stSineCosineUVScale(batchId);\n';
+ }
+ }
+
+ glsl +=
+ '}\n';
+
+ return glsl;
+ }
+
+ /**
+ * Tracks shader dependencies.
+ * @private
+ */
+ function ShaderDependencies() {
+ this._requiresEC = false;
+ this._requiresWC = false; // depends on eye coordinates, needed for material and for phong
+ this._requiresNormalEC = false; // depends on eye coordinates, needed for material
+ this._requiresTextureCoordinates = false; // depends on world coordinates, needed for material and for culling
+
+ this._usesNormalEC = false;
+ this._usesPositionToEyeEC = false;
+ this._usesTangentToEyeMat = false;
+ this._usesSt = false;
+ }
+
+ ShaderDependencies.prototype.reset = function() {
+ this._requiresEC = false;
+ this._requiresWC = false;
+ this._requiresNormalEC = false;
+ this._requiresTextureCoordinates = false;
+
+ this._usesNormalEC = false;
+ this._usesPositionToEyeEC = false;
+ this._usesTangentToEyeMat = false;
+ this._usesSt = false;
+ };
+
+ defineProperties(ShaderDependencies.prototype, {
+ // Set when assessing final shading (flat vs. phong) and culling using computed texture coordinates
+ requiresEC : {
+ get : function() {
+ return this._requiresEC;
+ },
+ set : function(value) {
+ this._requiresEC = value || this._requiresEC;
+ }
+ },
+ requiresWC : {
+ get : function() {
+ return this._requiresWC;
+ },
+ set : function(value) {
+ this._requiresWC = value || this._requiresWC;
+ this.requiresEC = this._requiresWC;
+ }
+ },
+ requiresNormalEC : {
+ get : function() {
+ return this._requiresNormalEC;
+ },
+ set : function(value) {
+ this._requiresNormalEC = value || this._requiresNormalEC;
+ this.requiresEC = this._requiresNormalEC;
+ }
+ },
+ requiresTextureCoordinates : {
+ get : function() {
+ return this._requiresTextureCoordinates;
+ },
+ set : function(value) {
+ this._requiresTextureCoordinates = value || this._requiresTextureCoordinates;
+ this.requiresWC = this._requiresTextureCoordinates;
+ }
+ },
+ // Get/Set when assessing material hookups
+ normalEC : {
+ set : function(value) {
+ this.requiresNormalEC = value;
+ this._usesNormalEC = value;
+ },
+ get : function() {
+ return this._usesNormalEC;
+ }
+ },
+ tangentToEyeMatrix : {
+ set : function(value) {
+ this.requiresWC = value;
+ this.requiresNormalEC = value;
+ this._usesTangentToEyeMat = value;
+ },
+ get : function() {
+ return this._usesTangentToEyeMat;
+ }
+ },
+ positionToEyeEC : {
+ set : function(value) {
+ this.requiresEC = value;
+ this._usesPositionToEyeEC = value;
+ },
+ get : function() {
+ return this._usesPositionToEyeEC;
+ }
+ },
+ st : {
+ set : function(value) {
+ this.requiresTextureCoordinates = value;
+ this._usesSt = value;
+ },
+ get : function() {
+ return this._usesSt;
+ }
+ }
+ });
+
+ var encodeScratch = new EncodedCartesian3();
+ function addAttributesForPoint(point, name, attributes) {
+ var encoded = EncodedCartesian3.fromCartesian(point, encodeScratch);
+
+ attributes[name + '_HIGH'] = new GeometryInstanceAttribute({
+ componentDatatype: ComponentDatatype.FLOAT,
+ componentsPerAttribute: 3,
+ normalize: false,
+ value : Cartesian3.pack(encoded.high, [0, 0, 0])
+ });
+
+ attributes[name + '_LOW'] = new GeometryInstanceAttribute({
+ componentDatatype: ComponentDatatype.FLOAT,
+ componentsPerAttribute: 3,
+ normalize: false,
+ value : Cartesian3.pack(encoded.low, [0, 0, 0])
+ });
+ }
+
+ var cartographicScratch = new Cartographic();
+ var rectangleCenterScratch = new Cartographic();
+ var northCenterScratch = new Cartesian3();
+ var southCenterScratch = new Cartesian3();
+ var eastCenterScratch = new Cartesian3();
+ var westCenterScratch = new Cartesian3();
+ var points2DScratch = [new Cartesian2(), new Cartesian2(), new Cartesian2(), new Cartesian2()];
+ var rotation2DScratch = new Matrix2();
+ var min2DScratch = new Cartesian2();
+ var max2DScratch = new Cartesian2();
+ function getTextureCoordinateRotationAttribute(rectangle, ellipsoid, textureCoordinateRotation) {
+ var theta = defaultValue(textureCoordinateRotation, 0.0);
+
+ // Compute approximate scale such that the rectangle, if scaled and rotated,
+ // will completely enclose the unrotated/unscaled rectangle.
+ var cosTheta = Math.cos(theta);
+ var sinTheta = Math.sin(theta);
+
+ // Build a rectangle centered in 2D space approximating the input rectangle's dimensions
+ var cartoCenter = Rectangle.center(rectangle, rectangleCenterScratch);
+
+ var carto = cartographicScratch;
+ carto.latitude = cartoCenter.latitude;
+
+ carto.longitude = rectangle.west;
+ var westCenter = Cartographic.toCartesian(carto, ellipsoid, westCenterScratch);
+
+ carto.longitude = rectangle.east;
+ var eastCenter = Cartographic.toCartesian(carto, ellipsoid, eastCenterScratch);
+
+ carto.longitude = cartoCenter.longitude;
+ carto.latitude = rectangle.north;
+ var northCenter = Cartographic.toCartesian(carto, ellipsoid, northCenterScratch);
+
+ carto.latitude = rectangle.south;
+ var southCenter = Cartographic.toCartesian(carto, ellipsoid, southCenterScratch);
+
+ var northSouthHalfDistance = Cartesian3.distance(northCenter, southCenter) * 0.5;
+ var eastWestHalfDistance = Cartesian3.distance(eastCenter, westCenter) * 0.5;
+
+ var points2D = points2DScratch;
+ points2D[0].x = eastWestHalfDistance;
+ points2D[0].y = northSouthHalfDistance;
+
+ points2D[1].x = -eastWestHalfDistance;
+ points2D[1].y = northSouthHalfDistance;
+
+ points2D[2].x = eastWestHalfDistance;
+ points2D[2].y = -northSouthHalfDistance;
+
+ points2D[3].x = -eastWestHalfDistance;
+ points2D[3].y = -northSouthHalfDistance;
+
+ // Rotate the dimensions rectangle and compute min/max in rotated space
+ var min2D = min2DScratch;
+ min2D.x = Number.POSITIVE_INFINITY;
+ min2D.y = Number.POSITIVE_INFINITY;
+ var max2D = max2DScratch;
+ max2D.x = Number.NEGATIVE_INFINITY;
+ max2D.y = Number.NEGATIVE_INFINITY;
+
+ var rotation2D = Matrix2.fromRotation(-theta, rotation2DScratch);
+ for (var i = 0; i < 4; ++i) {
+ var point2D = points2D[i];
+ Matrix2.multiplyByVector(rotation2D, point2D, point2D);
+ Cartesian2.minimumByComponent(point2D, min2D, min2D);
+ Cartesian2.maximumByComponent(point2D, max2D, max2D);
+ }
+
+ // Depending on the rotation, east/west may be more appropriate for vertical scale than horizontal
+ var scaleU, scaleV;
+ if (Math.abs(sinTheta) < Math.abs(cosTheta)) {
+ scaleU = eastWestHalfDistance / ((max2D.x - min2D.x) * 0.5);
+ scaleV = northSouthHalfDistance / ((max2D.y - min2D.y) * 0.5);
+ } else {
+ scaleU = eastWestHalfDistance / ((max2D.y - min2D.y) * 0.5);
+ scaleV = northSouthHalfDistance / ((max2D.x - min2D.x) * 0.5);
+ }
+
+ return new GeometryInstanceAttribute({
+ componentDatatype: ComponentDatatype.FLOAT,
+ componentsPerAttribute: 4,
+ normalize: false,
+ value : [sinTheta, cosTheta, scaleU, scaleV] // Precompute trigonometry for rotation and inverse of scale
+ });
+ }
+
+ // Swizzle to 2D/CV projected space. This produces positions that
+ // can directly be used in the VS for 2D/CV, but in practice there's
+ // a lot of duplicated and zero values (see below).
+ var swizzleScratch = new Cartesian3();
+ function swizzle(cartesian) {
+ Cartesian3.clone(cartesian, swizzleScratch);
+ cartesian.x = swizzleScratch.z;
+ cartesian.y = swizzleScratch.x;
+ cartesian.z = swizzleScratch.y;
+ return cartesian;
+ }
+
+ var cornerScratch = new Cartesian3();
+ var northWestScratch = new Cartesian3();
+ var southEastScratch = new Cartesian3();
+ var highLowScratch = {high : 0.0, low : 0.0};
+ function add2DTextureCoordinateAttributes(rectangle, projection, attributes) {
+ // Compute corner positions in double precision
+ var carto = cartographicScratch;
+ carto.height = 0.0;
+
+ carto.longitude = rectangle.west;
+ carto.latitude = rectangle.south;
+
+ var southWestCorner = swizzle(projection.project(carto, cornerScratch));
+
+ carto.latitude = rectangle.north;
+ var northWest = swizzle(projection.project(carto, northWestScratch));
+
+ carto.longitude = rectangle.east;
+ carto.latitude = rectangle.south;
+ var southEast = swizzle(projection.project(carto, southEastScratch));
+
+ // Since these positions are all in the 2D plane, there's a lot of zeros
+ // and a lot of repetition. So we only need to encode 4 values.
+ // Encode:
+ // x: y value for southWestCorner
+ // y: z value for southWestCorner
+ // z: z value for northWest
+ // w: y value for southEast
+ var valuesHigh = [0, 0, 0, 0];
+ var valuesLow = [0, 0, 0, 0];
+ var encoded = EncodedCartesian3.encode(southWestCorner.y, highLowScratch);
+ valuesHigh[0] = encoded.high;
+ valuesLow[0] = encoded.low;
+
+ encoded = EncodedCartesian3.encode(southWestCorner.z, highLowScratch);
+ valuesHigh[1] = encoded.high;
+ valuesLow[1] = encoded.low;
+
+ encoded = EncodedCartesian3.encode(northWest.z, highLowScratch);
+ valuesHigh[2] = encoded.high;
+ valuesLow[2] = encoded.low;
+
+ encoded = EncodedCartesian3.encode(southEast.y, 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
+ });
+ }
+
+ /**
+ * Gets an attributes object containing:
+ * - 3 high-precision points as 6 GeometryInstanceAttributes. These points are used to compute eye-space planes.
+ * - 1 texture coordinate rotation GeometryInstanceAttributes
+ * - 2 GeometryInstanceAttributes used to compute high-precision points in 2D and Columbus View.
+ * These points are used to compute eye-space planes like above.
+ *
+ * Used to compute texture coordinates for small-area ClassificationPrimitives with materials or multiple non-overlapping instances.
+ *
+ * @see ShadowVolumeAppearance
+ * @private
+ *
+ * @param {Rectangle} rectangle Rectangle object that the points will approximately bound
+ * @param {Ellipsoid} ellipsoid Ellipsoid for converting Rectangle points to world coordinates
+ * @param {MapProjection} projection The MapProjection used for 2D and Columbus View.
+ * @param {Number} [textureCoordinateRotation=0] Texture coordinate rotation
+ * @returns {Object} An attributes dictionary containing planar texture coordinate attributes.
+ */
+ ShadowVolumeAppearance.getPlanarTextureCoordinateAttributes = function(rectangle, ellipsoid, projection, textureCoordinateRotation) {
+ //>>includeStart('debug', pragmas.debug);
+ Check.typeOf.object('rectangle', rectangle);
+ Check.typeOf.object('ellipsoid', ellipsoid);
+ Check.typeOf.object('projection', projection);
+ //>>includeEnd('debug');
+
+ // Compute corner positions in double precision
+ var carto = cartographicScratch;
+ carto.height = 0.0;
+
+ carto.longitude = rectangle.west;
+ carto.latitude = rectangle.south;
+
+ var corner = Cartographic.toCartesian(carto, ellipsoid, cornerScratch);
+
+ carto.latitude = rectangle.north;
+ var northWest = Cartographic.toCartesian(carto, ellipsoid, northWestScratch);
+
+ carto.longitude = rectangle.east;
+ carto.latitude = rectangle.south;
+ var southEast = Cartographic.toCartesian(carto, ellipsoid, southEastScratch);
+
+ var attributes = {
+ stSineCosineUVScale : getTextureCoordinateRotationAttribute(rectangle, ellipsoid, textureCoordinateRotation)
+ };
+ addAttributesForPoint(corner, 'southWest', attributes);
+ addAttributesForPoint(northWest, 'northWest', attributes);
+ addAttributesForPoint(southEast, 'southEast', attributes);
+
+ add2DTextureCoordinateAttributes(rectangle, projection, attributes);
+ return attributes;
+ };
+
+ var spherePointScratch = new Cartesian3();
+ function latLongToSpherical(latitude, longitude, ellipsoid, result) {
+ var cartographic = cartographicScratch;
+ cartographic.latitude = latitude;
+ cartographic.longitude = longitude;
+ cartographic.height = 0.0;
+
+ var spherePoint = Cartographic.toCartesian(cartographic, ellipsoid, spherePointScratch);
+
+ // Project into plane with vertical for latitude
+ var magXY = Math.sqrt(spherePoint.x * spherePoint.x + spherePoint.y * spherePoint.y);
+
+ // Use fastApproximateAtan2 for alignment with shader
+ var sphereLatitude = CesiumMath.fastApproximateAtan2(magXY, spherePoint.z);
+ var sphereLongitude = CesiumMath.fastApproximateAtan2(spherePoint.x, spherePoint.y);
+
+ result.x = sphereLatitude;
+ result.y = sphereLongitude;
+
+ return result;
+ }
+
+ var sphericalScratch = new Cartesian2();
+ /**
+ * Gets an attributes object containing:
+ * - the southwest corner of a rectangular area in spherical coordinates, as well as the inverse of the latitude/longitude range.
+ * These are computed using the same atan2 approximation used in the shader.
+ * - 1 texture coordinate rotation GeometryInstanceAttributes
+ * - 2 GeometryInstanceAttributes used to compute high-precision points in 2D and Columbus View.
+ * These points are used to compute eye-space planes like above.
+ *
+ * Used when computing texture coordinates for large-area ClassificationPrimitives with materials or
+ * multiple non-overlapping instances.
+ * @see ShadowVolumeAppearance
+ * @private
+ *
+ * @param {Rectangle} rectangle Rectangle object that the spherical extents will approximately bound
+ * @param {Ellipsoid} ellipsoid Ellipsoid for converting Rectangle points to world coordinates
+ * @param {MapProjection} projection The MapProjection used for 2D and Columbus View.
+ * @param {Number} [textureCoordinateRotation=0] Texture coordinate rotation
+ * @returns {Object} An attributes dictionary containing spherical texture coordinate attributes.
+ */
+ ShadowVolumeAppearance.getSphericalExtentGeometryInstanceAttributes = function(rectangle, ellipsoid, projection, textureCoordinateRotation) {
+ //>>includeStart('debug', pragmas.debug);
+ Check.typeOf.object('rectangle', rectangle);
+ Check.typeOf.object('ellipsoid', ellipsoid);
+ Check.typeOf.object('projection', projection);
+ //>>includeEnd('debug');
+
+ // rectangle cartographic coords !== spherical because it's on an ellipsoid
+ var southWestExtents = latLongToSpherical(rectangle.south, rectangle.west, ellipsoid, sphericalScratch);
+
+ // Slightly pad extents to avoid floating point error when fragment culling at edges.
+ var south = southWestExtents.x - CesiumMath.EPSILON5;
+ var west = southWestExtents.y - CesiumMath.EPSILON5;
+
+ var northEastExtents = latLongToSpherical(rectangle.north, rectangle.east, ellipsoid, sphericalScratch);
+ var north = northEastExtents.x + CesiumMath.EPSILON5;
+ var east = northEastExtents.y + CesiumMath.EPSILON5;
+
+ var longitudeRangeInverse = 1.0 / (east - west);
+ var latitudeRangeInverse = 1.0 / (north - south);
+
+ var attributes = {
+ sphericalExtents : new GeometryInstanceAttribute({
+ componentDatatype: ComponentDatatype.FLOAT,
+ componentsPerAttribute: 4,
+ normalize: false,
+ value : [south, west, latitudeRangeInverse, longitudeRangeInverse]
+ }),
+ stSineCosineUVScale : getTextureCoordinateRotationAttribute(rectangle, ellipsoid, textureCoordinateRotation)
+ };
+
+ add2DTextureCoordinateAttributes(rectangle, projection, attributes);
+ return attributes;
+ };
+
+ ShadowVolumeAppearance.hasAttributesForTextureCoordinatePlanes = function(attributes) {
+ return defined(attributes.southWest_HIGH) && defined(attributes.southWest_LOW) &&
+ defined(attributes.northWest_HIGH) && defined(attributes.northWest_LOW) &&
+ defined(attributes.southEast_HIGH) && defined(attributes.southEast_LOW) &&
+ defined(attributes.planes2D_HIGH) && defined(attributes.planes2D_LOW) &&
+ defined(attributes.stSineCosineUVScale);
+ };
+
+ ShadowVolumeAppearance.hasAttributesForSphericalExtents = function(attributes) {
+ return defined(attributes.sphericalExtents) &&
+ defined(attributes.planes2D_HIGH) && defined(attributes.planes2D_LOW) &&
+ defined(attributes.stSineCosineUVScale);
+ };
+
+ function shouldUseSpherical(rectangle) {
+ return Math.max(rectangle.width, rectangle.height) > ShadowVolumeAppearance.MAX_WIDTH_FOR_PLANAR_EXTENTS;
+ }
+
+ /**
+ * Computes whether the given rectangle is wide enough that texture coordinates
+ * over its area should be computed using spherical extents instead of distance to planes.
+ *
+ * @param {Rectangle} rectangle A rectangle
+ * @private
+ */
+ ShadowVolumeAppearance.shouldUseSphericalCoordinates = function(rectangle) {
+ //>>includeStart('debug', pragmas.debug);
+ Check.typeOf.object('rectangle', rectangle);
+ //>>includeEnd('debug');
+
+ return shouldUseSpherical(rectangle);
+ };
+
+ /**
+ * Texture coordinates for ground primitives are computed either using spherical coordinates for large areas or
+ * using distance from planes for small areas.
+ *
+ * @type {Number}
+ * @constant
+ * @private
+ */
+ ShadowVolumeAppearance.MAX_WIDTH_FOR_PLANAR_EXTENTS = CesiumMath.toRadians(1.0);
+
+ return ShadowVolumeAppearance;
+});
diff --git a/Source/Scene/ShadowVolumeAppearanceShader.js b/Source/Scene/ShadowVolumeAppearanceShader.js
deleted file mode 100644
index 4812047c9a7..00000000000
--- a/Source/Scene/ShadowVolumeAppearanceShader.js
+++ /dev/null
@@ -1,474 +0,0 @@
-define([
- '../Core/Check',
- '../Core/defaultValue',
- '../Core/defined',
- '../Core/defineProperties',
- '../Renderer/PixelDatatype',
- '../Renderer/ShaderSource', // TODO: where should this file live actually?
- '../Scene/PerInstanceColorAppearance'
-], function(
- Check,
- defaultValue,
- defined,
- defineProperties,
- PixelDatatype,
- ShaderSource,
- PerInstanceColorAppearance) {
- 'use strict';
-
- /**
- * Creates the shadow volume fragment shader for a ClassificationPrimitive to use a given appearance.
- *
- * @param {Boolean} extentsCulling Discard fragments outside the instance's spherical extents.
- * @param {Boolean} planarExtents
- * @param {Boolean} columbusView2D
- * @param {Appearance} [appearance] An Appearance to be used with a ClassificationPrimitive. Leave undefined for picking.
- * @returns {String} Shader source for a fragment shader using the input appearance.
- * @private
- */
- function ShadowVolumeAppearanceShader(extentsCulling, planarExtents, columbusView2D, vertexShader, appearance) {
- //>>includeStart('debug', pragmas.debug);
- Check.typeOf.bool('extentsCulling', extentsCulling);
- Check.typeOf.bool('planarExtents', planarExtents);
- Check.typeOf.bool('columbusView2D', columbusView2D);
- Check.typeOf.string('vertexShader', vertexShader);
- //>>includeEnd('debug');
-
- var shaderDependencies = new ShaderDependencies();
- this._shaderDependencies = shaderDependencies;
- this._extentsCulling = extentsCulling;
- this._planarExtents = planarExtents || columbusView2D;
- this._fragmenShaderSource = createShadowVolumeAppearanceFS(shaderDependencies, appearance, this._extentsCulling, this._planarExtents);
- this._vertexShaderSource = createShadowVolumeAppearanceVS(shaderDependencies, appearance, planarExtents, columbusView2D, vertexShader);
- }
-
- defineProperties(ShadowVolumeAppearanceShader.prototype, {
- /**
- * Whether or not the resulting shader's texture coordinates are computed from planar extents.
- *
- * @memberof ShadowVolumeAppearanceShader.prototype
- * @type {Boolean}
- * @readonly
- */
- planarExtents : {
- get : function() {
- return this._planarExtents;
- }
- },
- /**
- * The fragment shader source.
- * @memberof ShadowVolumeAppearanceShader.prototype
- * @type {String}
- * @readonly
- */
- fragmentShaderSource : {
- get : function() {
- return this._fragmenShaderSource;
- }
- },
- /**
- * The vertex shader source.
- * @memberof ShadowVolumeAppearanceShader.prototype
- * @type {String}
- * @readonly
- */
- vertexShaderSource : {
- get : function() {
- return this._vertexShaderSource;
- }
- }
- });
-
- function createShadowVolumeAppearanceFS(shaderDependencies, appearance, extentsCull, planarExtents) {
- if (!defined(appearance)) {
- return getColorlessShaderFS(shaderDependencies, extentsCull, planarExtents);
- }
- if (appearance instanceof PerInstanceColorAppearance) {
- return getPerInstanceColorShaderFS(shaderDependencies, extentsCull, appearance.flat, planarExtents);
- }
-
- shaderDependencies.requiresTextureCoordinates = extentsCull;
- shaderDependencies.requiresEC = !appearance.flat;
-
- // Scan material source for what hookups are needed. Assume czm_materialInput materialInput.
- var materialShaderSource = appearance.material.shaderSource;
-
- var usesNormalEC = shaderDependencies.normalEC = materialShaderSource.includes('materialInput.normalEC') || materialShaderSource.includes('czm_getDefaultMaterial');
- var usesPositionToEyeEC = shaderDependencies.positionToEyeEC = materialShaderSource.includes('materialInput.positionToEyeEC');
- var usesTangentToEyeMat = shaderDependencies.tangentToEyeMatrix = materialShaderSource.includes('materialInput.tangentToEyeMatrix');
- var usesSt = shaderDependencies.st = materialShaderSource.includes('materialInput.st');
-
- var glsl =
- '#ifdef GL_EXT_frag_depth\n' +
- '#extension GL_EXT_frag_depth : enable\n' +
- '#endif\n';
- if (extentsCull || usesSt) {
- glsl += planarExtents ?
- 'varying vec2 v_inversePlaneExtents;\n' +
- 'varying vec4 v_westPlane;\n' +
- 'varying vec4 v_southPlane;\n' :
-
- 'varying vec4 v_sphericalExtents;\n';
- }
- if (usesSt) {
- glsl +=
- 'varying vec4 v_stSineCosineUVScale;\n';
- }
-
- glsl += getLocalFunctionsFS(shaderDependencies, planarExtents);
-
- glsl +=
- 'void main(void)\n' +
- '{\n';
-
- glsl += getDependenciesAndCullingFS(shaderDependencies, extentsCull, planarExtents);
-
- glsl += ' czm_materialInput materialInput;\n';
- if (usesNormalEC) {
- glsl += ' materialInput.normalEC = normalEC;\n';
- }
- if (usesPositionToEyeEC) {
- glsl += ' materialInput.positionToEyeEC = -eyeCoordinate.xyz;\n';
- }
- if (usesTangentToEyeMat) {
- glsl += ' materialInput.tangentToEyeMatrix = czm_eastNorthUpToEyeCoordinates(worldCoordinate, normalEC);\n';
- }
- if (usesSt) {
- // Scale texture coordinates and rotate around 0.5, 0.5
- glsl +=
- ' materialInput.st.x = v_stSineCosineUVScale.y * (v - 0.5) * v_stSineCosineUVScale.z + v_stSineCosineUVScale.x * (u - 0.5) * v_stSineCosineUVScale.w + 0.5;\n' +
- ' materialInput.st.y = v_stSineCosineUVScale.y * (u - 0.5) * v_stSineCosineUVScale.w - v_stSineCosineUVScale.x * (v - 0.5) * v_stSineCosineUVScale.z + 0.5;\n';
- }
- glsl += ' czm_material material = czm_getMaterial(materialInput);\n';
-
- if (appearance.flat) {
- glsl += ' gl_FragColor = vec4(material.diffuse + material.emission, material.alpha);\n';
- } else {
- glsl += ' gl_FragColor = czm_phong(normalize(-eyeCoordinate.xyz), material);\n';
- }
- glsl += ' czm_writeDepthClampedToFarPlane();\n';
- glsl += '}\n';
- return glsl;
- }
-
- function getColorlessShaderFS(shaderDependencies, extentsCulling, planarExtents) {
- var glsl =
- '#ifdef GL_EXT_frag_depth\n' +
- '#extension GL_EXT_frag_depth : enable\n' +
- '#endif\n';
- if (extentsCulling) {
- glsl += planarExtents ?
- 'varying vec2 v_inversePlaneExtents;\n' +
- 'varying vec4 v_westPlane;\n' +
- 'varying vec4 v_southPlane;\n' :
-
- 'varying vec4 v_sphericalExtents;\n';
- }
- shaderDependencies.requiresTextureCoordinates = extentsCulling;
- shaderDependencies.requiresNormalEC = false;
-
- glsl += getLocalFunctionsFS(shaderDependencies, planarExtents);
-
- glsl += 'void main(void)\n' +
- '{\n';
- glsl += ' bool culled = false;\n';
- var outOfBoundsSnippet =
- ' culled = true;\n';
- glsl += getDependenciesAndCullingFS(shaderDependencies, extentsCulling, planarExtents, outOfBoundsSnippet);
- glsl += ' if (!culled) {\n' +
- ' gl_FragColor.a = 1.0;\n' + // 0.0 alpha leads to discard from ShaderSource.createPickFragmentShaderSource
- ' czm_writeDepthClampedToFarPlane();\n' +
- ' }\n' +
- '}\n';
- return glsl;
- }
-
- function getPerInstanceColorShaderFS(shaderDependencies, extentsCulling, flatShading, planarExtents) {
- var glsl =
- '#ifdef GL_EXT_frag_depth\n' +
- '#extension GL_EXT_frag_depth : enable\n' +
- '#endif\n' +
- 'varying vec4 v_color;\n';
- if (extentsCulling) {
- glsl += planarExtents ?
- 'varying vec2 v_inversePlaneExtents;\n' +
- 'varying vec4 v_westPlane;\n' +
- 'varying vec4 v_southPlane;\n' :
-
- 'varying vec4 v_sphericalExtents;\n';
- }
- shaderDependencies.requiresTextureCoordinates = extentsCulling;
- shaderDependencies.requiresNormalEC = !flatShading;
-
- glsl += getLocalFunctionsFS(shaderDependencies, planarExtents);
-
- glsl += 'void main(void)\n' +
- '{\n';
-
- glsl += getDependenciesAndCullingFS(shaderDependencies, extentsCulling, planarExtents);
-
- if (flatShading) {
- glsl +=
- ' gl_FragColor = v_color;\n';
- } else {
- glsl +=
- ' czm_materialInput materialInput;\n' +
- ' materialInput.normalEC = normalEC;\n' +
- ' materialInput.positionToEyeEC = -eyeCoordinate.xyz;\n' +
- ' czm_material material = czm_getDefaultMaterial(materialInput);\n' +
- ' material.diffuse = v_color.rgb;\n' +
- ' material.alpha = v_color.a;\n' +
-
- ' gl_FragColor = czm_phong(normalize(-eyeCoordinate.xyz), material);\n';
- }
- glsl += ' czm_writeDepthClampedToFarPlane();\n';
- glsl += '}\n';
- return glsl;
- }
-
- function getDependenciesAndCullingFS(shaderDependencies, extentsCulling, planarExtents, outOfBoundsSnippet) {
- var glsl = '';
- if (shaderDependencies.requiresEC) {
- glsl +=
- ' vec4 eyeCoordinate = getEyeCoordinate(gl_FragCoord.xy);\n';
- }
- if (shaderDependencies.requiresWC) {
- glsl +=
- ' vec4 worldCoordinate4 = czm_inverseView * eyeCoordinate;\n' +
- ' vec3 worldCoordinate = worldCoordinate4.xyz / worldCoordinate4.w;\n';
- }
- if (shaderDependencies.requiresTextureCoordinates) {
- if (planarExtents) {
- glsl +=
- ' // Unpack planes and transform to eye space\n' +
- ' float u = computePlanarTextureCoordinates(v_southPlane, eyeCoordinate.xyz / eyeCoordinate.w, v_inversePlaneExtents.y);\n' +
- ' float v = computePlanarTextureCoordinates(v_westPlane, eyeCoordinate.xyz / eyeCoordinate.w, v_inversePlaneExtents.x);\n';
- } else {
- glsl +=
- ' // Treat world coords as a sphere normal for spherical coordinates\n' +
- ' vec2 sphericalLatLong = czm_approximateSphericalCoordinates(worldCoordinate);\n' +
- ' float u = (sphericalLatLong.x - v_sphericalExtents.x) * v_sphericalExtents.z;\n' +
- ' float v = (sphericalLatLong.y - v_sphericalExtents.y) * v_sphericalExtents.w;\n';
- }
- }
- if (extentsCulling) {
- if (!defined(outOfBoundsSnippet)) {
- outOfBoundsSnippet =
- ' discard;\n';
- }
- glsl +=
- ' if (u <= 0.0 || 1.0 <= u || v <= 0.0 || 1.0 <= v) {\n' +
- outOfBoundsSnippet +
- ' }\n';
- }
- // Lots of texture access, so lookup after discard check
- if (shaderDependencies.requiresNormalEC) {
- glsl +=
- ' // compute normal. sample adjacent pixels in 2x2 block in screen space\n' +
- ' vec3 downUp = getVectorFromOffset(eyeCoordinate, gl_FragCoord.xy, vec2(0.0, 1.0));\n' +
- ' vec3 leftRight = getVectorFromOffset(eyeCoordinate, gl_FragCoord.xy, vec2(1.0, 0.0));\n' +
- ' vec3 normalEC = normalize(cross(leftRight, downUp));\n' +
- '\n';
- }
- return glsl;
- }
-
- function getLocalFunctionsFS(shaderDependencies, planarExtents) {
- var glsl = '';
- if (shaderDependencies.requiresEC) {
- glsl +=
- 'vec4 getEyeCoordinate(vec2 fragCoord) {\n' +
- ' vec2 coords = fragCoord / czm_viewport.zw;\n' +
- ' float logDepthOrDepth = czm_unpackDepth(texture2D(czm_globeDepthTexture, coords));\n' +
- ' vec4 windowCoord = vec4(fragCoord, czm_reverseLogDepth(logDepthOrDepth), 1.0);\n' +
- ' vec4 eyeCoordinate = czm_windowToEyeCoordinates(windowCoord);\n' +
- '#ifdef LOG_DEPTH\n' +
- // Essentially same as reverseLogDepth but without normalization. Better precision when using log depth.
- ' eyeCoordinate.w = 1.0 / (pow(2.0, logDepthOrDepth * czm_log2FarPlusOne) - 1.0);\n' +
- '#endif\n' +
- ' return eyeCoordinate;\n' +
- '}\n';
- }
- if (shaderDependencies.requiresNormalEC) {
- glsl +=
- 'vec3 getEyeCoordinate3FromWindowCoordinate(vec2 fragCoord, float logDepthOrDepth) {\n' +
- ' vec4 windowCoord = vec4(fragCoord, czm_reverseLogDepth(logDepthOrDepth), 1.0);\n' +
- ' vec4 eyeCoordinate = czm_windowToEyeCoordinates(windowCoord);\n' +
- '#ifdef LOG_DEPTH\n' +
- // Essentially same as reverseLogDepth but without normalization. Better precision when using log depth.
- ' eyeCoordinate.w = 1.0 / (pow(2.0, logDepthOrDepth * czm_log2FarPlusOne) - 1.0);\n' +
- '#endif\n' +
- ' return eyeCoordinate.xyz / eyeCoordinate.w;\n' +
- '}\n' +
-
- 'vec3 getVectorFromOffset(vec4 eyeCoordinate, vec2 glFragCoordXY, vec2 positiveOffset) {\n' +
- ' // Sample depths at both offset and negative offset\n' +
- ' float upOrRightLogDepth = czm_unpackDepth(texture2D(czm_globeDepthTexture, (glFragCoordXY + positiveOffset) / czm_viewport.zw));\n' +
- ' float downOrLeftLogDepth = czm_unpackDepth(texture2D(czm_globeDepthTexture, (glFragCoordXY - positiveOffset) / czm_viewport.zw));\n' +
- ' // Explicitly evaluate both paths\n' + // Necessary for multifrustum and for GroundPrimitives at the edges of the screen
- ' bvec2 upOrRightInBounds = lessThan(glFragCoordXY + positiveOffset, czm_viewport.zw);\n' +
- ' float useUpOrRight = float(upOrRightLogDepth > 0.0 && upOrRightInBounds.x && upOrRightInBounds.y);\n' +
- ' float useDownOrLeft = float(useUpOrRight == 0.0);\n' +
- ' vec3 upOrRightEC = getEyeCoordinate3FromWindowCoordinate(glFragCoordXY + positiveOffset, upOrRightLogDepth);\n' +
- ' vec3 downOrLeftEC = getEyeCoordinate3FromWindowCoordinate(glFragCoordXY - positiveOffset, downOrLeftLogDepth);\n' +
-
- ' return (upOrRightEC - (eyeCoordinate.xyz / eyeCoordinate.w)) * useUpOrRight + ((eyeCoordinate.xyz / eyeCoordinate.w) - downOrLeftEC) * useDownOrLeft;\n' +
- '}\n';
- }
- if (shaderDependencies.requiresTextureCoordinates && planarExtents) {
- glsl +=
- 'float computePlanarTextureCoordinates(vec4 plane, vec3 eyeCoordinates, float inverseExtent) {\n' +
- ' return (dot(plane.xyz, eyeCoordinates) + plane.w) * inverseExtent;\n' +
- '}\n';
- }
- return glsl;
- }
-
- function createShadowVolumeAppearanceVS(shaderDependencies, appearance, planarExtents, columbusView2D, shadowVolumeVS) {
- var glsl = ShaderSource.replaceMain(shadowVolumeVS, 'computePosition');
-
- var isPerInstanceColor = defined(appearance) && appearance instanceof PerInstanceColorAppearance;
- if (isPerInstanceColor) {
- glsl += 'varying vec4 v_color;\n';
- }
-
- var spherical = !(planarExtents || columbusView2D);
- if (shaderDependencies.requiresTextureCoordinates) {
- if (spherical) {
- glsl +=
- 'varying vec4 v_sphericalExtents;\n' +
- 'varying vec4 v_stSineCosineUVScale;\n';
- } else {
- glsl +=
- 'varying vec2 v_inversePlaneExtents;\n' +
- 'varying vec4 v_westPlane;\n' +
- 'varying vec4 v_southPlane;\n' +
- 'varying vec4 v_stSineCosineUVScale;\n';
- }
- }
-
- glsl +=
- 'void main()\n' +
- '{\n' +
- ' computePosition();\n';
- if (isPerInstanceColor) {
- glsl += 'v_color = czm_batchTable_color(batchId);\n';
- }
-
- // Add code for computing texture coordinate dependencies
- if (shaderDependencies.requiresTextureCoordinates) {
- if (spherical) {
- glsl +=
- 'v_sphericalExtents = czm_batchTable_sphericalExtents(batchId);\n' +
- 'v_stSineCosineUVScale = czm_batchTable_stSineCosineUVScale(batchId);\n';
- } else {
- // Two varieties of planar texcoords. 2D/CV case is "compressed"
- if (columbusView2D) {
- glsl +=
- 'vec4 planes2D_high = czm_batchTable_planes2D_HIGH(batchId);\n' +
- 'vec4 planes2D_low = czm_batchTable_planes2D_LOW(batchId);\n' +
- 'vec3 southWestCorner = (czm_modelViewRelativeToEye * czm_translateRelativeToEye(vec3(0.0, planes2D_high.xy), vec3(0.0, planes2D_low.xy))).xyz;\n' +
- 'vec3 northWestCorner = (czm_modelViewRelativeToEye * czm_translateRelativeToEye(vec3(0.0, planes2D_high.x, planes2D_high.z), vec3(0.0, planes2D_low.x, planes2D_low.z))).xyz;\n' +
- '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;\n';
- } else {
- glsl +=
- 'vec3 southWestCorner = (czm_modelViewRelativeToEye * czm_translateRelativeToEye(czm_batchTable_southWest_HIGH(batchId), czm_batchTable_southWest_LOW(batchId))).xyz;\n' +
- 'vec3 northWestCorner = (czm_modelViewRelativeToEye * czm_translateRelativeToEye(czm_batchTable_northWest_HIGH(batchId), czm_batchTable_northWest_LOW(batchId))).xyz;\n' +
- 'vec3 southEastCorner = (czm_modelViewRelativeToEye * czm_translateRelativeToEye(czm_batchTable_southEast_HIGH(batchId), czm_batchTable_southEast_LOW(batchId))).xyz;\n';
- }
- glsl +=
- 'vec3 eastWard = southEastCorner - southWestCorner;\n' +
- 'float eastExtent = length(eastWard);\n' +
- 'eastWard /= eastExtent;\n' +
-
- 'vec3 northWard = northWestCorner - southWestCorner;\n' +
- 'float northExtent = length(northWard);\n' +
- 'northWard /= northExtent;\n' +
-
- 'v_westPlane = vec4(eastWard, -dot(eastWard, southWestCorner));\n' +
- 'v_southPlane = vec4(northWard, -dot(northWard, southWestCorner));\n' +
- 'v_inversePlaneExtents = vec2(1.0 / eastExtent, 1.0 / northExtent);\n' +
- 'v_stSineCosineUVScale = czm_batchTable_stSineCosineUVScale(batchId);\n';
- }
- }
-
- glsl +=
- '}\n';
-
- return glsl;
- }
-
- /**
- * Tracks shader dependencies.
- * @private
- */
- function ShaderDependencies() {
- this._requiresEC = false;
- this._requiresWC = false; // depends on eye coordinates, needed for material and for phong
- this._requiresNormalEC = false; // depends on eye coordinates, needed for material
- this._requiresTextureCoordinates = false; // depends on world coordinates, needed for material and for culling
- }
-
- defineProperties(ShaderDependencies.prototype, {
- // Set when assessing final shading (flat vs. phong) and culling using computed texture coordinates
- requiresEC : {
- get : function() {
- return this._requiresEC;
- },
- set : function(value) {
- this._requiresEC = value || this._requiresEC;
- }
- },
- requiresWC : {
- get : function() {
- return this._requiresWC;
- },
- set : function(value) {
- this._requiresWC = value || this._requiresWC;
- this.requiresEC = this._requiresWC;
- }
- },
- requiresNormalEC : {
- get : function() {
- return this._requiresNormalEC;
- },
- set : function(value) {
- this._requiresNormalEC = value || this._requiresNormalEC;
- this.requiresEC = this._requiresNormalEC;
- }
- },
- requiresTextureCoordinates : {
- get : function() {
- return this._requiresTextureCoordinates;
- },
- set : function(value) {
- this._requiresTextureCoordinates = value || this._requiresTextureCoordinates;
- this.requiresWC = this._requiresTextureCoordinates;
- }
- },
- // Set when assessing material hookups
- normalEC : {
- set : function(value) {
- this.requiresNormalEC = value;
- }
- },
- tangentToEyeMatrix : {
- set : function(value) {
- this.requiresWC = value;
- this.requiresNormalEC = value;
- }
- },
- positionToEyeEC : {
- set : function(value) {
- this.requiresEC = value;
- }
- },
- st : {
- set : function(value) {
- this.requiresTextureCoordinates = value;
- }
- }
- });
-
- return ShadowVolumeAppearanceShader;
-});
From d9ed5c56cf01ceaf08167432aca09ff8f00ca20a Mon Sep 17 00:00:00 2001
From: Kangning Li
@@ -234,13 +240,6 @@ define([
this._boundingSpheresKeys = [];
this._boundingSpheres = [];
- var uniformMap = {
- u_globeMinimumAltitude: function() {
- return 55000.0;
- }
- };
- this._uniformMap = uniformMap;
-
var that = this;
this._classificationPrimitiveOptions = {
geometryInstances : undefined,
@@ -255,7 +254,7 @@ define([
_updateAndQueueCommandsFunction : undefined,
_pickPrimitive : that,
_extruded : true,
- _uniformMap : uniformMap
+ _uniformMap : GroundPrimitiveUniformMap
};
}
@@ -630,6 +629,14 @@ define([
for (i = 0; i < colorLength; ++i) {
colorCommand = colorCommands[i];
+
+ // derive a separate appearance command for 2D if needed
+ if (frameState.mode !== SceneMode.SCENE3D &&
+ colorCommand.shaderProgram === classificationPrimitive._spColor &&
+ classificationPrimitive._needs2DShader) {
+ colorCommand = colorCommand.derivedCommands.appearance2D;
+ }
+
colorCommand.owner = groundPrimitive;
colorCommand.modelMatrix = modelMatrix;
colorCommand.boundingVolume = boundingVolumes[boundingVolumeIndex(i, colorLength)];
@@ -637,18 +644,6 @@ define([
colorCommand.debugShowBoundingVolume = debugShowBoundingVolume;
colorCommand.pass = pass;
- // derive a separate appearance command for 2D
- if (frameState.mode !== SceneMode.SCENE3D &&
- colorCommand.shaderProgram === classificationPrimitive._spColor) {
- var derivedColorCommand = colorCommand.derivedCommands.appearance2D;
- if (!defined(derivedColorCommand)) {
- derivedColorCommand = DrawCommand.shallowClone(colorCommand);
- derivedColorCommand.shaderProgram = classificationPrimitive._spColor2D;
- colorCommand.derivedCommands.appearance2D = derivedColorCommand;
- }
- colorCommand = derivedColorCommand;
- }
-
commandList.push(colorCommand);
}
@@ -674,23 +669,19 @@ define([
for (var j = 0; j < pickLength; ++j) {
var pickCommand = pickCommands[j];
+ // derive a separate appearance command for 2D if needed
+ if (frameState.mode !== SceneMode.SCENE3D &&
+ pickCommand.shaderProgram === classificationPrimitive._spPick &&
+ classificationPrimitive._needs2DShader) {
+ pickCommand = pickCommand.derivedCommands.pick2D;
+ }
+
pickCommand.owner = groundPrimitive;
pickCommand.modelMatrix = modelMatrix;
pickCommand.boundingVolume = boundingVolumes[boundingVolumeIndex(j, pickLength)];
pickCommand.cull = cull;
pickCommand.pass = pass;
- // derive a separate appearance command for 2D
- if (frameState.mode !== SceneMode.SCENE3D &&
- pickCommand.shaderProgram === classificationPrimitive._spPick) {
- var derivedPickCommand = pickCommand.derivedCommands.pick2D;
- if (!defined(derivedPickCommand)) {
- derivedPickCommand = DrawCommand.shallowClone(pickCommand);
- derivedPickCommand.shaderProgram = classificationPrimitive._spPick2D;
- pickCommand.derivedCommands.pick2D = derivedPickCommand;
- }
- pickCommand = derivedPickCommand;
- }
commandList.push(pickCommand);
}
}
diff --git a/Source/Scene/Scene.js b/Source/Scene/Scene.js
index 776143d5827..61c0c42ed51 100644
--- a/Source/Scene/Scene.js
+++ b/Source/Scene/Scene.js
@@ -644,16 +644,6 @@ define([
*/
this.cameraEventWaitTime = 500.0;
- /**
- * Set to true to copy the depth texture after rendering the globe. Makes czm_globeDepthTexture valid.
- * Set to false if Entities on terrain or GroundPrimitives are not used for a potential performance improvement.
- *
- * @type {Boolean}
- * @default true
- * @private
- */
- this.copyGlobeDepth = true;
-
/**
* Blends the atmosphere to geometry far from the camera for horizon views. Allows for additional
* performance improvements by rendering less geometry and dispatching less terrain requests.
@@ -2199,7 +2189,7 @@ define([
executeCommand(commands[j], scene, context, passState);
}
- if (defined(globeDepth) && environmentState.useGlobeDepthFramebuffer && (scene.copyGlobeDepth || scene.debugShowGlobeDepth)) {
+ if (defined(globeDepth) && environmentState.useGlobeDepthFramebuffer) {
globeDepth.update(context, passState);
globeDepth.executeCopyDepth(context, passState);
}
diff --git a/Source/Scene/ShadowVolumeAppearance.js b/Source/Scene/ShadowVolumeAppearance.js
index 6f38b4fa74d..1493104525c 100644
--- a/Source/Scene/ShadowVolumeAppearance.js
+++ b/Source/Scene/ShadowVolumeAppearance.js
@@ -15,7 +15,8 @@ define([
'../Core/Rectangle',
'../Core/Transforms',
'../Renderer/ShaderSource',
- '../Scene/PerInstanceColorAppearance'
+ '../Scene/PerInstanceColorAppearance',
+ '../Shaders/ShadowVolumeAppearanceFS'
], function(
Cartographic,
Cartesian2,
@@ -33,7 +34,8 @@ define([
Rectangle,
Transforms,
ShaderSource,
- PerInstanceColorAppearance) {
+ PerInstanceColorAppearance,
+ ShadowVolumeAppearanceFS) {
'use strict';
/**
@@ -52,24 +54,28 @@ define([
//>>includeEnd('debug');
// Compute shader dependencies
- var shaderDependencies = new ShaderDependencies();
- shaderDependencies.requiresTextureCoordinates = extentsCulling;
- shaderDependencies.requiresEC = !appearance.flat;
+ var colorShaderDependencies = new ShaderDependencies();
+ colorShaderDependencies.requiresTextureCoordinates = extentsCulling;
+ colorShaderDependencies.requiresEC = !appearance.flat;
+
+ var pickShaderDependencies = new ShaderDependencies();
+ pickShaderDependencies.requiresTextureCoordinates = extentsCulling;
if (appearance instanceof PerInstanceColorAppearance) {
// PerInstanceColorAppearance doesn't have material.shaderSource, instead it has its own vertex and fragment shaders
- shaderDependencies.requiresNormalEC = !appearance.flat;
+ colorShaderDependencies.requiresNormalEC = !appearance.flat;
} else {
// Scan material source for what hookups are needed. Assume czm_materialInput materialInput.
var materialShaderSource = appearance.material.shaderSource + '\n' + appearance.fragmentShaderSource;
- shaderDependencies.normalEC = materialShaderSource.includes('materialInput.normalEC') || materialShaderSource.includes('czm_getDefaultMaterial');
- shaderDependencies.positionToEyeEC = materialShaderSource.includes('materialInput.positionToEyeEC');
- shaderDependencies.tangentToEyeMatrix = materialShaderSource.includes('materialInput.tangentToEyeMatrix');
- shaderDependencies.st = materialShaderSource.includes('materialInput.st');
+ colorShaderDependencies.normalEC = materialShaderSource.indexOf('materialInput.normalEC') !== -1 || materialShaderSource.indexOf('czm_getDefaultMaterial') !== -1;
+ colorShaderDependencies.positionToEyeEC = materialShaderSource.indexOf('materialInput.positionToEyeEC') !== -1;
+ colorShaderDependencies.tangentToEyeMatrix = materialShaderSource.indexOf('materialInput.tangentToEyeMatrix') !== -1;
+ colorShaderDependencies.st = materialShaderSource.indexOf('materialInput.st') !== -1;
}
- this._shaderDependencies = shaderDependencies;
+ this._colorShaderDependencies = colorShaderDependencies;
+ this._pickShaderDependencies = pickShaderDependencies;
this._appearance = appearance;
this._extentsCulling = extentsCulling;
this._planarExtents = planarExtents;
@@ -79,372 +85,154 @@ define([
* Create the fragment shader for a ClassificationPrimitive's color pass when rendering for color.
*
* @param {Boolean} columbusView2D Whether the shader will be used for Columbus View or 2D.
- * @returns {String} Shader source for the fragment shader including its material.
+ * @returns {ShaderSource} Shader source for the fragment shader.
*/
- ShadowVolumeAppearance.prototype.createAppearanceFragmentShader = function(columbusView2D) {
+ ShadowVolumeAppearance.prototype.createFragmentShader = function(columbusView2D) {
//>>includeStart('debug', pragmas.debug);
Check.typeOf.bool('columbusView2D', columbusView2D);
//>>includeEnd('debug');
var appearance = this._appearance;
- var materialHookups = createShadowVolumeAppearanceFS(this._shaderDependencies, appearance, this._extentsCulling, this._planarExtents || columbusView2D);
- if (appearance instanceof PerInstanceColorAppearance) {
- return materialHookups;
- }
- return appearance.material.shaderSource + '\n' + materialHookups;
- };
+ var dependencies = this._colorShaderDependencies;
- /**
- * Create the fragment shader for a ClassificationPrimitive's color pass when rendering for pick.
- *
- * @param {Boolean} columbusView2D Whether the shader will be used for Columbus View or 2D.
- * @returns {String} Shader source for the fragment shader.
- */
- ShadowVolumeAppearance.prototype.createPickingFragmentShader = function(columbusView2D) {
- //>>includeStart('debug', pragmas.debug);
- Check.typeOf.bool('columbusView2D', columbusView2D);
- //>>includeEnd('debug');
-
- return getPickShaderFS(this._extentsCulling, this._planarExtents || columbusView2D);
- };
-
- /**
- * Create the vertex shader for a ClassificationPrimitive's color pass, both when rendering for color and for pick.
- *
- * @param {String} vertexShaderSource Vertex shader source.
- * @param {Boolean} columbusView2D Whether the shader will be used for Columbus View or 2D.
- * @returns {String} Shader source for the vertex shader.
- */
- ShadowVolumeAppearance.prototype.createVertexShader = function(vertexShaderSource, columbusView2D) {
- //>>includeStart('debug', pragmas.debug);
- Check.typeOf.string('vertexShaderSource', vertexShaderSource);
- Check.typeOf.bool('columbusView2D', columbusView2D);
- //>>includeEnd('debug');
-
- return createShadowVolumeAppearanceVS(this._shaderDependencies, this._appearance, this._planarExtents, columbusView2D, vertexShaderSource);
- };
-
- function createShadowVolumeAppearanceFS(shaderDependencies, appearance, extentsCull, planarExtents) {
- if (appearance instanceof PerInstanceColorAppearance) {
- return getPerInstanceColorShaderFS(shaderDependencies, extentsCull, appearance.flat, planarExtents);
+ var defines = [];
+ if (!columbusView2D && !this._planarExtents) {
+ defines.push('SPHERICAL');
}
-
- var usesNormalEC = shaderDependencies.normalEC;
- var usesPositionToEyeEC = shaderDependencies.positionToEyeEC;
- var usesTangentToEyeMat = shaderDependencies.tangentToEyeMatrix;
- var usesSt = shaderDependencies.st;
-
- var glsl =
- '#ifdef GL_EXT_frag_depth\n' +
- '#extension GL_EXT_frag_depth : enable\n' +
- '#endif\n';
- if (extentsCull || usesSt) {
- glsl += planarExtents ?
- 'varying vec2 v_inversePlaneExtents;\n' +
- 'varying vec4 v_westPlane;\n' +
- 'varying vec4 v_southPlane;\n' :
-
- 'varying vec4 v_sphericalExtents;\n';
+ if (dependencies.requiresEC) {
+ defines.push('REQUIRES_EC');
}
- if (usesSt) {
- glsl +=
- 'varying vec4 v_stSineCosineUVScale;\n';
+ if (dependencies.requiresWC) {
+ defines.push('REQUIRES_WC');
}
-
- // Get local functions
- glsl += getLocalFunctionsFS(shaderDependencies, planarExtents);
-
- glsl +=
- 'void main(void)\n' +
- '{\n';
-
- // Compute material input stuff and cull if outside texture coordinate extents
- glsl += getDependenciesAndCullingFS(shaderDependencies, extentsCull, planarExtents);
-
- glsl += ' czm_materialInput materialInput;\n';
- if (usesNormalEC) {
- glsl += ' materialInput.normalEC = normalEC;\n';
+ if (dependencies.requiresTextureCoordinates) {
+ defines.push('TEXTURE_COORDINATES');
}
- if (usesPositionToEyeEC) {
- glsl += ' materialInput.positionToEyeEC = -eyeCoordinate.xyz;\n';
+ if (this._extentsCulling) {
+ defines.push('CULL_FRAGMENTS');
}
- if (usesTangentToEyeMat) {
- glsl += ' materialInput.tangentToEyeMatrix = czm_eastNorthUpToEyeCoordinates(worldCoordinate, normalEC);\n';
+ if (dependencies.requiresNormalEC) {
+ defines.push('NORMAL_EC');
}
- if (usesSt) {
- // Scale texture coordinates and rotate around 0.5, 0.5
- glsl +=
- ' materialInput.st.x = v_stSineCosineUVScale.y * (v - 0.5) * v_stSineCosineUVScale.z + v_stSineCosineUVScale.x * (u - 0.5) * v_stSineCosineUVScale.w + 0.5;\n' +
- ' materialInput.st.y = v_stSineCosineUVScale.y * (u - 0.5) * v_stSineCosineUVScale.w - v_stSineCosineUVScale.x * (v - 0.5) * v_stSineCosineUVScale.z + 0.5;\n';
+ if (appearance instanceof PerInstanceColorAppearance) {
+ defines.push('PER_INSTANCE_COLOR');
}
- glsl += ' czm_material material = czm_getMaterial(materialInput);\n';
- if (appearance.flat) {
- glsl += ' gl_FragColor = vec4(material.diffuse + material.emission, material.alpha);\n';
- } else {
- glsl += ' gl_FragColor = czm_phong(normalize(-eyeCoordinate.xyz), material);\n';
+ // Material inputs. Use of parameters in the material is different
+ // from requirement of the parameters in the overall shader, for example,
+ // texture coordinates may be used for fragment culling but not for the material itself.
+ if (dependencies.normalEC) {
+ defines.push('USES_NORMAL_EC');
}
- glsl += ' czm_writeDepthClampedToFarPlane();\n';
- glsl += '}\n';
- return glsl;
- }
-
- var pickingShaderDependenciesScratch = new ShaderDependencies();
- function getPickShaderFS(extentsCulling, planarExtents) {
- var glsl =
- '#ifdef GL_EXT_frag_depth\n' +
- '#extension GL_EXT_frag_depth : enable\n' +
- '#endif\n';
- if (extentsCulling) {
- glsl += planarExtents ?
- 'varying vec2 v_inversePlaneExtents;\n' +
- 'varying vec4 v_westPlane;\n' +
- 'varying vec4 v_southPlane;\n' :
-
- 'varying vec4 v_sphericalExtents;\n';
+ if (dependencies.positionToEyeEC) {
+ defines.push('USES_POSITION_TO_EYE_EC');
+ }
+ if (dependencies.tangentToEyeMatrix) {
+ defines.push('USES_TANGENT_TO_EYE');
+ }
+ if (dependencies.st) {
+ defines.push('USES_ST');
}
- var shaderDependencies = pickingShaderDependenciesScratch;
- shaderDependencies.reset();
- shaderDependencies.requiresTextureCoordinates = extentsCulling;
- shaderDependencies.requiresNormalEC = false;
-
- glsl += getLocalFunctionsFS(shaderDependencies, planarExtents);
-
- glsl += 'void main(void)\n' +
- '{\n';
- glsl += ' bool culled = false;\n';
- var outOfBoundsSnippet =
- ' culled = true;\n';
- glsl += getDependenciesAndCullingFS(shaderDependencies, extentsCulling, planarExtents, outOfBoundsSnippet);
- glsl += ' if (!culled) {\n' +
- ' gl_FragColor.a = 1.0;\n' + // 0.0 alpha leads to discard from ShaderSource.createPickFragmentShaderSource
- ' czm_writeDepthClampedToFarPlane();\n' +
- ' }\n' +
- '}\n';
- return glsl;
- }
- function getPerInstanceColorShaderFS(shaderDependencies, extentsCulling, flatShading, planarExtents) {
- var glsl =
- '#ifdef GL_EXT_frag_depth\n' +
- '#extension GL_EXT_frag_depth : enable\n' +
- '#endif\n' +
- 'varying vec4 v_color;\n';
- if (extentsCulling) {
- glsl += planarExtents ?
- 'varying vec2 v_inversePlaneExtents;\n' +
- 'varying vec4 v_westPlane;\n' +
- 'varying vec4 v_southPlane;\n' :
-
- 'varying vec4 v_sphericalExtents;\n';
+ if (appearance.flat) {
+ defines.push('FLAT');
}
- glsl += getLocalFunctionsFS(shaderDependencies, planarExtents);
+ var materialSource = '';
+ if (!(appearance instanceof PerInstanceColorAppearance)) {
+ materialSource = appearance.material.shaderSource;
+ }
- glsl += 'void main(void)\n' +
- '{\n';
+ return new ShaderSource({
+ defines : defines,
+ sources : [materialSource, ShadowVolumeAppearanceFS]
+ });
+ };
- glsl += getDependenciesAndCullingFS(shaderDependencies, extentsCulling, planarExtents);
+ ShadowVolumeAppearance.prototype.createPickFragmentShader = function(columbusView2D) {
+ //>>includeStart('debug', pragmas.debug);
+ Check.typeOf.bool('columbusView2D', columbusView2D);
+ //>>includeEnd('debug');
- if (flatShading) {
- glsl +=
- ' gl_FragColor = v_color;\n';
- } else {
- glsl +=
- ' czm_materialInput materialInput;\n' +
- ' materialInput.normalEC = normalEC;\n' +
- ' materialInput.positionToEyeEC = -eyeCoordinate.xyz;\n' +
- ' czm_material material = czm_getDefaultMaterial(materialInput);\n' +
- ' material.diffuse = v_color.rgb;\n' +
- ' material.alpha = v_color.a;\n' +
-
- ' gl_FragColor = czm_phong(normalize(-eyeCoordinate.xyz), material);\n';
- }
- glsl += ' czm_writeDepthClampedToFarPlane();\n';
- glsl += '}\n';
- return glsl;
- }
+ var dependencies = this._pickShaderDependencies;
- function getDependenciesAndCullingFS(shaderDependencies, extentsCulling, planarExtents, outOfBoundsSnippet) {
- var glsl = '';
- if (shaderDependencies.requiresEC) {
- glsl +=
- ' vec4 eyeCoordinate = getEyeCoordinate(gl_FragCoord.xy);\n';
+ var defines = ['PICK'];
+ if (!columbusView2D && !this._planarExtents) {
+ defines.push('SPHERICAL');
}
- if (shaderDependencies.requiresWC) {
- glsl +=
- ' vec4 worldCoordinate4 = czm_inverseView * eyeCoordinate;\n' +
- ' vec3 worldCoordinate = worldCoordinate4.xyz / worldCoordinate4.w;\n';
+ if (dependencies.requiresEC) {
+ defines.push('REQUIRES_EC');
}
- if (shaderDependencies.requiresTextureCoordinates) {
- if (planarExtents) {
- glsl +=
- ' // Unpack planes and transform to eye space\n' +
- ' float u = computePlanarTextureCoordinates(v_southPlane, eyeCoordinate.xyz / eyeCoordinate.w, v_inversePlaneExtents.y);\n' +
- ' float v = computePlanarTextureCoordinates(v_westPlane, eyeCoordinate.xyz / eyeCoordinate.w, v_inversePlaneExtents.x);\n';
- } else {
- glsl +=
- ' // Treat world coords as a sphere normal for spherical coordinates\n' +
- ' vec2 sphericalLatLong = czm_approximateSphericalCoordinates(worldCoordinate);\n' +
- ' float u = (sphericalLatLong.x - v_sphericalExtents.x) * v_sphericalExtents.z;\n' +
- ' float v = (sphericalLatLong.y - v_sphericalExtents.y) * v_sphericalExtents.w;\n';
- }
+ if (dependencies.requiresWC) {
+ defines.push('REQUIRES_WC');
}
- if (extentsCulling) {
- if (!defined(outOfBoundsSnippet)) {
- outOfBoundsSnippet =
- ' discard;\n';
- }
- glsl +=
- ' if (u <= 0.0 || 1.0 <= u || v <= 0.0 || 1.0 <= v) {\n' +
- outOfBoundsSnippet +
- ' }\n';
+ if (dependencies.requiresTextureCoordinates) {
+ defines.push('TEXTURE_COORDINATES');
}
- // Lots of texture access, so lookup after discard check
- if (shaderDependencies.requiresNormalEC) {
- glsl +=
- ' // compute normal. sample adjacent pixels in 2x2 block in screen space\n' +
- ' vec3 downUp = getVectorFromOffset(eyeCoordinate, gl_FragCoord.xy, vec2(0.0, 1.0));\n' +
- ' vec3 leftRight = getVectorFromOffset(eyeCoordinate, gl_FragCoord.xy, vec2(1.0, 0.0));\n' +
- ' vec3 normalEC = normalize(cross(leftRight, downUp));\n' +
- '\n';
- }
- return glsl;
- }
-
- function getLocalFunctionsFS(shaderDependencies, planarExtents) {
- var glsl = '';
- if (shaderDependencies.requiresEC || shaderDependencies.requiresNormalEC) {
- glsl +=
- 'vec4 windowToEyeCoordinates(vec2 xy, float depthOrLogDepth) {\n' +
- // See reverseLogDepth.glsl. This is separate to re-use the pow.
- '#ifdef LOG_DEPTH\n' +
- ' float near = czm_currentFrustum.x;\n' +
- ' float far = czm_currentFrustum.y;\n' +
- ' float unscaledDepth = pow(2.0, depthOrLogDepth * czm_log2FarPlusOne) - 1.0;\n' +
- ' vec4 windowCoord = vec4(xy, far * (1.0 - near / unscaledDepth) / (far - near), 1.0);\n' +
- ' vec4 eyeCoordinate = czm_windowToEyeCoordinates(windowCoord);\n' +
- ' eyeCoordinate.w = 1.0 / unscaledDepth;\n' + // Better precision
- '#else\n' +
- ' vec4 windowCoord = vec4(xy, depthOrLogDepth, 1.0);\n' +
- ' vec4 eyeCoordinate = czm_windowToEyeCoordinates(windowCoord);\n' +
- '#endif\n' +
- ' return eyeCoordinate;\n' +
- '}\n';
+ if (this._extentsCulling) {
+ defines.push('CULL_FRAGMENTS');
}
- if (shaderDependencies.requiresEC) {
- glsl +=
- 'vec4 getEyeCoordinate(vec2 fragCoord) {\n' +
- ' vec2 coords = fragCoord / czm_viewport.zw;\n' +
- ' float logDepthOrDepth = czm_unpackDepth(texture2D(czm_globeDepthTexture, coords));\n' +
- ' return windowToEyeCoordinates(fragCoord, logDepthOrDepth);\n' +
- '}\n';
- }
- if (shaderDependencies.requiresNormalEC) {
- glsl +=
- 'vec3 getEyeCoordinate3FromWindowCoordinate(vec2 fragCoord, float logDepthOrDepth) {\n' +
- ' vec4 eyeCoordinate = windowToEyeCoordinates(fragCoord, logDepthOrDepth);\n' +
- ' return eyeCoordinate.xyz / eyeCoordinate.w;\n' +
- '}\n' +
-
- 'vec3 getVectorFromOffset(vec4 eyeCoordinate, vec2 glFragCoordXY, vec2 positiveOffset) {\n' +
- ' // Sample depths at both offset and negative offset\n' +
- ' float upOrRightLogDepth = czm_unpackDepth(texture2D(czm_globeDepthTexture, (glFragCoordXY + positiveOffset) / czm_viewport.zw));\n' +
- ' float downOrLeftLogDepth = czm_unpackDepth(texture2D(czm_globeDepthTexture, (glFragCoordXY - positiveOffset) / czm_viewport.zw));\n' +
- ' // Explicitly evaluate both paths\n' + // Necessary for multifrustum and for GroundPrimitives at the edges of the screen
- ' bvec2 upOrRightInBounds = lessThan(glFragCoordXY + positiveOffset, czm_viewport.zw);\n' +
- ' float useUpOrRight = float(upOrRightLogDepth > 0.0 && upOrRightInBounds.x && upOrRightInBounds.y);\n' +
- ' float useDownOrLeft = float(useUpOrRight == 0.0);\n' +
- ' vec3 upOrRightEC = getEyeCoordinate3FromWindowCoordinate(glFragCoordXY + positiveOffset, upOrRightLogDepth);\n' +
- ' vec3 downOrLeftEC = getEyeCoordinate3FromWindowCoordinate(glFragCoordXY - positiveOffset, downOrLeftLogDepth);\n' +
-
- ' return (upOrRightEC - (eyeCoordinate.xyz / eyeCoordinate.w)) * useUpOrRight + ((eyeCoordinate.xyz / eyeCoordinate.w) - downOrLeftEC) * useDownOrLeft;\n' +
- '}\n';
- }
- if (shaderDependencies.requiresTextureCoordinates && planarExtents) {
- glsl +=
- 'float computePlanarTextureCoordinates(vec4 plane, vec3 eyeCoordinates, float inverseExtent) {\n' +
- ' return (dot(plane.xyz, eyeCoordinates) + plane.w) * inverseExtent;\n' +
- '}\n';
- }
- return glsl;
- }
+ return new ShaderSource({
+ defines : defines,
+ sources : [ShadowVolumeAppearanceFS],
+ pickColorQualifier : 'varying'
+ });
+ };
- function createShadowVolumeAppearanceVS(shaderDependencies, appearance, planarExtents, columbusView2D, shadowVolumeVS) {
- var glsl = ShaderSource.replaceMain(shadowVolumeVS, 'computePosition');
+ /**
+ * Create the vertex shader for a ClassificationPrimitive's color pass on the final of 3 shadow volume passes
+ *
+ * @param {String[]} defines External defines to pass to the vertex shader.
+ * @param {String} vertexShaderSource ShadowVolumeAppearanceVS with any required modifications for computing position.
+ * @param {Boolean} columbusView2D Whether the shader will be used for Columbus View or 2D.
+ * @returns {String} Shader source for the vertex shader.
+ */
+ ShadowVolumeAppearance.prototype.createVertexShader = function(defines, vertexShaderSource, columbusView2D) {
+ //>>includeStart('debug', pragmas.debug);
+ Check.defined('defines', defines);
+ Check.typeOf.string('vertexShaderSource', vertexShaderSource);
+ Check.typeOf.bool('columbusView2D', columbusView2D);
+ //>>includeEnd('debug');
+ return createShadowVolumeAppearanceVS(this._colorShaderDependencies, this._planarExtents, columbusView2D, defines, vertexShaderSource, this._appearance);
+ };
- var isPerInstanceColor = defined(appearance) && appearance instanceof PerInstanceColorAppearance;
- if (isPerInstanceColor) {
- glsl += 'varying vec4 v_color;\n';
- }
+ /**
+ * Create the vertex shader for a ClassificationPrimitive's pick pass on the final of 3 shadow volume passes
+ *
+ * @param {String[]} defines External defines to pass to the vertex shader.
+ * @param {String} vertexShaderSource ShadowVolumeAppearanceVS with any required modifications for computing position and picking.
+ * @param {Boolean} columbusView2D Whether the shader will be used for Columbus View or 2D.
+ * @returns {String} Shader source for the vertex shader.
+ */
+ ShadowVolumeAppearance.prototype.createPickVertexShader = function(defines, vertexShaderSource, columbusView2D) {
+ //>>includeStart('debug', pragmas.debug);
+ Check.defined('defines', defines);
+ Check.typeOf.string('vertexShaderSource', vertexShaderSource);
+ Check.typeOf.bool('columbusView2D', columbusView2D);
+ //>>includeEnd('debug');
+ return createShadowVolumeAppearanceVS(this._pickShaderDependencies, this._planarExtents, columbusView2D, defines, vertexShaderSource);
+ };
- var spherical = !(planarExtents || columbusView2D);
- if (shaderDependencies.requiresTextureCoordinates) {
- if (spherical) {
- glsl +=
- 'varying vec4 v_sphericalExtents;\n' +
- 'varying vec4 v_stSineCosineUVScale;\n';
- } else {
- glsl +=
- 'varying vec2 v_inversePlaneExtents;\n' +
- 'varying vec4 v_westPlane;\n' +
- 'varying vec4 v_southPlane;\n' +
- 'varying vec4 v_stSineCosineUVScale;\n';
- }
- }
+ function createShadowVolumeAppearanceVS(shaderDependencies, planarExtents, columbusView2D, defines, vertexShaderSource, appearance) {
+ var allDefines = defines.slice();
- glsl +=
- 'void main()\n' +
- '{\n' +
- ' computePosition();\n';
- if (isPerInstanceColor) {
- glsl += 'v_color = czm_batchTable_color(batchId);\n';
+ if (defined(appearance) && appearance instanceof PerInstanceColorAppearance) {
+ allDefines.push('PER_INSTANCE_COLOR');
}
-
- // Add code for computing texture coordinate dependencies
if (shaderDependencies.requiresTextureCoordinates) {
- if (spherical) {
- glsl +=
- 'v_sphericalExtents = czm_batchTable_sphericalExtents(batchId);\n' +
- 'v_stSineCosineUVScale = czm_batchTable_stSineCosineUVScale(batchId);\n';
- } else {
- // Two varieties of planar texcoords
- if (columbusView2D) {
- // 2D/CV case may have very large "plane extents," so planes and distances encoded as 3 64 bit positions,
- // which in 2D can be encoded as 2 64 bit vec2s
- glsl +=
- 'vec4 planes2D_high = czm_batchTable_planes2D_HIGH(batchId);\n' +
- 'vec4 planes2D_low = czm_batchTable_planes2D_LOW(batchId);\n' +
- 'vec3 southWestCorner = (czm_modelViewRelativeToEye * czm_translateRelativeToEye(vec3(0.0, planes2D_high.xy), vec3(0.0, planes2D_low.xy))).xyz;\n' +
- 'vec3 northWestCorner = (czm_modelViewRelativeToEye * czm_translateRelativeToEye(vec3(0.0, planes2D_high.x, planes2D_high.z), vec3(0.0, planes2D_low.x, planes2D_low.z))).xyz;\n' +
- '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;\n';
- } else {
- glsl +=
- // 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;\n' +
- 'vec3 northWestCorner = czm_normal * czm_batchTable_northward(batchId) + southWestCorner;\n' +
- 'vec3 southEastCorner = czm_normal * czm_batchTable_eastward(batchId) + southWestCorner;\n';
- }
- glsl +=
- 'vec3 eastWard = southEastCorner - southWestCorner;\n' +
- 'float eastExtent = length(eastWard);\n' +
- 'eastWard /= eastExtent;\n' +
-
- 'vec3 northWard = northWestCorner - southWestCorner;\n' +
- 'float northExtent = length(northWard);\n' +
- 'northWard /= northExtent;\n' +
-
- 'v_westPlane = vec4(eastWard, -dot(eastWard, southWestCorner));\n' +
- 'v_southPlane = vec4(northWard, -dot(northWard, southWestCorner));\n' +
- 'v_inversePlaneExtents = vec2(1.0 / eastExtent, 1.0 / northExtent);\n' +
- 'v_stSineCosineUVScale = czm_batchTable_stSineCosineUVScale(batchId);\n';
+ allDefines.push('TEXTURE_COORDINATES');
+ if (!(planarExtents || columbusView2D)) {
+ allDefines.push('SPHERICAL');
+ }
+ if (columbusView2D) {
+ allDefines.push('COLUMBUS_VIEW_2D');
}
}
- glsl +=
- '}\n';
-
- return glsl;
+ return new ShaderSource({
+ defines : allDefines,
+ sources : [vertexShaderSource]
+ });
}
/**
@@ -463,18 +251,6 @@ define([
this._usesSt = false;
}
- ShaderDependencies.prototype.reset = function() {
- this._requiresEC = false;
- this._requiresWC = false;
- this._requiresNormalEC = false;
- this._requiresTextureCoordinates = false;
-
- this._usesNormalEC = false;
- this._usesPositionToEyeEC = false;
- this._usesTangentToEyeMat = false;
- this._usesSt = false;
- };
-
defineProperties(ShaderDependencies.prototype, {
// Set when assessing final shading (flat vs. phong) and culling using computed texture coordinates
requiresEC : {
@@ -622,7 +398,8 @@ define([
}
// Depending on the rotation, east/west may be more appropriate for vertical scale than horizontal
- var scaleU, scaleV;
+ var scaleU = 1.0;
+ var scaleV = 1.0;
if (Math.abs(sinTheta) < Math.abs(cosTheta)) {
scaleU = eastWestHalfDistance / ((max2D.x - min2D.x) * 0.5);
scaleV = northSouthHalfDistance / ((max2D.y - min2D.y) * 0.5);
diff --git a/Source/Scene/Vector3DTilePrimitive.js b/Source/Scene/Vector3DTilePrimitive.js
index 112035c9110..b9cbb67804b 100644
--- a/Source/Scene/Vector3DTilePrimitive.js
+++ b/Source/Scene/Vector3DTilePrimitive.js
@@ -18,7 +18,7 @@ define([
'../Renderer/ShaderSource',
'../Renderer/VertexArray',
'../Shaders/ShadowVolumeFS',
- '../Shaders/ShadowVolumeVS',
+ '../Shaders/VectorTileVS',
'./BlendingState',
'./Cesium3DTileFeature',
'./ClassificationType',
@@ -47,7 +47,7 @@ define([
ShaderSource,
VertexArray,
ShadowVolumeFS,
- ShadowVolumeVS,
+ VectorTileVS,
BlendingState,
Cesium3DTileFeature,
ClassificationType,
@@ -297,11 +297,10 @@ define([
return;
}
- var vsSource = batchTable.getVertexShaderCallback(false, 'a_batchId', undefined)(ShadowVolumeVS);
+ var vsSource = batchTable.getVertexShaderCallback(false, 'a_batchId', undefined)(VectorTileVS);
var fsSource = batchTable.getFragmentShaderCallback()(ShadowVolumeFS, false, undefined);
var vs = new ShaderSource({
- defines : ['VECTOR_TILE'],
sources : [vsSource]
});
var fs = new ShaderSource({
@@ -317,8 +316,7 @@ define([
});
vs = new ShaderSource({
- defines : ['VECTOR_TILE'],
- sources : [ShadowVolumeVS]
+ sources : [VectorTileVS]
});
fs = new ShaderSource({
defines : ['VECTOR_TILE'],
@@ -332,11 +330,10 @@ define([
attributeLocations : attributeLocations
});
- vsSource = batchTable.getPickVertexShaderCallbackIgnoreShow('a_batchId')(ShadowVolumeVS);
+ vsSource = batchTable.getPickVertexShaderCallbackIgnoreShow('a_batchId')(VectorTileVS);
fsSource = batchTable.getPickFragmentShaderCallbackIgnoreShow()(ShadowVolumeFS);
var pickVS = new ShaderSource({
- defines : ['VECTOR_TILE'],
sources : [vsSource]
});
var pickFS = new ShaderSource({
diff --git a/Source/Shaders/Builtin/Functions/planeDistance.glsl b/Source/Shaders/Builtin/Functions/planeDistance.glsl
new file mode 100644
index 00000000000..38db05a173c
--- /dev/null
+++ b/Source/Shaders/Builtin/Functions/planeDistance.glsl
@@ -0,0 +1,13 @@
+/**
+ * Computes distance from an point to a plane, typically in eye space.
+ *
+ * @name czm_planeDistance
+ * @glslFunction
+ *
+ * param {vec4} plane A Plane in Hessian Normal Form. See Plane.js
+ * param {vec3} point A point in the same space as the plane.
+ * returns {float} The distance from the point to the plane.
+ */
+float czm_planeDistance(vec4 plane, vec3 point) {
+ return (dot(plane.xyz, point) + plane.w);
+}
diff --git a/Source/Shaders/Builtin/Functions/windowToEyeCoordinates.glsl b/Source/Shaders/Builtin/Functions/windowToEyeCoordinates.glsl
index 91bd5e3164f..c95f4f04739 100644
--- a/Source/Shaders/Builtin/Functions/windowToEyeCoordinates.glsl
+++ b/Source/Shaders/Builtin/Functions/windowToEyeCoordinates.glsl
@@ -53,3 +53,40 @@ vec4 czm_windowToEyeCoordinates(vec4 fragmentCoordinate)
return q;
}
+
+/**
+ * Transforms a position given as window x/y and a depth or a log depth from window to eye coordinates.
+ * This function produces more accurate results for window positions with log depth than
+ * conventionally unpacking the log depth using czm_reverseLogDepth and using the standard version
+ * of czm_windowToEyeCoordinates.
+ *
+ * @name czm_windowToEyeCoordinates
+ * @glslFunction
+ *
+ * @param {vec2} fragmentCoordinateXY The XY position in window coordinates to transform.
+ * @param {float} depthOrLogDepth A depth or log depth for the fragment.
+ *
+ * @see czm_modelToWindowCoordinates
+ * @see czm_eyeToWindowCoordinates
+ * @see czm_inverseProjection
+ * @see czm_viewport
+ * @see czm_viewportTransformation
+ *
+ * @returns {vec4} The transformed position in eye coordinates.
+ */
+vec4 czm_windowToEyeCoordinates(vec2 fragmentCoordinateXY, float depthOrLogDepth)
+{
+ // See reverseLogDepth.glsl. This is separate to re-use the pow.
+#ifdef LOG_DEPTH
+ float near = czm_currentFrustum.x;
+ float far = czm_currentFrustum.y;
+ float unscaledDepth = pow(2.0, depthOrLogDepth * czm_log2FarPlusOne) - 1.0;
+ vec4 windowCoord = vec4(fragmentCoordinateXY, far * (1.0 - near / unscaledDepth) / (far - near), 1.0);
+ vec4 eyeCoordinate = czm_windowToEyeCoordinates(windowCoord);
+ eyeCoordinate.w = 1.0 / unscaledDepth;\n // Better precision
+#else
+ vec4 windowCoord = vec4(fragmentCoordinateXY, depthOrLogDepth, 1.0);
+ vec4 eyeCoordinate = czm_windowToEyeCoordinates(windowCoord);
+#endif
+ return eyeCoordinate;
+}
diff --git a/Source/Shaders/ShadowVolumeAppearanceFS.glsl b/Source/Shaders/ShadowVolumeAppearanceFS.glsl
new file mode 100644
index 00000000000..3d285759fde
--- /dev/null
+++ b/Source/Shaders/ShadowVolumeAppearanceFS.glsl
@@ -0,0 +1,143 @@
+#ifdef GL_EXT_frag_depth
+#extension GL_EXT_frag_depth : enable
+#endif
+
+#ifdef TEXTURE_COORDINATES
+#ifdef SPHERICAL
+varying vec4 v_sphericalExtents;
+#else // SPHERICAL
+varying vec2 v_inversePlaneExtents;
+varying vec4 v_westPlane;
+varying vec4 v_southPlane;
+#endif // SPHERICAL
+varying vec4 v_stSineCosineUVScale;
+#endif // TEXTURE_COORDINATES
+
+#ifdef PER_INSTANCE_COLOR
+varying vec4 v_color;
+#endif
+
+#ifdef NORMAL_EC
+vec3 getEyeCoordinate3FromWindowCoordinate(vec2 fragCoord, float logDepthOrDepth) {
+ vec4 eyeCoordinate = czm_windowToEyeCoordinates(fragCoord, logDepthOrDepth);
+ return eyeCoordinate.xyz / eyeCoordinate.w;
+}
+
+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));
+ float downOrLeftLogDepth = czm_unpackDepth(texture2D(czm_globeDepthTexture, (glFragCoordXY - positiveOffset) / czm_viewport.zw));
+ // Explicitly evaluate both paths
+ // Necessary for multifrustum and for edges of the screen
+ bvec2 upOrRightInBounds = lessThan(glFragCoordXY + positiveOffset, czm_viewport.zw);
+ float useUpOrRight = float(upOrRightLogDepth > 0.0 && upOrRightInBounds.x && upOrRightInBounds.y);
+ float useDownOrLeft = float(useUpOrRight == 0.0);
+ vec3 upOrRightEC = getEyeCoordinate3FromWindowCoordinate(glFragCoordXY + positiveOffset, upOrRightLogDepth);
+ vec3 downOrLeftEC = getEyeCoordinate3FromWindowCoordinate(glFragCoordXY - positiveOffset, downOrLeftLogDepth);
+ return (upOrRightEC - (eyeCoordinate.xyz / eyeCoordinate.w)) * useUpOrRight + ((eyeCoordinate.xyz / eyeCoordinate.w) - downOrLeftEC) * useDownOrLeft;
+}
+#endif // NORMAL_EC
+
+void main(void)
+{
+#ifdef REQUIRES_EC
+ float logDepthOrDepth = czm_unpackDepth(texture2D(czm_globeDepthTexture, gl_FragCoord.xy / czm_viewport.zw));
+ vec4 eyeCoordinate = czm_windowToEyeCoordinates(gl_FragCoord.xy, logDepthOrDepth);
+#endif
+
+#ifdef REQUIRES_WC
+ vec4 worldCoordinate4 = czm_inverseView * eyeCoordinate;
+ vec3 worldCoordinate = worldCoordinate4.xyz / worldCoordinate4.w;
+#endif
+
+#ifdef TEXTURE_COORDINATES
+#ifdef SPHERICAL
+ // Treat world coords as a sphere normal for spherical coordinates
+ vec2 sphericalLatLong = czm_approximateSphericalCoordinates(worldCoordinate);
+ float u = (sphericalLatLong.x - v_sphericalExtents.x) * v_sphericalExtents.z;
+ float v = (sphericalLatLong.y - v_sphericalExtents.y) * v_sphericalExtents.w;
+#else // SPHERICAL
+ // Unpack planes and transform to eye space
+ float u = czm_planeDistance(v_southPlane, eyeCoordinate.xyz / eyeCoordinate.w) * v_inversePlaneExtents.y;
+ float v = czm_planeDistance(v_westPlane, eyeCoordinate.xyz / eyeCoordinate.w) * v_inversePlaneExtents.x;
+#endif // SPHERICAL
+#endif // TEXTURE_COORDINATES
+
+#ifdef PICK
+#ifdef CULL_FRAGMENTS
+ if (0.0 <= u && u <= 1.0 && 0.0 <= v && v <= 1.0) {
+ gl_FragColor.a = 1.0; // 0.0 alpha leads to discard from ShaderSource.createPickFragmentShaderSource
+ czm_writeDepthClampedToFarPlane();
+ }
+#else // CULL_FRAGMENTS
+ gl_FragColor.a = 1.0;
+#endif // CULL_FRAGMENTS
+#else // PICK
+
+#ifdef CULL_FRAGMENTS
+ if (u <= 0.0 || 1.0 <= u || v <= 0.0 || 1.0 <= v) {
+ discard;
+ }
+#endif
+
+#ifdef NORMAL_EC
+ // Compute normal by sampling adjacent pixels in 2x2 block in screen space
+ vec3 downUp = vectorFromOffset(eyeCoordinate, vec2(0.0, 1.0));
+ vec3 leftRight = vectorFromOffset(eyeCoordinate, vec2(1.0, 0.0));
+ vec3 normalEC = normalize(cross(leftRight, downUp));
+#endif
+
+
+#ifdef PER_INSTANCE_COLOR
+
+#ifdef FLAT
+ gl_FragColor = v_color;
+#else // FLAT
+ czm_materialInput materialInput;
+ materialInput.normalEC = normalEC;
+ materialInput.positionToEyeEC = -eyeCoordinate.xyz;
+ czm_material material = czm_getDefaultMaterial(materialInput);
+ material.diffuse = v_color.rgb;
+ material.alpha = v_color.a;
+
+ gl_FragColor = czm_phong(normalize(-eyeCoordinate.xyz), material);
+#endif // FLAT
+
+#else // PER_INSTANCE_COLOR
+
+// Material support.
+// USES_ is distinct from REQUIRES_, because some things are dependencies of each other or
+// dependencies for culling but might not actually be used by the material.
+
+ czm_materialInput materialInput;
+
+#ifdef USES_NORMAL_EC
+ materialInput.normalEC = normalEC;
+#endif
+
+#ifdef USES_POSITION_TO_EYE_EC
+ materialInput.positionToEyeEC = -eyeCoordinate.xyz;
+#endif
+
+#ifdef USES_TANGENT_TO_EYE
+ materialInput.tangentToEyeMatrix = czm_eastNorthUpToEyeCoordinates(worldCoordinate, normalEC);
+#endif
+
+#ifdef USES_ST
+ materialInput.st.x = v_stSineCosineUVScale.y * (v - 0.5) * v_stSineCosineUVScale.z + v_stSineCosineUVScale.x * (u - 0.5) * v_stSineCosineUVScale.w + 0.5;
+ materialInput.st.y = v_stSineCosineUVScale.y * (u - 0.5) * v_stSineCosineUVScale.w - v_stSineCosineUVScale.x * (v - 0.5) * v_stSineCosineUVScale.z + 0.5;
+#endif
+
+ czm_material material = czm_getMaterial(materialInput);
+
+#ifdef FLAT
+ gl_FragColor = vec4(material.diffuse + material.emission, material.alpha);
+#else // FLAT
+ gl_FragColor = czm_phong(normalize(-eyeCoordinate.xyz), material);
+#endif // FLAT
+
+#endif // PER_INSTANCE_COLOR
+ czm_writeDepthClampedToFarPlane();
+#endif // PICK
+}
diff --git a/Source/Shaders/ShadowVolumeAppearanceVS.glsl b/Source/Shaders/ShadowVolumeAppearanceVS.glsl
new file mode 100644
index 00000000000..74f4dfca525
--- /dev/null
+++ b/Source/Shaders/ShadowVolumeAppearanceVS.glsl
@@ -0,0 +1,76 @@
+attribute vec3 position3DHigh;
+attribute vec3 position3DLow;
+attribute float batchId;
+
+#ifdef EXTRUDED_GEOMETRY
+attribute vec3 extrudeDirection;
+
+uniform float u_globeMinimumAltitude;
+#endif // EXTRUDED_GEOMETRY
+
+#ifdef PER_INSTANCE_COLOR
+varying vec4 v_color;
+#endif // PER_INSTANCE_COLOR
+
+#ifdef TEXTURE_COORDINATES
+#ifdef SPHERICAL
+varying vec4 v_sphericalExtents;
+#else // SPHERICAL
+varying vec2 v_inversePlaneExtents;
+varying vec4 v_westPlane;
+varying vec4 v_southPlane;
+#endif // SPHERICAL
+varying vec4 v_stSineCosineUVScale;
+#endif // TEXTURE_COORDINATES
+
+void main()
+{
+ vec4 position = czm_computePosition();
+
+#ifdef EXTRUDED_GEOMETRY
+ float delta = min(u_globeMinimumAltitude, czm_geometricToleranceOverMeter * length(position.xyz));
+ delta *= czm_sceneMode == czm_sceneMode3D ? 1.0 : 0.0;
+
+ //extrudeDirection is zero for the top layer
+ position = position + vec4(extrudeDirection * delta, 0.0);
+#endif
+
+#ifdef TEXTURE_COORDINATES
+#ifdef SPHERICAL
+ v_sphericalExtents = czm_batchTable_sphericalExtents(batchId);
+ v_stSineCosineUVScale = czm_batchTable_stSineCosineUVScale(batchId);
+#else // SPHERICAL
+#ifdef COLUMBUS_VIEW_2D
+ vec4 planes2D_high = czm_batchTable_planes2D_HIGH(batchId);
+ vec4 planes2D_low = czm_batchTable_planes2D_LOW(batchId);
+ vec3 southWestCorner = (czm_modelViewRelativeToEye * czm_translateRelativeToEye(vec3(0.0, planes2D_high.xy), vec3(0.0, planes2D_low.xy))).xyz;
+ vec3 northWestCorner = (czm_modelViewRelativeToEye * czm_translateRelativeToEye(vec3(0.0, planes2D_high.x, planes2D_high.z), vec3(0.0, planes2D_low.x, planes2D_low.z))).xyz;
+ vec3 southEastCorner = (czm_modelViewRelativeToEye * czm_translateRelativeToEye(vec3(0.0, planes2D_high.w, planes2D_high.y), vec3(0.0, planes2D_low.w, planes2D_low.y))).xyz;
+#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;
+#endif // COLUMBUS_VIEW_2D
+
+ vec3 eastWard = southEastCorner - southWestCorner;
+ float eastExtent = length(eastWard);
+ eastWard /= eastExtent;
+
+ vec3 northWard = northWestCorner - southWestCorner;
+ float northExtent = length(northWard);
+ northWard /= northExtent;
+
+ v_westPlane = vec4(eastWard, -dot(eastWard, southWestCorner));
+ v_southPlane = vec4(northWard, -dot(northWard, southWestCorner));
+ v_inversePlaneExtents = vec2(1.0 / eastExtent, 1.0 / northExtent);
+#endif // SPHERICAL
+ v_stSineCosineUVScale = czm_batchTable_stSineCosineUVScale(batchId);
+#endif // TEXTURE_COORDINATES
+
+#ifdef PER_INSTANCE_COLOR
+ v_color = czm_batchTable_color(batchId);
+#endif
+
+ gl_Position = czm_depthClampFarPlane(czm_modelViewProjectionRelativeToEye * position);
+}
diff --git a/Source/Shaders/ShadowVolumeVS.glsl b/Source/Shaders/ShadowVolumeVS.glsl
deleted file mode 100644
index 33554d4f3f5..00000000000
--- a/Source/Shaders/ShadowVolumeVS.glsl
+++ /dev/null
@@ -1,34 +0,0 @@
-#ifdef VECTOR_TILE
-attribute vec3 position;
-attribute float a_batchId;
-
-uniform mat4 u_modifiedModelViewProjection;
-#else
-attribute vec3 position3DHigh;
-attribute vec3 position3DLow;
-attribute float batchId;
-#endif
-
-#ifdef EXTRUDED_GEOMETRY
-attribute vec3 extrudeDirection;
-
-uniform float u_globeMinimumAltitude;
-#endif
-
-void main()
-{
-#ifdef VECTOR_TILE
- gl_Position = czm_depthClampFarPlane(u_modifiedModelViewProjection * vec4(position, 1.0));
-#else
- vec4 position = czm_computePosition();
-
-#ifdef EXTRUDED_GEOMETRY
- float delta = min(u_globeMinimumAltitude, czm_geometricToleranceOverMeter * length(position.xyz));
- delta *= czm_sceneMode == czm_sceneMode3D ? 1.0 : 0.0;
-
- //extrudeDirection is zero for the top layer
- position = position + vec4(extrudeDirection * delta, 0.0);
-#endif
- gl_Position = czm_depthClampFarPlane(czm_modelViewProjectionRelativeToEye * position);
-#endif
-}
diff --git a/Source/Shaders/VectorTileVS.glsl b/Source/Shaders/VectorTileVS.glsl
new file mode 100644
index 00000000000..6c7a5278e8a
--- /dev/null
+++ b/Source/Shaders/VectorTileVS.glsl
@@ -0,0 +1,9 @@
+attribute vec3 position;
+attribute float a_batchId;
+
+uniform mat4 u_modifiedModelViewProjection;
+
+void main()
+{
+ gl_Position = czm_depthClampFarPlane(u_modifiedModelViewProjection * vec4(position, 1.0));
+}
diff --git a/Specs/Core/MathSpec.js b/Specs/Core/MathSpec.js
index d9d07607981..60876d81eef 100644
--- a/Specs/Core/MathSpec.js
+++ b/Specs/Core/MathSpec.js
@@ -462,4 +462,10 @@ defineSuite([
expect(CesiumMath.fastApproximateAtan2(1.0, 1.0)).toEqualEpsilon(CesiumMath.PI_OVER_FOUR, CesiumMath.EPSILON3);
expect(CesiumMath.fastApproximateAtan2(-1.0, 1.0)).toEqualEpsilon(CesiumMath.PI_OVER_FOUR + CesiumMath.PI_OVER_TWO, CesiumMath.EPSILON3);
});
+
+ it('fastApproximateAtan2 throws if both arguments are zero', function() {
+ expect(function() {
+ CesiumMath.fastApproximateAtan2(0, 0);
+ }).toThrowDeveloperError();
+ });
});
diff --git a/Specs/Renderer/BuiltinFunctionsSpec.js b/Specs/Renderer/BuiltinFunctionsSpec.js
index 4138cbfd93b..911a327440a 100644
--- a/Specs/Renderer/BuiltinFunctionsSpec.js
+++ b/Specs/Renderer/BuiltinFunctionsSpec.js
@@ -124,6 +124,37 @@ defineSuite([
context : context,
fragmentShader : fs
}).contextToRender();
+
+ fs =
+ 'void main() { ' +
+ ' float z = czm_projection[3][2] / czm_projection[2][2];' +
+ ' float x = z / czm_projection[0][0];' +
+ ' float y = z / czm_projection[1][1];' +
+ ' vec3 pointEC = vec3(x, y, z);' +
+ ' vec4 actual = czm_windowToEyeCoordinates(vec2(0.0, 0.0), 0.0);' +
+ ' vec3 diff = actual.xyz - pointEC;' +
+ ' gl_FragColor = vec4(all(lessThan(diff, vec3(czm_epsilon6))));' +
+ '}';
+
+ expect({
+ context : context,
+ fragmentShader : fs
+ }).contextToRender();
+ });
+
+ it('has czm_planeDistance', function() {
+ var fs =
+ 'void main() { ' +
+ ' vec4 plane = vec4(1.0, 0.0, 0.0, 0.0); ' +
+ ' vec3 point = vec3(1.0, 0.0, 0.0); ' +
+ ' float expected = 1.0; ' +
+ ' float actual = czm_planeDistance(plane, point); ' +
+ ' gl_FragColor = vec4(actual == expected); ' +
+ '}';
+ expect({
+ context : context,
+ fragmentShader : fs
+ }).contextToRender();
});
it('has czm_tangentToEyeSpaceMatrix', function() {
diff --git a/Specs/Scene/SceneSpec.js b/Specs/Scene/SceneSpec.js
index b83a9890fde..8291341509f 100644
--- a/Specs/Scene/SceneSpec.js
+++ b/Specs/Scene/SceneSpec.js
@@ -715,12 +715,6 @@ defineSuite([
var uniformState = scene.context.uniformState;
- scene.copyGlobeDepth = false;
- expect(scene).toRenderAndCall(function(rgba) {
- expect(uniformState.globeDepthTexture).not.toBeDefined();
- });
-
- scene.copyGlobeDepth = true;
expect(scene).toRenderAndCall(function(rgba) {
expect(uniformState.globeDepthTexture).toBeDefined();
});
diff --git a/Specs/Scene/ShadowVolumeAppearanceSpec.js b/Specs/Scene/ShadowVolumeAppearanceSpec.js
index ade4d308560..b2f9d3be195 100644
--- a/Specs/Scene/ShadowVolumeAppearanceSpec.js
+++ b/Specs/Scene/ShadowVolumeAppearanceSpec.js
@@ -28,7 +28,7 @@ defineSuite([
PerInstanceColorAppearance) {
'use strict';
- // using ShadowVolumeVS directly fails on Travis with the --release test
+ // using ShadowVolumeAppearanceVS directly fails on Travis with the --release test
var testVs =
'attribute vec3 position3DHigh;\n' +
'attribute vec3 position3DLow;\n' +
@@ -207,91 +207,167 @@ defineSuite([
expect(ShadowVolumeAppearance.shouldUseSphericalCoordinates(largeTestRectangle)).toBe(true);
});
- it('creates vertex shaders', function() {
- // Check for varying declarations and that they get set
+ it('creates vertex shaders for color', function() {
+ // Check defines
var sphericalTexturedAppearance = new ShadowVolumeAppearance(true, false, textureMaterialAppearance);
- var sphericalTexturedVS3D = sphericalTexturedAppearance.createVertexShader(testVs, false);
- expect(sphericalTexturedVS3D.includes('varying vec4 v_sphericalExtents;')).toBe(true);
- expect(sphericalTexturedVS3D.includes('varying vec4 v_stSineCosineUVScale;')).toBe(true);
-
- expect(sphericalTexturedVS3D.includes('v_sphericalExtents =')).toBe(true);
- expect(sphericalTexturedVS3D.includes('v_stSineCosineUVScale =')).toBe(true);
-
- var sphericalTexturedVS2D = sphericalTexturedAppearance.createVertexShader(testVs, true);
- expect(sphericalTexturedVS2D.includes('varying vec2 v_inversePlaneExtents;')).toBe(true);
- expect(sphericalTexturedVS2D.includes('varying vec4 v_westPlane;')).toBe(true);
- expect(sphericalTexturedVS2D.includes('varying vec4 v_southPlane;')).toBe(true);
- expect(sphericalTexturedVS2D.includes('varying vec4 v_stSineCosineUVScale;')).toBe(true);
-
- expect(sphericalTexturedVS2D.includes('v_inversePlaneExtents =')).toBe(true);
- expect(sphericalTexturedVS2D.includes('v_westPlane =')).toBe(true);
- expect(sphericalTexturedVS2D.includes('v_southPlane =')).toBe(true);
- expect(sphericalTexturedVS2D.includes('v_stSineCosineUVScale =')).toBe(true);
+ var shaderSource = sphericalTexturedAppearance.createVertexShader([], testVs, false);
+ var defines = shaderSource.defines;
+ expect(defines.length).toEqual(2);
+ expect(defines.indexOf('TEXTURE_COORDINATES')).not.toEqual(-1);
+ expect(defines.indexOf('SPHERICAL')).not.toEqual(-1);
+
+ // 2D variant
+ shaderSource = sphericalTexturedAppearance.createVertexShader([], testVs, true);
+ defines = shaderSource.defines;
+ expect(defines.length).toEqual(2);
+ expect(defines.indexOf('TEXTURE_COORDINATES')).not.toEqual(-1);
+ expect(defines.indexOf('COLUMBUS_VIEW_2D')).not.toEqual(-1);
+
+ // Unculled color appearance - no texcoords at all
+ var sphericalUnculledColorAppearance = new ShadowVolumeAppearance(false, false, perInstanceColorMaterialAppearance);
+ shaderSource = sphericalUnculledColorAppearance.createVertexShader([], testVs, false);
+ defines = shaderSource.defines;
+ expect(defines.length).toEqual(1);
+ expect(defines.indexOf('PER_INSTANCE_COLOR')).not.toEqual(-1);
+
+ // 2D variant
+ shaderSource = sphericalUnculledColorAppearance.createVertexShader([], testVs, true);
+ defines = shaderSource.defines;
+ expect(defines.length).toEqual(1);
+ expect(defines.indexOf('PER_INSTANCE_COLOR')).not.toEqual(-1);
+
+ // Planar textured, without culling
+ var planarTexturedAppearance = new ShadowVolumeAppearance(false, true, textureMaterialAppearance);
+ shaderSource = planarTexturedAppearance.createVertexShader([], testVs, false);
+ defines = shaderSource.defines;
+ expect(defines.indexOf('TEXTURE_COORDINATES')).not.toEqual(-1);
+ expect(defines.length).toEqual(1);
+
+ shaderSource = planarTexturedAppearance.createVertexShader([], testVs, true);
+ defines = shaderSource.defines;
+ expect(defines.indexOf('TEXTURE_COORDINATES')).not.toEqual(-1);
+ expect(defines.indexOf('COLUMBUS_VIEW_2D')).not.toEqual(-1);
+ expect(defines.length).toEqual(2);
+ });
+ it('creates vertex shaders for pick', function() {
+ // Check defines
+ var sphericalTexturedAppearance = new ShadowVolumeAppearance(true, false, textureMaterialAppearance);
+ var shaderSource = sphericalTexturedAppearance.createPickVertexShader([], testVs, false);
+ var defines = shaderSource.defines;
+ expect(defines.length).toEqual(2);
+ expect(defines.indexOf('TEXTURE_COORDINATES')).not.toEqual(-1);
+ expect(defines.indexOf('SPHERICAL')).not.toEqual(-1);
+
+ // 2D variant
+ shaderSource = sphericalTexturedAppearance.createPickVertexShader([], testVs, true);
+ defines = shaderSource.defines;
+ expect(defines.length).toEqual(2);
+ expect(defines.indexOf('TEXTURE_COORDINATES')).not.toEqual(-1);
+ expect(defines.indexOf('COLUMBUS_VIEW_2D')).not.toEqual(-1);
+
+ // Unculled color appearance - no texcoords at all
var sphericalUnculledColorAppearance = new ShadowVolumeAppearance(false, false, perInstanceColorMaterialAppearance);
- var sphericalUnculledColorVS3D = sphericalUnculledColorAppearance.createVertexShader(testVs, false);
- expect(sphericalUnculledColorVS3D.includes('varying vec4 v_color;')).toBe(true);
- expect(sphericalUnculledColorVS3D.includes('v_color =')).toBe(true);
+ shaderSource = sphericalUnculledColorAppearance.createPickVertexShader([], testVs, false);
+ defines = shaderSource.defines;
+ expect(defines.length).toEqual(0);
- var sphericalUnculledColorVS2D = sphericalUnculledColorAppearance.createVertexShader(testVs, true);
- expect(sphericalUnculledColorVS2D.includes('varying vec4 v_color;')).toBe(true);
- expect(sphericalUnculledColorVS2D.includes('v_color =')).toBe(true);
+ // 2D variant
+ shaderSource = sphericalUnculledColorAppearance.createPickVertexShader([], testVs, true);
+ defines = shaderSource.defines;
+ expect(defines.length).toEqual(0);
+ // Planar textured, without culling
var planarTexturedAppearance = new ShadowVolumeAppearance(false, true, textureMaterialAppearance);
- var planarTexturedAppearanceVS3D = planarTexturedAppearance.createVertexShader(testVs, false);
+ shaderSource = planarTexturedAppearance.createPickVertexShader([], testVs, false);
+ defines = shaderSource.defines;
+ expect(defines.length).toEqual(0);
- expect(planarTexturedAppearanceVS3D.includes('varying vec2 v_inversePlaneExtents;')).toBe(true);
- expect(planarTexturedAppearanceVS3D.includes('varying vec4 v_westPlane;')).toBe(true);
- expect(planarTexturedAppearanceVS3D.includes('varying vec4 v_southPlane;')).toBe(true);
- expect(planarTexturedAppearanceVS3D.includes('varying vec4 v_stSineCosineUVScale;')).toBe(true);
-
- expect(planarTexturedAppearanceVS3D.includes('v_inversePlaneExtents =')).toBe(true);
- expect(planarTexturedAppearanceVS3D.includes('v_westPlane =')).toBe(true);
- expect(planarTexturedAppearanceVS3D.includes('v_southPlane =')).toBe(true);
- expect(planarTexturedAppearanceVS3D.includes('v_stSineCosineUVScale =')).toBe(true);
+ shaderSource = planarTexturedAppearance.createPickVertexShader([], testVs, true);
+ defines = shaderSource.defines;
+ expect(defines.length).toEqual(0);
});
- it('creates fragment shaders', function() {
+ it('creates fragment shaders for color and pick', function() {
+ // Check defines
var sphericalTexturedAppearance = new ShadowVolumeAppearance(true, false, textureMaterialAppearance);
- var sphericalTexturedFS3D = sphericalTexturedAppearance.createAppearanceFragmentShader(false);
+ var shaderSource = sphericalTexturedAppearance.createFragmentShader(false);
+ var defines = shaderSource.defines;
// Check material hookups, discard for culling, and phong shading
- expect(sphericalTexturedFS3D.includes('.normalEC =')).toBe(true);
- expect(sphericalTexturedFS3D.includes('.positionToEyeEC =')).toBe(true);
- expect(sphericalTexturedFS3D.includes('.tangentToEyeMatrix =')).toBe(true);
- expect(sphericalTexturedFS3D.includes('.st.x =')).toBe(true);
- expect(sphericalTexturedFS3D.includes('.st.y =')).toBe(true);
- expect(sphericalTexturedFS3D.includes('discard;')).toBe(true);
- expect(sphericalTexturedFS3D.includes('czm_phong')).toBe(true);
-
- var sphericalTexturedFS2D = sphericalTexturedAppearance.createAppearanceFragmentShader(true);
-
- expect(sphericalTexturedFS2D.includes('.normalEC =')).toBe(true);
- expect(sphericalTexturedFS2D.includes('.positionToEyeEC =')).toBe(true);
- expect(sphericalTexturedFS2D.includes('.tangentToEyeMatrix =')).toBe(true);
- expect(sphericalTexturedFS2D.includes('.st.x =')).toBe(true);
- expect(sphericalTexturedFS2D.includes('.st.y =')).toBe(true);
- expect(sphericalTexturedFS2D.includes('discard;')).toBe(true);
- expect(sphericalTexturedFS2D.includes('czm_phong')).toBe(true);
-
- var planarColorAppearance = new ShadowVolumeAppearance(true, false, perInstanceColorMaterialAppearance);
- var planarColorFS3D = planarColorAppearance.createAppearanceFragmentShader(false);
- expect(planarColorFS3D.includes('= v_color')).toBe(true);
- expect(planarColorFS3D.includes('varying vec4 v_color;')).toBe(true);
- expect(planarColorFS3D.includes('discard;')).toBe(true);
- expect(planarColorFS3D.includes('czm_phong')).toBe(true);
+ expect(defines.indexOf('SPHERICAL')).not.toEqual(-1);
+ expect(defines.indexOf('REQUIRES_EC')).not.toEqual(-1);
+ expect(defines.indexOf('REQUIRES_WC')).not.toEqual(-1);
+ expect(defines.indexOf('TEXTURE_COORDINATES')).not.toEqual(-1);
+ expect(defines.indexOf('CULL_FRAGMENTS')).not.toEqual(-1);
+ expect(defines.indexOf('NORMAL_EC')).not.toEqual(-1);
+ expect(defines.indexOf('USES_NORMAL_EC')).not.toEqual(-1);
+ expect(defines.indexOf('USES_POSITION_TO_EYE_EC')).not.toEqual(-1);
+ expect(defines.indexOf('USES_TANGENT_TO_EYE')).not.toEqual(-1);
+ expect(defines.indexOf('USES_ST')).not.toEqual(-1);
+ expect(defines.length).toEqual(10);
+
+ // 2D case
+ shaderSource = sphericalTexturedAppearance.createFragmentShader(true);
+ defines = shaderSource.defines;
+
+ expect(defines.indexOf('REQUIRES_EC')).not.toEqual(-1);
+ expect(defines.indexOf('REQUIRES_WC')).not.toEqual(-1);
+ expect(defines.indexOf('TEXTURE_COORDINATES')).not.toEqual(-1);
+ expect(defines.indexOf('CULL_FRAGMENTS')).not.toEqual(-1);
+ expect(defines.indexOf('NORMAL_EC')).not.toEqual(-1);
+ expect(defines.indexOf('USES_NORMAL_EC')).not.toEqual(-1);
+ expect(defines.indexOf('USES_POSITION_TO_EYE_EC')).not.toEqual(-1);
+ expect(defines.indexOf('USES_TANGENT_TO_EYE')).not.toEqual(-1);
+ expect(defines.indexOf('USES_ST')).not.toEqual(-1);
+ expect(defines.length).toEqual(9);
+
+ // Culling with planar texture coordinates on a per-color material
+ var planarColorAppearance = new ShadowVolumeAppearance(true, true, perInstanceColorMaterialAppearance);
+ shaderSource = planarColorAppearance.createFragmentShader(false);
+ defines = shaderSource.defines;
+
+ expect(defines.indexOf('PER_INSTANCE_COLOR')).not.toEqual(-1);
+ expect(defines.indexOf('REQUIRES_EC')).not.toEqual(-1);
+ expect(defines.indexOf('REQUIRES_WC')).not.toEqual(-1);
+ expect(defines.indexOf('TEXTURE_COORDINATES')).not.toEqual(-1);
+ expect(defines.indexOf('CULL_FRAGMENTS')).not.toEqual(-1);
+ expect(defines.indexOf('NORMAL_EC')).not.toEqual(-1);
+ expect(defines.length).toEqual(6);
// Pick
- var pickColorFS2D = planarColorAppearance.createPickingFragmentShader(true);
- expect(pickColorFS2D.includes('gl_FragColor.a = 1.0')).toBe(true);
+ shaderSource = planarColorAppearance.createPickFragmentShader(true);
+ defines = shaderSource.defines;
+
+ expect(defines.indexOf('REQUIRES_EC')).not.toEqual(-1);
+ expect(defines.indexOf('REQUIRES_WC')).not.toEqual(-1);
+ expect(defines.indexOf('TEXTURE_COORDINATES')).not.toEqual(-1);
+ expect(defines.indexOf('CULL_FRAGMENTS')).not.toEqual(-1);
+ expect(defines.indexOf('PICK')).not.toEqual(-1);
+ expect(defines.length).toEqual(5);
// Flat
var flatSphericalTexturedAppearance = new ShadowVolumeAppearance(true, false, flatTextureMaterialAppearance);
- var flatSphericalTexturedFS3D = flatSphericalTexturedAppearance.createAppearanceFragmentShader(false);
- expect(flatSphericalTexturedFS3D.includes('gl_FragColor = vec4')).toBe(true);
+ shaderSource = flatSphericalTexturedAppearance.createFragmentShader(false);
+ defines = shaderSource.defines;
+ expect(defines.indexOf('SPHERICAL')).not.toEqual(-1);
+ expect(defines.indexOf('REQUIRES_EC')).not.toEqual(-1);
+ expect(defines.indexOf('REQUIRES_WC')).not.toEqual(-1);
+ expect(defines.indexOf('TEXTURE_COORDINATES')).not.toEqual(-1);
+ expect(defines.indexOf('CULL_FRAGMENTS')).not.toEqual(-1);
+ expect(defines.indexOf('NORMAL_EC')).not.toEqual(-1);
+ expect(defines.indexOf('USES_NORMAL_EC')).not.toEqual(-1);
+ expect(defines.indexOf('USES_POSITION_TO_EYE_EC')).not.toEqual(-1);
+ expect(defines.indexOf('USES_ST')).not.toEqual(-1);
+ expect(defines.indexOf('FLAT')).not.toEqual(-1);
+ expect(defines.length).toEqual(10);
var flatSphericalColorAppearance = new ShadowVolumeAppearance(false, false, flatPerInstanceColorMaterialAppearance);
- var flatSphericalColorFS3D = flatSphericalColorAppearance.createAppearanceFragmentShader(false);
- expect(flatSphericalColorFS3D.includes('gl_FragColor = v_color;')).toBe(true);
+ shaderSource = flatSphericalColorAppearance.createFragmentShader(false);
+ defines = shaderSource.defines;
+ expect(defines.indexOf('SPHERICAL')).not.toEqual(-1);
+ expect(defines.indexOf('PER_INSTANCE_COLOR')).not.toEqual(-1);
+ expect(defines.indexOf('FLAT')).not.toEqual(-1);
+ expect(defines.length).toEqual(3);
});
});
From 5b0c259d1bb5f5c0cc29fb52aa05d151a323cabf Mon Sep 17 00:00:00 2001
From: Kangning Li true
, geometry vertices are optimized for the pre and post-vertex-shader caches.
* @param {Boolean} [options.interleave=false] When true
, geometry vertex attributes are interleaved, which can slightly improve rendering performance but increases load time.
@@ -134,6 +134,7 @@ define([
function GroundPrimitive(options) {
options = defaultValue(options, defaultValue.EMPTY_OBJECT);
+ this.appearance = options.appearance;
/**
* The geometry instance rendered with this primitive. This may
* be undefined
if options.releaseGeometryInstances
@@ -200,7 +201,7 @@ define([
this._ready = false;
this._readyPromise = when.defer();
- this._primitive = undefined;
+ this._classificationPrimitive = undefined;
this._maxHeight = undefined;
this._minHeight = undefined;
@@ -219,8 +220,9 @@ define([
this._uniformMap = uniformMap;
var that = this;
- this._primitiveOptions = {
+ this._classificationPrimitiveOptions = {
geometryInstances : undefined,
+ appearance : undefined,
vertexCacheOptimize : defaultValue(options.vertexCacheOptimize, false),
interleave : defaultValue(options.interleave, false),
releaseGeometryInstances : defaultValue(options.releaseGeometryInstances, true),
@@ -248,7 +250,7 @@ define([
*/
vertexCacheOptimize : {
get : function() {
- return this._primitiveOptions.vertexCacheOptimize;
+ return this._classificationPrimitiveOptions.vertexCacheOptimize;
}
},
@@ -264,7 +266,7 @@ define([
*/
interleave : {
get : function() {
- return this._primitiveOptions.interleave;
+ return this._classificationPrimitiveOptions.interleave;
}
},
@@ -280,7 +282,7 @@ define([
*/
releaseGeometryInstances : {
get : function() {
- return this._primitiveOptions.releaseGeometryInstances;
+ return this._classificationPrimitiveOptions.releaseGeometryInstances;
}
},
@@ -296,7 +298,7 @@ define([
*/
allowPicking : {
get : function() {
- return this._primitiveOptions.allowPicking;
+ return this._classificationPrimitiveOptions.allowPicking;
}
},
@@ -312,7 +314,7 @@ define([
*/
asynchronous : {
get : function() {
- return this._primitiveOptions.asynchronous;
+ return this._classificationPrimitiveOptions.asynchronous;
}
},
@@ -328,7 +330,7 @@ define([
*/
compressVertices : {
get : function() {
- return this._primitiveOptions.compressVertices;
+ return this._classificationPrimitiveOptions.compressVertices;
}
},
@@ -616,7 +618,7 @@ define([
}
if (frameState.invertClassification) {
- var ignoreShowCommands = groundPrimitive._primitive._commandsIgnoreShow;
+ var ignoreShowCommands = groundPrimitive._classificationPrimitive._commandsIgnoreShow;
var ignoreShowCommandsLength = ignoreShowCommands.length;
for (i = 0; i < ignoreShowCommandsLength; ++i) {
@@ -634,7 +636,7 @@ define([
if (passes.pick) {
var pickLength = pickCommands.length;
- var primitive = groundPrimitive._primitive._primitive;
+ var primitive = groundPrimitive._classificationPrimitive._primitive;
var pickOffsets = primitive._pickOffsets;
for (var j = 0; j < pickLength; ++j) {
var pickOffset = pickOffsets[boundingVolumeIndex(j, pickLength)];
@@ -689,7 +691,7 @@ define([
* @exception {DeveloperError} Not all of the geometry instances have the same color attribute.
*/
GroundPrimitive.prototype.update = function(frameState) {
- if (!this.show || (!defined(this._primitive) && !defined(this.geometryInstances))) {
+ if (!this.show || (!defined(this._classificationPrimitive) && !defined(this.geometryInstances))) {
return;
}
@@ -705,9 +707,9 @@ define([
}
var that = this;
- var primitiveOptions = this._primitiveOptions;
+ var primitiveOptions = this._classificationPrimitiveOptions;
- if (!defined(this._primitive)) {
+ if (!defined(this._classificationPrimitive)) {
var ellipsoid = frameState.mapProjection.ellipsoid;
var instance;
@@ -756,9 +758,8 @@ define([
geometry = instance.geometry;
instanceType = geometry.constructor;
- // TODO: what to do if not all the geometryInstances are polygonHierarchies? TODO: does this even happen here?
var attributes = {
- sphericalExtents : new SphericalExtentsGeometryInstanceAttribute(geometry._rectangle)
+ sphericalExtents : new SphericalExtentsGeometryInstanceAttribute(getRectangle(frameState, geometry))
};
var instanceAttributes = instance.attributes;
for (var attributeKey in instanceAttributes) {
@@ -776,6 +777,7 @@ define([
}
primitiveOptions.geometryInstances = groundInstances;
+ primitiveOptions.appearance = this.appearance;
primitiveOptions._createBoundingVolumeFunction = function(frameState, geometry) {
createBoundingVolume(that, frameState, geometry);
@@ -784,8 +786,8 @@ define([
updateAndQueueCommands(that, frameState, colorCommands, pickCommands, modelMatrix, cull, debugShowBoundingVolume, twoPasses);
};
- this._primitive = new ClassificationPrimitive(primitiveOptions);
- this._primitive.readyPromise.then(function(primitive) {
+ this._classificationPrimitive = new ClassificationPrimitive(primitiveOptions);
+ this._classificationPrimitive.readyPromise.then(function(primitive) {
that._ready = true;
if (that.releaseGeometryInstances) {
@@ -801,9 +803,10 @@ define([
});
}
- this._primitive.debugShowShadowVolume = this.debugShowShadowVolume;
- this._primitive.debugShowBoundingVolume = this.debugShowBoundingVolume;
- this._primitive.update(frameState);
+ this._classificationPrimitive.appearance = this.appearance;
+ this._classificationPrimitive.debugShowShadowVolume = this.debugShowShadowVolume;
+ this._classificationPrimitive.debugShowBoundingVolume = this.debugShowBoundingVolume;
+ this._classificationPrimitive.update(frameState);
};
/**
@@ -833,11 +836,11 @@ define([
*/
GroundPrimitive.prototype.getGeometryInstanceAttributes = function(id) {
//>>includeStart('debug', pragmas.debug);
- if (!defined(this._primitive)) {
+ if (!defined(this._classificationPrimitive)) {
throw new DeveloperError('must call update before calling getGeometryInstanceAttributes');
}
//>>includeEnd('debug');
- return this._primitive.getGeometryInstanceAttributes(id);
+ return this._classificationPrimitive.getGeometryInstanceAttributes(id);
};
/**
@@ -874,7 +877,7 @@ define([
* @see GroundPrimitive#isDestroyed
*/
GroundPrimitive.prototype.destroy = function() {
- this._primitive = this._primitive && this._primitive.destroy();
+ this._classificationPrimitive = this._classificationPrimitive && this._classificationPrimitive.destroy();
return destroyObject(this);
};
diff --git a/Source/Shaders/Appearances/EllipsoidSurfaceAppearanceFS.glsl b/Source/Shaders/Appearances/EllipsoidSurfaceAppearanceFS.glsl
index 7b1054b4acc..647a5120908 100644
--- a/Source/Shaders/Appearances/EllipsoidSurfaceAppearanceFS.glsl
+++ b/Source/Shaders/Appearances/EllipsoidSurfaceAppearanceFS.glsl
@@ -5,29 +5,30 @@ varying vec2 v_st;
void main()
{
czm_materialInput materialInput;
-
+
vec3 normalEC = normalize(czm_normal3D * czm_geodeticSurfaceNormal(v_positionMC, vec3(0.0), vec3(1.0)));
#ifdef FACE_FORWARD
normalEC = faceforward(normalEC, vec3(0.0, 0.0, 1.0), -normalEC);
#endif
-
+
materialInput.s = v_st.s;
materialInput.st = v_st;
materialInput.str = vec3(v_st, 0.0);
-
+
// Convert tangent space material normal to eye space
materialInput.normalEC = normalEC;
materialInput.tangentToEyeMatrix = czm_eastNorthUpToEyeCoordinates(v_positionMC, materialInput.normalEC);
-
+
// Convert view vector to world space
- vec3 positionToEyeEC = -v_positionEC;
+ vec3 positionToEyeEC = -v_positionEC;
materialInput.positionToEyeEC = positionToEyeEC;
czm_material material = czm_getMaterial(materialInput);
-
-#ifdef FLAT
+
+#ifdef FLAT
gl_FragColor = vec4(material.diffuse + material.emission, material.alpha);
#else
gl_FragColor = czm_phong(normalize(positionToEyeEC), material);
#endif
+ //gl_FragColor = vec4(positionToEyeEC, 1.0);
}
diff --git a/Source/Shaders/Materials/CheckerboardMaterial.glsl b/Source/Shaders/Materials/CheckerboardMaterial.glsl
index 56d1fdb230a..5c7a566c313 100644
--- a/Source/Shaders/Materials/CheckerboardMaterial.glsl
+++ b/Source/Shaders/Materials/CheckerboardMaterial.glsl
@@ -7,22 +7,22 @@ czm_material czm_getMaterial(czm_materialInput materialInput)
czm_material material = czm_getDefaultMaterial(materialInput);
vec2 st = materialInput.st;
-
+
// From Stefan Gustavson's Procedural Textures in GLSL in OpenGL Insights
float b = mod(floor(repeat.s * st.s) + floor(repeat.t * st.t), 2.0); // 0.0 or 1.0
-
+
// Find the distance from the closest separator (region between two colors)
float scaledWidth = fract(repeat.s * st.s);
scaledWidth = abs(scaledWidth - floor(scaledWidth + 0.5));
float scaledHeight = fract(repeat.t * st.t);
scaledHeight = abs(scaledHeight - floor(scaledHeight + 0.5));
float value = min(scaledWidth, scaledHeight);
-
+
vec4 currentColor = mix(lightColor, darkColor, b);
vec4 color = czm_antialias(lightColor, darkColor, currentColor, value, 0.03);
-
+
material.diffuse = color.rgb;
material.alpha = color.a;
-
+
return material;
}
diff --git a/Source/Shaders/ShadowVolumeColorFS.glsl b/Source/Shaders/ShadowVolumeColorFS.glsl
index 344aad27c39..682f3a3699e 100644
--- a/Source/Shaders/ShadowVolumeColorFS.glsl
+++ b/Source/Shaders/ShadowVolumeColorFS.glsl
@@ -5,10 +5,13 @@
#ifdef VECTOR_TILE
uniform vec4 u_highlightColor;
#else
-varying vec4 v_color;
varying vec4 v_sphericalExtents;
#endif
+#ifdef PER_INSTANCE_COLOR
+varying vec4 v_color;
+#endif
+
float rez = 0.1;
// http://developer.download.nvidia.com/cg/atan2.html
@@ -47,19 +50,25 @@ float completelyFakeAsin(float x)
return (x * x * x + x) * 0.78539816339;
}
-void main(void)
-{
-#ifdef VECTOR_TILE
- gl_FragColor = u_highlightColor;
-#else
- vec2 coords = gl_FragCoord.xy / czm_viewport.zw;
+vec3 getWorldPos(vec2 fragCoord) {
+ vec2 coords = fragCoord / czm_viewport.zw;
float depth = czm_unpackDepth(texture2D(czm_globeDepthTexture, coords));
-
- vec4 windowCoord = vec4(gl_FragCoord.xy, depth, 1.0);
+ vec4 windowCoord = vec4(fragCoord, depth, 1.0);
vec4 eyeCoord = czm_windowToEyeCoordinates(windowCoord);
vec4 worldCoord4 = czm_inverseView * eyeCoord;
vec3 worldCoord = worldCoord4.xyz / worldCoord4.w;
+ return worldCoord;
+}
+void main(void)
+{
+#ifdef VECTOR_TILE
+ gl_FragColor = u_highlightColor;
+#else
+ #ifdef PER_INSTANCE_COLOR
+ gl_FragColor = v_color;
+ #else
+ vec3 worldCoord = getWorldPos(gl_FragCoord.xy);
vec3 sphereNormal = normalize(worldCoord);
float latitude = completelyFakeAsin(sphereNormal.z); // find a dress for the ball Sinderella
@@ -68,16 +77,42 @@ void main(void)
float u = (latitude - v_sphericalExtents.y) * v_sphericalExtents.w;
float v = (longitude - v_sphericalExtents.x) * v_sphericalExtents.z;
+ /*
if (u <= 0.0 || 1.0 <= u || v <= 0.0 || 1.0 <= v) {
discard;
- } else {
- // UV checkerboard
- if (((mod(floor(u / rez), 2.0) == 1.0) && (mod(floor(v / rez), 2.0) == 0.0)) || ((mod(floor(u / rez), 2.0) == 0.0) && (mod(floor(v / rez), 2.0) == 1.0))) {
- gl_FragColor = vec4(u, v, 0.0, 1.0);
- } else {
- gl_FragColor = v_color;
- }
- }
+ }*/
+
+ vec3 positionToEyeEC = -(czm_modelView * vec4(worldCoord, 1.0)).xyz;
+
+ // compute normal
+ vec2 fragCoord = gl_FragCoord.xy;
+ float d = 1.0;
+
+ // sample up, down, left, and right in screen space
+ vec3 downUp = getWorldPos(fragCoord + vec2(0.0, d)) - getWorldPos(fragCoord - vec2(0.0, d));
+ vec3 leftRight = getWorldPos(fragCoord - vec2(d, 0.0)) - getWorldPos(fragCoord + vec2(d, 0.0));
+ vec3 normal = normalize(cross(downUp, leftRight));
+
+ //vec3 normal = sphereNormal; // TODO: do better?
+
+ // TODO: might need optional rotations down here...
+ vec3 normalEC = czm_normal * normal;
+ vec3 tangent = cross(vec3(0, 0, 1), normal);
+ vec3 tangentEC = czm_normal * tangent;
+ vec3 bitangentEC = czm_normal * cross(normal, tangent);
+
+ czm_materialInput materialInput;
+ materialInput.normalEC = normalEC;
+ materialInput.tangentToEyeMatrix = czm_tangentToEyeSpaceMatrix(normalEC, tangentEC, bitangentEC);
+ //materialInput.tangentToEyeMatrix = czm_eastNorthUpToEyeCoordinates(worldCoord, normalEC);
+ materialInput.positionToEyeEC = positionToEyeEC;
+ materialInput.st.x = v;
+ materialInput.st.y = u;
+ czm_material material = czm_getMaterial(materialInput);
+
+ gl_FragColor = czm_phong(normalize(positionToEyeEC), material);
+ //gl_FragColor = vec4(u, v, 0.0, 1.0);
+ #endif
#endif
czm_writeDepthClampedToFarPlane();
diff --git a/Source/Shaders/ShadowVolumeFS.glsl b/Source/Shaders/ShadowVolumeFS.glsl
index 51e951b07b9..777150ea67e 100644
--- a/Source/Shaders/ShadowVolumeFS.glsl
+++ b/Source/Shaders/ShadowVolumeFS.glsl
@@ -4,8 +4,8 @@
#ifdef VECTOR_TILE
uniform vec4 u_highlightColor;
-#else
-varying vec4 v_color;
+//#else
+//varying vec4 v_color;
#endif
void main(void)
@@ -13,7 +13,7 @@ void main(void)
#ifdef VECTOR_TILE
gl_FragColor = u_highlightColor;
#else
- gl_FragColor = v_color;
+ gl_FragColor = vec4(1.0);
#endif
czm_writeDepthClampedToFarPlane();
}
diff --git a/Source/Shaders/ShadowVolumeVS.glsl b/Source/Shaders/ShadowVolumeVS.glsl
index bb7721936ed..7e89b63a114 100644
--- a/Source/Shaders/ShadowVolumeVS.glsl
+++ b/Source/Shaders/ShadowVolumeVS.glsl
@@ -6,7 +6,7 @@ uniform mat4 u_modifiedModelViewProjection;
#else
attribute vec3 position3DHigh;
attribute vec3 position3DLow;
-attribute vec4 color;
+//attribute vec4 color;
attribute float batchId;
#endif
@@ -17,16 +17,23 @@ uniform float u_globeMinimumAltitude;
#endif
#ifndef VECTOR_TILE
-varying vec4 v_color;
varying vec4 v_sphericalExtents;
#endif
+#ifdef PER_INSTANCE_COLOR
+varying vec4 v_color;
+#endif
+
void main()
{
#ifdef VECTOR_TILE
gl_Position = czm_depthClampFarPlane(u_modifiedModelViewProjection * vec4(position, 1.0));
#else
- v_color = color;
+
+#ifdef PER_INSTANCE_COLOR
+ v_color = czm_batchTable_color(batchId);
+#endif
+
v_sphericalExtents = czm_batchTable_sphericalExtents(batchId);
vec4 position = czm_computePosition();
From 0433738200d7bedeacac749ad70c91307beee742 Mon Sep 17 00:00:00 2001
From: Kangning Li true
, geometry vertices are optimized for the pre and post-vertex-shader caches.
* @param {Boolean} [options.interleave=false] When true
, geometry vertex attributes are interleaved, which can slightly improve rendering performance but increases load time.
@@ -196,32 +196,45 @@ define([
var appearance = options.appearance;
- // Require SphericalExtents attribute on all geometries if material isn't PerInstanceColor
- if (defined(appearance) && defined(appearance.material) && defined(geometryInstances)) {
+ var hasPerColorAttribute = false;
+ var hasSphericalExtentsAttribute = false;
var geometryInstancesArray = isArray(geometryInstances) ? geometryInstances : [geometryInstances];
- var geometryInstanceCount = geometryInstances.length;
+ var geometryInstanceCount = geometryInstancesArray.length;
for (var i = 0; i < geometryInstanceCount; i++) {
- var attributes = geometryInstances[i].attributes;
- if (!defined(attributes) || !defined(attributes.sphericalExtents)) {
- throw new DeveloperError('Materials on ClassificationPrimitives require sphericalExtents attribute');
+ var attributes = geometryInstancesArray[i].attributes;
+ if (defined(attributes)) {
+ if (defined(attributes.color)) {
+ hasPerColorAttribute = true;
+ } else if (hasPerColorAttribute) {
+ throw new DeveloperError('All GeometryInstances must have the same attributes.');
}
+ if (defined(attributes.sphericalExtents)) {
+ hasSphericalExtentsAttribute = true;
+ } else if (hasSphericalExtentsAttribute) {
+ throw new DeveloperError('All GeometryInstances must have the same attributes.');
}
+ } else if (hasPerColorAttribute || hasSphericalExtentsAttribute) {
+ throw new DeveloperError('All GeometryInstances must have the same attributes.');
+ }
}
- // If attributes include color and appearance is undefined, then default to a color appearance
- if (!defined(appearance)) {
- var geometryInstancesArray = isArray(geometryInstances) ? geometryInstances : [geometryInstances];
- var geometryInstanceCount = geometryInstances.length;
- for (var i = 0; i < geometryInstanceCount; i++) {
- var attributes = geometryInstances[i].attributes;
- if (defined(attributes) && defined(attributes.color)) {
+ // If attributes include color and appearance is undefined, default to a color appearance
+ if (!defined(appearance) && hasPerColorAttribute) {
appearance = new PerInstanceColorAppearance({
flat : true
});
- break;
}
+ if (!hasPerColorAttribute && appearance instanceof PerInstanceColorAppearance) {
+ throw new DeveloperError('PerInstanceColorAppearance requires color GeometryInstanceAttribute');
}
+
+ // TODO: SphericalExtents needed if PerInstanceColor isn't all the same
+ if (defined(appearance.material) && !hasSphericalExtentsAttribute) {
+ throw new DeveloperError('Materials on ClassificationPrimitives requires sphericalExtents GeometryInstanceAttribute');
}
+
+ this._hasPerColorAttribute = hasPerColorAttribute;
+ this._hasSphericalExtentsAttribute = hasSphericalExtentsAttribute;
this.appearance = appearance;
var readOnlyAttributes;
@@ -549,7 +562,7 @@ define([
}
}
- function createShaderProgram(classificationPrimitive, frameState, appearance) {
+ function createShaderProgram(classificationPrimitive, frameState) {
var context = frameState.context;
var primitive = classificationPrimitive._primitive;
var vs = ShadowVolumeVS;
@@ -635,17 +648,16 @@ define([
});
var parts;
+
+ // Create a fragment shader that computes only required material hookups using screen space techniques
+ var shadowVolumeAppearanceFS = createShadowVolumeAppearanceShader(appearance);
if (isPerInstanceColor) {
- parts = [ShadowVolumeColorFS];
+ parts = [shadowVolumeAppearanceFS];
} else {
- // Modify fsColorSource for material (yay!)
- // Only have to modify the FS b/c all material hookups happen in there b/c lol VS
- // TODO: scan shaderSource to determine what material inputs are needed for ShadowVolumeColorFS?
- parts = [appearance.material.shaderSource, ShadowVolumeColorFS];
+ parts = [appearance.material.shaderSource, shadowVolumeAppearanceFS];
}
var fsColorSource = new ShaderSource({
- defines : isPerInstanceColor ? ['PER_INSTANCE_COLOR'] : [],
sources : [parts.join('\n')]
});
@@ -715,7 +727,7 @@ define([
var appearance = classificationPrimitive.appearance;
var material = appearance.material;
if (defined(material)) {
- uniformMap = combine(uniformMap, material._uniforms)
+ uniformMap = combine(uniformMap, material._uniforms);
}
command.uniformMap = uniformMap;
@@ -1010,7 +1022,16 @@ define([
this._rsColorPass = RenderState.fromCache(getColorRenderState(true));
}
// Update primitive appearance
+ if (this._primitive.appearance !== appearance) {
+ // Check if the appearance is supported by the geometry attributes
+ if (!this._hasSphericalExtentsAttribute && defined(appearance.material)) {
+ throw new DeveloperError('Materials on ClassificationPrimitives requires sphericalExtents GeometryInstanceAttribute');
+ }
+ if (!this._hasPerColorAttribute && appearance instanceof PerInstanceColorAppearance) {
+ throw new DeveloperError('PerInstanceColorAppearance requires color GeometryInstanceAttribute');
+ }
this._primitive.appearance = appearance;
+ }
this._primitive.debugShowBoundingVolume = this.debugShowBoundingVolume;
this._primitive.update(frameState);
diff --git a/Source/Scene/GroundPrimitive.js b/Source/Scene/GroundPrimitive.js
index 821169e3dfd..eb1a5b54ef1 100644
--- a/Source/Scene/GroundPrimitive.js
+++ b/Source/Scene/GroundPrimitive.js
@@ -22,6 +22,7 @@ define([
'../ThirdParty/when',
'./ClassificationPrimitive',
'./ClassificationType',
+ './PerInstanceColorAppearance',
'./SceneMode'
], function(
BoundingSphere,
@@ -47,6 +48,7 @@ define([
when,
ClassificationPrimitive,
ClassificationType,
+ PerInstanceColorAppearance,
SceneMode) {
'use strict';
@@ -72,7 +74,7 @@ define([
*
* @param {Object} [options] Object with the following properties:
* @param {Array|GeometryInstance} [options.geometryInstances] The geometry instances to render.
- * @param {Appearance} [options.appearance] The appearance used to render the primitive.
+ * @param {Appearance} [options.appearance] The appearance used to render the primitive. Defaults to PerInstanceColorAppearance when GeometryInstances have a color attribute.
* @param {Boolean} [options.show=true] Determines if this primitive will be shown.
* @param {Boolean} [options.vertexCacheOptimize=false] When true
, geometry vertices are optimized for the pre and post-vertex-shader caches.
* @param {Boolean} [options.interleave=false] When true
, geometry vertex attributes are interleaved, which can slightly improve rendering performance but increases load time.
@@ -134,7 +136,24 @@ define([
function GroundPrimitive(options) {
options = defaultValue(options, defaultValue.EMPTY_OBJECT);
- this.appearance = options.appearance;
+ var appearance = options.appearance;
+ var geometryInstances = options.geometryInstances;
+ if (!defined(appearance) && defined(geometryInstances)) {
+ var geometryInstancesArray = isArray(geometryInstances) ? geometryInstances : [geometryInstances];
+ var geometryInstanceCount = geometryInstancesArray.length;
+ for (var i = 0; i < geometryInstanceCount; i++) {
+ var attributes = geometryInstancesArray[i].attributes;
+ if (defined(attributes) && defined(attributes.color)) {
+ appearance = new PerInstanceColorAppearance({
+ flat : true
+ });
+ break;
+ }
+ }
+ }
+
+ this.appearance = appearance;
+
/**
* The geometry instance rendered with this primitive. This may
* be undefined
if options.releaseGeometryInstances
diff --git a/Source/Scene/createShadowVolumeAppearanceShader.js b/Source/Scene/createShadowVolumeAppearanceShader.js
new file mode 100644
index 00000000000..f7c58abf713
--- /dev/null
+++ b/Source/Scene/createShadowVolumeAppearanceShader.js
@@ -0,0 +1,297 @@
+define([
+ '../Core/Check',
+ '../Core/defaultValue',
+ '../Core/defineProperties',
+ '../Renderer/PixelDatatype',
+ '../Scene/PerInstanceColorAppearance'
+], function(
+ Check,
+ defaultValue,
+ defineProperties,
+ PixelDatatype,
+ PerInstanceColorAppearance) {
+ 'use strict';
+
+ var shaderDependenciesScratch = new ShaderDependencies();
+ /**
+ * Creates the shadow volume fragment shader for a ClassificationPrimitive to use a given appearance.
+ *
+ * @param {Appearance} appearance An Appearance to be used with a ClassificationPrimitive.
+ * @param {Boolean} [sphericalExtentsCulling=false] Discard fragments outside the instance's spherical extents.
+ * @returns {String} Shader source for a fragment shader using the input appearance.
+ * @private
+ */
+ function createShadowVolumeAppearanceShader(appearance, sphericalExtentsCulling) {
+ //>>includeStart('debug', pragmas.debug);
+ Check.typeOf.object('appearance', appearance);
+ //>>includeEnd('debug');
+
+ var extentsCull = defaultValue(sphericalExtentsCulling, false);
+
+ if (appearance instanceof PerInstanceColorAppearance) {
+ return getPerInstanceColorShader(extentsCull, appearance.flat);
+ }
+
+ var shaderDependencies = shaderDependenciesScratch.reset();
+ shaderDependencies.requiresTexcoords = extentsCull;
+ shaderDependencies.requiresEyeCoord = !appearance.flat;
+
+ // Scan material source for what hookups are needed. Assume czm_materialInput materialInput.
+ var materialShaderSource = appearance.material.shaderSource;
+
+ var usesNormalEC = shaderDependencies.normalEC = materialShaderSource.includes('materialInput.normalEC') || materialShaderSource.includes('czm_getDefaultMaterial');
+ var usesPositionToEyeEC = shaderDependencies.positionToEyeEC = materialShaderSource.includes('materialInput.positionToEyeEC');
+ var usesTangentToEyeMat = shaderDependencies.tangentToEyeMatrix = materialShaderSource.includes('materialInput.tangentToEyeMatrix');
+ var usesSt = shaderDependencies.st = materialShaderSource.includes('materialInput.st');
+
+ var glsl =
+ '#ifdef GL_EXT_frag_depth\n' +
+ '#extension GL_EXT_frag_depth : enable\n' +
+ '#endif\n';
+ if (extentsCull || usesSt) {
+ glsl +=
+ 'varying vec4 v_sphericalExtents;\n';
+ }
+
+ glsl += getLocalFunctions(shaderDependencies);
+
+ glsl +=
+ 'void main(void)\n' +
+ '{\n';
+
+ glsl += getDependenciesAndCulling(shaderDependencies, extentsCull);
+
+ glsl += ' czm_materialInput materialInput;\n';
+ if (usesNormalEC) {
+ glsl += ' materialInput.normalEC = normalEC;\n';
+ }
+ if (usesPositionToEyeEC) {
+ glsl += ' materialInput.positionToEyeEC = -eyeCoord.xyz;\n';
+ }
+ if (usesTangentToEyeMat) {
+ glsl += ' materialInput.tangentToEyeMatrix = czm_eastNorthUpToEyeCoordinates(worldCoord, normalEC);\n';
+ }
+ if (usesSt) {
+ glsl += ' materialInput.st = vec2(v, u);\n';
+ }
+ glsl += ' czm_material material = czm_getMaterial(materialInput);\n';
+
+ if (appearance.flat) {
+ glsl += ' gl_FragColor = vec4(material.diffuse + material.emission, material.alpha);\n';
+ } else {
+ glsl += ' gl_FragColor = czm_phong(normalize(-eyeCoord.xyz), material);\n';
+ }
+
+ glsl += '}\n';
+ return glsl;
+ }
+
+ function getPerInstanceColorShader(sphericalExtentsCulling, flatShading) {
+ var glsl =
+ '#ifdef GL_EXT_frag_depth\n' +
+ '#extension GL_EXT_frag_depth : enable\n' +
+ '#endif\n' +
+ 'varying vec4 v_color;\n';
+ if (sphericalExtentsCulling) {
+ glsl +=
+ 'varying vec4 v_sphericalExtents;\n';
+ }
+ var shaderDependencies = shaderDependenciesScratch.reset();
+ shaderDependencies.requiresTexcoords = sphericalExtentsCulling;
+ shaderDependencies.requiresNormalEC = !flatShading;
+
+ glsl += getLocalFunctions(shaderDependencies);
+
+ glsl += 'void main(void)\n' +
+ '{\n';
+
+ glsl += getDependenciesAndCulling(shaderDependencies, sphericalExtentsCulling);
+
+ if (flatShading) {
+ glsl +=
+ ' gl_FragColor = v_color;\n';
+ } else {
+ glsl +=
+ ' czm_materialInput materialInput;\n' +
+ ' materialInput.normalEC = normalEC;\n' +
+ ' materialInput.positionToEyeEC = -eyeCoord.xyz;\n' +
+ ' czm_material material = czm_getDefaultMaterial(materialInput);\n' +
+ ' material.diffuse = v_color.rgb;\n' +
+ ' material.alpha = v_color.a;\n' +
+
+ ' gl_FragColor = czm_phong(normalize(-eyeCoord.xyz), material);\n';
+ }
+ glsl += '}\n';
+ return glsl;
+ }
+
+ function getDependenciesAndCulling(shaderDependencies, sphericalExtentsCulling) {
+ var glsl = '';
+ if (shaderDependencies.requiresEyeCoord) {
+ glsl +=
+ ' vec4 eyeCoord = getEyeCoord(gl_FragCoord.xy);\n';
+ }
+ if (shaderDependencies.requiresWorldCoord) {
+ glsl +=
+ ' vec4 worldCoord4 = czm_inverseView * eyeCoord;\n' +
+ ' vec3 worldCoord = worldCoord4.xyz / worldCoord4.w;\n';
+ }
+ if (shaderDependencies.requiresTexcoords) {
+ glsl +=
+ ' // compute sphere normal for spherical coordinates\n' +
+ ' vec3 sphereNormal = normalize(worldCoord);\n' +
+ ' // cubic asign approximation\n' +
+ ' float latitude = ' + approximateAsinForValue('sphereNormal.z') + ';\n' +
+ ' float longitude = czm_atan2cg(sphereNormal.y, sphereNormal.x);\n' +
+ ' float u = (latitude - v_sphericalExtents.y) * v_sphericalExtents.w;\n' +
+ ' float v = (longitude - v_sphericalExtents.x) * v_sphericalExtents.z;\n';
+ }
+ if (sphericalExtentsCulling) {
+ glsl +=
+ ' if (u <= 0.0 || 1.0 <= u || v <= 0.0 || 1.0 <= v) {\n' + // TODO: there's floating point problems at the edges of rectangles. Use remapping.
+ ' discard;\n' +
+ ' }\n';
+ }
+ // Lots of texture access, so lookup after discard check
+ if (shaderDependencies.requiresNormalEC) {
+ glsl +=
+ ' // compute normal. sample adjacent pixels in 2x2 block in screen space\n' +
+ ' vec3 downUp = getVectorFromOffset(eyeCoord, gl_FragCoord.xy, vec2(0.0, 1.0));\n' +
+ ' vec3 leftRight = getVectorFromOffset(eyeCoord, gl_FragCoord.xy, vec2(1.0, 0.0));\n' +
+ ' vec3 normalEC = normalize(cross(leftRight, downUp));\n' +
+ '\n';
+ }
+ return glsl;
+ }
+
+ function getLocalFunctions(shaderDependencies) {
+ var glsl = '';
+ if (shaderDependencies.requiresEyeCoord) {
+ glsl +=
+ 'vec4 getEyeCoord(vec2 fragCoord) {\n' +
+ ' vec2 coords = fragCoord / czm_viewport.zw;\n' +
+ ' float depth = czm_unpackDepth(texture2D(czm_globeDepthTexture, coords));\n' +
+ ' vec4 windowCoord = vec4(fragCoord, depth, 1.0);\n' +
+ ' vec4 eyeCoord = czm_windowToEyeCoordinates(windowCoord);\n' +
+ ' return eyeCoord;\n' +
+ '}\n';
+ }
+ if (shaderDependencies.requiresNormalEC) {
+ glsl +=
+ 'vec3 getEyeCoord3FromWindowCoord(vec2 fragCoord, float depth) {\n' +
+ ' vec4 windowCoord = vec4(fragCoord, depth, 1.0);\n' +
+ ' vec4 eyeCoord = czm_windowToEyeCoordinates(windowCoord);\n' +
+ ' return eyeCoord.xyz / eyeCoord.w;\n' +
+ '}\n' +
+
+ 'vec3 getVectorFromOffset(vec4 eyeCoord, vec2 fragCoord2, vec2 positiveOffset) {\n' +
+ ' // Sample depths at both offset and negative offset\n' +
+ ' float upOrRightDepth = czm_unpackDepth(texture2D(czm_globeDepthTexture, (fragCoord2 + positiveOffset) / czm_viewport.zw));\n' +
+ ' float downOrLeftDepth = czm_unpackDepth(texture2D(czm_globeDepthTexture, (fragCoord2 - positiveOffset) / czm_viewport.zw));\n' +
+ // TODO: could re-ordering here help performance? do texture fetches, then logic, then unpack?
+ ' // Explicitly evaluate both paths\n' +
+ ' bvec2 upOrRightInBounds = lessThan(fragCoord2 + positiveOffset, czm_viewport.zw);\n' +
+ ' float useUpOrRight = float(upOrRightDepth > 0.0 && upOrRightInBounds.x && upOrRightInBounds.y);\n' +
+ ' float useDownOrLeft = float(useUpOrRight == 0.0);\n' +
+
+ ' vec3 upOrRightEC = getEyeCoord3FromWindowCoord(fragCoord2 + positiveOffset, upOrRightDepth);\n' +
+ ' vec3 downOrLeftEC = getEyeCoord3FromWindowCoord(fragCoord2 - positiveOffset, downOrLeftDepth);\n' +
+
+ ' return (upOrRightEC - (eyeCoord.xyz / eyeCoord.w)) * useUpOrRight + ((eyeCoord.xyz / eyeCoord.w) - downOrLeftEC) * useDownOrLeft;\n' +
+ '}\n';
+ }
+ return glsl;
+ }
+
+ // Inline-approximate asin(value) using a very rough cubic approximation, (x^3 + x) * PI/4.
+ // Native glsl asin can vary between vendors, sometimes we need a consistent approximation.
+ //
+ // This approximation is relatively inaccurate but does not have first-derivative discontinuity
+ // for input 0, which is a common problem with sqrt-based approximations that use range reduction to cover [-1, 1].
+ // When computing spherical coordinates, such discontinuities cause pinching problems at the equator.
+ function approximateAsinForValue(valueToken) {
+ return '(' + valueToken + ' * ' + valueToken + ' * ' + valueToken + ' + ' + valueToken + ') * czm_piOverFour';
+ }
+
+ /**
+ * Tracks shader dependencies.
+ * @private
+ */
+ function ShaderDependencies() {
+ this._requiresEyeCoord = false;
+ this._requiresWorldCoord = false; // depends on eyeCoord, needed for material and for phong
+ this._requiresNormalEC = false; // depends on eyeCoord, needed for material
+ this._requiresTexcoords = false; // depends on worldCoord, needed for material and for culling
+ }
+
+ ShaderDependencies.prototype.reset = function() {
+ this._requiresEyeCoord = false;
+ this._requiresWorldCoord = false;
+ this._requiresNormalEC = false;
+ this._requiresTexcoords = false;
+ return this;
+ };
+
+ defineProperties(ShaderDependencies.prototype, {
+ // Set when assessing final shading (flat vs. phong) and spherical extent culling
+ requiresEyeCoord : {
+ get : function() {
+ return this._requiresEyeCoord;
+ },
+ set : function(value) {
+ this._requiresEyeCoord = value || this._requiresEyeCoord;
+ }
+ },
+ requiresWorldCoord : {
+ get : function() {
+ return this._requiresWorldCoord;
+ },
+ set : function(value) {
+ this._requiresWorldCoord = value || this._requiresWorldCoord;
+ this.requiresEyeCoord = this._requiresWorldCoord;
+ }
+ },
+ requiresNormalEC : {
+ get : function() {
+ return this._requiresNormalEC;
+ },
+ set : function(value) {
+ this._requiresNormalEC = value || this._requiresNormalEC;
+ this.requiresEyeCoord = this._requiresNormalEC;
+ }
+ },
+ requiresTexcoords : {
+ get : function() {
+ return this._requiresTexcoords;
+ },
+ set : function(value) {
+ this._requiresTexcoords = value || this._requiresTexcoords;
+ this.requiresWorldCoord = this._requiresTexcoords;
+ }
+ },
+ // Set when assessing material hookups
+ normalEC : {
+ set : function(value) {
+ this.requiresNormalEC = value;
+ }
+ },
+ tangentToEyeMatrix : {
+ set : function(value) {
+ this.requiresWorldCoord = value;
+ this.requiresNormalEC = value;
+ }
+ },
+ positionToEyeEC : {
+ set : function(value) {
+ this.requiresEyeCoord = value;
+ }
+ },
+ st : {
+ set : function(value) {
+ this.requiresTexcoords = value;
+ }
+ }
+ });
+
+ return createShadowVolumeAppearanceShader;
+});
diff --git a/Source/Shaders/Appearances/PerInstanceColorAppearanceFS.glsl b/Source/Shaders/Appearances/PerInstanceColorAppearanceFS.glsl
index 6bef5b43865..c2709e847ea 100644
--- a/Source/Shaders/Appearances/PerInstanceColorAppearanceFS.glsl
+++ b/Source/Shaders/Appearances/PerInstanceColorAppearanceFS.glsl
@@ -5,18 +5,18 @@ varying vec4 v_color;
void main()
{
vec3 positionToEyeEC = -v_positionEC;
-
+
vec3 normalEC = normalize(v_normalEC);
#ifdef FACE_FORWARD
normalEC = faceforward(normalEC, vec3(0.0, 0.0, 1.0), -normalEC);
#endif
-
+
czm_materialInput materialInput;
materialInput.normalEC = normalEC;
materialInput.positionToEyeEC = positionToEyeEC;
czm_material material = czm_getDefaultMaterial(materialInput);
material.diffuse = v_color.rgb;
material.alpha = v_color.a;
-
+
gl_FragColor = czm_phong(normalize(positionToEyeEC), material);
}
diff --git a/Source/Shaders/Builtin/Functions/atan2cg.glsl b/Source/Shaders/Builtin/Functions/atan2cg.glsl
new file mode 100644
index 00000000000..1e130af401d
--- /dev/null
+++ b/Source/Shaders/Builtin/Functions/atan2cg.glsl
@@ -0,0 +1,42 @@
+/**
+ * Approximates atan2 for inputs y and x.
+ * Native implementations of atan2 can differ between vendors, so use this approximation for
+ * computations that require consistency across platforms and between CPU/GPU.
+ *
+ * Based on the nvidia cg reference implementation: http://developer.download.nvidia.com/cg/atan2.html
+ * atan2 is difficult to approximate using identities and other trigonometric approximations because of limited input range.
+ *
+ * @name czm_atan2cg
+ * @glslFunction
+ *
+ * @param {float} y A nonzero y-component of a coordinate.
+ * @param {float} x A nonzero x-component of a coordinate
+ *
+ * @returns {float} The floating-point atan2 of y and x
+ */
+float czm_atan2cg(float y, float x)
+{
+ float t0, t1, t3, t4;
+
+ t3 = abs(x);
+ t1 = abs(y);
+ t0 = max(t3, t1);
+ t1 = min(t3, t1);
+ t3 = 1.0 / t0;
+ t3 = t1 * t3;
+
+ t4 = t3 * t3;
+ t0 = - 0.013480470;
+ t0 = t0 * t4 + 0.057477314;
+ t0 = t0 * t4 - 0.121239071;
+ t0 = t0 * t4 + 0.195635925;
+ t0 = t0 * t4 - 0.332994597;
+ t0 = t0 * t4 + 0.999995630;
+ t3 = t0 * t3;
+
+ t3 = (abs(y) > abs(x)) ? 1.570796327 - t3 : t3;
+ t3 = (x < 0.0) ? 3.141592654 - t3 : t3;
+ t3 = (y < 0.0) ? -t3 : t3;
+
+ return t3;
+}
diff --git a/Source/Shaders/Builtin/Functions/getDefaultMaterial.glsl b/Source/Shaders/Builtin/Functions/getDefaultMaterial.glsl
index 409d00bf3e7..14ade737e03 100644
--- a/Source/Shaders/Builtin/Functions/getDefaultMaterial.glsl
+++ b/Source/Shaders/Builtin/Functions/getDefaultMaterial.glsl
@@ -4,10 +4,10 @@
* The default normal value is given by materialInput.normalEC.
*
* @name czm_getDefaultMaterial
- * @glslFunction
+ * @glslFunction
*
* @param {czm_materialInput} input The input used to construct the default material.
- *
+ *
* @returns {czm_material} The default material.
*
* @see czm_materialInput
diff --git a/Source/Shaders/Materials/BumpMapMaterial.glsl b/Source/Shaders/Materials/BumpMapMaterial.glsl
index 350f6a7c3e8..2316a17fa04 100644
--- a/Source/Shaders/Materials/BumpMapMaterial.glsl
+++ b/Source/Shaders/Materials/BumpMapMaterial.glsl
@@ -7,23 +7,23 @@ czm_material czm_getMaterial(czm_materialInput materialInput)
czm_material material = czm_getDefaultMaterial(materialInput);
vec2 st = materialInput.st;
-
+
vec2 centerPixel = fract(repeat * st);
float centerBump = texture2D(image, centerPixel).channel;
-
+
float imageWidth = float(imageDimensions.x);
vec2 rightPixel = fract(repeat * (st + vec2(1.0 / imageWidth, 0.0)));
float rightBump = texture2D(image, rightPixel).channel;
-
+
float imageHeight = float(imageDimensions.y);
vec2 leftPixel = fract(repeat * (st + vec2(0.0, 1.0 / imageHeight)));
float topBump = texture2D(image, leftPixel).channel;
-
+
vec3 normalTangentSpace = normalize(vec3(centerBump - rightBump, centerBump - topBump, clamp(1.0 - strength, 0.1, 1.0)));
vec3 normalEC = materialInput.tangentToEyeMatrix * normalTangentSpace;
-
+
material.normal = normalEC;
material.diffuse = vec3(0.01);
-
+
return material;
}
diff --git a/Source/Shaders/ShadowVolumeColorFS.glsl b/Source/Shaders/ShadowVolumeColorFS.glsl
deleted file mode 100644
index ad4c1423cdb..00000000000
--- a/Source/Shaders/ShadowVolumeColorFS.glsl
+++ /dev/null
@@ -1,133 +0,0 @@
-#ifdef GL_EXT_frag_depth
-#extension GL_EXT_frag_depth : enable
-#endif
-
-#ifdef VECTOR_TILE
-uniform vec4 u_highlightColor;
-#else
-varying vec4 v_sphericalExtents;
-#endif
-
-#ifdef PER_INSTANCE_COLOR
-varying vec4 v_color;
-#endif
-
-float rez = 0.1;
-
-// http://developer.download.nvidia.com/cg/atan2.html
-// Using this instead of identities + approximations of atan,
-// because atan approximations usually only work between -1 and 1.
-float atan2Ref(float y, float x)
-{
- float t0, t1, t3, t4;
-
- t3 = abs(x);
- t1 = abs(y);
- t0 = max(t3, t1);
- t1 = min(t3, t1);
- t3 = 1.0 / t0;
- t3 = t1 * t3;
-
- t4 = t3 * t3;
- t0 = - 0.013480470;
- t0 = t0 * t4 + 0.057477314;
- t0 = t0 * t4 - 0.121239071;
- t0 = t0 * t4 + 0.195635925;
- t0 = t0 * t4 - 0.332994597;
- t0 = t0 * t4 + 0.999995630;
- t3 = t0 * t3;
-
- t3 = (abs(y) > abs(x)) ? 1.570796327 - t3 : t3;
- t3 = (x < 0.0) ? 3.141592654 - t3 : t3;
- t3 = (y < 0.0) ? -t3 : t3;
-
- return t3;
-}
-
-// kind of inaccurate, but no sucky discontinuities!
-float completelyFakeAsin(float x)
-{
- return (x * x * x + x) * 0.78539816339;
-}
-
-vec4 getEyeCoord(vec2 fragCoord) {
- vec2 coords = fragCoord / czm_viewport.zw;
- float depth = czm_unpackDepth(texture2D(czm_globeDepthTexture, coords));
- vec4 windowCoord = vec4(fragCoord, depth, 1.0);
- vec4 eyeCoord = czm_windowToEyeCoordinates(windowCoord);
- return eyeCoord;
-}
-
-vec3 getEyeCoord3FromWindowCoord(vec2 fragCoord, float depth) {
- vec4 windowCoord = vec4(fragCoord, depth, 1.0);
- vec4 eyeCoord = czm_windowToEyeCoordinates(windowCoord);
- return eyeCoord.xyz / eyeCoord.w;
-}
-
-vec3 getVectorFromOffset(vec3 eyeCoord, vec2 fragCoord2, vec2 positiveOffset) {
- // Sample depths at both offset and negative offset
- float upOrRightDepth = czm_unpackDepth(texture2D(czm_globeDepthTexture, (fragCoord2 + positiveOffset) / czm_viewport.zw));
- float downOrLeftDepth = czm_unpackDepth(texture2D(czm_globeDepthTexture, (fragCoord2 - positiveOffset) / czm_viewport.zw));
-
- // Explicitly evaluate both paths
- bvec2 upOrRightInBounds = lessThan(fragCoord2 + positiveOffset, czm_viewport.zw);
- float useUpOrRight = float(upOrRightDepth > 0.0 && upOrRightInBounds.x && upOrRightInBounds.y);
- float useDownOrLeft = float(useUpOrRight == 0.0);
-
- vec3 upOrRightEC = getEyeCoord3FromWindowCoord(fragCoord2 + positiveOffset, upOrRightDepth);
- vec3 downOrLeftEC = getEyeCoord3FromWindowCoord(fragCoord2 - positiveOffset, downOrLeftDepth);
-
- return (upOrRightEC - eyeCoord) * useUpOrRight + (eyeCoord - downOrLeftEC) * useDownOrLeft;
-}
-
-void main(void)
-{
-#ifdef VECTOR_TILE
- gl_FragColor = u_highlightColor;
-#else
- #ifdef PER_INSTANCE_COLOR
- gl_FragColor = v_color;
- #else
-
- vec2 fragCoord2 = gl_FragCoord.xy;
- vec4 eyeCoord = getEyeCoord(fragCoord2);
- vec4 worldCoord4 = czm_inverseView * eyeCoord;
- vec3 worldCoord = worldCoord4.xyz / worldCoord4.w;
-
- vec3 sphereNormal = normalize(worldCoord);
-
- float latitude = completelyFakeAsin(sphereNormal.z); // find a dress for the ball Sinderella
- float longitude = atan2Ref(sphereNormal.y, sphereNormal.x); // the kitTans weep
-
- float u = (latitude - v_sphericalExtents.y) * v_sphericalExtents.w;
- float v = (longitude - v_sphericalExtents.x) * v_sphericalExtents.z;
-
- /*
- if (u <= 0.0 || 1.0 <= u || v <= 0.0 || 1.0 <= v) {
- discard; // TODO: re-enable me when Ellipses aren't broken and when batching is necessary
- }*/
-
- vec3 positionToEyeEC = -(czm_modelView * vec4(worldCoord, 1.0)).xyz;
-
- // compute normal. sample adjacent pixels in 2x2 block in screen space
- float d = 1.0;
- vec3 eyeCoord3 = eyeCoord.xyz / eyeCoord.w;
- vec3 downUp = getVectorFromOffset(eyeCoord3, fragCoord2, vec2(0.0, d));
- vec3 leftRight = getVectorFromOffset(eyeCoord3, fragCoord2, vec2(d, 0.0));
-
- vec3 normalEC = normalize(cross(downUp, leftRight));
-
- czm_materialInput materialInput;
- materialInput.normalEC = normalEC;
- materialInput.tangentToEyeMatrix = czm_eastNorthUpToEyeCoordinates(worldCoord, normalEC);
- materialInput.positionToEyeEC = positionToEyeEC;
- materialInput.st.x = v;
- materialInput.st.y = u;
- czm_material material = czm_getMaterial(materialInput);
-
- gl_FragColor = czm_phong(normalize(positionToEyeEC), material);
- #endif
-
-#endif
- czm_writeDepthClampedToFarPlane();
-}
From f9ca2604604a8b5a9750ba18fd5601443308a0bb Mon Sep 17 00:00:00 2001
From: Kangning Li value
.
*/
CesiumMath.sinh = function(value) {
- var part1 = Math.pow(Math.E, value);
- var part2 = Math.pow(Math.E, -1.0 * value);
+ var paropposite = Math.pow(Math.E, value);
+ var part = Math.pow(Math.E, -1.0 * value);
- return (part1 - part2) * 0.5;
+ return (paropposite - part) * 0.5;
};
/**
@@ -291,10 +291,10 @@ define([
* @returns {Number} The hyperbolic cosine of value
.
*/
CesiumMath.cosh = function(value) {
- var part1 = Math.pow(Math.E, value);
- var part2 = Math.pow(Math.E, -1.0 * value);
+ var paropposite = Math.pow(Math.E, value);
+ var part = Math.pow(Math.E, -1.0 * value);
- return (part1 + part2) * 0.5;
+ return (paropposite + part) * 0.5;
};
/**
@@ -871,7 +871,35 @@ define([
*/
CesiumMath.fastApproximateAtan = function(x) {
return x * (-0.1784 * Math.abs(x) - 0.0663 * x * x + 1.0301);
- }
+ };
+
+ /**
+ * Computes a fast approximation of Atan2(x, y) for arbitrary input scalars.
+ *
+ * Range reduction math based on nvidia's cg reference implementation: http://developer.download.nvidia.com/cg/atan2.html
+ *
+ * @param {Number} x An input number that isn't zero if y is zero.
+ * @param {Number} y An input number that isn't zero if x is zero.
+ * @returns {Number} An approximation of atan2(x, y)
+ * @private
+ */
+ CesiumMath.fastApproximateAtan2 = function(x, y) {
+ // atan approximations are usually only reliable over [-1, 1]
+ // So reduce the range by flipping whether x or y is on top.
+ var opposite, adjacent, t; // t used as swap and atan result.
+ t = Math.abs(x);
+ opposite = Math.abs(y);
+ adjacent = Math.max(t, opposite);
+ opposite = Math.min(t, opposite);
+
+ t = CesiumMath.fastApproximateAtan(opposite / adjacent);
+
+ // Undo range reduction
+ t = Math.abs(y) > Math.abs(x) ? CesiumMath.PI_OVER_TWO - t : t;
+ t = x < 0.0 ? CesiumMath.PI - t : t;
+ t = y < 0.0 ? -t : t;
+ return t;
+ };
return CesiumMath;
});
diff --git a/Source/Core/SphericalExtentsGeometryInstanceAttribute.js b/Source/Core/SphericalExtentsGeometryInstanceAttribute.js
index ede903c7953..38ae807a88b 100644
--- a/Source/Core/SphericalExtentsGeometryInstanceAttribute.js
+++ b/Source/Core/SphericalExtentsGeometryInstanceAttribute.js
@@ -16,29 +16,14 @@ define([
Ellipsoid) {
'use strict';
- function approximateSphericalLatitude(normal) {
- var normalZ = normal.z;
- var magXY = Math.sqrt(normal.x * normal.x + normal.y * normal.y);
- var q = normalZ / magXY;
- if (Math.abs(q) < 1.0) {
- return CesiumMath.fastApproximateAtan(normalZ / magXY);
- } else {
- return CesiumMath.sign(normalZ) * CesiumMath.PI_OVER_TWO - CesiumMath.fastApproximateAtan(magXY / normalZ);
- }
+ function approximateSphericalLatitude(spherePoint) {
+ // Project into plane with vertical for latitude
+ var magXY = Math.sqrt(spherePoint.x * spherePoint.x + spherePoint.y * spherePoint.y);
+ return CesiumMath.fastApproximateAtan2(magXY, spherePoint.z);
}
- function approximateSphericalLongitude(normal) {
- var magXY = Math.sqrt(normal.x * normal.x + normal.y * normal.y);
- var x = normal.x / magXY;
- var y = normal.y / magXY;
- if (Math.abs(y / x) < 1.0) {
- if (x < 0.0) {
- return CesiumMath.sign(y) * CesiumMath.PI - CesiumMath.fastApproximateAtan(y / Math.abs(x));
- }
- return CesiumMath.fastApproximateAtan(y / x);
- } else {
- return CesiumMath.sign(y) * CesiumMath.PI_OVER_TWO - CesiumMath.fastApproximateAtan(x / y);
- }
+ function approximateSphericalLongitude(spherePoint) {
+ return CesiumMath.fastApproximateAtan2(spherePoint.x, spherePoint.y);
}
var cartographicScratch = new Cartographic();
@@ -50,10 +35,8 @@ define([
carto.height = 0.0;
var cartesian = Cartographic.toCartesian(carto, Ellipsoid.WGS84, cartesian3Scratch);
- var sphereNormal = Cartesian3.normalize(cartesian, cartesian);
-
- var sphereLatitude = approximateSphericalLatitude(sphereNormal);
- var sphereLongitude = approximateSphericalLongitude(sphereNormal);
+ var sphereLatitude = approximateSphericalLatitude(cartesian);
+ var sphereLongitude = approximateSphericalLongitude(cartesian);
result.x = sphereLatitude;
result.y = sphereLongitude;
diff --git a/Source/Scene/createShadowVolumeAppearanceShader.js b/Source/Scene/createShadowVolumeAppearanceShader.js
index 5475515c6f8..49b4c22b90a 100644
--- a/Source/Scene/createShadowVolumeAppearanceShader.js
+++ b/Source/Scene/createShadowVolumeAppearanceShader.js
@@ -138,9 +138,8 @@ define([
}
if (shaderDependencies.requiresTexcoords) {
glsl +=
- ' // compute sphere normal for spherical coordinates\n' +
- ' vec3 sphereNormal = normalize(worldCoord);\n' +
- ' vec2 sphericalLatLong = czm_approximateSphericalCoordinates(sphereNormal);\n' +
+ ' // Treat world coords as a sphere normal for spherical coordinates\n' +
+ ' vec2 sphericalLatLong = czm_approximateSphericalCoordinates(worldCoord);\n' +
' float u = (sphericalLatLong.x - v_sphericalExtents.y) * v_sphericalExtents.w;\n' +
' float v = (sphericalLatLong.y - v_sphericalExtents.x) * v_sphericalExtents.z;\n';
}
diff --git a/Source/Shaders/Builtin/Functions/approximateSphericalCoordinates.glsl b/Source/Shaders/Builtin/Functions/approximateSphericalCoordinates.glsl
index a7d6aaa399f..d9d915da0cc 100644
--- a/Source/Shaders/Builtin/Functions/approximateSphericalCoordinates.glsl
+++ b/Source/Shaders/Builtin/Functions/approximateSphericalCoordinates.glsl
@@ -2,60 +2,40 @@
// "Efficient approximations for the arctangent function," Rajan, S. Sichun Wang Inkol, R. Joyal, A., May 2006.
// Adapted from ShaderFastLibs under MIT License.
//
-// Chosen for the following characteristics over range [-1, 1]:
-// - basically no error at -1 and 1, important for getting around range limit (atan2 via atan requires infinite range atan)
-// - no need for function mirroring due to range reduction (neede when only approximating [0, 1])
+// Chosen for the following characteristics over range [0, 1]:
+// - basically no error at 0 and 1, important for getting around range limit (naive atan2 via atan requires infinite range atan)
// - no visible artifacts from first-derivative discontinuities, unlike latitude via range-reduced sqrt asin approximations (at equator)
-float fastApproximateAtan(float x) {
- return x * (-0.1784 * abs(x) - 0.0663 * x * x + 1.0301);
+//
+// The original code is x * (-0.1784 * abs(x) - 0.0663 * x * x + 1.0301);
+// Removed the abs() in here because it isn't needed, the input range is guaranteed as [0, 1] by how we're approximating atan2.
+float fastApproximateAtan01(float x) {
+ return x * (-0.1784 * x - 0.0663 * x * x + 1.0301);
}
-// Compute longitude using an approximate Atan function
-// Because our Atan approximation doesn't have infinite range,
-// need to "flip and offset" the result periodically.
-float longitudeApproximateAtan(vec2 xy) {
- float inAtanBounds = float(abs(xy.y / xy.x) < 1.0);
- float outAtanBounds = float(inAtanBounds == 0.0);
- float q = inAtanBounds * (xy.y / (sign(xy.x) * xy.x)) + outAtanBounds * (xy.x / xy.y);
-
- return inAtanBounds * (abs(min(sign(xy.x), 0.0)) * (sign(xy.y) * czm_pi)) + outAtanBounds * (sign(xy.y) * czm_piOverTwo) +
- (inAtanBounds * sign(xy.x) - outAtanBounds) * fastApproximateAtan(q);
-
- /* branch equivalent: */
- //if (abs(xy.y / xy.x) < 1.0) {
- // float signX = sign(xy.x);
- // return abs(min(signX, 0.0)) * (sign(xy.y) * czm_pi) + signX * fastApproximateAtan(xy.y / (signX * xy.x));
- // /* branch equivalent: */
- // //if (xy.x < 0.0) {
- // // return sign(xy.y) * czm_pi - fastApproximateAtan(xy.y / abs(xy.x));
- // //}
- // return fastApproximateAtan(xy.y / xy.x);
- //} else {
- // return sign(xy.y) * czm_piOverTwo - fastApproximateAtan(xy.x / xy.y);
- //}
+// Used in place of ternaries to trade some math for branching
+float branchFree(bool comparison, float a, float b) {
+ float useA = float(comparison);
+ return a * useA + b * (1.0 - useA);
}
-// Compute latitude using an approximate Atan function.
-// Because our Atan approximation doesn't have infinite range,
-// need to "flip and offset" the result when the vector passes 45 degrees offset from equator.
-// Consider:
-// atan(2 / 1) == pi/2 - atan(1 / 2)
-// atan(2 / -1) == -pi/2 - atan(1 / -2)
-// Using atan instead of asin because most asin approximations (and even some vendor implementations!)
-// are based on range reduction and sqrt, which causes first-derivative discontuinity and pinching at the equator.
-float latitudeApproximateAtan(float magXY, float normalZ) {
- float inAtanBounds = float(abs(normalZ / magXY) < 1.0);
- float outAtanBounds = float(inAtanBounds == 0.0);
- float q = inAtanBounds * (normalZ / magXY) + outAtanBounds * (magXY / normalZ);
- return outAtanBounds * sign(normalZ) * czm_piOverTwo + (inAtanBounds - outAtanBounds) * fastApproximateAtan(q);
-
- /* branch equivalent: */
- //float q = normalZ / magXY;
- //if (abs(q) < 1.0) {
- // return fastApproximateAtan(normalZ / magXY);
- //} else {
- // return sign(normalZ) * czm_piOverTwo - fastApproximateAtan(magXY / normalZ);
- //}
+// Range reduction math based on nvidia's cg reference implementation for atan2: http://developer.download.nvidia.com/cg/atan2.html
+// However, we replaced their atan curve with Michael Drobot's.
+float fastApproximateAtan2(float x, float y) {
+ // atan approximations are usually only reliable over [-1, 1], or, in our case, [0, 1] due to modifications.
+ // So range-reduce using abs and by flipping whether x or y is on top.
+ float opposite, adjacent, t; // t used as swap and atan result.
+ t = abs(x);
+ opposite = abs(y);
+ adjacent = max(t, opposite);
+ opposite = min(t, opposite);
+
+ t = fastApproximateAtan01(opposite / adjacent);
+
+ // Undo range reduction
+ t = branchFree(abs(y) > abs(x), czm_piOverTwo - t, t);
+ t = branchFree(x < 0.0, czm_pi - t, t);
+ t = branchFree(y < 0.0, -t, t);
+ return t;
}
/**
@@ -72,10 +52,7 @@ float latitudeApproximateAtan(float magXY, float normalZ) {
*/
vec2 czm_approximateSphericalCoordinates(vec3 normal) {
// Project into plane with vertical for latitude
- float magXY = sqrt(normal.x * normal.x + normal.y * normal.y);
-
- // Project into equatorial plane for longitude
- vec2 xy = normal.xy / magXY;
-
- return vec2(latitudeApproximateAtan(magXY, normal.z), longitudeApproximateAtan(xy));
+ float latitudeApproximation = fastApproximateAtan2(sqrt(normal.x * normal.x + normal.y * normal.y), normal.z);
+ float longitudeApproximation = fastApproximateAtan2(normal.x, normal.y);
+ return vec2(latitudeApproximation, longitudeApproximation);
}
diff --git a/Specs/Core/MathSpec.js b/Specs/Core/MathSpec.js
index ff75ba27569..47761187e8e 100644
--- a/Specs/Core/MathSpec.js
+++ b/Specs/Core/MathSpec.js
@@ -444,8 +444,14 @@ defineSuite([
});
it('fastApproximateAtan', function() {
- expect(CesiumMath.fastApproximateAtan(0.0)).toEqualEpsilon(0.0, CesiumMath.EPSILON7);
- expect(CesiumMath.fastApproximateAtan(1.0)).toEqualEpsilon(CesiumMath.PI_OVER_FOUR, CesiumMath.EPSILON7);
- expect(CesiumMath.fastApproximateAtan(-1.0)).toEqualEpsilon(-CesiumMath.PI_OVER_FOUR, CesiumMath.EPSILON7);
+ expect(CesiumMath.fastApproximateAtan(0.0)).toEqualEpsilon(0.0, CesiumMath.EPSILON3);
+ expect(CesiumMath.fastApproximateAtan(1.0)).toEqualEpsilon(CesiumMath.PI_OVER_FOUR, CesiumMath.EPSILON3);
+ expect(CesiumMath.fastApproximateAtan(-1.0)).toEqualEpsilon(-CesiumMath.PI_OVER_FOUR, CesiumMath.EPSILON3);
+ });
+
+ it('fastApproximateAtan2', function() {
+ expect(CesiumMath.fastApproximateAtan2(1.0, 0.0)).toEqualEpsilon(0.0, CesiumMath.EPSILON3);
+ expect(CesiumMath.fastApproximateAtan2(1.0, 1.0)).toEqualEpsilon(CesiumMath.PI_OVER_FOUR, CesiumMath.EPSILON3);
+ expect(CesiumMath.fastApproximateAtan2(-1.0, 1.0)).toEqualEpsilon(CesiumMath.PI_OVER_FOUR + CesiumMath.PI_OVER_TWO, CesiumMath.EPSILON3);
});
});
diff --git a/Specs/Renderer/BuiltinFunctionsSpec.js b/Specs/Renderer/BuiltinFunctionsSpec.js
index b1e80ffad5a..8d4e31bc613 100644
--- a/Specs/Renderer/BuiltinFunctionsSpec.js
+++ b/Specs/Renderer/BuiltinFunctionsSpec.js
@@ -366,4 +366,15 @@ defineSuite([
fragmentShader : fs
}).contextToRender();
});
+
+ it('has czm_approximateSphericalCoordinates', function() {
+ var fs =
+ 'void main() { ' +
+ ' gl_FragColor = vec4(all(equal(czm_approximateSphericalCoordinates(vec3(1.0, 0.0, 0.0)), vec2(0.0, 0.0))));' +
+ '}';
+ expect({
+ context : context,
+ fragmentShader : fs
+ }).contextToRender();
+ });
}, 'WebGL');
From e7c4679e4bdc0b984873293785a3399d78fa5705 Mon Sep 17 00:00:00 2001
From: Kangning Li true
and componentDatatype
is an integer format,
+ * indicate that the components should be mapped to the range [0, 1] (unsigned)
+ * or [-1, 1] (signed) when they are accessed as floating-point for rendering.
+ *
+ * @memberof PlanarExtentsGeometryInstanceAttribute.prototype
+ *
+ * @type {Boolean}
+ * @readonly
+ *
+ * @default false
+ */
+ normalize : {
+ get : function() {
+ return false;
+ }
+ }
+ });
+
+ var cartographicScratch = new Cartographic();
+ var northMiddleScratch = new Cartesian3();
+ var southMiddleScratch = new Cartesian3();
+ /**
+ * Plane extents needed when computing ground primitive texture coordinates per-instance in the latitude direction.
+ * Used for "small distances."
+ * Consists of an oct-32 encoded normal packed to a float, a float distance, and a float range
+ *
+ * @alias PlanarExtentsGeometryInstanceAttribute
+ * @constructor
+ *
+ * @param {Rectangle} rectangle Conservative bounding rectangle around the instance.
+ * @param {Ellipoid} ellipsoid Ellipsoid for converting rectangle bounds to intertial fixed coordinates.
+ *
+ * @see GeometryInstance
+ * @see GeometryInstanceAttribute
+ * @see createShadowVolumeAppearanceShader
+ * @private
+ */
+ PlanarExtentsGeometryInstanceAttribute.getLatitudeExtents = function(rectangle, ellipsoid) {
+ //>>includeStart('debug', pragmas.debug);
+ Check.typeOf.object('rectangle', rectangle);
+ Check.typeOf.object('ellipsoid', ellipsoid);
+ //>>includeEnd('debug');
+
+ var cartographic = cartographicScratch;
+
+ cartographic.latitude = rectangle.north;
+ cartographic.longitude = (rectangle.east + rectangle.west) * 0.5;
+ var northMiddle = Cartographic.toCartesian(cartographic, ellipsoid, northMiddleScratch);
+
+ cartographic.latitude = rectangle.south;
+ var southMiddle = Cartographic.toCartesian(cartographic, ellipsoid, southMiddleScratch);
+
+ return new PlanarExtentsGeometryInstanceAttribute(southMiddle, northMiddle);
+ }
+
+ var eastMiddleScratch = new Cartesian3();
+ var westMiddleScratch = new Cartesian3();
+
+ /**
+ * Plane extents needed when computing ground primitive texture coordinates per-instance in the longitude direction.
+ * Used for "small distances."
+ * Consists of an oct-32 encoded normal packed to a float, a float distance, and a float range
+ *
+ * @alias PlanarExtentsGeometryInstanceAttribute
+ * @constructor
+ *
+ * @param {Rectangle} rectangle Conservative bounding rectangle around the instance.
+ * @param {Ellipoid} ellipsoid Ellipsoid for converting rectangle bounds to intertial fixed coordinates.
+ *
+ * @see GeometryInstance
+ * @see GeometryInstanceAttribute
+ * @see createShadowVolumeAppearanceShader
+ * @private
+ */
+ PlanarExtentsGeometryInstanceAttribute.getLongitudeExtents = function(rectangle, ellipsoid) {
+ //>>includeStart('debug', pragmas.debug);
+ Check.typeOf.object('rectangle', rectangle);
+ Check.typeOf.object('ellipsoid', ellipsoid);
+ //>>includeEnd('debug');
+
+ var cartographic = cartographicScratch;
+
+ cartographic.latitude = (rectangle.north + rectangle.south) * 0.5;
+ cartographic.longitude = rectangle.east;
+ var eastMiddle = Cartographic.toCartesian(cartographic, ellipsoid, eastMiddleScratch);
+
+ cartographic.longitude = rectangle.west;
+ var westMiddle = Cartographic.toCartesian(cartographic, ellipsoid, westMiddleScratch);
+
+ return new PlanarExtentsGeometryInstanceAttribute(westMiddle, eastMiddle);
+ }
+
+ return PlanarExtentsGeometryInstanceAttribute;
+});
diff --git a/Source/Core/SphericalExtentsGeometryInstanceAttribute.js b/Source/Core/SphericalExtentsGeometryInstanceAttribute.js
index 38ae807a88b..796c1691d0a 100644
--- a/Source/Core/SphericalExtentsGeometryInstanceAttribute.js
+++ b/Source/Core/SphericalExtentsGeometryInstanceAttribute.js
@@ -2,6 +2,7 @@ define([
'./Cartesian2',
'./Cartesian3',
'./Cartographic',
+ './Check',
'./Math',
'./ComponentDatatype',
'./defineProperties',
@@ -10,6 +11,7 @@ define([
Cartesian2,
Cartesian3,
Cartographic,
+ Check,
CesiumMath,
ComponentDatatype,
defineProperties,
@@ -44,24 +46,44 @@ define([
}
var sphericalScratch = new Cartesian2();
+
+ /**
+ * Spherical extents needed when computing ground primitive texture coordinates per-instance.
+ * Used for "large distances."
+ * Computation is matched to in-shader approximations.
+ *
+ * Consists of western and southern spherical coordinates and inverse ranges.
+ *
+ * @alias SphericalExtentsGeometryInstanceAttribute
+ * @constructor
+ *
+ * @param {Rectangle} rectangle Conservative bounding rectangle around the instance.
+ *
+ * @see GeometryInstance
+ * @see GeometryInstanceAttribute
+ * @see createShadowVolumeAppearanceShader
+ * @private
+ */
function SphericalExtentsGeometryInstanceAttribute(rectangle) {
+ //>>includeStart('debug', pragmas.debug);
+ Check.typeOf.object('rectangle', rectangle);
+ //>>includeEnd('debug');
+
// rectangle cartographic coords !== spherical because it's on an ellipsoid
var southWestExtents = latLongToSpherical(rectangle.south, rectangle.west, sphericalScratch);
// Slightly pad extents to avoid floating point error when fragment culling at edges.
- // TODO: what's the best value for this?
- // TODO: should we undo this in the shader?
- var south = southWestExtents.x - 0.00001;
- var west = southWestExtents.y - 0.00001;
+ var south = southWestExtents.x - CesiumMath.EPSILON5;
+ var west = southWestExtents.y - CesiumMath.EPSILON5;
var northEastExtents = latLongToSpherical(rectangle.north, rectangle.east, sphericalScratch);
- var north = northEastExtents.x + 0.00001;
- var east = northEastExtents.y + 0.00001;
+ var north = northEastExtents.x + CesiumMath.EPSILON5;
+ var east = northEastExtents.y + CesiumMath.EPSILON5;
- var longitudeRange = 1.0 / (east - west);
- var latitudeRange = 1.0 / (north - south);
+ var longitudeRangeInverse = 1.0 / (east - west);
+ var latitudeRangeInverse = 1.0 / (north - south);
- this.value = new Float32Array([west, south, longitudeRange, latitudeRange]);
+ this.value = new Float32Array([west, south, longitudeRangeInverse, latitudeRangeInverse]);
}
defineProperties(SphericalExtentsGeometryInstanceAttribute.prototype, {
diff --git a/Source/Scene/GroundPrimitive.js b/Source/Scene/GroundPrimitive.js
index a19f277b606..5728934179c 100644
--- a/Source/Scene/GroundPrimitive.js
+++ b/Source/Scene/GroundPrimitive.js
@@ -15,6 +15,7 @@ define([
'../Core/isArray',
'../Core/Math',
'../Core/OrientedBoundingBox',
+ '../Core/PlanarExtentsGeometryInstanceAttribute',
'../Core/Rectangle',
'../Core/Resource',
'../Core/SphericalExtentsGeometryInstanceAttribute',
@@ -41,6 +42,7 @@ define([
isArray,
CesiumMath,
OrientedBoundingBox,
+ PlanarExtentsGeometryInstanceAttribute,
Rectangle,
Resource,
SphericalExtentsGeometryInstanceAttribute,
@@ -767,7 +769,7 @@ define([
}
// Now compute the min/max heights for the primitive
- setMinMaxTerrainHeights(this, rectangle, frameState.mapProjection.ellipsoid);
+ setMinMaxTerrainHeights(this, rectangle, ellipsoid);
var exaggeration = frameState.terrainExaggeration;
this._minHeight = this._minTerrainHeight * exaggeration;
this._maxHeight = this._maxTerrainHeight * exaggeration;
@@ -777,9 +779,13 @@ define([
geometry = instance.geometry;
instanceType = geometry.constructor;
+ var rectangle = getRectangle(frameState, geometry);
var attributes = {
- sphericalExtents : new SphericalExtentsGeometryInstanceAttribute(getRectangle(frameState, geometry))
+ sphericalExtents : new SphericalExtentsGeometryInstanceAttribute(rectangle),
+ longitudePlaneExtents : PlanarExtentsGeometryInstanceAttribute.getLongitudeExtents(rectangle, ellipsoid),
+ latitudePlaneExtents : PlanarExtentsGeometryInstanceAttribute.getLatitudeExtents(rectangle, ellipsoid)
};
+ // TODO: pick and choose?
var instanceAttributes = instance.attributes;
for (var attributeKey in instanceAttributes) {
if (instanceAttributes.hasOwnProperty(attributeKey)) {
diff --git a/Source/Scene/createShadowVolumeAppearanceShader.js b/Source/Scene/createShadowVolumeAppearanceShader.js
index 49b4c22b90a..daacdbe5e0c 100644
--- a/Source/Scene/createShadowVolumeAppearanceShader.js
+++ b/Source/Scene/createShadowVolumeAppearanceShader.js
@@ -17,19 +17,20 @@ define([
* Creates the shadow volume fragment shader for a ClassificationPrimitive to use a given appearance.
*
* @param {Appearance} appearance An Appearance to be used with a ClassificationPrimitive.
- * @param {Boolean} [sphericalExtentsCulling=false] Discard fragments outside the instance's spherical extents.
+ * @param {Boolean} [extentsCulling=false] Discard fragments outside the instance's spherical extents.
* @returns {String} Shader source for a fragment shader using the input appearance.
* @private
*/
- function createShadowVolumeAppearanceShader(appearance, sphericalExtentsCulling) {
+ function createShadowVolumeAppearanceShader(appearance, extentsCulling, small) {
//>>includeStart('debug', pragmas.debug);
Check.typeOf.object('appearance', appearance);
//>>includeEnd('debug');
- var extentsCull = defaultValue(sphericalExtentsCulling, false);
+ var extentsCull = defaultValue(extentsCulling, true);
+ var smallExtents = defaultValue(small, true);
if (appearance instanceof PerInstanceColorAppearance) {
- return getPerInstanceColorShader(extentsCull, appearance.flat);
+ return getPerInstanceColorShader(extentsCull, appearance.flat, smallExtents);
}
var shaderDependencies = shaderDependenciesScratch.reset();
@@ -50,16 +51,18 @@ define([
'#endif\n';
if (extentsCull || usesSt) {
glsl +=
- 'varying vec4 v_sphericalExtents;\n';
+ 'varying vec4 v_sphericalExtents;\n' +
+ 'varying vec4 v_planarExtentsLatitude;\n' +
+ 'varying vec4 v_planarExtentsLongitude;\n';
}
- glsl += getLocalFunctions(shaderDependencies);
+ glsl += getLocalFunctions(shaderDependencies, smallExtents);
glsl +=
'void main(void)\n' +
'{\n';
- glsl += getDependenciesAndCulling(shaderDependencies, extentsCull);
+ glsl += getDependenciesAndCulling(shaderDependencies, extentsCull, smallExtents);
glsl += ' czm_materialInput materialInput;\n';
if (usesNormalEC) {
@@ -86,26 +89,26 @@ define([
return glsl;
}
- function getPerInstanceColorShader(sphericalExtentsCulling, flatShading) {
+ function getPerInstanceColorShader(extentsCulling, flatShading, smallExtents) {
var glsl =
'#ifdef GL_EXT_frag_depth\n' +
'#extension GL_EXT_frag_depth : enable\n' +
'#endif\n' +
'varying vec4 v_color;\n';
- if (sphericalExtentsCulling) {
+ if (extentsCulling) {
glsl +=
'varying vec4 v_sphericalExtents;\n';
}
var shaderDependencies = shaderDependenciesScratch.reset();
- shaderDependencies.requiresTexcoords = sphericalExtentsCulling;
+ shaderDependencies.requiresTexcoords = extentsCulling;
shaderDependencies.requiresNormalEC = !flatShading;
- glsl += getLocalFunctions(shaderDependencies);
+ glsl += getLocalFunctions(shaderDependencies, smallExtents);
glsl += 'void main(void)\n' +
'{\n';
- glsl += getDependenciesAndCulling(shaderDependencies, sphericalExtentsCulling);
+ glsl += getDependenciesAndCulling(shaderDependencies, extentsCulling, smallExtents);
if (flatShading) {
glsl +=
@@ -125,7 +128,7 @@ define([
return glsl;
}
- function getDependenciesAndCulling(shaderDependencies, sphericalExtentsCulling) {
+ function getDependenciesAndCulling(shaderDependencies, extentsCulling, smallExtents) {
var glsl = '';
if (shaderDependencies.requiresEyeCoord) {
glsl +=
@@ -137,13 +140,20 @@ define([
' vec3 worldCoord = worldCoord4.xyz / worldCoord4.w;\n';
}
if (shaderDependencies.requiresTexcoords) {
- glsl +=
+ if (smallExtents) { // TODO: add ability to do long-and-narrows?
+ glsl +=
+ ' // Unpack planes and transform to eye space\n' +
+ ' float u = computePlanarTexcoord(v_planarExtentsLatitude, worldCoord);\n' +
+ ' float v = computePlanarTexcoord(v_planarExtentsLongitude, worldCoord);\n';
+ } else {
+ glsl +=
' // Treat world coords as a sphere normal for spherical coordinates\n' +
' vec2 sphericalLatLong = czm_approximateSphericalCoordinates(worldCoord);\n' +
' float u = (sphericalLatLong.x - v_sphericalExtents.y) * v_sphericalExtents.w;\n' +
- ' float v = (sphericalLatLong.y - v_sphericalExtents.x) * v_sphericalExtents.z;\n';
+ ' float v = (sphericalLatLong.y - v_sphericalExtents.x) * v_sphericalExtents.z;\n'; // TODO: clean up...
+ }
}
- if (sphericalExtentsCulling) {
+ if (extentsCulling) {
glsl +=
' if (u <= 0.0 || 1.0 <= u || v <= 0.0 || 1.0 <= v) {\n' + // TODO: there's floating point problems at the edges of rectangles. Use remapping.
' discard;\n' +
@@ -161,7 +171,7 @@ define([
return glsl;
}
- function getLocalFunctions(shaderDependencies) {
+ function getLocalFunctions(shaderDependencies, smallExtents) {
var glsl = '';
if (shaderDependencies.requiresEyeCoord) {
glsl +=
@@ -197,6 +207,13 @@ define([
' return (upOrRightEC - (eyeCoord.xyz / eyeCoord.w)) * useUpOrRight + ((eyeCoord.xyz / eyeCoord.w) - downOrLeftEC) * useDownOrLeft;\n' +
'}\n';
}
+ if (shaderDependencies.requiresTexcoords && smallExtents) {
+ glsl +=
+ 'float computePlanarTexcoord(vec4 packedPlanarExtent, vec3 worldCoords) {\n' +
+ ' // planar extent is a plane at the origin (so just a direction) and an extent distance.\n' +
+ ' return (dot(packedPlanarExtent.xyz, worldCoords)) * packedPlanarExtent.w;\n' +
+ '}\n';
+ }
return glsl;
}
diff --git a/Source/Shaders/Builtin/Functions/approximateSphericalCoordinates.glsl b/Source/Shaders/Builtin/Functions/approximateSphericalCoordinates.glsl
index d9d915da0cc..ace9edae9f0 100644
--- a/Source/Shaders/Builtin/Functions/approximateSphericalCoordinates.glsl
+++ b/Source/Shaders/Builtin/Functions/approximateSphericalCoordinates.glsl
@@ -46,7 +46,7 @@ float fastApproximateAtan2(float x, float y) {
* @name czm_approximateSphericalCoordinates
* @glslFunction
*
- * @param {vec3} normal Unit-length normal.
+ * @param {vec3} normal arbitrary-length normal.
*
* @returns {vec2} Approximate latitude and longitude spherical coordinates.
*/
diff --git a/Source/Shaders/ShadowVolumeVS.glsl b/Source/Shaders/ShadowVolumeVS.glsl
index 7e89b63a114..64f9297ac55 100644
--- a/Source/Shaders/ShadowVolumeVS.glsl
+++ b/Source/Shaders/ShadowVolumeVS.glsl
@@ -18,6 +18,8 @@ uniform float u_globeMinimumAltitude;
#ifndef VECTOR_TILE
varying vec4 v_sphericalExtents;
+varying vec4 v_planarExtentsLatitude;
+varying vec4 v_planarExtentsLongitude;
#endif
#ifdef PER_INSTANCE_COLOR
@@ -35,6 +37,8 @@ void main()
#endif
v_sphericalExtents = czm_batchTable_sphericalExtents(batchId);
+ v_planarExtentsLatitude = czm_batchTable_latitudePlaneExtents(batchId);
+ v_planarExtentsLongitude = czm_batchTable_longitudePlaneExtents(batchId);
vec4 position = czm_computePosition();
From 23d6dfbfc16c97b7bc81ed47059656ca2ebf4856 Mon Sep 17 00:00:00 2001
From: Kangning Li true
and componentDatatype
is an integer format,
+ * indicate that the components should be mapped to the range [0, 1] (unsigned)
+ * or [-1, 1] (signed) when they are accessed as floating-point for rendering.
+ *
+ * @memberof InversePlaneExtentsGeometryAttribute.prototype
+ *
+ * @type {Boolean}
+ * @readonly
+ *
+ * @default false
+ */
+ normalize : {
+ get : function() {
+ return false;
+ }
+ }
+ });
+
+ return InversePlaneExtentsGeometryAttribute;
+});
diff --git a/Source/Core/MatrixColumnGeometryInstanceAttribute.js b/Source/Core/MatrixColumnGeometryInstanceAttribute.js
new file mode 100644
index 00000000000..2e1e3e5680c
--- /dev/null
+++ b/Source/Core/MatrixColumnGeometryInstanceAttribute.js
@@ -0,0 +1,87 @@
+define([
+ './ComponentDatatype',
+ './defineProperties',
+ './Matrix4',
+ './Transforms'
+ ], function(
+ ComponentDatatype,
+ defineProperties,
+ Matrix4,
+ Transforms) {
+ 'use strict';
+
+ function MatrixColumnGeometryInstanceAttribute(array, startIndex) {
+ this.value = new Float32Array(array.slice(startIndex, startIndex + 4));
+ }
+
+ defineProperties(MatrixColumnGeometryInstanceAttribute.prototype, {
+ /**
+ * The datatype of each component in the attribute, e.g., individual elements in
+ * {@link MatrixColumnGeometryInstanceAttribute#value}.
+ *
+ * @memberof MatrixColumnGeometryInstanceAttribute.prototype
+ *
+ * @type {ComponentDatatype}
+ * @readonly
+ *
+ * @default {@link ComponentDatatype.FLOAT}
+ */
+ componentDatatype : {
+ get : function() {
+ return ComponentDatatype.FLOAT;
+ }
+ },
+
+ /**
+ * The number of components in the attributes, i.e., {@link MatrixColumnGeometryInstanceAttribute#value}.
+ *
+ * @memberof MatrixColumnGeometryInstanceAttribute.prototype
+ *
+ * @type {Number}
+ * @readonly
+ *
+ * @default 4
+ */
+ componentsPerAttribute : {
+ get : function() {
+ return 4;
+ }
+ },
+
+ /**
+ * When true
and componentDatatype
is an integer format,
+ * indicate that the components should be mapped to the range [0, 1] (unsigned)
+ * or [-1, 1] (signed) when they are accessed as floating-point for rendering.
+ *
+ * @memberof MatrixColumnGeometryInstanceAttribute.prototype
+ *
+ * @type {Boolean}
+ * @readonly
+ *
+ * @default false
+ */
+ normalize : {
+ get : function() {
+ return false;
+ }
+ }
+ });
+
+
+ var transformScratch = new Matrix4();
+ var packedArray = new Array(16).fill(0.0);
+ MatrixColumnGeometryInstanceAttribute.addAttributes = function(cartographicCenter, ellipsoid, attributes) { // TODO: this should prolly just swallow matrices
+ var transform = Transforms.eastNorthUpToFixedFrame(cartographicCenter, ellipsoid, transformScratch);
+
+ Matrix4.pack(transform, packedArray);
+ // TODO: should probably accept a name
+ attributes.column0 = new MatrixColumnGeometryInstanceAttribute(packedArray, 0);
+ attributes.column1 = new MatrixColumnGeometryInstanceAttribute(packedArray, 4);
+ attributes.column2 = new MatrixColumnGeometryInstanceAttribute(packedArray, 8);
+ attributes.column3 = new MatrixColumnGeometryInstanceAttribute(packedArray, 12);
+
+ console.log(packedArray);
+ }
+
+ return MatrixColumnGeometryInstanceAttribute;
+});
diff --git a/Source/Core/PlanarExtentsGeometryInstanceAttribute.js b/Source/Core/PlanarExtentsGeometryInstanceAttribute.js
deleted file mode 100644
index e0b8f257de2..00000000000
--- a/Source/Core/PlanarExtentsGeometryInstanceAttribute.js
+++ /dev/null
@@ -1,193 +0,0 @@
-define([
- './Cartesian2',
- './Cartesian3',
- './Cartographic',
- './Math',
- './Check',
- './ComponentDatatype',
- './defineProperties',
- './Ellipsoid',
- './Plane'
- ], function(
- Cartesian2,
- Cartesian3,
- Cartographic,
- CesiumMath,
- Check,
- ComponentDatatype,
- defineProperties,
- Ellipsoid,
- Plane) {
- 'use strict';
-
- var forwardScratch = new Cartesian3();
- var normalScratch = new Cartesian3();
- var upScratch = new Cartesian3();
- var rightScratch = new Cartesian3();
- var planeScratch = new Plane(Cartesian3.UNIT_X, 0.0);
- /**
- * Plane extents needed when computing ground primitive texture coordinates per-instance.
- * Used for "small distances."
- * Consists of a normal of magnitude range and a distance.
- *
- * @alias PlanarExtentsGeometryInstanceAttribute
- * @constructor
- *
- * @param {Cartesian3} rectangle Conservative bounding rectangle around the instance.
- * @param {Cartesian3} ellipsoid Ellipsoid for converting rectangle bounds to intertial fixed coordinates.
- *
- * @see GeometryInstance
- * @see GeometryInstanceAttribute
- * @see createShadowVolumeAppearanceShader
- * @private
- */
- function PlanarExtentsGeometryInstanceAttribute(origin, end) {
- //>>includeStart('debug', pragmas.debug);
- Check.typeOf.object('origin', origin);
- Check.typeOf.object('end', end);
- //>>includeEnd('debug');
-
- var forward = Cartesian3.subtract(end, origin, forwardScratch);
- forward = Cartesian3.normalize(forward, forward);
- var up = Cartesian3.normalize(origin, upScratch);
- var right = Cartesian3.cross(up, forward, rightScratch);
-
- var normal = Cartesian3.cross(up, right, normalScratch);
-
- var plane = planeScratch;
- plane.normal = normal;
- plane.distance = 0.0;
- var planeDistance = Plane.getPointDistance(plane, end);
-
- this.value = new Float32Array([normal.x, normal.y, normal.z, 1.0 / planeDistance]);
- }
-
- defineProperties(PlanarExtentsGeometryInstanceAttribute.prototype, {
- /**
- * The datatype of each component in the attribute, e.g., individual elements in
- * {@link PlanarExtentsGeometryInstanceAttribute#value}.
- *
- * @memberof PlanarExtentsGeometryInstanceAttribute.prototype
- *
- * @type {ComponentDatatype}
- * @readonly
- *
- * @default {@link ComponentDatatype.FLOAT}
- */
- componentDatatype : {
- get : function() {
- return ComponentDatatype.FLOAT;
- }
- },
-
- /**
- * The number of components in the attributes, i.e., {@link PlanarExtentsGeometryInstanceAttribute#value}.
- *
- * @memberof PlanarExtentsGeometryInstanceAttribute.prototype
- *
- * @type {Number}
- * @readonly
- *
- * @default 4
- */
- componentsPerAttribute : {
- get : function() {
- return 4;
- }
- },
-
- /**
- * When true
and componentDatatype
is an integer format,
- * indicate that the components should be mapped to the range [0, 1] (unsigned)
- * or [-1, 1] (signed) when they are accessed as floating-point for rendering.
- *
- * @memberof PlanarExtentsGeometryInstanceAttribute.prototype
- *
- * @type {Boolean}
- * @readonly
- *
- * @default false
- */
- normalize : {
- get : function() {
- return false;
- }
- }
- });
-
- var cartographicScratch = new Cartographic();
- var northMiddleScratch = new Cartesian3();
- var southMiddleScratch = new Cartesian3();
- /**
- * Plane extents needed when computing ground primitive texture coordinates per-instance in the latitude direction.
- * Used for "small distances."
- * Consists of an oct-32 encoded normal packed to a float, a float distance, and a float range
- *
- * @alias PlanarExtentsGeometryInstanceAttribute
- * @constructor
- *
- * @param {Rectangle} rectangle Conservative bounding rectangle around the instance.
- * @param {Ellipoid} ellipsoid Ellipsoid for converting rectangle bounds to intertial fixed coordinates.
- *
- * @see GeometryInstance
- * @see GeometryInstanceAttribute
- * @see createShadowVolumeAppearanceShader
- * @private
- */
- PlanarExtentsGeometryInstanceAttribute.getLatitudeExtents = function(rectangle, ellipsoid) {
- //>>includeStart('debug', pragmas.debug);
- Check.typeOf.object('rectangle', rectangle);
- Check.typeOf.object('ellipsoid', ellipsoid);
- //>>includeEnd('debug');
-
- var cartographic = cartographicScratch;
-
- cartographic.latitude = rectangle.north;
- cartographic.longitude = (rectangle.east + rectangle.west) * 0.5;
- var northMiddle = Cartographic.toCartesian(cartographic, ellipsoid, northMiddleScratch);
-
- cartographic.latitude = rectangle.south;
- var southMiddle = Cartographic.toCartesian(cartographic, ellipsoid, southMiddleScratch);
-
- return new PlanarExtentsGeometryInstanceAttribute(southMiddle, northMiddle);
- }
-
- var eastMiddleScratch = new Cartesian3();
- var westMiddleScratch = new Cartesian3();
-
- /**
- * Plane extents needed when computing ground primitive texture coordinates per-instance in the longitude direction.
- * Used for "small distances."
- * Consists of an oct-32 encoded normal packed to a float, a float distance, and a float range
- *
- * @alias PlanarExtentsGeometryInstanceAttribute
- * @constructor
- *
- * @param {Rectangle} rectangle Conservative bounding rectangle around the instance.
- * @param {Ellipoid} ellipsoid Ellipsoid for converting rectangle bounds to intertial fixed coordinates.
- *
- * @see GeometryInstance
- * @see GeometryInstanceAttribute
- * @see createShadowVolumeAppearanceShader
- * @private
- */
- PlanarExtentsGeometryInstanceAttribute.getLongitudeExtents = function(rectangle, ellipsoid) {
- //>>includeStart('debug', pragmas.debug);
- Check.typeOf.object('rectangle', rectangle);
- Check.typeOf.object('ellipsoid', ellipsoid);
- //>>includeEnd('debug');
-
- var cartographic = cartographicScratch;
-
- cartographic.latitude = (rectangle.north + rectangle.south) * 0.5;
- cartographic.longitude = rectangle.east;
- var eastMiddle = Cartographic.toCartesian(cartographic, ellipsoid, eastMiddleScratch);
-
- cartographic.longitude = rectangle.west;
- var westMiddle = Cartographic.toCartesian(cartographic, ellipsoid, westMiddleScratch);
-
- return new PlanarExtentsGeometryInstanceAttribute(westMiddle, eastMiddle);
- }
-
- return PlanarExtentsGeometryInstanceAttribute;
-});
diff --git a/Source/Scene/GroundPrimitive.js b/Source/Scene/GroundPrimitive.js
index 5728934179c..a6c8231f23f 100644
--- a/Source/Scene/GroundPrimitive.js
+++ b/Source/Scene/GroundPrimitive.js
@@ -15,7 +15,8 @@ define([
'../Core/isArray',
'../Core/Math',
'../Core/OrientedBoundingBox',
- '../Core/PlanarExtentsGeometryInstanceAttribute',
+ '../Core/InversePlaneExtentsGeometryAttribute',
+ '../Core/MatrixColumnGeometryInstanceAttribute',
'../Core/Rectangle',
'../Core/Resource',
'../Core/SphericalExtentsGeometryInstanceAttribute',
@@ -42,7 +43,8 @@ define([
isArray,
CesiumMath,
OrientedBoundingBox,
- PlanarExtentsGeometryInstanceAttribute,
+ InversePlaneExtentsGeometryAttribute,
+ MatrixColumnGeometryInstanceAttribute,
Rectangle,
Resource,
SphericalExtentsGeometryInstanceAttribute,
@@ -782,9 +784,12 @@ define([
var rectangle = getRectangle(frameState, geometry);
var attributes = {
sphericalExtents : new SphericalExtentsGeometryInstanceAttribute(rectangle),
- longitudePlaneExtents : PlanarExtentsGeometryInstanceAttribute.getLongitudeExtents(rectangle, ellipsoid),
- latitudePlaneExtents : PlanarExtentsGeometryInstanceAttribute.getLatitudeExtents(rectangle, ellipsoid)
+ inversePlaneExtents : new InversePlaneExtentsGeometryAttribute(rectangle, ellipsoid)
};
+
+ var rectangleCenter = Rectangle.center(rectangle, new Cartographic());
+ MatrixColumnGeometryInstanceAttribute.addAttributes(Cartographic.toCartesian(rectangleCenter, ellipsoid, new Cartesian3()), ellipsoid, attributes);
+
// TODO: pick and choose?
var instanceAttributes = instance.attributes;
for (var attributeKey in instanceAttributes) {
diff --git a/Source/Scene/createShadowVolumeAppearanceShader.js b/Source/Scene/createShadowVolumeAppearanceShader.js
index daacdbe5e0c..1026bf42811 100644
--- a/Source/Scene/createShadowVolumeAppearanceShader.js
+++ b/Source/Scene/createShadowVolumeAppearanceShader.js
@@ -26,7 +26,7 @@ define([
Check.typeOf.object('appearance', appearance);
//>>includeEnd('debug');
- var extentsCull = defaultValue(extentsCulling, true);
+ var extentsCull = defaultValue(extentsCulling, false);
var smallExtents = defaultValue(small, true);
if (appearance instanceof PerInstanceColorAppearance) {
@@ -52,8 +52,9 @@ define([
if (extentsCull || usesSt) {
glsl +=
'varying vec4 v_sphericalExtents;\n' +
- 'varying vec4 v_planarExtentsLatitude;\n' +
- 'varying vec4 v_planarExtentsLongitude;\n';
+ 'varying vec2 v_inversePlaneExtents;\n' +
+ 'varying vec4 v_westPlane;\n' +
+ 'varying vec4 v_southPlane;\n';
}
glsl += getLocalFunctions(shaderDependencies, smallExtents);
@@ -143,8 +144,8 @@ define([
if (smallExtents) { // TODO: add ability to do long-and-narrows?
glsl +=
' // Unpack planes and transform to eye space\n' +
- ' float u = computePlanarTexcoord(v_planarExtentsLatitude, worldCoord);\n' +
- ' float v = computePlanarTexcoord(v_planarExtentsLongitude, worldCoord);\n';
+ ' float u = computePlanarTexcoord(v_southPlane, eyeCoord.xyz / eyeCoord.w, v_inversePlaneExtents.y);\n' +
+ ' float v = computePlanarTexcoord(v_westPlane, eyeCoord.xyz / eyeCoord.w, v_inversePlaneExtents.x);\n';
} else {
glsl +=
' // Treat world coords as a sphere normal for spherical coordinates\n' +
@@ -209,9 +210,9 @@ define([
}
if (shaderDependencies.requiresTexcoords && smallExtents) {
glsl +=
- 'float computePlanarTexcoord(vec4 packedPlanarExtent, vec3 worldCoords) {\n' +
+ 'float computePlanarTexcoord(vec4 plane, vec3 eyeCoords, float inverseExtent) {\n' +
' // planar extent is a plane at the origin (so just a direction) and an extent distance.\n' +
- ' return (dot(packedPlanarExtent.xyz, worldCoords)) * packedPlanarExtent.w;\n' +
+ ' return (dot(plane.xyz, eyeCoords) + plane.w) * inverseExtent;\n' +
'}\n';
}
return glsl;
diff --git a/Source/Shaders/ShadowVolumeVS.glsl b/Source/Shaders/ShadowVolumeVS.glsl
index 64f9297ac55..2273e8cc611 100644
--- a/Source/Shaders/ShadowVolumeVS.glsl
+++ b/Source/Shaders/ShadowVolumeVS.glsl
@@ -18,8 +18,9 @@ uniform float u_globeMinimumAltitude;
#ifndef VECTOR_TILE
varying vec4 v_sphericalExtents;
-varying vec4 v_planarExtentsLatitude;
-varying vec4 v_planarExtentsLongitude;
+varying vec2 v_inversePlaneExtents;
+varying vec4 v_westPlane;
+varying vec4 v_southPlane;
#endif
#ifdef PER_INSTANCE_COLOR
@@ -37,8 +38,23 @@ void main()
#endif
v_sphericalExtents = czm_batchTable_sphericalExtents(batchId);
- v_planarExtentsLatitude = czm_batchTable_latitudePlaneExtents(batchId);
- v_planarExtentsLongitude = czm_batchTable_longitudePlaneExtents(batchId);
+ vec2 inversePlaneExtents = czm_batchTable_inversePlaneExtents(batchId);
+
+ mat4 planesModel;
+ planesMatrix[0] = czm_batchTable_column0(batchId);
+ planesMatrix[1] = czm_batchTable_column1(batchId);
+ planesMatrix[2] = czm_batchTable_column2(batchId);
+ planesMatrix[3] = czm_batchTable_column3(batchId);
+
+ // Planes in local ENU coordinate system
+ vec4 westPlane = vec4(1.0, 0.0, 0.0, -0.5 / inversePlaneExtents.x);
+ vec4 southPlane = vec4(0.0, 1.0, 0.0, -0.5 / inversePlaneExtents.y);
+
+ mat4 planesModelView = czm_view * planesModel;
+
+ v_inversePlaneExtents = inversePlaneExtents;
+ v_westPlane = czm_transformPlane(westPlane, planesModelView);
+ v_southPlane = czm_transformPlane(southPlane, planesModelView);
vec4 position = czm_computePosition();
From 62ab0ba993ab8a0bd85c9f45fb141355039238da Mon Sep 17 00:00:00 2001
From: Kangning Li true
and componentDatatype
is an integer format,
- * indicate that the components should be mapped to the range [0, 1] (unsigned)
- * or [-1, 1] (signed) when they are accessed as floating-point for rendering.
- *
- * @memberof InversePlaneExtentsGeometryAttribute.prototype
- *
- * @type {Boolean}
- * @readonly
- *
- * @default false
- */
- normalize : {
- get : function() {
- return false;
- }
- }
- });
-
- return InversePlaneExtentsGeometryAttribute;
-});
diff --git a/Source/Core/MatrixColumnGeometryInstanceAttribute.js b/Source/Core/MatrixColumnGeometryInstanceAttribute.js
deleted file mode 100644
index 2e1e3e5680c..00000000000
--- a/Source/Core/MatrixColumnGeometryInstanceAttribute.js
+++ /dev/null
@@ -1,87 +0,0 @@
-define([
- './ComponentDatatype',
- './defineProperties',
- './Matrix4',
- './Transforms'
- ], function(
- ComponentDatatype,
- defineProperties,
- Matrix4,
- Transforms) {
- 'use strict';
-
- function MatrixColumnGeometryInstanceAttribute(array, startIndex) {
- this.value = new Float32Array(array.slice(startIndex, startIndex + 4));
- }
-
- defineProperties(MatrixColumnGeometryInstanceAttribute.prototype, {
- /**
- * The datatype of each component in the attribute, e.g., individual elements in
- * {@link MatrixColumnGeometryInstanceAttribute#value}.
- *
- * @memberof MatrixColumnGeometryInstanceAttribute.prototype
- *
- * @type {ComponentDatatype}
- * @readonly
- *
- * @default {@link ComponentDatatype.FLOAT}
- */
- componentDatatype : {
- get : function() {
- return ComponentDatatype.FLOAT;
- }
- },
-
- /**
- * The number of components in the attributes, i.e., {@link MatrixColumnGeometryInstanceAttribute#value}.
- *
- * @memberof MatrixColumnGeometryInstanceAttribute.prototype
- *
- * @type {Number}
- * @readonly
- *
- * @default 4
- */
- componentsPerAttribute : {
- get : function() {
- return 4;
- }
- },
-
- /**
- * When true
and componentDatatype
is an integer format,
- * indicate that the components should be mapped to the range [0, 1] (unsigned)
- * or [-1, 1] (signed) when they are accessed as floating-point for rendering.
- *
- * @memberof MatrixColumnGeometryInstanceAttribute.prototype
- *
- * @type {Boolean}
- * @readonly
- *
- * @default false
- */
- normalize : {
- get : function() {
- return false;
- }
- }
- });
-
-
- var transformScratch = new Matrix4();
- var packedArray = new Array(16).fill(0.0);
- MatrixColumnGeometryInstanceAttribute.addAttributes = function(cartographicCenter, ellipsoid, attributes) { // TODO: this should prolly just swallow matrices
- var transform = Transforms.eastNorthUpToFixedFrame(cartographicCenter, ellipsoid, transformScratch);
-
- Matrix4.pack(transform, packedArray);
- // TODO: should probably accept a name
- attributes.column0 = new MatrixColumnGeometryInstanceAttribute(packedArray, 0);
- attributes.column1 = new MatrixColumnGeometryInstanceAttribute(packedArray, 4);
- attributes.column2 = new MatrixColumnGeometryInstanceAttribute(packedArray, 8);
- attributes.column3 = new MatrixColumnGeometryInstanceAttribute(packedArray, 12);
-
- console.log(packedArray);
- }
-
- return MatrixColumnGeometryInstanceAttribute;
-});
diff --git a/Source/Core/ReferencePointGeometryInstanceAttribute.js b/Source/Core/ReferencePointGeometryInstanceAttribute.js
new file mode 100644
index 00000000000..844ef132029
--- /dev/null
+++ b/Source/Core/ReferencePointGeometryInstanceAttribute.js
@@ -0,0 +1,150 @@
+define([
+ './Cartesian3',
+ './Cartographic',
+ './Check',
+ './ComponentDatatype',
+ './defined',
+ './defineProperties',
+ './EncodedCartesian3',
+ './Matrix4',
+ './Transforms'
+ ], function(
+ Cartesian3,
+ Cartographic,
+ Check,
+ ComponentDatatype,
+ defined,
+ defineProperties,
+ EncodedCartesian3,
+ Matrix4,
+ Transforms) {
+ 'use strict';
+
+ /**
+ * Batch table attribute representing the HIGH or LOW bits of an EncodedCartesian3.
+ *
+ * @param {Cartesian3} vec3 HIGH or LOW bits of an EncodedCartesian3
+ * @private
+ */
+ function ReferencePointGeometryInstanceAttribute(vec3) {
+ this.value = new Float32Array([vec3.x, vec3.y, vec3.z]);
+ }
+
+ defineProperties(ReferencePointGeometryInstanceAttribute.prototype, {
+ /**
+ * The datatype of each component in the attribute, e.g., individual elements in
+ * {@link ReferencePointGeometryInstanceAttribute#value}.
+ *
+ * @memberof ReferencePointGeometryInstanceAttribute.prototype
+ *
+ * @type {ComponentDatatype}
+ * @readonly
+ *
+ * @default {@link ComponentDatatype.FLOAT}
+ */
+ componentDatatype : {
+ get : function() {
+ return ComponentDatatype.FLOAT;
+ }
+ },
+
+ /**
+ * The number of components in the attributes, i.e., {@link ReferencePointGeometryInstanceAttribute#value}.
+ *
+ * @memberof ReferencePointGeometryInstanceAttribute.prototype
+ *
+ * @type {Number}
+ * @readonly
+ *
+ * @default 3
+ */
+ componentsPerAttribute : {
+ get : function() {
+ return 3;
+ }
+ },
+
+ /**
+ * When true
and componentDatatype
is an integer format,
+ * indicate that the components should be mapped to the range [0, 1] (unsigned)
+ * or [-1, 1] (signed) when they are accessed as floating-point for rendering.
+ *
+ * @memberof ReferencePointGeometryInstanceAttribute.prototype
+ *
+ * @type {Boolean}
+ * @readonly
+ *
+ * @default false
+ */
+ normalize : {
+ get : function() {
+ return false;
+ }
+ }
+ });
+
+ var encodeScratch = new EncodedCartesian3();
+ function addAttributesForPoint(point, name, attributes) {
+ var encoded = EncodedCartesian3.fromCartesian(point, encodeScratch);
+ attributes[name + '_HIGH'] = new ReferencePointGeometryInstanceAttribute(encoded.high);
+ attributes[name + '_LOW'] = new ReferencePointGeometryInstanceAttribute(encoded.low);
+ }
+
+ var cartographicScratch = new Cartographic();
+ var cornerScratch = new Cartesian3();
+ var northWestScratch = new Cartesian3();
+ var southEastScratch = new Cartesian3();
+ /**
+ * Gets a set of 6 GeometryInstanceAttributes containing double-precision points in world/CBF space.
+ * These points can be used to form planes, which can then be used to compute per-fragment texture coordinates
+ * over a small rectangle area.
+ *
+ * @param {Rectangle} rectangle Rectangle bounds over which texture coordinates should be computed.
+ * @param {Ellipsoid} ellipsoid Ellipsoid for computing CBF/World coordinates from the rectangle.
+ * @private
+ */
+ ReferencePointGeometryInstanceAttribute.getAttributesForPlanes = function(rectangle, ellipsoid) {
+ //>>includeStart('debug', pragmas.debug);
+ Check.typeOf.object('rectangle', rectangle);
+ Check.typeOf.object('ellipsoid', ellipsoid);
+ //>>includeEnd('debug');
+
+ // Compute corner positions in double precision
+ var carto = cartographicScratch;
+ carto.longitude = rectangle.west;
+ carto.latitude = rectangle.south;
+
+ var corner = Cartographic.toCartesian(carto, ellipsoid, cornerScratch);
+
+ carto.latitude = rectangle.north;
+ var northWest = Cartographic.toCartesian(carto, ellipsoid, northWestScratch);
+
+ carto.longitude = rectangle.east;
+ carto.latitude = rectangle.south;
+ var southEast = Cartographic.toCartesian(carto, ellipsoid, southEastScratch);
+
+ var attributes = {};
+ addAttributesForPoint(corner, 'southWest', attributes);
+ addAttributesForPoint(northWest, 'northWest', attributes);
+ addAttributesForPoint(southEast, 'southEast', attributes);
+ return attributes;
+ };
+
+ /**
+ * Checks if the given attributes contain all the attributes needed for double-precision planes.
+ *
+ * @param {Object} attributes Attributes object.
+ * @return {Boolean} Whether the attributes contain all the attributes for double-precision planes.
+ * @private
+ */
+ ReferencePointGeometryInstanceAttribute.hasAttributesForPlanes = function(attributes) {
+ //>>includeStart('debug', pragmas.debug);
+ Check.typeOf.object('attributes', attributes);
+ //>>includeEnd('debug');
+ return defined(attributes.southWest_HIGH) && defined(attributes.southWest_LOW) &&
+ defined(attributes.northWest_HIGH) && defined(attributes.northWest_LOW) &&
+ defined(attributes.southEast_HIGH) && defined(attributes.southEast_LOW);
+ };
+
+ return ReferencePointGeometryInstanceAttribute;
+});
diff --git a/Source/Scene/ClassificationPrimitive.js b/Source/Scene/ClassificationPrimitive.js
index fc9835cd939..d9df35177c6 100644
--- a/Source/Scene/ClassificationPrimitive.js
+++ b/Source/Scene/ClassificationPrimitive.js
@@ -8,6 +8,7 @@ define([
'../Core/DeveloperError',
'../Core/GeometryInstance',
'../Core/Rectangle',
+ '../Core/ReferencePointGeometryInstanceAttribute',
'../Core/WebGLConstants',
'../Core/isArray',
'../Renderer/DrawCommand',
@@ -20,13 +21,13 @@ define([
'../ThirdParty/when',
'./BlendingState',
'./ClassificationType',
- './createShadowVolumeAppearanceShader',
'./DepthFunction',
'./Material',
'./MaterialAppearance',
'./PerInstanceColorAppearance',
'./Primitive',
'./SceneMode',
+ './ShadowVolumeAppearanceShader',
'./StencilFunction',
'./StencilOperation'
], function(
@@ -39,6 +40,7 @@ define([
DeveloperError,
GeometryInstance,
Rectangle,
+ ReferencePointGeometryInstanceAttribute,
WebGLConstants,
isArray,
DrawCommand,
@@ -51,13 +53,13 @@ define([
when,
BlendingState,
ClassificationType,
- createShadowVolumeAppearanceShader,
DepthFunction,
Material,
MaterialAppearance,
PerInstanceColorAppearance,
Primitive,
SceneMode,
+ ShadowVolumeAppearanceShader,
StencilFunction,
StencilOperation) {
'use strict';
@@ -198,7 +200,9 @@ define([
var hasPerColorAttribute = false;
var hasSphericalExtentsAttribute = false;
- var geometryInstancesArray = isArray(geometryInstances) ? geometryInstances : [geometryInstances];
+ var hasPlanarExtentsAttributes = false;
+
+ var geometryInstancesArray = isArray(geometryInstances) ? geometryInstances : [geometryInstances];
var geometryInstanceCount = geometryInstancesArray.length;
for (var i = 0; i < geometryInstanceCount; i++) {
var attributes = geometryInstancesArray[i].attributes;
@@ -212,7 +216,13 @@ define([
hasSphericalExtentsAttribute = true;
} else if (hasSphericalExtentsAttribute) {
throw new DeveloperError('All GeometryInstances must have the same attributes.');
- }
+ }
+ if (ReferencePointGeometryInstanceAttribute.hasAttributesForPlanes(attributes)) {
+ hasPlanarExtentsAttributes = true;
+ } else if (hasPlanarExtentsAttributes) {
+ throw new DeveloperError('All GeometryInstances must have the same attributes.');
+ }
+
} else if (hasPerColorAttribute || hasSphericalExtentsAttribute) {
throw new DeveloperError('All GeometryInstances must have the same attributes.');
}
@@ -228,13 +238,14 @@ define([
throw new DeveloperError('PerInstanceColorAppearance requires color GeometryInstanceAttribute');
}
- // TODO: SphericalExtents needed if PerInstanceColor isn't all the same
- if (defined(appearance.material) && !hasSphericalExtentsAttribute) {
- throw new DeveloperError('Materials on ClassificationPrimitives requires sphericalExtents GeometryInstanceAttribute');
+ // TODO: SphericalExtents or PlanarExtents needed if PerInstanceColor isn't all the same
+ if (defined(appearance.material) && !hasSphericalExtentsAttribute && !hasPlanarExtentsAttributes) {
+ throw new DeveloperError('Materials on ClassificationPrimitives requires sphericalExtents GeometryInstanceAttribute or GeometryInstanceAttributes for computing planes');
}
this._hasPerColorAttribute = hasPerColorAttribute;
this._hasSphericalExtentsAttribute = hasSphericalExtentsAttribute;
+ this._hasPlanarExtentsAttributes = hasPlanarExtentsAttributes;
this.appearance = appearance;
var readOnlyAttributes;
@@ -642,21 +653,32 @@ define([
var appearance = classificationPrimitive.appearance;
var isPerInstanceColor = appearance instanceof PerInstanceColorAppearance;
- var vsColorSource = new ShaderSource({
- defines : isPerInstanceColor ? ['PER_INSTANCE_COLOR'] : [],
- sources : [vs]
- });
-
var parts;
// Create a fragment shader that computes only required material hookups using screen space techniques
- var shadowVolumeAppearanceFS = createShadowVolumeAppearanceShader(appearance);
+ var usePlanarExtents = classificationPrimitive._hasPlanarExtentsAttributes;
+ var cullUsingExtents = classificationPrimitive._hasPlanarExtentsAttributes || classificationPrimitive._hasSphericalExtentsAttribute;
+ var shadowVolumeAppearanceShader = new ShadowVolumeAppearanceShader(appearance, cullUsingExtents, usePlanarExtents);
+ var shadowVolumeAppearanceFS = shadowVolumeAppearanceShader.fragmentShaderSource;
if (isPerInstanceColor) {
parts = [shadowVolumeAppearanceFS];
} else {
parts = [appearance.material.shaderSource, shadowVolumeAppearanceFS];
}
+ var colorVSDefines = isPerInstanceColor ? ['PER_INSTANCE_COLOR'] : [];
+ if (shadowVolumeAppearanceShader.usesTexcoords) {
+ if (shadowVolumeAppearanceShader.planarExtents) {
+ colorVSDefines.push('PLANAR_EXTENTS');
+ } else {
+ colorVSDefines.push('SPHERICAL_EXTENTS');
+ }
+ }
+ var vsColorSource = new ShaderSource({
+ defines : colorVSDefines,
+ sources : [vs]
+ });
+
var fsColorSource = new ShaderSource({
sources : [parts.join('\n')]
});
@@ -1024,8 +1046,8 @@ define([
// Update primitive appearance
if (this._primitive.appearance !== appearance) {
// Check if the appearance is supported by the geometry attributes
- if (!this._hasSphericalExtentsAttribute && defined(appearance.material)) {
- throw new DeveloperError('Materials on ClassificationPrimitives requires sphericalExtents GeometryInstanceAttribute');
+ if (!this._hasSphericalExtentsAttribute && !this._hasPlanarExtentsAttributes && defined(appearance.material)) {
+ throw new DeveloperError('Materials on ClassificationPrimitives requires sphericalExtents GeometryInstanceAttribute or GeometryInstanceAttributes for computing planes');
}
if (!this._hasPerColorAttribute && appearance instanceof PerInstanceColorAppearance) {
throw new DeveloperError('PerInstanceColorAppearance requires color GeometryInstanceAttribute');
diff --git a/Source/Scene/GroundPrimitive.js b/Source/Scene/GroundPrimitive.js
index a6c8231f23f..1279fbeb29e 100644
--- a/Source/Scene/GroundPrimitive.js
+++ b/Source/Scene/GroundPrimitive.js
@@ -15,9 +15,8 @@ define([
'../Core/isArray',
'../Core/Math',
'../Core/OrientedBoundingBox',
- '../Core/InversePlaneExtentsGeometryAttribute',
- '../Core/MatrixColumnGeometryInstanceAttribute',
'../Core/Rectangle',
+ '../Core/ReferencePointGeometryInstanceAttribute',
'../Core/Resource',
'../Core/SphericalExtentsGeometryInstanceAttribute',
'../Renderer/Pass',
@@ -43,9 +42,8 @@ define([
isArray,
CesiumMath,
OrientedBoundingBox,
- InversePlaneExtentsGeometryAttribute,
- MatrixColumnGeometryInstanceAttribute,
Rectangle,
+ ReferencePointGeometryInstanceAttribute,
Resource,
SphericalExtentsGeometryInstanceAttribute,
Pass,
@@ -776,21 +774,34 @@ define([
this._minHeight = this._minTerrainHeight * exaggeration;
this._maxHeight = this._maxTerrainHeight * exaggeration;
+ // Determine whether to add spherical or planar extent attributes
+ var usePlanarExtents = true;
+ for (i = 0; i < length; ++i) {
+ instance = instances[i];
+ geometry = instance.geometry;
+ rectangle = getRectangle(frameState, geometry);
+ if (shouldUseSpherical(rectangle)) {
+ usePlanarExtents = false;
+ break;
+ }
+ }
+
for (i = 0; i < length; ++i) {
instance = instances[i];
geometry = instance.geometry;
instanceType = geometry.constructor;
- var rectangle = getRectangle(frameState, geometry);
- var attributes = {
- sphericalExtents : new SphericalExtentsGeometryInstanceAttribute(rectangle),
- inversePlaneExtents : new InversePlaneExtentsGeometryAttribute(rectangle, ellipsoid)
- };
+ rectangle = getRectangle(frameState, geometry);
+ var attributes;
- var rectangleCenter = Rectangle.center(rectangle, new Cartographic());
- MatrixColumnGeometryInstanceAttribute.addAttributes(Cartographic.toCartesian(rectangleCenter, ellipsoid, new Cartesian3()), ellipsoid, attributes);
+ if (usePlanarExtents) {
+ attributes = ReferencePointGeometryInstanceAttribute.getAttributesForPlanes(rectangle, ellipsoid, attributes);
+ } else {
+ attributes = {
+ sphericalExtents : new SphericalExtentsGeometryInstanceAttribute(rectangle)
+ };
+ }
- // TODO: pick and choose?
var instanceAttributes = instance.attributes;
for (var attributeKey in instanceAttributes) {
if (instanceAttributes.hasOwnProperty(attributeKey)) {
@@ -839,6 +850,10 @@ define([
this._classificationPrimitive.update(frameState);
};
+ function shouldUseSpherical(rectangle) {
+ return Math.max(rectangle.width, rectangle.height) > GroundPrimitive.MAX_WIDTH_FOR_PLANAR_EXTENTS;
+ }
+
/**
* @private
*/
@@ -909,5 +924,15 @@ define([
return destroyObject(this);
};
+ /**
+ * Texture coordinates for ground primitives are computed either using spherical coordinates for large areas or
+ * using distance from planes for small areas.
+ *
+ * @type {Number}
+ * @constant
+ * @private
+ */
+ GroundPrimitive.MAX_WIDTH_FOR_PLANAR_EXTENTS = CesiumMath.toRadians(1.0);
+
return GroundPrimitive;
});
diff --git a/Source/Scene/createShadowVolumeAppearanceShader.js b/Source/Scene/ShadowVolumeAppearanceShader.js
similarity index 83%
rename from Source/Scene/createShadowVolumeAppearanceShader.js
rename to Source/Scene/ShadowVolumeAppearanceShader.js
index 1026bf42811..db8ffb9115f 100644
--- a/Source/Scene/createShadowVolumeAppearanceShader.js
+++ b/Source/Scene/ShadowVolumeAppearanceShader.js
@@ -21,19 +21,61 @@ define([
* @returns {String} Shader source for a fragment shader using the input appearance.
* @private
*/
- function createShadowVolumeAppearanceShader(appearance, extentsCulling, small) {
+ function ShadowVolumeAppearanceShader(appearance, extentsCulling, planarExtents) {
//>>includeStart('debug', pragmas.debug);
Check.typeOf.object('appearance', appearance);
//>>includeEnd('debug');
- var extentsCull = defaultValue(extentsCulling, false);
- var smallExtents = defaultValue(small, true);
+ this._extentsCulling = defaultValue(extentsCulling, false);
+ this._planarExtents = defaultValue(planarExtents, false);
+ this._shaderSource = createShadowVolumeAppearanceShader(appearance, this._extentsCulling, this._planarExtents);
+ this._usesTexcoords = shaderDependenciesScratch._requiresTexcoords;
+ }
- if (appearance instanceof PerInstanceColorAppearance) {
- return getPerInstanceColorShader(extentsCull, appearance.flat, smallExtents);
+ defineProperties(ShadowVolumeAppearanceShader.prototype, {
+ /**
+ * Whether or not the resulting shader uses texture coordinates.
+ *
+ * @memberof ShadowVolumeAppearanceShader.prototype
+ * @type {Boolean}
+ * @readonly
+ */
+ usesTexcoords : {
+ get : function() {
+ return this._usesTexcoords;
+ }
+ },
+ /**
+ * Whether or not the resulting shader's texture coordinates are computed from planar extents.
+ *
+ * @memberof ShadowVolumeAppearanceShader.prototype
+ * @type {Boolean}
+ * @readonly
+ */
+ planarExtents : {
+ get : function() {
+ return this._planarExtents;
+ }
+ },
+ /**
+ * The fragment shader source.
+ * @memberof ShadowVolumeAppearanceShader.prototype
+ * @type {String}
+ * @readonly
+ */
+ fragmentShaderSource : {
+ get : function() {
+ return this._shaderSource;
+ }
}
+ });
+ function createShadowVolumeAppearanceShader(appearance, extentsCull, planarExtents) {
var shaderDependencies = shaderDependenciesScratch.reset();
+ if (appearance instanceof PerInstanceColorAppearance) {
+ return getPerInstanceColorShader(extentsCull, appearance.flat, planarExtents);
+ }
+
shaderDependencies.requiresTexcoords = extentsCull;
shaderDependencies.requiresEyeCoord = !appearance.flat;
@@ -50,20 +92,21 @@ define([
'#extension GL_EXT_frag_depth : enable\n' +
'#endif\n';
if (extentsCull || usesSt) {
- glsl +=
- 'varying vec4 v_sphericalExtents;\n' +
+ glsl += planarExtents ?
'varying vec2 v_inversePlaneExtents;\n' +
'varying vec4 v_westPlane;\n' +
- 'varying vec4 v_southPlane;\n';
+ 'varying vec4 v_southPlane;\n' :
+
+ 'varying vec4 v_sphericalExtents;\n';
}
- glsl += getLocalFunctions(shaderDependencies, smallExtents);
+ glsl += getLocalFunctions(shaderDependencies, planarExtents);
glsl +=
'void main(void)\n' +
'{\n';
- glsl += getDependenciesAndCulling(shaderDependencies, extentsCull, smallExtents);
+ glsl += getDependenciesAndCulling(shaderDependencies, extentsCull, planarExtents);
glsl += ' czm_materialInput materialInput;\n';
if (usesNormalEC) {
@@ -90,26 +133,30 @@ define([
return glsl;
}
- function getPerInstanceColorShader(extentsCulling, flatShading, smallExtents) {
+ function getPerInstanceColorShader(extentsCulling, flatShading, planarExtents) {
var glsl =
'#ifdef GL_EXT_frag_depth\n' +
'#extension GL_EXT_frag_depth : enable\n' +
'#endif\n' +
'varying vec4 v_color;\n';
if (extentsCulling) {
- glsl +=
+ glsl += planarExtents ?
+ 'varying vec2 v_inversePlaneExtents;\n' +
+ 'varying vec4 v_westPlane;\n' +
+ 'varying vec4 v_southPlane;\n' :
+
'varying vec4 v_sphericalExtents;\n';
}
- var shaderDependencies = shaderDependenciesScratch.reset();
+ var shaderDependencies = shaderDependenciesScratch;
shaderDependencies.requiresTexcoords = extentsCulling;
shaderDependencies.requiresNormalEC = !flatShading;
- glsl += getLocalFunctions(shaderDependencies, smallExtents);
+ glsl += getLocalFunctions(shaderDependencies, planarExtents);
glsl += 'void main(void)\n' +
'{\n';
- glsl += getDependenciesAndCulling(shaderDependencies, extentsCulling, smallExtents);
+ glsl += getDependenciesAndCulling(shaderDependencies, extentsCulling, planarExtents);
if (flatShading) {
glsl +=
@@ -129,7 +176,7 @@ define([
return glsl;
}
- function getDependenciesAndCulling(shaderDependencies, extentsCulling, smallExtents) {
+ function getDependenciesAndCulling(shaderDependencies, extentsCulling, planarExtents) {
var glsl = '';
if (shaderDependencies.requiresEyeCoord) {
glsl +=
@@ -141,7 +188,7 @@ define([
' vec3 worldCoord = worldCoord4.xyz / worldCoord4.w;\n';
}
if (shaderDependencies.requiresTexcoords) {
- if (smallExtents) { // TODO: add ability to do long-and-narrows?
+ if (planarExtents) { // TODO: add ability to do long-and-narrows?
glsl +=
' // Unpack planes and transform to eye space\n' +
' float u = computePlanarTexcoord(v_southPlane, eyeCoord.xyz / eyeCoord.w, v_inversePlaneExtents.y);\n' +
@@ -172,7 +219,7 @@ define([
return glsl;
}
- function getLocalFunctions(shaderDependencies, smallExtents) {
+ function getLocalFunctions(shaderDependencies, planarExtents) {
var glsl = '';
if (shaderDependencies.requiresEyeCoord) {
glsl +=
@@ -196,7 +243,6 @@ define([
' // Sample depths at both offset and negative offset\n' +
' float upOrRightDepth = czm_unpackDepth(texture2D(czm_globeDepthTexture, (fragCoord2 + positiveOffset) / czm_viewport.zw));\n' +
' float downOrLeftDepth = czm_unpackDepth(texture2D(czm_globeDepthTexture, (fragCoord2 - positiveOffset) / czm_viewport.zw));\n' +
- // TODO: could re-ordering here help performance? do texture fetches, then logic, then unpack?
' // Explicitly evaluate both paths\n' +
' bvec2 upOrRightInBounds = lessThan(fragCoord2 + positiveOffset, czm_viewport.zw);\n' +
' float useUpOrRight = float(upOrRightDepth > 0.0 && upOrRightInBounds.x && upOrRightInBounds.y);\n' +
@@ -208,10 +254,9 @@ define([
' return (upOrRightEC - (eyeCoord.xyz / eyeCoord.w)) * useUpOrRight + ((eyeCoord.xyz / eyeCoord.w) - downOrLeftEC) * useDownOrLeft;\n' +
'}\n';
}
- if (shaderDependencies.requiresTexcoords && smallExtents) {
+ if (shaderDependencies.requiresTexcoords && planarExtents) {
glsl +=
'float computePlanarTexcoord(vec4 plane, vec3 eyeCoords, float inverseExtent) {\n' +
- ' // planar extent is a plane at the origin (so just a direction) and an extent distance.\n' +
' return (dot(plane.xyz, eyeCoords) + plane.w) * inverseExtent;\n' +
'}\n';
}
@@ -298,5 +343,5 @@ define([
}
});
- return createShadowVolumeAppearanceShader;
+ return ShadowVolumeAppearanceShader;
});
diff --git a/Source/Shaders/ShadowVolumeVS.glsl b/Source/Shaders/ShadowVolumeVS.glsl
index 2273e8cc611..55a0c9e1262 100644
--- a/Source/Shaders/ShadowVolumeVS.glsl
+++ b/Source/Shaders/ShadowVolumeVS.glsl
@@ -17,12 +17,19 @@ uniform float u_globeMinimumAltitude;
#endif
#ifndef VECTOR_TILE
+
+#ifdef SPHERICAL_EXTENTS
varying vec4 v_sphericalExtents;
+#endif
+
+#ifdef PLANAR_EXTENTS
varying vec2 v_inversePlaneExtents;
varying vec4 v_westPlane;
varying vec4 v_southPlane;
#endif
+#endif
+
#ifdef PER_INSTANCE_COLOR
varying vec4 v_color;
#endif
@@ -37,24 +44,27 @@ void main()
v_color = czm_batchTable_color(batchId);
#endif
+#ifdef SPHERICAL_EXTENTS
v_sphericalExtents = czm_batchTable_sphericalExtents(batchId);
- vec2 inversePlaneExtents = czm_batchTable_inversePlaneExtents(batchId);
+#endif
- mat4 planesModel;
- planesMatrix[0] = czm_batchTable_column0(batchId);
- planesMatrix[1] = czm_batchTable_column1(batchId);
- planesMatrix[2] = czm_batchTable_column2(batchId);
- planesMatrix[3] = czm_batchTable_column3(batchId);
+#ifdef PLANAR_EXTENTS
+ vec3 southWestCorner = (czm_modelViewRelativeToEye * czm_translateRelativeToEye(czm_batchTable_southWest_HIGH(batchId), czm_batchTable_southWest_LOW(batchId))).xyz;
+ vec3 northWestCorner = (czm_modelViewRelativeToEye * czm_translateRelativeToEye(czm_batchTable_northWest_HIGH(batchId), czm_batchTable_northWest_LOW(batchId))).xyz;
+ vec3 southEastCorner = (czm_modelViewRelativeToEye * czm_translateRelativeToEye(czm_batchTable_southEast_HIGH(batchId), czm_batchTable_southEast_LOW(batchId))).xyz;
- // Planes in local ENU coordinate system
- vec4 westPlane = vec4(1.0, 0.0, 0.0, -0.5 / inversePlaneExtents.x);
- vec4 southPlane = vec4(0.0, 1.0, 0.0, -0.5 / inversePlaneExtents.y);
+ vec3 eastWard = southEastCorner - southWestCorner;
+ float eastExtent = length(eastWard);
+ eastWard /= eastExtent;
- mat4 planesModelView = czm_view * planesModel;
+ vec3 northWard = northWestCorner - southWestCorner;
+ float northExtent = length(northWard);
+ northWard /= northExtent;
- v_inversePlaneExtents = inversePlaneExtents;
- v_westPlane = czm_transformPlane(westPlane, planesModelView);
- v_southPlane = czm_transformPlane(southPlane, planesModelView);
+ v_westPlane = vec4(eastWard, -dot(eastWard, southWestCorner));
+ v_southPlane = vec4(northWard, -dot(northWard, southWestCorner));
+ v_inversePlaneExtents = vec2(1.0 / eastExtent, 1.0 / northExtent);
+#endif
vec4 position = czm_computePosition();
From 2cb51327ad55cbd64b931ee2fe4eaa6c8215ff8e Mon Sep 17 00:00:00 2001
From: Kangning Li Loading...
Loading...
true
and componentDatatype
is an integer format,
- * indicate that the components should be mapped to the range [0, 1] (unsigned)
- * or [-1, 1] (signed) when they are accessed as floating-point for rendering.
- *
- * @memberof ReferencePointGeometryInstanceAttribute.prototype
- *
- * @type {Boolean}
- * @readonly
- *
- * @default false
- */
- normalize : {
- get : function() {
- return false;
- }
- }
- });
-
- var encodeScratch = new EncodedCartesian3();
- function addAttributesForPoint(point, name, attributes) {
- var encoded = EncodedCartesian3.fromCartesian(point, encodeScratch);
- attributes[name + '_HIGH'] = new ReferencePointGeometryInstanceAttribute(encoded.high);
- attributes[name + '_LOW'] = new ReferencePointGeometryInstanceAttribute(encoded.low);
- }
-
- var cartographicScratch = new Cartographic();
- var cornerScratch = new Cartesian3();
- var northWestScratch = new Cartesian3();
- var southEastScratch = new Cartesian3();
- /**
- * Gets a set of 6 GeometryInstanceAttributes containing double-precision points in world/CBF space.
- * These points can be used to form planes, which can then be used to compute per-fragment texture coordinates
- * over a small rectangle area.
- *
- * @param {Rectangle} rectangle Rectangle bounds over which texture coordinates should be computed.
- * @param {Ellipsoid} ellipsoid Ellipsoid for computing CBF/World coordinates from the rectangle.
- * @private
- */
- ReferencePointGeometryInstanceAttribute.getAttributesForPlanes = function(rectangle, ellipsoid) {
- //>>includeStart('debug', pragmas.debug);
- Check.typeOf.object('rectangle', rectangle);
- Check.typeOf.object('ellipsoid', ellipsoid);
- //>>includeEnd('debug');
-
- // Compute corner positions in double precision
- var carto = cartographicScratch;
- carto.longitude = rectangle.west;
- carto.latitude = rectangle.south;
-
- var corner = Cartographic.toCartesian(carto, ellipsoid, cornerScratch);
-
- carto.latitude = rectangle.north;
- var northWest = Cartographic.toCartesian(carto, ellipsoid, northWestScratch);
-
- carto.longitude = rectangle.east;
- carto.latitude = rectangle.south;
- var southEast = Cartographic.toCartesian(carto, ellipsoid, southEastScratch);
-
- var attributes = {};
- addAttributesForPoint(corner, 'southWest', attributes);
- addAttributesForPoint(northWest, 'northWest', attributes);
- addAttributesForPoint(southEast, 'southEast', attributes);
- return attributes;
- };
-
- /**
- * Checks if the given attributes contain all the attributes needed for double-precision planes.
- *
- * @param {Object} attributes Attributes object.
- * @return {Boolean} Whether the attributes contain all the attributes for double-precision planes.
- * @private
- */
- ReferencePointGeometryInstanceAttribute.hasAttributesForPlanes = function(attributes) {
- //>>includeStart('debug', pragmas.debug);
- Check.typeOf.object('attributes', attributes);
- //>>includeEnd('debug');
- return defined(attributes.southWest_HIGH) && defined(attributes.southWest_LOW) &&
- defined(attributes.northWest_HIGH) && defined(attributes.northWest_LOW) &&
- defined(attributes.southEast_HIGH) && defined(attributes.southEast_LOW);
- };
-
- return ReferencePointGeometryInstanceAttribute;
-});
diff --git a/Source/Core/SphericalExtentsGeometryInstanceAttribute.js b/Source/Core/SphericalExtentsGeometryInstanceAttribute.js
deleted file mode 100644
index 796c1691d0a..00000000000
--- a/Source/Core/SphericalExtentsGeometryInstanceAttribute.js
+++ /dev/null
@@ -1,143 +0,0 @@
-define([
- './Cartesian2',
- './Cartesian3',
- './Cartographic',
- './Check',
- './Math',
- './ComponentDatatype',
- './defineProperties',
- './Ellipsoid'
- ], function(
- Cartesian2,
- Cartesian3,
- Cartographic,
- Check,
- CesiumMath,
- ComponentDatatype,
- defineProperties,
- Ellipsoid) {
- 'use strict';
-
- function approximateSphericalLatitude(spherePoint) {
- // Project into plane with vertical for latitude
- var magXY = Math.sqrt(spherePoint.x * spherePoint.x + spherePoint.y * spherePoint.y);
- return CesiumMath.fastApproximateAtan2(magXY, spherePoint.z);
- }
-
- function approximateSphericalLongitude(spherePoint) {
- return CesiumMath.fastApproximateAtan2(spherePoint.x, spherePoint.y);
- }
-
- var cartographicScratch = new Cartographic();
- var cartesian3Scratch = new Cartesian3();
- function latLongToSpherical(latitude, longitude, result) {
- var carto = cartographicScratch;
- carto.latitude = latitude;
- carto.longitude = longitude;
- carto.height = 0.0;
-
- var cartesian = Cartographic.toCartesian(carto, Ellipsoid.WGS84, cartesian3Scratch);
- var sphereLatitude = approximateSphericalLatitude(cartesian);
- var sphereLongitude = approximateSphericalLongitude(cartesian);
- result.x = sphereLatitude;
- result.y = sphereLongitude;
-
- return result;
- }
-
- var sphericalScratch = new Cartesian2();
-
- /**
- * Spherical extents needed when computing ground primitive texture coordinates per-instance.
- * Used for "large distances."
- * Computation is matched to in-shader approximations.
- *
- * Consists of western and southern spherical coordinates and inverse ranges.
- *
- * @alias SphericalExtentsGeometryInstanceAttribute
- * @constructor
- *
- * @param {Rectangle} rectangle Conservative bounding rectangle around the instance.
- *
- * @see GeometryInstance
- * @see GeometryInstanceAttribute
- * @see createShadowVolumeAppearanceShader
- * @private
- */
- function SphericalExtentsGeometryInstanceAttribute(rectangle) {
- //>>includeStart('debug', pragmas.debug);
- Check.typeOf.object('rectangle', rectangle);
- //>>includeEnd('debug');
-
- // rectangle cartographic coords !== spherical because it's on an ellipsoid
- var southWestExtents = latLongToSpherical(rectangle.south, rectangle.west, sphericalScratch);
-
- // Slightly pad extents to avoid floating point error when fragment culling at edges.
- var south = southWestExtents.x - CesiumMath.EPSILON5;
- var west = southWestExtents.y - CesiumMath.EPSILON5;
-
- var northEastExtents = latLongToSpherical(rectangle.north, rectangle.east, sphericalScratch);
- var north = northEastExtents.x + CesiumMath.EPSILON5;
- var east = northEastExtents.y + CesiumMath.EPSILON5;
-
- var longitudeRangeInverse = 1.0 / (east - west);
- var latitudeRangeInverse = 1.0 / (north - south);
-
- this.value = new Float32Array([west, south, longitudeRangeInverse, latitudeRangeInverse]);
- }
-
- defineProperties(SphericalExtentsGeometryInstanceAttribute.prototype, {
- /**
- * The datatype of each component in the attribute, e.g., individual elements in
- * {@link SphericalExtentsGeometryInstanceAttribute#value}.
- *
- * @memberof SphericalExtentsGeometryInstanceAttribute.prototype
- *
- * @type {ComponentDatatype}
- * @readonly
- *
- * @default {@link ComponentDatatype.FLOAT}
- */
- componentDatatype : {
- get : function() {
- return ComponentDatatype.FLOAT;
- }
- },
-
- /**
- * The number of components in the attributes, i.e., {@link SphericalExtentsGeometryInstanceAttribute#value}.
- *
- * @memberof SphericalExtentsGeometryInstanceAttribute.prototype
- *
- * @type {Number}
- * @readonly
- *
- * @default 4
- */
- componentsPerAttribute : {
- get : function() {
- return 4;
- }
- },
-
- /**
- * When true
and componentDatatype
is an integer format,
- * indicate that the components should be mapped to the range [0, 1] (unsigned)
- * or [-1, 1] (signed) when they are accessed as floating-point for rendering.
- *
- * @memberof SphericalExtentsGeometryInstanceAttribute.prototype
- *
- * @type {Boolean}
- * @readonly
- *
- * @default false
- */
- normalize : {
- get : function() {
- return false;
- }
- }
- });
-
- return SphericalExtentsGeometryInstanceAttribute;
-});
diff --git a/Source/DataSources/CorridorGeometryUpdater.js b/Source/DataSources/CorridorGeometryUpdater.js
index dcf281359a6..1351b25b692 100644
--- a/Source/DataSources/CorridorGeometryUpdater.js
+++ b/Source/DataSources/CorridorGeometryUpdater.js
@@ -165,10 +165,8 @@ define([
};
CorridorGeometryUpdater.prototype._isOnTerrain = function(entity, corridor) {
- //var isColorMaterial = this._materialProperty instanceof ColorMaterialProperty;
-
return this._fillEnabled && !defined(corridor.height) && !defined(corridor.extrudedHeight) &&
- GroundPrimitive.isSupported(this._scene);// && isColorMaterial;
+ GroundPrimitive.isSupported(this._scene);
};
CorridorGeometryUpdater.prototype._getIsClosed = function(options) {
diff --git a/Source/DataSources/EllipseGeometryUpdater.js b/Source/DataSources/EllipseGeometryUpdater.js
index ec3f535408d..1da875c75e6 100644
--- a/Source/DataSources/EllipseGeometryUpdater.js
+++ b/Source/DataSources/EllipseGeometryUpdater.js
@@ -172,9 +172,7 @@ define([
};
EllipseGeometryUpdater.prototype._isOnTerrain = function(entity, ellipse) {
- //var isColorMaterial = this._materialProperty instanceof ColorMaterialProperty;
-
- return this._fillEnabled && !defined(ellipse.height) && !defined(ellipse.extrudedHeight) && GroundPrimitive.isSupported(this._scene); //&& isColorMaterial;
+ return this._fillEnabled && !defined(ellipse.height) && !defined(ellipse.extrudedHeight) && GroundPrimitive.isSupported(this._scene);
};
EllipseGeometryUpdater.prototype._isDynamic = function(entity, ellipse) {
diff --git a/Source/DataSources/PolygonGeometryUpdater.js b/Source/DataSources/PolygonGeometryUpdater.js
index 0f3067d3ece..cf537ebd95f 100644
--- a/Source/DataSources/PolygonGeometryUpdater.js
+++ b/Source/DataSources/PolygonGeometryUpdater.js
@@ -173,10 +173,9 @@ define([
};
PolygonGeometryUpdater.prototype._isOnTerrain = function(entity, polygon) {
- //var isColorMaterial = this._materialProperty instanceof ColorMaterialProperty;
var perPositionHeightProperty = polygon.perPositionHeight;
var perPositionHeightEnabled = defined(perPositionHeightProperty) && (perPositionHeightProperty.isConstant ? perPositionHeightProperty.getValue(Iso8601.MINIMUM_VALUE) : true);
- return this._fillEnabled && !defined(polygon.height) && !defined(polygon.extrudedHeight) &&// isColorMaterial &&
+ return this._fillEnabled && !defined(polygon.height) && !defined(polygon.extrudedHeight) &&
!perPositionHeightEnabled && GroundPrimitive.isSupported(this._scene);
};
diff --git a/Source/DataSources/RectangleGeometryUpdater.js b/Source/DataSources/RectangleGeometryUpdater.js
index a336bf4827c..256b17a1cb6 100644
--- a/Source/DataSources/RectangleGeometryUpdater.js
+++ b/Source/DataSources/RectangleGeometryUpdater.js
@@ -167,9 +167,7 @@ define([
};
RectangleGeometryUpdater.prototype._isOnTerrain = function(entity, rectangle) {
- //var isColorMaterial = this._materialProperty instanceof ColorMaterialProperty;
-
- return this._fillEnabled && !defined(rectangle.height) && !defined(rectangle.extrudedHeight) && GroundPrimitive.isSupported(this._scene); // && isColorMaterial;
+ return this._fillEnabled && !defined(rectangle.height) && !defined(rectangle.extrudedHeight) && GroundPrimitive.isSupported(this._scene);
};
RectangleGeometryUpdater.prototype._isDynamic = function(entity, rectangle) {
diff --git a/Source/DataSources/StaticGroundGeometryPerMaterialBatch.js b/Source/DataSources/StaticGroundGeometryPerMaterialBatch.js
index 9d4c9255354..d0c1971a121 100644
--- a/Source/DataSources/StaticGroundGeometryPerMaterialBatch.js
+++ b/Source/DataSources/StaticGroundGeometryPerMaterialBatch.js
@@ -6,7 +6,7 @@ define([
'../Core/DistanceDisplayCondition',
'../Core/DistanceDisplayConditionGeometryInstanceAttribute',
'../Core/ShowGeometryInstanceAttribute',
- '../Core/RectangleRbush',
+ '../Core/RectangleCollisionChecker',
'../Scene/GroundPrimitive',
'./BoundingSphereState',
'./ColorMaterialProperty',
@@ -20,7 +20,7 @@ define([
DistanceDisplayCondition,
DistanceDisplayConditionGeometryInstanceAttribute,
ShowGeometryInstanceAttribute,
- RectangleRbush,
+ RectangleCollisionChecker,
GroundPrimitive,
BoundingSphereState,
ColorMaterialProperty,
@@ -49,7 +49,7 @@ define([
this.showsUpdated = new AssociativeArray();
this.shadows = shadows;
this.usingSphericalCoordinates = usingSphericalCoordinates;
- this.rbush = new RectangleRbush();
+ this.rectangleCollisionCheck = new RectangleCollisionChecker();
}
Batch.prototype.onMaterialChanged = function() {
@@ -57,7 +57,7 @@ define([
};
Batch.prototype.nonOverlapping = function(rectangle) {
- return !this.rbush.collides(rectangle);
+ return !this.rectangleCollisionCheck.collides(rectangle);
};
Batch.prototype.isMaterial = function(updater) {
@@ -75,7 +75,7 @@ define([
var id = updater.id;
this.updaters.set(id, updater);
this.geometry.set(id, geometryInstance);
- this.rbush.insert(id, geometryInstance.geometry.rectangle);
+ this.rectangleCollisionCheck.insert(id, geometryInstance.geometry.rectangle);
if (!updater.hasConstantFill || !updater.fillMaterialProperty.isConstant || !Property.isConstant(updater.distanceDisplayConditionProperty)) {
this.updatersWithAttributes.set(id, updater);
} else {
@@ -94,7 +94,7 @@ define([
var geometryInstance = this.geometry.get(id);
this.createPrimitive = this.geometry.remove(id) || this.createPrimitive;
if (this.updaters.remove(id)) {
- this.rbush.remove(id, geometryInstance.geometry.rectangle);
+ this.rectangleCollisionCheck.remove(id, geometryInstance.geometry.rectangle);
this.updatersWithAttributes.remove(id);
var unsubscribe = this.subscriptions.get(id);
if (defined(unsubscribe)) {
diff --git a/Source/Scene/ClassificationPrimitive.js b/Source/Scene/ClassificationPrimitive.js
index d9df35177c6..9ac42e6a9fb 100644
--- a/Source/Scene/ClassificationPrimitive.js
+++ b/Source/Scene/ClassificationPrimitive.js
@@ -1,14 +1,21 @@
define([
+ '../Core/Cartesian2',
+ '../Core/Cartesian3',
+ '../Core/Cartographic',
+ '../Core/Math',
+ '../Core/Check',
'../Core/ColorGeometryInstanceAttribute',
'../Core/combine',
+ '../Core/ComponentDatatype',
'../Core/defaultValue',
'../Core/defined',
'../Core/defineProperties',
'../Core/destroyObject',
'../Core/DeveloperError',
+ '../Core/EncodedCartesian3',
'../Core/GeometryInstance',
+ '../Core/GeometryInstanceAttribute',
'../Core/Rectangle',
- '../Core/ReferencePointGeometryInstanceAttribute',
'../Core/WebGLConstants',
'../Core/isArray',
'../Renderer/DrawCommand',
@@ -31,16 +38,23 @@ define([
'./StencilFunction',
'./StencilOperation'
], function(
+ Cartesian2,
+ Cartesian3,
+ Cartographic,
+ CesiumMath,
+ Check,
ColorGeometryInstanceAttribute,
combine,
+ ComponentDatatype,
defaultValue,
defined,
defineProperties,
destroyObject,
DeveloperError,
+ EncodedCartesian3,
GeometryInstance,
+ GeometryInstanceAttribute,
Rectangle,
- ReferencePointGeometryInstanceAttribute,
WebGLConstants,
isArray,
DrawCommand,
@@ -67,10 +81,9 @@ define([
var ClassificationPrimitiveReadOnlyInstanceAttributes = ['color'];
/**
- * A classification primitive represents a volume enclosing geometry in the {@link Scene} to be highlighted. The geometry must be from a single {@link GeometryInstance}.
- * Batching multiple geometries is not yet supported.
+ * A classification primitive represents a volume enclosing geometry in the {@link Scene} to be highlighted.
* x
, y
, width
,
+ * and height
properties in an vec4
's x
, y
, z
,
+ * and w
components, respectively.
+ *
+ * @alias czm_viewport
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform vec4 czm_viewport;
+ *
+ * // 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({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_VEC4,
+ getValue : function(uniformState) {
+ return uniformState.viewportCartesian4;
+ }
+ }),
- var datatypeToGlsl = {};
- datatypeToGlsl[WebGLConstants.FLOAT] = 'float';
- datatypeToGlsl[WebGLConstants.FLOAT_VEC2] = 'vec2';
- datatypeToGlsl[WebGLConstants.FLOAT_VEC3] = 'vec3';
- datatypeToGlsl[WebGLConstants.FLOAT_VEC4] = 'vec4';
- datatypeToGlsl[WebGLConstants.INT] = 'int';
- datatypeToGlsl[WebGLConstants.INT_VEC2] = 'ivec2';
- datatypeToGlsl[WebGLConstants.INT_VEC3] = 'ivec3';
- datatypeToGlsl[WebGLConstants.INT_VEC4] = 'ivec4';
- datatypeToGlsl[WebGLConstants.BOOL] = 'bool';
- datatypeToGlsl[WebGLConstants.BOOL_VEC2] = 'bvec2';
- datatypeToGlsl[WebGLConstants.BOOL_VEC3] = 'bvec3';
- datatypeToGlsl[WebGLConstants.BOOL_VEC4] = 'bvec4';
- datatypeToGlsl[WebGLConstants.FLOAT_MAT2] = 'mat2';
- datatypeToGlsl[WebGLConstants.FLOAT_MAT3] = 'mat3';
- datatypeToGlsl[WebGLConstants.FLOAT_MAT4] = 'mat4';
- datatypeToGlsl[WebGLConstants.SAMPLER_2D] = 'sampler2D';
- datatypeToGlsl[WebGLConstants.SAMPLER_CUBE] = 'samplerCube';
-
- AutomaticUniform.prototype.getDeclaration = function(name) {
- var declaration = 'uniform ' + datatypeToGlsl[this._datatype] + ' ' + name;
-
- var size = this._size;
- if (size === 1) {
- declaration += ';';
- } else {
- declaration += '[' + size.toString() + '];';
+ /**
+ * An automatic GLSL uniform representing a 4x4 orthographic projection matrix that
+ * transforms window coordinates to clip coordinates. Clip coordinates is the
+ * coordinate system for a vertex shader's gl_Position
output.
+ *
+ * This transform is useful when a vertex shader inputs or manipulates window coordinates
+ * as done by {@link BillboardCollection}.
+ *
+ * Do not confuse {@link czm_viewportTransformation} with czm_viewportOrthographic
.
+ * The former transforms from normalized device coordinates to window coordinates; the later transforms
+ * from window coordinates to clip coordinates, and is often used to assign to gl_Position
.
+ *
+ * @alias czm_viewportOrthographic
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat4 czm_viewportOrthographic;
+ *
+ * // Example
+ * gl_Position = czm_viewportOrthographic * vec4(windowPosition, 0.0, 1.0);
+ *
+ * @see UniformState#viewportOrthographic
+ * @see czm_viewport
+ * @see czm_viewportTransformation
+ * @see BillboardCollection
+ */
+ czm_viewportOrthographic : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT4,
+ getValue : function(uniformState) {
+ return uniformState.viewportOrthographic;
}
+ }),
- return declaration;
- };
+ /**
+ * An automatic GLSL uniform representing a 4x4 transformation matrix that
+ * transforms normalized device coordinates to window coordinates. The context's
+ * full viewport is used, and the depth range is assumed to be near = 0
+ * and far = 1
.
+ *
+ * This transform is useful when there is a need to manipulate window coordinates
+ * in a vertex shader as done by {@link BillboardCollection}. In many cases,
+ * this matrix will not be used directly; instead, {@link czm_modelToWindowCoordinates}
+ * will be used to transform directly from model to window coordinates.
+ *
+ * Do not confuse czm_viewportTransformation
with {@link czm_viewportOrthographic}.
+ * The former transforms from normalized device coordinates to window coordinates; the later transforms
+ * from window coordinates to clip coordinates, and is often used to assign to gl_Position
.
+ *
+ * @alias czm_viewportTransformation
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat4 czm_viewportTransformation;
+ *
+ * // Use czm_viewportTransformation as part of the
+ * // transform from model to window coordinates.
+ * 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
+ * @see czm_modelToWindowCoordinates
+ * @see BillboardCollection
+ */
+ czm_viewportTransformation : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT4,
+ getValue : function(uniformState) {
+ return uniformState.viewportTransformation;
+ }
+ }),
/**
+ * An automatic GLSL uniform representing the depth after
+ * only the globe has been rendered and packed into an RGBA texture.
+ *
* @private
+ *
+ * @alias czm_globeDepthTexture
+ * @glslUniform
+ *
+ * @example
+ * // GLSL declaration
+ * uniform sampler2D czm_globeDepthTexture;
+ *
+ * // Get the depth at the current fragment
+ * vec2 coords = gl_FragCoord.xy / czm_viewport.zw;
+ * float depth = czm_unpackDepth(texture2D(czm_globeDepthTexture, coords));
+ */
+ czm_globeDepthTexture : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.SAMPLER_2D,
+ getValue : function(uniformState) {
+ return uniformState.globeDepthTexture;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 4x4 model transformation matrix that
+ * transforms model coordinates to world coordinates.
+ *
+ * @alias czm_model
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat4 czm_model;
+ *
+ * // Example
+ * vec4 worldPosition = czm_model * modelPosition;
+ *
+ * @see UniformState#model
+ * @see czm_inverseModel
+ * @see czm_modelView
+ * @see czm_modelViewProjection
+ */
+ czm_model : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT4,
+ getValue : function(uniformState) {
+ return uniformState.model;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 4x4 model transformation matrix that
+ * transforms world coordinates to model coordinates.
+ *
+ * @alias czm_inverseModel
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat4 czm_inverseModel;
+ *
+ * // Example
+ * vec4 modelPosition = czm_inverseModel * worldPosition;
+ *
+ * @see UniformState#inverseModel
+ * @see czm_model
+ * @see czm_inverseModelView
+ */
+ czm_inverseModel : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT4,
+ getValue : function(uniformState) {
+ return uniformState.inverseModel;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 4x4 view transformation matrix that
+ * transforms world coordinates to eye coordinates.
+ *
+ * @alias czm_view
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat4 czm_view;
+ *
+ * // Example
+ * vec4 eyePosition = czm_view * worldPosition;
+ *
+ * @see UniformState#view
+ * @see czm_viewRotation
+ * @see czm_modelView
+ * @see czm_viewProjection
+ * @see czm_modelViewProjection
+ * @see czm_inverseView
+ */
+ czm_view : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT4,
+ getValue : function(uniformState) {
+ return uniformState.view;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 4x4 view transformation matrix that
+ * transforms 3D world coordinates to eye coordinates. In 3D mode, this is identical to
+ * {@link czm_view}, but in 2D and Columbus View it represents the view matrix
+ * as if the camera were at an equivalent location in 3D mode. This is useful for lighting
+ * 2D and Columbus View in the same way that 3D is lit.
+ *
+ * @alias czm_view3D
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat4 czm_view3D;
+ *
+ * // Example
+ * vec4 eyePosition3D = czm_view3D * worldPosition3D;
+ *
+ * @see UniformState#view3D
+ * @see czm_view
+ */
+ czm_view3D : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT4,
+ getValue : function(uniformState) {
+ return uniformState.view3D;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 3x3 view rotation matrix that
+ * transforms vectors in world coordinates to eye coordinates.
+ *
+ * @alias czm_viewRotation
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat3 czm_viewRotation;
+ *
+ * // Example
+ * vec3 eyeVector = czm_viewRotation * worldVector;
+ *
+ * @see UniformState#viewRotation
+ * @see czm_view
+ * @see czm_inverseView
+ * @see czm_inverseViewRotation
+ */
+ czm_viewRotation : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT3,
+ getValue : function(uniformState) {
+ return uniformState.viewRotation;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 3x3 view rotation matrix that
+ * transforms vectors in 3D world coordinates to eye coordinates. In 3D mode, this is identical to
+ * {@link czm_viewRotation}, but in 2D and Columbus View it represents the view matrix
+ * as if the camera were at an equivalent location in 3D mode. This is useful for lighting
+ * 2D and Columbus View in the same way that 3D is lit.
+ *
+ * @alias czm_viewRotation3D
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat3 czm_viewRotation3D;
+ *
+ * // Example
+ * vec3 eyeVector = czm_viewRotation3D * worldVector;
+ *
+ * @see UniformState#viewRotation3D
+ * @see czm_viewRotation
+ */
+ czm_viewRotation3D : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT3,
+ getValue : function(uniformState) {
+ return uniformState.viewRotation3D;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 4x4 transformation matrix that
+ * transforms from eye coordinates to world coordinates.
+ *
+ * @alias czm_inverseView
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat4 czm_inverseView;
+ *
+ * // Example
+ * vec4 worldPosition = czm_inverseView * eyePosition;
+ *
+ * @see UniformState#inverseView
+ * @see czm_view
+ * @see czm_inverseNormal
+ */
+ czm_inverseView : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT4,
+ getValue : function(uniformState) {
+ return uniformState.inverseView;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 4x4 transformation matrix that
+ * transforms from 3D eye coordinates to world coordinates. In 3D mode, this is identical to
+ * {@link czm_inverseView}, but in 2D and Columbus View it represents the inverse view matrix
+ * as if the camera were at an equivalent location in 3D mode. This is useful for lighting
+ * 2D and Columbus View in the same way that 3D is lit.
+ *
+ * @alias czm_inverseView3D
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat4 czm_inverseView3D;
+ *
+ * // Example
+ * vec4 worldPosition = czm_inverseView3D * eyePosition;
+ *
+ * @see UniformState#inverseView3D
+ * @see czm_inverseView
+ */
+ czm_inverseView3D : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT4,
+ getValue : function(uniformState) {
+ return uniformState.inverseView3D;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 3x3 rotation matrix that
+ * transforms vectors from eye coordinates to world coordinates.
+ *
+ * @alias czm_inverseViewRotation
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat3 czm_inverseViewRotation;
+ *
+ * // Example
+ * vec4 worldVector = czm_inverseViewRotation * eyeVector;
+ *
+ * @see UniformState#inverseView
+ * @see czm_view
+ * @see czm_viewRotation
+ * @see czm_inverseViewRotation
+ */
+ czm_inverseViewRotation : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT3,
+ getValue : function(uniformState) {
+ return uniformState.inverseViewRotation;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 3x3 rotation matrix that
+ * transforms vectors from 3D eye coordinates to world coordinates. In 3D mode, this is identical to
+ * {@link czm_inverseViewRotation}, but in 2D and Columbus View it represents the inverse view matrix
+ * as if the camera were at an equivalent location in 3D mode. This is useful for lighting
+ * 2D and Columbus View in the same way that 3D is lit.
+ *
+ * @alias czm_inverseViewRotation3D
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat3 czm_inverseViewRotation3D;
+ *
+ * // Example
+ * vec4 worldVector = czm_inverseViewRotation3D * eyeVector;
+ *
+ * @see UniformState#inverseView3D
+ * @see czm_inverseViewRotation
+ */
+ czm_inverseViewRotation3D : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT3,
+ getValue : function(uniformState) {
+ return uniformState.inverseViewRotation3D;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 4x4 projection transformation matrix that
+ * transforms eye coordinates to clip coordinates. Clip coordinates is the
+ * coordinate system for a vertex shader's gl_Position
output.
+ *
+ * @alias czm_projection
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat4 czm_projection;
+ *
+ * // Example
+ * gl_Position = czm_projection * eyePosition;
+ *
+ * @see UniformState#projection
+ * @see czm_viewProjection
+ * @see czm_modelViewProjection
+ * @see czm_infiniteProjection
+ */
+ czm_projection : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT4,
+ getValue : function(uniformState) {
+ return uniformState.projection;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 4x4 inverse projection transformation matrix that
+ * transforms from clip coordinates to eye coordinates. Clip coordinates is the
+ * coordinate system for a vertex shader's gl_Position
output.
+ *
+ * @alias czm_inverseProjection
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat4 czm_inverseProjection;
+ *
+ * // Example
+ * vec4 eyePosition = czm_inverseProjection * clipPosition;
+ *
+ * @see UniformState#inverseProjection
+ * @see czm_projection
+ */
+ czm_inverseProjection : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT4,
+ getValue : function(uniformState) {
+ return uniformState.inverseProjection;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 4x4 projection transformation matrix with the far plane at infinity,
+ * that transforms eye coordinates to clip coordinates. Clip coordinates is the
+ * coordinate system for a vertex shader's gl_Position
output. An infinite far plane is used
+ * in algorithms like shadow volumes and GPU ray casting with proxy geometry to ensure that triangles
+ * are not clipped by the far plane.
+ *
+ * @alias czm_infiniteProjection
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat4 czm_infiniteProjection;
+ *
+ * // Example
+ * gl_Position = czm_infiniteProjection * eyePosition;
+ *
+ * @see UniformState#infiniteProjection
+ * @see czm_projection
+ * @see czm_modelViewInfiniteProjection
+ */
+ czm_infiniteProjection : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT4,
+ getValue : function(uniformState) {
+ return uniformState.infiniteProjection;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 4x4 model-view transformation matrix that
+ * transforms model coordinates to eye coordinates.
+ *
+ * Positions should be transformed to eye coordinates using czm_modelView
and
+ * normals should be transformed using {@link czm_normal}.
+ *
+ * @alias czm_modelView
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat4 czm_modelView;
+ *
+ * // Example
+ * vec4 eyePosition = czm_modelView * modelPosition;
+ *
+ * // 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
+ * @see czm_modelViewProjection
+ * @see czm_normal
+ */
+ czm_modelView : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT4,
+ getValue : function(uniformState) {
+ return uniformState.modelView;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 4x4 model-view transformation matrix that
+ * transforms 3D model coordinates to eye coordinates. In 3D mode, this is identical to
+ * {@link czm_modelView}, but in 2D and Columbus View it represents the model-view matrix
+ * as if the camera were at an equivalent location in 3D mode. This is useful for lighting
+ * 2D and Columbus View in the same way that 3D is lit.
+ *
+ * Positions should be transformed to eye coordinates using czm_modelView3D
and
+ * normals should be transformed using {@link czm_normal3D}.
+ *
+ * @alias czm_modelView3D
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat4 czm_modelView3D;
+ *
+ * // Example
+ * vec4 eyePosition = czm_modelView3D * modelPosition;
+ *
+ * // The above is equivalent to, but more efficient than:
+ * vec4 eyePosition = czm_view3D * czm_model * modelPosition;
+ *
+ * @see UniformState#modelView3D
+ * @see czm_modelView
+ */
+ czm_modelView3D : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT4,
+ getValue : function(uniformState) {
+ return uniformState.modelView3D;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 4x4 model-view transformation matrix that
+ * transforms model coordinates, relative to the eye, to eye coordinates. This is used
+ * in conjunction with {@link czm_translateRelativeToEye}.
+ *
+ * @alias czm_modelViewRelativeToEye
+ * @glslUniform
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat4 czm_modelViewRelativeToEye;
+ *
+ * // Example
+ * attribute vec3 positionHigh;
+ * attribute vec3 positionLow;
+ *
+ * void main()
+ * {
+ * vec4 p = czm_translateRelativeToEye(positionHigh, positionLow);
+ * gl_Position = czm_projection * (czm_modelViewRelativeToEye * p);
+ * }
+ *
+ * @see czm_modelViewProjectionRelativeToEye
+ * @see czm_translateRelativeToEye
+ * @see EncodedCartesian3
+ */
+ czm_modelViewRelativeToEye : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT4,
+ getValue : function(uniformState) {
+ return uniformState.modelViewRelativeToEye;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 4x4 transformation matrix that
+ * transforms from eye coordinates to model coordinates.
+ *
+ * @alias czm_inverseModelView
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat4 czm_inverseModelView;
+ *
+ * // Example
+ * vec4 modelPosition = czm_inverseModelView * eyePosition;
+ *
+ * @see UniformState#inverseModelView
+ * @see czm_modelView
+ */
+ czm_inverseModelView : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT4,
+ getValue : function(uniformState) {
+ return uniformState.inverseModelView;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 4x4 transformation matrix that
+ * transforms from eye coordinates to 3D model coordinates. In 3D mode, this is identical to
+ * {@link czm_inverseModelView}, but in 2D and Columbus View it represents the inverse model-view matrix
+ * as if the camera were at an equivalent location in 3D mode. This is useful for lighting
+ * 2D and Columbus View in the same way that 3D is lit.
+ *
+ * @alias czm_inverseModelView3D
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat4 czm_inverseModelView3D;
+ *
+ * // Example
+ * vec4 modelPosition = czm_inverseModelView3D * eyePosition;
+ *
+ * @see UniformState#inverseModelView
+ * @see czm_inverseModelView
+ * @see czm_modelView3D
+ */
+ czm_inverseModelView3D : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT4,
+ getValue : function(uniformState) {
+ return uniformState.inverseModelView3D;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 4x4 view-projection transformation matrix that
+ * transforms world coordinates to clip coordinates. Clip coordinates is the
+ * coordinate system for a vertex shader's gl_Position
output.
+ *
+ * @alias czm_viewProjection
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat4 czm_viewProjection;
+ *
+ * // Example
+ * vec4 gl_Position = czm_viewProjection * czm_model * modelPosition;
+ *
+ * // 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
+ * @see czm_modelViewProjection
+ * @see czm_inverseViewProjection
+ */
+ czm_viewProjection : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT4,
+ getValue : function(uniformState) {
+ return uniformState.viewProjection;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 4x4 view-projection transformation matrix that
+ * transforms clip coordinates to world coordinates. Clip coordinates is the
+ * coordinate system for a vertex shader's gl_Position
output.
+ *
+ * @alias czm_inverseViewProjection
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat4 czm_inverseViewProjection;
+ *
+ * // Example
+ * vec4 worldPosition = czm_inverseViewProjection * clipPosition;
+ *
+ * @see UniformState#inverseViewProjection
+ * @see czm_viewProjection
+ */
+ czm_inverseViewProjection : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT4,
+ getValue : function(uniformState) {
+ return uniformState.inverseViewProjection;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 4x4 model-view-projection transformation matrix that
+ * transforms model coordinates to clip coordinates. Clip coordinates is the
+ * coordinate system for a vertex shader's gl_Position
output.
+ *
+ * @alias czm_modelViewProjection
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat4 czm_modelViewProjection;
+ *
+ * // Example
+ * vec4 gl_Position = czm_modelViewProjection * modelPosition;
+ *
+ * // 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
+ * @see czm_projection
+ * @see czm_modelView
+ * @see czm_viewProjection
+ * @see czm_modelViewInfiniteProjection
+ * @see czm_inverseModelViewProjection
+ */
+ czm_modelViewProjection : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT4,
+ getValue : function(uniformState) {
+ return uniformState.modelViewProjection;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 4x4 inverse model-view-projection transformation matrix that
+ * transforms clip coordinates to model coordinates. Clip coordinates is the
+ * coordinate system for a vertex shader's gl_Position
output.
+ *
+ * @alias czm_inverseModelViewProjection
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat4 czm_inverseModelViewProjection;
+ *
+ * // Example
+ * vec4 modelPosition = czm_inverseModelViewProjection * clipPosition;
+ *
+ * @see UniformState#modelViewProjection
+ * @see czm_modelViewProjection
+ */
+ czm_inverseModelViewProjection : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT4,
+ getValue : function(uniformState) {
+ return uniformState.inverseModelViewProjection;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 4x4 model-view-projection transformation matrix that
+ * transforms model coordinates, relative to the eye, to clip coordinates. Clip coordinates is the
+ * coordinate system for a vertex shader's gl_Position
output. This is used in
+ * conjunction with {@link czm_translateRelativeToEye}.
+ *
+ * @alias czm_modelViewProjectionRelativeToEye
+ * @glslUniform
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat4 czm_modelViewProjectionRelativeToEye;
+ *
+ * // Example
+ * attribute vec3 positionHigh;
+ * attribute vec3 positionLow;
+ *
+ * void main()
+ * {
+ * vec4 p = czm_translateRelativeToEye(positionHigh, positionLow);
+ * gl_Position = czm_modelViewProjectionRelativeToEye * p;
+ * }
+ *
+ * @see czm_modelViewRelativeToEye
+ * @see czm_translateRelativeToEye
+ * @see EncodedCartesian3
+ */
+ czm_modelViewProjectionRelativeToEye : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT4,
+ getValue : function(uniformState) {
+ return uniformState.modelViewProjectionRelativeToEye;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 4x4 model-view-projection transformation matrix that
+ * transforms model coordinates to clip coordinates. Clip coordinates is the
+ * coordinate system for a vertex shader's gl_Position
output. The projection matrix places
+ * the far plane at infinity. This is useful in algorithms like shadow volumes and GPU ray casting with
+ * proxy geometry to ensure that triangles are not clipped by the far plane.
+ *
+ * @alias czm_modelViewInfiniteProjection
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat4 czm_modelViewInfiniteProjection;
+ *
+ * // Example
+ * vec4 gl_Position = czm_modelViewInfiniteProjection * modelPosition;
+ *
+ * // 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
+ * @see czm_infiniteProjection
+ * @see czm_modelViewProjection
+ */
+ czm_modelViewInfiniteProjection : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT4,
+ getValue : function(uniformState) {
+ return uniformState.modelViewInfiniteProjection;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform that indicates if the current camera is orthographic in 3D.
+ *
+ * @alias czm_orthographicIn3D
+ * @see UniformState#orthographicIn3D
+ */
+ czm_orthographicIn3D : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT,
+ getValue : function(uniformState) {
+ return uniformState.orthographicIn3D ? 1 : 0;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 3x3 normal transformation matrix that
+ * transforms normal vectors in model coordinates to eye coordinates.
+ *
+ * Positions should be transformed to eye coordinates using {@link czm_modelView} and
+ * normals should be transformed using czm_normal
.
+ *
+ * @alias czm_normal
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat3 czm_normal;
+ *
+ * // Example
+ * vec3 eyeNormal = czm_normal * normal;
+ *
+ * @see UniformState#normal
+ * @see czm_inverseNormal
+ * @see czm_modelView
+ */
+ czm_normal : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT3,
+ getValue : function(uniformState) {
+ return uniformState.normal;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 3x3 normal transformation matrix that
+ * transforms normal vectors in 3D model coordinates to eye coordinates.
+ * In 3D mode, this is identical to
+ * {@link czm_normal}, but in 2D and Columbus View it represents the normal transformation
+ * matrix as if the camera were at an equivalent location in 3D mode. This is useful for lighting
+ * 2D and Columbus View in the same way that 3D is lit.
+ *
+ * Positions should be transformed to eye coordinates using {@link czm_modelView3D} and
+ * normals should be transformed using czm_normal3D
.
+ *
+ * @alias czm_normal3D
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat3 czm_normal3D;
+ *
+ * // Example
+ * vec3 eyeNormal = czm_normal3D * normal;
+ *
+ * @see UniformState#normal3D
+ * @see czm_normal
+ */
+ czm_normal3D : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT3,
+ getValue : function(uniformState) {
+ return uniformState.normal3D;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 3x3 normal transformation matrix that
+ * transforms normal vectors in eye coordinates to model coordinates. This is
+ * the opposite of the transform provided by {@link czm_normal}.
+ *
+ * @alias czm_inverseNormal
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat3 czm_inverseNormal;
+ *
+ * // Example
+ * vec3 normalMC = czm_inverseNormal * normalEC;
+ *
+ * @see UniformState#inverseNormal
+ * @see czm_normal
+ * @see czm_modelView
+ * @see czm_inverseView
*/
- var AutomaticUniforms = {
- /**
- * An automatic GLSL uniform containing the viewport's x
, y
, width
,
- * and height
properties in an vec4
's x
, y
, z
,
- * and w
components, respectively.
- *
- * @alias czm_viewport
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform vec4 czm_viewport;
- *
- * // 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({
- size : 1,
- datatype : WebGLConstants.FLOAT_VEC4,
- getValue : function(uniformState) {
- return uniformState.viewportCartesian4;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 4x4 orthographic projection matrix that
- * transforms window coordinates to clip coordinates. Clip coordinates is the
- * coordinate system for a vertex shader's gl_Position
output.
- *
- * This transform is useful when a vertex shader inputs or manipulates window coordinates
- * as done by {@link BillboardCollection}.
- *
- * Do not confuse {@link czm_viewportTransformation} with czm_viewportOrthographic
.
- * The former transforms from normalized device coordinates to window coordinates; the later transforms
- * from window coordinates to clip coordinates, and is often used to assign to gl_Position
.
- *
- * @alias czm_viewportOrthographic
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat4 czm_viewportOrthographic;
- *
- * // Example
- * gl_Position = czm_viewportOrthographic * vec4(windowPosition, 0.0, 1.0);
- *
- * @see UniformState#viewportOrthographic
- * @see czm_viewport
- * @see czm_viewportTransformation
- * @see BillboardCollection
- */
- czm_viewportOrthographic : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT4,
- getValue : function(uniformState) {
- return uniformState.viewportOrthographic;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 4x4 transformation matrix that
- * transforms normalized device coordinates to window coordinates. The context's
- * full viewport is used, and the depth range is assumed to be near = 0
- * and far = 1
.
- *
- * This transform is useful when there is a need to manipulate window coordinates
- * in a vertex shader as done by {@link BillboardCollection}. In many cases,
- * this matrix will not be used directly; instead, {@link czm_modelToWindowCoordinates}
- * will be used to transform directly from model to window coordinates.
- *
- * Do not confuse czm_viewportTransformation
with {@link czm_viewportOrthographic}.
- * The former transforms from normalized device coordinates to window coordinates; the later transforms
- * from window coordinates to clip coordinates, and is often used to assign to gl_Position
.
- *
- * @alias czm_viewportTransformation
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat4 czm_viewportTransformation;
- *
- * // Use czm_viewportTransformation as part of the
- * // transform from model to window coordinates.
- * 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
- * @see czm_modelToWindowCoordinates
- * @see BillboardCollection
- */
- czm_viewportTransformation : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT4,
- getValue : function(uniformState) {
- return uniformState.viewportTransformation;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing the depth after
- * only the globe has been rendered and packed into an RGBA texture.
- *
- * @private
- *
- * @alias czm_globeDepthTexture
- * @glslUniform
- *
- * @example
- * // GLSL declaration
- * uniform sampler2D czm_globeDepthTexture;
- *
- * // Get the depth at the current fragment
- * vec2 coords = gl_FragCoord.xy / czm_viewport.zw;
- * float depth = czm_unpackDepth(texture2D(czm_globeDepthTexture, coords));
- */
- czm_globeDepthTexture : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.SAMPLER_2D,
- getValue : function(uniformState) {
- return uniformState.globeDepthTexture;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 4x4 model transformation matrix that
- * transforms model coordinates to world coordinates.
- *
- * @alias czm_model
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat4 czm_model;
- *
- * // Example
- * vec4 worldPosition = czm_model * modelPosition;
- *
- * @see UniformState#model
- * @see czm_inverseModel
- * @see czm_modelView
- * @see czm_modelViewProjection
- */
- czm_model : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT4,
- getValue : function(uniformState) {
- return uniformState.model;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 4x4 model transformation matrix that
- * transforms world coordinates to model coordinates.
- *
- * @alias czm_inverseModel
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat4 czm_inverseModel;
- *
- * // Example
- * vec4 modelPosition = czm_inverseModel * worldPosition;
- *
- * @see UniformState#inverseModel
- * @see czm_model
- * @see czm_inverseModelView
- */
- czm_inverseModel : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT4,
- getValue : function(uniformState) {
- return uniformState.inverseModel;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 4x4 view transformation matrix that
- * transforms world coordinates to eye coordinates.
- *
- * @alias czm_view
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat4 czm_view;
- *
- * // Example
- * vec4 eyePosition = czm_view * worldPosition;
- *
- * @see UniformState#view
- * @see czm_viewRotation
- * @see czm_modelView
- * @see czm_viewProjection
- * @see czm_modelViewProjection
- * @see czm_inverseView
- */
- czm_view : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT4,
- getValue : function(uniformState) {
- return uniformState.view;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 4x4 view transformation matrix that
- * transforms 3D world coordinates to eye coordinates. In 3D mode, this is identical to
- * {@link czm_view}, but in 2D and Columbus View it represents the view matrix
- * as if the camera were at an equivalent location in 3D mode. This is useful for lighting
- * 2D and Columbus View in the same way that 3D is lit.
- *
- * @alias czm_view3D
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat4 czm_view3D;
- *
- * // Example
- * vec4 eyePosition3D = czm_view3D * worldPosition3D;
- *
- * @see UniformState#view3D
- * @see czm_view
- */
- czm_view3D : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT4,
- getValue : function(uniformState) {
- return uniformState.view3D;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 3x3 view rotation matrix that
- * transforms vectors in world coordinates to eye coordinates.
- *
- * @alias czm_viewRotation
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat3 czm_viewRotation;
- *
- * // Example
- * vec3 eyeVector = czm_viewRotation * worldVector;
- *
- * @see UniformState#viewRotation
- * @see czm_view
- * @see czm_inverseView
- * @see czm_inverseViewRotation
- */
- czm_viewRotation : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT3,
- getValue : function(uniformState) {
- return uniformState.viewRotation;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 3x3 view rotation matrix that
- * transforms vectors in 3D world coordinates to eye coordinates. In 3D mode, this is identical to
- * {@link czm_viewRotation}, but in 2D and Columbus View it represents the view matrix
- * as if the camera were at an equivalent location in 3D mode. This is useful for lighting
- * 2D and Columbus View in the same way that 3D is lit.
- *
- * @alias czm_viewRotation3D
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat3 czm_viewRotation3D;
- *
- * // Example
- * vec3 eyeVector = czm_viewRotation3D * worldVector;
- *
- * @see UniformState#viewRotation3D
- * @see czm_viewRotation
- */
- czm_viewRotation3D : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT3,
- getValue : function(uniformState) {
- return uniformState.viewRotation3D;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 4x4 transformation matrix that
- * transforms from eye coordinates to world coordinates.
- *
- * @alias czm_inverseView
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat4 czm_inverseView;
- *
- * // Example
- * vec4 worldPosition = czm_inverseView * eyePosition;
- *
- * @see UniformState#inverseView
- * @see czm_view
- * @see czm_inverseNormal
- */
- czm_inverseView : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT4,
- getValue : function(uniformState) {
- return uniformState.inverseView;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 4x4 transformation matrix that
- * transforms from 3D eye coordinates to world coordinates. In 3D mode, this is identical to
- * {@link czm_inverseView}, but in 2D and Columbus View it represents the inverse view matrix
- * as if the camera were at an equivalent location in 3D mode. This is useful for lighting
- * 2D and Columbus View in the same way that 3D is lit.
- *
- * @alias czm_inverseView3D
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat4 czm_inverseView3D;
- *
- * // Example
- * vec4 worldPosition = czm_inverseView3D * eyePosition;
- *
- * @see UniformState#inverseView3D
- * @see czm_inverseView
- */
- czm_inverseView3D : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT4,
- getValue : function(uniformState) {
- return uniformState.inverseView3D;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 3x3 rotation matrix that
- * transforms vectors from eye coordinates to world coordinates.
- *
- * @alias czm_inverseViewRotation
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat3 czm_inverseViewRotation;
- *
- * // Example
- * vec4 worldVector = czm_inverseViewRotation * eyeVector;
- *
- * @see UniformState#inverseView
- * @see czm_view
- * @see czm_viewRotation
- * @see czm_inverseViewRotation
- */
- czm_inverseViewRotation : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT3,
- getValue : function(uniformState) {
- return uniformState.inverseViewRotation;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 3x3 rotation matrix that
- * transforms vectors from 3D eye coordinates to world coordinates. In 3D mode, this is identical to
- * {@link czm_inverseViewRotation}, but in 2D and Columbus View it represents the inverse view matrix
- * as if the camera were at an equivalent location in 3D mode. This is useful for lighting
- * 2D and Columbus View in the same way that 3D is lit.
- *
- * @alias czm_inverseViewRotation3D
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat3 czm_inverseViewRotation3D;
- *
- * // Example
- * vec4 worldVector = czm_inverseViewRotation3D * eyeVector;
- *
- * @see UniformState#inverseView3D
- * @see czm_inverseViewRotation
- */
- czm_inverseViewRotation3D : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT3,
- getValue : function(uniformState) {
- return uniformState.inverseViewRotation3D;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 4x4 projection transformation matrix that
- * transforms eye coordinates to clip coordinates. Clip coordinates is the
- * coordinate system for a vertex shader's gl_Position
output.
- *
- * @alias czm_projection
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat4 czm_projection;
- *
- * // Example
- * gl_Position = czm_projection * eyePosition;
- *
- * @see UniformState#projection
- * @see czm_viewProjection
- * @see czm_modelViewProjection
- * @see czm_infiniteProjection
- */
- czm_projection : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT4,
- getValue : function(uniformState) {
- return uniformState.projection;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 4x4 inverse projection transformation matrix that
- * transforms from clip coordinates to eye coordinates. Clip coordinates is the
- * coordinate system for a vertex shader's gl_Position
output.
- *
- * @alias czm_inverseProjection
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat4 czm_inverseProjection;
- *
- * // Example
- * vec4 eyePosition = czm_inverseProjection * clipPosition;
- *
- * @see UniformState#inverseProjection
- * @see czm_projection
- */
- czm_inverseProjection : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT4,
- getValue : function(uniformState) {
- return uniformState.inverseProjection;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 4x4 projection transformation matrix with the far plane at infinity,
- * that transforms eye coordinates to clip coordinates. Clip coordinates is the
- * coordinate system for a vertex shader's gl_Position
output. An infinite far plane is used
- * in algorithms like shadow volumes and GPU ray casting with proxy geometry to ensure that triangles
- * are not clipped by the far plane.
- *
- * @alias czm_infiniteProjection
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat4 czm_infiniteProjection;
- *
- * // Example
- * gl_Position = czm_infiniteProjection * eyePosition;
- *
- * @see UniformState#infiniteProjection
- * @see czm_projection
- * @see czm_modelViewInfiniteProjection
- */
- czm_infiniteProjection : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT4,
- getValue : function(uniformState) {
- return uniformState.infiniteProjection;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 4x4 model-view transformation matrix that
- * transforms model coordinates to eye coordinates.
- *
- * Positions should be transformed to eye coordinates using czm_modelView
and
- * normals should be transformed using {@link czm_normal}.
- *
- * @alias czm_modelView
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat4 czm_modelView;
- *
- * // Example
- * vec4 eyePosition = czm_modelView * modelPosition;
- *
- * // 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
- * @see czm_modelViewProjection
- * @see czm_normal
- */
- czm_modelView : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT4,
- getValue : function(uniformState) {
- return uniformState.modelView;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 4x4 model-view transformation matrix that
- * transforms 3D model coordinates to eye coordinates. In 3D mode, this is identical to
- * {@link czm_modelView}, but in 2D and Columbus View it represents the model-view matrix
- * as if the camera were at an equivalent location in 3D mode. This is useful for lighting
- * 2D and Columbus View in the same way that 3D is lit.
- *
- * Positions should be transformed to eye coordinates using czm_modelView3D
and
- * normals should be transformed using {@link czm_normal3D}.
- *
- * @alias czm_modelView3D
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat4 czm_modelView3D;
- *
- * // Example
- * vec4 eyePosition = czm_modelView3D * modelPosition;
- *
- * // The above is equivalent to, but more efficient than:
- * vec4 eyePosition = czm_view3D * czm_model * modelPosition;
- *
- * @see UniformState#modelView3D
- * @see czm_modelView
- */
- czm_modelView3D : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT4,
- getValue : function(uniformState) {
- return uniformState.modelView3D;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 4x4 model-view transformation matrix that
- * transforms model coordinates, relative to the eye, to eye coordinates. This is used
- * in conjunction with {@link czm_translateRelativeToEye}.
- *
- * @alias czm_modelViewRelativeToEye
- * @glslUniform
- *
- * @example
- * // GLSL declaration
- * uniform mat4 czm_modelViewRelativeToEye;
- *
- * // Example
- * attribute vec3 positionHigh;
- * attribute vec3 positionLow;
- *
- * void main()
- * {
- * vec4 p = czm_translateRelativeToEye(positionHigh, positionLow);
- * gl_Position = czm_projection * (czm_modelViewRelativeToEye * p);
- * }
- *
- * @see czm_modelViewProjectionRelativeToEye
- * @see czm_translateRelativeToEye
- * @see EncodedCartesian3
- */
- czm_modelViewRelativeToEye : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT4,
- getValue : function(uniformState) {
- return uniformState.modelViewRelativeToEye;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 4x4 transformation matrix that
- * transforms from eye coordinates to model coordinates.
- *
- * @alias czm_inverseModelView
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat4 czm_inverseModelView;
- *
- * // Example
- * vec4 modelPosition = czm_inverseModelView * eyePosition;
- *
- * @see UniformState#inverseModelView
- * @see czm_modelView
- */
- czm_inverseModelView : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT4,
- getValue : function(uniformState) {
- return uniformState.inverseModelView;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 4x4 transformation matrix that
- * transforms from eye coordinates to 3D model coordinates. In 3D mode, this is identical to
- * {@link czm_inverseModelView}, but in 2D and Columbus View it represents the inverse model-view matrix
- * as if the camera were at an equivalent location in 3D mode. This is useful for lighting
- * 2D and Columbus View in the same way that 3D is lit.
- *
- * @alias czm_inverseModelView3D
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat4 czm_inverseModelView3D;
- *
- * // Example
- * vec4 modelPosition = czm_inverseModelView3D * eyePosition;
- *
- * @see UniformState#inverseModelView
- * @see czm_inverseModelView
- * @see czm_modelView3D
- */
- czm_inverseModelView3D : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT4,
- getValue : function(uniformState) {
- return uniformState.inverseModelView3D;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 4x4 view-projection transformation matrix that
- * transforms world coordinates to clip coordinates. Clip coordinates is the
- * coordinate system for a vertex shader's gl_Position
output.
- *
- * @alias czm_viewProjection
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat4 czm_viewProjection;
- *
- * // Example
- * vec4 gl_Position = czm_viewProjection * czm_model * modelPosition;
- *
- * // 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
- * @see czm_modelViewProjection
- * @see czm_inverseViewProjection
- */
- czm_viewProjection : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT4,
- getValue : function(uniformState) {
- return uniformState.viewProjection;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 4x4 view-projection transformation matrix that
- * transforms clip coordinates to world coordinates. Clip coordinates is the
- * coordinate system for a vertex shader's gl_Position
output.
- *
- * @alias czm_inverseViewProjection
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat4 czm_inverseViewProjection;
- *
- * // Example
- * vec4 worldPosition = czm_inverseViewProjection * clipPosition;
- *
- * @see UniformState#inverseViewProjection
- * @see czm_viewProjection
- */
- czm_inverseViewProjection : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT4,
- getValue : function(uniformState) {
- return uniformState.inverseViewProjection;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 4x4 model-view-projection transformation matrix that
- * transforms model coordinates to clip coordinates. Clip coordinates is the
- * coordinate system for a vertex shader's gl_Position
output.
- *
- * @alias czm_modelViewProjection
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat4 czm_modelViewProjection;
- *
- * // Example
- * vec4 gl_Position = czm_modelViewProjection * modelPosition;
- *
- * // 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
- * @see czm_projection
- * @see czm_modelView
- * @see czm_viewProjection
- * @see czm_modelViewInfiniteProjection
- * @see czm_inverseModelViewProjection
- */
- czm_modelViewProjection : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT4,
- getValue : function(uniformState) {
- return uniformState.modelViewProjection;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 4x4 inverse model-view-projection transformation matrix that
- * transforms clip coordinates to model coordinates. Clip coordinates is the
- * coordinate system for a vertex shader's gl_Position
output.
- *
- * @alias czm_inverseModelViewProjection
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat4 czm_inverseModelViewProjection;
- *
- * // Example
- * vec4 modelPosition = czm_inverseModelViewProjection * clipPosition;
- *
- * @see UniformState#modelViewProjection
- * @see czm_modelViewProjection
- */
- czm_inverseModelViewProjection : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT4,
- getValue : function(uniformState) {
- return uniformState.inverseModelViewProjection;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 4x4 model-view-projection transformation matrix that
- * transforms model coordinates, relative to the eye, to clip coordinates. Clip coordinates is the
- * coordinate system for a vertex shader's gl_Position
output. This is used in
- * conjunction with {@link czm_translateRelativeToEye}.
- *
- * @alias czm_modelViewProjectionRelativeToEye
- * @glslUniform
- *
- * @example
- * // GLSL declaration
- * uniform mat4 czm_modelViewProjectionRelativeToEye;
- *
- * // Example
- * attribute vec3 positionHigh;
- * attribute vec3 positionLow;
- *
- * void main()
- * {
- * vec4 p = czm_translateRelativeToEye(positionHigh, positionLow);
- * gl_Position = czm_modelViewProjectionRelativeToEye * p;
- * }
- *
- * @see czm_modelViewRelativeToEye
- * @see czm_translateRelativeToEye
- * @see EncodedCartesian3
- */
- czm_modelViewProjectionRelativeToEye : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT4,
- getValue : function(uniformState) {
- return uniformState.modelViewProjectionRelativeToEye;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 4x4 model-view-projection transformation matrix that
- * transforms model coordinates to clip coordinates. Clip coordinates is the
- * coordinate system for a vertex shader's gl_Position
output. The projection matrix places
- * the far plane at infinity. This is useful in algorithms like shadow volumes and GPU ray casting with
- * proxy geometry to ensure that triangles are not clipped by the far plane.
- *
- * @alias czm_modelViewInfiniteProjection
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat4 czm_modelViewInfiniteProjection;
- *
- * // Example
- * vec4 gl_Position = czm_modelViewInfiniteProjection * modelPosition;
- *
- * // 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
- * @see czm_infiniteProjection
- * @see czm_modelViewProjection
- */
- czm_modelViewInfiniteProjection : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT4,
- getValue : function(uniformState) {
- return uniformState.modelViewInfiniteProjection;
- }
- }),
-
- /**
- * An automatic GLSL uniform that indicates if the current camera is orthographic in 3D.
- *
- * @alias czm_orthographicIn3D
- * @see UniformState#orthographicIn3D
- */
- czm_orthographicIn3D : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT,
- getValue : function(uniformState) {
- return uniformState.orthographicIn3D ? 1 : 0;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 3x3 normal transformation matrix that
- * transforms normal vectors in model coordinates to eye coordinates.
- *
- * Positions should be transformed to eye coordinates using {@link czm_modelView} and
- * normals should be transformed using czm_normal
.
- *
- * @alias czm_normal
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat3 czm_normal;
- *
- * // Example
- * vec3 eyeNormal = czm_normal * normal;
- *
- * @see UniformState#normal
- * @see czm_inverseNormal
- * @see czm_modelView
- */
- czm_normal : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT3,
- getValue : function(uniformState) {
- return uniformState.normal;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 3x3 normal transformation matrix that
- * transforms normal vectors in 3D model coordinates to eye coordinates.
- * In 3D mode, this is identical to
- * {@link czm_normal}, but in 2D and Columbus View it represents the normal transformation
- * matrix as if the camera were at an equivalent location in 3D mode. This is useful for lighting
- * 2D and Columbus View in the same way that 3D is lit.
- *
- * Positions should be transformed to eye coordinates using {@link czm_modelView3D} and
- * normals should be transformed using czm_normal3D
.
- *
- * @alias czm_normal3D
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat3 czm_normal3D;
- *
- * // Example
- * vec3 eyeNormal = czm_normal3D * normal;
- *
- * @see UniformState#normal3D
- * @see czm_normal
- */
- czm_normal3D : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT3,
- getValue : function(uniformState) {
- return uniformState.normal3D;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 3x3 normal transformation matrix that
- * transforms normal vectors in eye coordinates to model coordinates. This is
- * the opposite of the transform provided by {@link czm_normal}.
- *
- * @alias czm_inverseNormal
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat3 czm_inverseNormal;
- *
- * // Example
- * vec3 normalMC = czm_inverseNormal * normalEC;
- *
- * @see UniformState#inverseNormal
- * @see czm_normal
- * @see czm_modelView
- * @see czm_inverseView
- */
- czm_inverseNormal : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT3,
- getValue : function(uniformState) {
- return uniformState.inverseNormal;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 3x3 normal transformation matrix that
- * transforms normal vectors in eye coordinates to 3D model coordinates. This is
- * the opposite of the transform provided by {@link czm_normal}.
- * In 3D mode, this is identical to
- * {@link czm_inverseNormal}, but in 2D and Columbus View it represents the inverse normal transformation
- * matrix as if the camera were at an equivalent location in 3D mode. This is useful for lighting
- * 2D and Columbus View in the same way that 3D is lit.
- *
- * @alias czm_inverseNormal3D
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat3 czm_inverseNormal3D;
- *
- * // Example
- * vec3 normalMC = czm_inverseNormal3D * normalEC;
- *
- * @see UniformState#inverseNormal3D
- * @see czm_inverseNormal
- */
- czm_inverseNormal3D : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT3,
- getValue : function(uniformState) {
- return uniformState.inverseNormal3D;
- }
- }),
-
- /**
- * An automatic GLSL uniform containing height (x
) and height squared (y
)
- * of the eye (camera) in the 2D scene in meters.
- *
- * @alias czm_eyeHeight2D
- * @glslUniform
- *
- * @see UniformState#eyeHeight2D
- */
- czm_eyeHeight2D : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_VEC2,
- getValue : function(uniformState) {
- return uniformState.eyeHeight2D;
- }
- }),
-
- /**
- * An automatic GLSL uniform containing the near distance (x
) and the far distance (y
)
- * of the frustum defined by the camera. This is the largest possible frustum, not an individual
- * frustum used for multi-frustum rendering.
- *
- * @alias czm_entireFrustum
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform vec2 czm_entireFrustum;
- *
- * // Example
- * float frustumLength = czm_entireFrustum.y - czm_entireFrustum.x;
- *
- * @see UniformState#entireFrustum
- * @see czm_currentFrustum
- */
- czm_entireFrustum : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_VEC2,
- getValue : function(uniformState) {
- return uniformState.entireFrustum;
- }
- }),
-
- /**
- * An automatic GLSL uniform containing the near distance (x
) and the far distance (y
)
- * of the frustum defined by the camera. This is the individual
- * frustum used for multi-frustum rendering.
- *
- * @alias czm_currentFrustum
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform vec2 czm_currentFrustum;
- *
- * // Example
- * float frustumLength = czm_currentFrustum.y - czm_currentFrustum.x;
- *
- * @see UniformState#currentFrustum
- * @see czm_entireFrustum
- */
- czm_currentFrustum : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_VEC2,
- getValue : function(uniformState) {
- return uniformState.currentFrustum;
- }
- }),
-
- /**
- * The distances to the frustum planes. The top, bottom, left and right distances are
- * the x, y, z, and w components, respectively.
- *
- * @alias czm_frustumPlanes
- * @glslUniform
- */
- czm_frustumPlanes : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_VEC4,
- getValue : function(uniformState) {
- return uniformState.frustumPlanes;
- }
- }),
-
- /**
- * The log of the current frustums far plane. Used for computing the log depth.
- *
- * @alias czm_logFarDistance
- * @glslUniform
- *
- * @private
- */
- czm_logFarDistance : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT,
- getValue : function(uniformState) {
- return uniformState.logFarDistance;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing the sun position in world coordinates.
- *
- * @alias czm_sunPositionWC
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform vec3 czm_sunPositionWC;
- *
- * @see UniformState#sunPositionWC
- * @see czm_sunPositionColumbusView
- * @see czm_sunDirectionWC
- */
- czm_sunPositionWC : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_VEC3,
- getValue : function(uniformState) {
- return uniformState.sunPositionWC;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing the sun position in Columbus view world coordinates.
- *
- * @alias czm_sunPositionColumbusView
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform vec3 czm_sunPositionColumbusView;
- *
- * @see UniformState#sunPositionColumbusView
- * @see czm_sunPositionWC
- */
- czm_sunPositionColumbusView : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_VEC3,
- getValue : function(uniformState) {
- return uniformState.sunPositionColumbusView;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing the normalized direction to the sun in eye coordinates.
- * This is commonly used for directional lighting computations.
- *
- * @alias czm_sunDirectionEC
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform vec3 czm_sunDirectionEC;
- *
- * // Example
- * float diffuse = max(dot(czm_sunDirectionEC, normalEC), 0.0);
- *
- * @see UniformState#sunDirectionEC
- * @see czm_moonDirectionEC
- * @see czm_sunDirectionWC
- */
- czm_sunDirectionEC : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_VEC3,
- getValue : function(uniformState) {
- return uniformState.sunDirectionEC;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing the normalized direction to the sun in world coordinates.
- * This is commonly used for directional lighting computations.
- *
- * @alias czm_sunDirectionWC
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform vec3 czm_sunDirectionWC;
- *
- * @see UniformState#sunDirectionWC
- * @see czm_sunPositionWC
- * @see czm_sunDirectionEC
- */
- czm_sunDirectionWC : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_VEC3,
- getValue : function(uniformState) {
- return uniformState.sunDirectionWC;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing the normalized direction to the moon in eye coordinates.
- * This is commonly used for directional lighting computations.
- *
- * @alias czm_moonDirectionEC
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform vec3 czm_moonDirectionEC;
- *
- * // Example
- * float diffuse = max(dot(czm_moonDirectionEC, normalEC), 0.0);
- *
- * @see UniformState#moonDirectionEC
- * @see czm_sunDirectionEC
- */
- czm_moonDirectionEC : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_VEC3,
- getValue : function(uniformState) {
- return uniformState.moonDirectionEC;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing the high bits of the camera position in model
- * coordinates. This is used for GPU RTE to eliminate jittering artifacts when rendering
- * as described in {@link http://blogs.agi.com/insight3d/index.php/2008/09/03/precisions-precisions/|Precisions, Precisions}.
- *
- * @alias czm_encodedCameraPositionMCHigh
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform vec3 czm_encodedCameraPositionMCHigh;
- *
- * @see czm_encodedCameraPositionMCLow
- * @see czm_modelViewRelativeToEye
- * @see czm_modelViewProjectionRelativeToEye
- */
- czm_encodedCameraPositionMCHigh : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_VEC3,
- getValue : function(uniformState) {
- return uniformState.encodedCameraPositionMCHigh;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing the low bits of the camera position in model
- * coordinates. This is used for GPU RTE to eliminate jittering artifacts when rendering
- * as described in {@link http://blogs.agi.com/insight3d/index.php/2008/09/03/precisions-precisions/|Precisions, Precisions}.
- *
- * @alias czm_encodedCameraPositionMCLow
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform vec3 czm_encodedCameraPositionMCLow;
- *
- * @see czm_encodedCameraPositionMCHigh
- * @see czm_modelViewRelativeToEye
- * @see czm_modelViewProjectionRelativeToEye
- */
- czm_encodedCameraPositionMCLow : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_VEC3,
- getValue : function(uniformState) {
- return uniformState.encodedCameraPositionMCLow;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing the position of the viewer (camera) in world coordinates.
- *
- * @alias czm_viewerPositionWC
- * @glslUniform
- *
- * @example
- * // GLSL declaration
- * uniform vec3 czm_viewerPositionWC;
- */
- czm_viewerPositionWC : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_VEC3,
- getValue : function(uniformState) {
- return Matrix4.getTranslation(uniformState.inverseView, viewerPositionWCScratch);
- }
- }),
-
- /**
- * An automatic GLSL uniform representing the frame number. This uniform is automatically incremented
- * every frame.
- *
- * @alias czm_frameNumber
- * @glslUniform
- *
- * @example
- * // GLSL declaration
- * uniform float czm_frameNumber;
- */
- czm_frameNumber : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT,
- getValue : function(uniformState) {
- return uniformState.frameState.frameNumber;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing the current morph transition time between
- * 2D/Columbus View and 3D, with 0.0 being 2D or Columbus View and 1.0 being 3D.
- *
- * @alias czm_morphTime
- * @glslUniform
- *
- * @example
- * // GLSL declaration
- * uniform float czm_morphTime;
- *
- * // Example
- * vec4 p = czm_columbusViewMorph(position2D, position3D, czm_morphTime);
- */
- czm_morphTime : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT,
- getValue : function(uniformState) {
- return uniformState.frameState.morphTime;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing the current {@link SceneMode}, expressed
- * as a float.
- *
- * @alias czm_sceneMode
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform float czm_sceneMode;
- *
- * // Example
- * if (czm_sceneMode == czm_sceneMode2D)
- * {
- * eyeHeightSq = czm_eyeHeight2D.y;
- * }
- *
- * @see czm_sceneMode2D
- * @see czm_sceneModeColumbusView
- * @see czm_sceneMode3D
- * @see czm_sceneModeMorphing
- */
- czm_sceneMode : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT,
- getValue : function(uniformState) {
- return uniformState.frameState.mode;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing the current rendering pass.
- *
- * @alias czm_pass
- * @glslUniform
- *
- * @example
- * // GLSL declaration
- * uniform float czm_pass;
- *
- * // Example
- * if ((czm_pass == czm_passTranslucent) && isOpaque())
- * {
- * gl_Position *= 0.0; // Cull opaque geometry in the translucent pass
- * }
- */
- czm_pass : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT,
- getValue : function(uniformState) {
- return uniformState.pass;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing the current scene background color.
- *
- * @alias czm_backgroundColor
- * @glslUniform
- *
- * @example
- * // GLSL declaration
- * uniform vec4 czm_backgroundColor;
- *
- * // Example: If the given color's RGB matches the background color, invert it.
- * vec4 adjustColorForContrast(vec4 color)
- * {
- * if (czm_backgroundColor.rgb == color.rgb)
- * {
- * color.rgb = vec3(1.0) - color.rgb;
- * }
- *
- * return color;
- * }
- */
- czm_backgroundColor : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_VEC4,
- getValue : function(uniformState) {
- return uniformState.backgroundColor;
- }
- }),
-
- /**
- * An automatic GLSL uniform containing the BRDF look up texture used for image-based lighting computations.
- *
- * @alias czm_brdfLut
- * @glslUniform
- *
- * @example
- * // GLSL declaration
- * uniform sampler2D czm_brdfLut;
- *
- * // Example: For a given roughness and NdotV value, find the material's BRDF information in the red and green channels
- * float roughness = 0.5;
- * float NdotV = dot(normal, view);
- * vec2 brdfLut = texture2D(czm_brdfLut, vec2(NdotV, 1.0 - roughness)).rg;
- */
- czm_brdfLut : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.SAMPLER_2D,
- getValue : function(uniformState) {
- return uniformState.brdfLut;
- }
- }),
-
- /**
- * An automatic GLSL uniform containing the environment map used within the scene.
- *
- * @alias czm_environmentMap
- * @glslUniform
- *
- * @example
- * // GLSL declaration
- * uniform samplerCube czm_environmentMap;
- *
- * // Example: Create a perfect reflection of the environment map on a model
- * float reflected = reflect(view, normal);
- * vec4 reflectedColor = textureCube(czm_environmentMap, reflected);
- */
- czm_environmentMap : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.SAMPLER_CUBE,
- getValue : function(uniformState) {
- return uniformState.environmentMap;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 3x3 rotation matrix that transforms
- * from True Equator Mean Equinox (TEME) axes to the pseudo-fixed axes at the current scene time.
- *
- * @alias czm_temeToPseudoFixed
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat3 czm_temeToPseudoFixed;
- *
- * // Example
- * vec3 pseudoFixed = czm_temeToPseudoFixed * teme;
- *
- * @see UniformState#temeToPseudoFixedMatrix
- * @see Transforms.computeTemeToPseudoFixedMatrix
- */
- czm_temeToPseudoFixed : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT3,
- getValue : function(uniformState) {
- return uniformState.temeToPseudoFixedMatrix;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing the ratio of canvas coordinate space to canvas pixel space.
- *
- * @alias czm_resolutionScale
- * @glslUniform
- *
- * @example
- * uniform float czm_resolutionScale;
- */
- czm_resolutionScale : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT,
- getValue : function(uniformState) {
- return uniformState.resolutionScale;
- }
- }),
-
- /**
- * An automatic GLSL uniform scalar used to mix a color with the fog color based on the distance to the camera.
- *
- * @alias czm_fogDensity
- * @glslUniform
- *
- * @see czm_fog
- */
- czm_fogDensity : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT,
- getValue : function(uniformState) {
- return uniformState.fogDensity;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing the splitter position to use when rendering imagery layers with a splitter.
- * This will be in pixel coordinates relative to the canvas.
- *
- * @alias czm_imagerySplitPosition
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform float czm_imagerySplitPosition;
- */
- czm_imagerySplitPosition : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT,
- getValue : function(uniformState) {
- return uniformState.imagerySplitPosition;
- }
- }),
-
- /**
- * An automatic GLSL uniform scalar representing the geometric tolerance per meter
- *
- * @alias czm_geometricToleranceOverMeter
- * @glslUniform
- */
- czm_geometricToleranceOverMeter : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT,
- getValue : function(uniformState) {
- return uniformState.geometricToleranceOverMeter;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing the distance from the camera at which to disable the depth test of billboards, labels and points
- * to, for example, prevent clipping against terrain. When set to zero, the depth test should always be applied. When less than zero,
- * the depth test should never be applied.
- *
- * @alias czm_minimumDisableDepthTestDistance
- * @glslUniform
- */
- czm_minimumDisableDepthTestDistance : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT,
- getValue : function(uniformState) {
- return uniformState.minimumDisableDepthTestDistance;
- }
- }),
-
- /**
- * An automatic GLSL uniform that will be the highlight color of unclassified 3D Tiles.
- *
- * @alias czm_invertClassificationColor
- * @glslUniform
- */
- czm_invertClassificationColor : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_VEC4,
- getValue : function(uniformState) {
- return uniformState.invertClassificationColor;
- }
- })
- };
-
- return AutomaticUniforms;
+ czm_inverseNormal : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT3,
+ getValue : function(uniformState) {
+ return uniformState.inverseNormal;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 3x3 normal transformation matrix that
+ * transforms normal vectors in eye coordinates to 3D model coordinates. This is
+ * the opposite of the transform provided by {@link czm_normal}.
+ * In 3D mode, this is identical to
+ * {@link czm_inverseNormal}, but in 2D and Columbus View it represents the inverse normal transformation
+ * matrix as if the camera were at an equivalent location in 3D mode. This is useful for lighting
+ * 2D and Columbus View in the same way that 3D is lit.
+ *
+ * @alias czm_inverseNormal3D
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat3 czm_inverseNormal3D;
+ *
+ * // Example
+ * vec3 normalMC = czm_inverseNormal3D * normalEC;
+ *
+ * @see UniformState#inverseNormal3D
+ * @see czm_inverseNormal
+ */
+ czm_inverseNormal3D : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT3,
+ getValue : function(uniformState) {
+ return uniformState.inverseNormal3D;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform containing height (x
) and height squared (y
)
+ * of the eye (camera) in the 2D scene in meters.
+ *
+ * @alias czm_eyeHeight2D
+ * @glslUniform
+ *
+ * @see UniformState#eyeHeight2D
+ */
+ czm_eyeHeight2D : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_VEC2,
+ getValue : function(uniformState) {
+ return uniformState.eyeHeight2D;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform containing the near distance (x
) and the far distance (y
)
+ * of the frustum defined by the camera. This is the largest possible frustum, not an individual
+ * frustum used for multi-frustum rendering.
+ *
+ * @alias czm_entireFrustum
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform vec2 czm_entireFrustum;
+ *
+ * // Example
+ * float frustumLength = czm_entireFrustum.y - czm_entireFrustum.x;
+ *
+ * @see UniformState#entireFrustum
+ * @see czm_currentFrustum
+ */
+ czm_entireFrustum : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_VEC2,
+ getValue : function(uniformState) {
+ return uniformState.entireFrustum;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform containing the near distance (x
) and the far distance (y
)
+ * of the frustum defined by the camera. This is the individual
+ * frustum used for multi-frustum rendering.
+ *
+ * @alias czm_currentFrustum
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform vec2 czm_currentFrustum;
+ *
+ * // Example
+ * float frustumLength = czm_currentFrustum.y - czm_currentFrustum.x;
+ *
+ * @see UniformState#currentFrustum
+ * @see czm_entireFrustum
+ */
+ czm_currentFrustum : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_VEC2,
+ getValue : function(uniformState) {
+ return uniformState.currentFrustum;
+ }
+ }),
+
+ /**
+ * The distances to the frustum planes. The top, bottom, left and right distances are
+ * the x, y, z, and w components, respectively.
+ *
+ * @alias czm_frustumPlanes
+ * @glslUniform
+ */
+ czm_frustumPlanes : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_VEC4,
+ getValue : function(uniformState) {
+ return uniformState.frustumPlanes;
+ }
+ }),
+
+ /**
+ * The log2 of the current frustums far plane. Used for computing the log depth.
+ *
+ * @alias czm_log2FarDistance
+ * @glslUniform
+ *
+ * @private
+ */
+ czm_log2FarDistance : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT,
+ getValue : function(uniformState) {
+ return uniformState.logFarDistance;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform containing log2 of the far distance + 1.0.
+ * This is used when reversing log depth computations.
+ *
+ * @alias czm_log2FarPlusOne
+ * @glslUniform
+ */
+ czm_log2FarPlusOne : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT,
+ getValue : function(uniformState) {
+ return CesiumMath.log2(uniformState.currentFrustum.y + 1.0);
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform containing log2 of the near distance.
+ * This is used when writing log depth in the fragment shader.
+ *
+ * @alias czm_log2NearDistance
+ * @glslUniform
+ */
+ czm_log2NearDistance : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT,
+ getValue : function(uniformState) {
+ return CesiumMath.log2(uniformState.currentFrustum.x);
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing the sun position in world coordinates.
+ *
+ * @alias czm_sunPositionWC
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform vec3 czm_sunPositionWC;
+ *
+ * @see UniformState#sunPositionWC
+ * @see czm_sunPositionColumbusView
+ * @see czm_sunDirectionWC
+ */
+ czm_sunPositionWC : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_VEC3,
+ getValue : function(uniformState) {
+ return uniformState.sunPositionWC;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing the sun position in Columbus view world coordinates.
+ *
+ * @alias czm_sunPositionColumbusView
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform vec3 czm_sunPositionColumbusView;
+ *
+ * @see UniformState#sunPositionColumbusView
+ * @see czm_sunPositionWC
+ */
+ czm_sunPositionColumbusView : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_VEC3,
+ getValue : function(uniformState) {
+ return uniformState.sunPositionColumbusView;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing the normalized direction to the sun in eye coordinates.
+ * This is commonly used for directional lighting computations.
+ *
+ * @alias czm_sunDirectionEC
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform vec3 czm_sunDirectionEC;
+ *
+ * // Example
+ * float diffuse = max(dot(czm_sunDirectionEC, normalEC), 0.0);
+ *
+ * @see UniformState#sunDirectionEC
+ * @see czm_moonDirectionEC
+ * @see czm_sunDirectionWC
+ */
+ czm_sunDirectionEC : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_VEC3,
+ getValue : function(uniformState) {
+ return uniformState.sunDirectionEC;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing the normalized direction to the sun in world coordinates.
+ * This is commonly used for directional lighting computations.
+ *
+ * @alias czm_sunDirectionWC
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform vec3 czm_sunDirectionWC;
+ *
+ * @see UniformState#sunDirectionWC
+ * @see czm_sunPositionWC
+ * @see czm_sunDirectionEC
+ */
+ czm_sunDirectionWC : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_VEC3,
+ getValue : function(uniformState) {
+ return uniformState.sunDirectionWC;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing the normalized direction to the moon in eye coordinates.
+ * This is commonly used for directional lighting computations.
+ *
+ * @alias czm_moonDirectionEC
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform vec3 czm_moonDirectionEC;
+ *
+ * // Example
+ * float diffuse = max(dot(czm_moonDirectionEC, normalEC), 0.0);
+ *
+ * @see UniformState#moonDirectionEC
+ * @see czm_sunDirectionEC
+ */
+ czm_moonDirectionEC : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_VEC3,
+ getValue : function(uniformState) {
+ return uniformState.moonDirectionEC;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing the high bits of the camera position in model
+ * coordinates. This is used for GPU RTE to eliminate jittering artifacts when rendering
+ * as described in {@link http://blogs.agi.com/insight3d/index.php/2008/09/03/precisions-precisions/|Precisions, Precisions}.
+ *
+ * @alias czm_encodedCameraPositionMCHigh
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform vec3 czm_encodedCameraPositionMCHigh;
+ *
+ * @see czm_encodedCameraPositionMCLow
+ * @see czm_modelViewRelativeToEye
+ * @see czm_modelViewProjectionRelativeToEye
+ */
+ czm_encodedCameraPositionMCHigh : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_VEC3,
+ getValue : function(uniformState) {
+ return uniformState.encodedCameraPositionMCHigh;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing the low bits of the camera position in model
+ * coordinates. This is used for GPU RTE to eliminate jittering artifacts when rendering
+ * as described in {@link http://blogs.agi.com/insight3d/index.php/2008/09/03/precisions-precisions/|Precisions, Precisions}.
+ *
+ * @alias czm_encodedCameraPositionMCLow
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform vec3 czm_encodedCameraPositionMCLow;
+ *
+ * @see czm_encodedCameraPositionMCHigh
+ * @see czm_modelViewRelativeToEye
+ * @see czm_modelViewProjectionRelativeToEye
+ */
+ czm_encodedCameraPositionMCLow : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_VEC3,
+ getValue : function(uniformState) {
+ return uniformState.encodedCameraPositionMCLow;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing the position of the viewer (camera) in world coordinates.
+ *
+ * @alias czm_viewerPositionWC
+ * @glslUniform
+ *
+ * @example
+ * // GLSL declaration
+ * uniform vec3 czm_viewerPositionWC;
+ */
+ czm_viewerPositionWC : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_VEC3,
+ getValue : function(uniformState) {
+ return Matrix4.getTranslation(uniformState.inverseView, viewerPositionWCScratch);
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing the frame number. This uniform is automatically incremented
+ * every frame.
+ *
+ * @alias czm_frameNumber
+ * @glslUniform
+ *
+ * @example
+ * // GLSL declaration
+ * uniform float czm_frameNumber;
+ */
+ czm_frameNumber : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT,
+ getValue : function(uniformState) {
+ return uniformState.frameState.frameNumber;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing the current morph transition time between
+ * 2D/Columbus View and 3D, with 0.0 being 2D or Columbus View and 1.0 being 3D.
+ *
+ * @alias czm_morphTime
+ * @glslUniform
+ *
+ * @example
+ * // GLSL declaration
+ * uniform float czm_morphTime;
+ *
+ * // Example
+ * vec4 p = czm_columbusViewMorph(position2D, position3D, czm_morphTime);
+ */
+ czm_morphTime : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT,
+ getValue : function(uniformState) {
+ return uniformState.frameState.morphTime;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing the current {@link SceneMode}, expressed
+ * as a float.
+ *
+ * @alias czm_sceneMode
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform float czm_sceneMode;
+ *
+ * // Example
+ * if (czm_sceneMode == czm_sceneMode2D)
+ * {
+ * eyeHeightSq = czm_eyeHeight2D.y;
+ * }
+ *
+ * @see czm_sceneMode2D
+ * @see czm_sceneModeColumbusView
+ * @see czm_sceneMode3D
+ * @see czm_sceneModeMorphing
+ */
+ czm_sceneMode : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT,
+ getValue : function(uniformState) {
+ return uniformState.frameState.mode;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing the current rendering pass.
+ *
+ * @alias czm_pass
+ * @glslUniform
+ *
+ * @example
+ * // GLSL declaration
+ * uniform float czm_pass;
+ *
+ * // Example
+ * if ((czm_pass == czm_passTranslucent) && isOpaque())
+ * {
+ * gl_Position *= 0.0; // Cull opaque geometry in the translucent pass
+ * }
+ */
+ czm_pass : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT,
+ getValue : function(uniformState) {
+ return uniformState.pass;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing the current scene background color.
+ *
+ * @alias czm_backgroundColor
+ * @glslUniform
+ *
+ * @example
+ * // GLSL declaration
+ * uniform vec4 czm_backgroundColor;
+ *
+ * // Example: If the given color's RGB matches the background color, invert it.
+ * vec4 adjustColorForContrast(vec4 color)
+ * {
+ * if (czm_backgroundColor.rgb == color.rgb)
+ * {
+ * color.rgb = vec3(1.0) - color.rgb;
+ * }
+ *
+ * return color;
+ * }
+ */
+ czm_backgroundColor : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_VEC4,
+ getValue : function(uniformState) {
+ return uniformState.backgroundColor;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform containing the BRDF look up texture used for image-based lighting computations.
+ *
+ * @alias czm_brdfLut
+ * @glslUniform
+ *
+ * @example
+ * // GLSL declaration
+ * uniform sampler2D czm_brdfLut;
+ *
+ * // Example: For a given roughness and NdotV value, find the material's BRDF information in the red and green channels
+ * float roughness = 0.5;
+ * float NdotV = dot(normal, view);
+ * vec2 brdfLut = texture2D(czm_brdfLut, vec2(NdotV, 1.0 - roughness)).rg;
+ */
+ czm_brdfLut : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.SAMPLER_2D,
+ getValue : function(uniformState) {
+ return uniformState.brdfLut;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform containing the environment map used within the scene.
+ *
+ * @alias czm_environmentMap
+ * @glslUniform
+ *
+ * @example
+ * // GLSL declaration
+ * uniform samplerCube czm_environmentMap;
+ *
+ * // Example: Create a perfect reflection of the environment map on a model
+ * float reflected = reflect(view, normal);
+ * vec4 reflectedColor = textureCube(czm_environmentMap, reflected);
+ */
+ czm_environmentMap : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.SAMPLER_CUBE,
+ getValue : function(uniformState) {
+ return uniformState.environmentMap;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 3x3 rotation matrix that transforms
+ * from True Equator Mean Equinox (TEME) axes to the pseudo-fixed axes at the current scene time.
+ *
+ * @alias czm_temeToPseudoFixed
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat3 czm_temeToPseudoFixed;
+ *
+ * // Example
+ * vec3 pseudoFixed = czm_temeToPseudoFixed * teme;
+ *
+ * @see UniformState#temeToPseudoFixedMatrix
+ * @see Transforms.computeTemeToPseudoFixedMatrix
+ */
+ czm_temeToPseudoFixed : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT3,
+ getValue : function(uniformState) {
+ return uniformState.temeToPseudoFixedMatrix;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing the ratio of canvas coordinate space to canvas pixel space.
+ *
+ * @alias czm_resolutionScale
+ * @glslUniform
+ *
+ * @example
+ * uniform float czm_resolutionScale;
+ */
+ czm_resolutionScale : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT,
+ getValue : function(uniformState) {
+ return uniformState.resolutionScale;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform scalar used to mix a color with the fog color based on the distance to the camera.
+ *
+ * @alias czm_fogDensity
+ * @glslUniform
+ *
+ * @see czm_fog
+ */
+ czm_fogDensity : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT,
+ getValue : function(uniformState) {
+ return uniformState.fogDensity;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing the splitter position to use when rendering imagery layers with a splitter.
+ * This will be in pixel coordinates relative to the canvas.
+ *
+ * @alias czm_imagerySplitPosition
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform float czm_imagerySplitPosition;
+ */
+ czm_imagerySplitPosition : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT,
+ getValue : function(uniformState) {
+ return uniformState.imagerySplitPosition;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform scalar representing the geometric tolerance per meter
+ *
+ * @alias czm_geometricToleranceOverMeter
+ * @glslUniform
+ */
+ czm_geometricToleranceOverMeter : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT,
+ getValue : function(uniformState) {
+ return uniformState.geometricToleranceOverMeter;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing the distance from the camera at which to disable the depth test of billboards, labels and points
+ * to, for example, prevent clipping against terrain. When set to zero, the depth test should always be applied. When less than zero,
+ * the depth test should never be applied.
+ *
+ * @alias czm_minimumDisableDepthTestDistance
+ * @glslUniform
+ */
+ czm_minimumDisableDepthTestDistance : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT,
+ getValue : function(uniformState) {
+ return uniformState.minimumDisableDepthTestDistance;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform that will be the highlight color of unclassified 3D Tiles.
+ *
+ * @alias czm_invertClassificationColor
+ * @glslUniform
+ */
+ czm_invertClassificationColor : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_VEC4,
+ getValue : function(uniformState) {
+ return uniformState.invertClassificationColor;
+ }
+ })
+};
+
+return AutomaticUniforms;
});
diff --git a/Source/Scene/ShadowVolumeAppearanceShader.js b/Source/Scene/ShadowVolumeAppearanceShader.js
index 94bbd19b9e9..4812047c9a7 100644
--- a/Source/Scene/ShadowVolumeAppearanceShader.js
+++ b/Source/Scene/ShadowVolumeAppearanceShader.js
@@ -279,31 +279,38 @@ define([
glsl +=
'vec4 getEyeCoordinate(vec2 fragCoord) {\n' +
' vec2 coords = fragCoord / czm_viewport.zw;\n' +
- ' float depth = czm_reverseLogDepth(czm_unpackDepth(texture2D(czm_globeDepthTexture, coords)));\n' +
- ' vec4 windowCoord = vec4(fragCoord, depth, 1.0);\n' +
+ ' float logDepthOrDepth = czm_unpackDepth(texture2D(czm_globeDepthTexture, coords));\n' +
+ ' vec4 windowCoord = vec4(fragCoord, czm_reverseLogDepth(logDepthOrDepth), 1.0);\n' +
' vec4 eyeCoordinate = czm_windowToEyeCoordinates(windowCoord);\n' +
+ '#ifdef LOG_DEPTH\n' +
+ // Essentially same as reverseLogDepth but without normalization. Better precision when using log depth.
+ ' eyeCoordinate.w = 1.0 / (pow(2.0, logDepthOrDepth * czm_log2FarPlusOne) - 1.0);\n' +
+ '#endif\n' +
' return eyeCoordinate;\n' +
'}\n';
}
if (shaderDependencies.requiresNormalEC) {
glsl +=
- 'vec3 getEyeCoordinate3FromWindowCoordordinate(vec2 fragCoord, float depth) {\n' +
- ' vec4 windowCoord = vec4(fragCoord, depth, 1.0);\n' +
+ 'vec3 getEyeCoordinate3FromWindowCoordinate(vec2 fragCoord, float logDepthOrDepth) {\n' +
+ ' vec4 windowCoord = vec4(fragCoord, czm_reverseLogDepth(logDepthOrDepth), 1.0);\n' +
' vec4 eyeCoordinate = czm_windowToEyeCoordinates(windowCoord);\n' +
+ '#ifdef LOG_DEPTH\n' +
+ // Essentially same as reverseLogDepth but without normalization. Better precision when using log depth.
+ ' eyeCoordinate.w = 1.0 / (pow(2.0, logDepthOrDepth * czm_log2FarPlusOne) - 1.0);\n' +
+ '#endif\n' +
' return eyeCoordinate.xyz / eyeCoordinate.w;\n' +
'}\n' +
'vec3 getVectorFromOffset(vec4 eyeCoordinate, vec2 glFragCoordXY, vec2 positiveOffset) {\n' +
' // Sample depths at both offset and negative offset\n' +
- ' float upOrRightDepth = czm_reverseLogDepth(czm_unpackDepth(texture2D(czm_globeDepthTexture, (glFragCoordXY + positiveOffset) / czm_viewport.zw)));\n' +
- ' float downOrLeftDepth = czm_reverseLogDepth(czm_unpackDepth(texture2D(czm_globeDepthTexture, (glFragCoordXY - positiveOffset) / czm_viewport.zw)));\n' +
- ' // Explicitly evaluate both paths\n' +
+ ' float upOrRightLogDepth = czm_unpackDepth(texture2D(czm_globeDepthTexture, (glFragCoordXY + positiveOffset) / czm_viewport.zw));\n' +
+ ' float downOrLeftLogDepth = czm_unpackDepth(texture2D(czm_globeDepthTexture, (glFragCoordXY - positiveOffset) / czm_viewport.zw));\n' +
+ ' // Explicitly evaluate both paths\n' + // Necessary for multifrustum and for GroundPrimitives at the edges of the screen
' bvec2 upOrRightInBounds = lessThan(glFragCoordXY + positiveOffset, czm_viewport.zw);\n' +
- ' float useUpOrRight = float(upOrRightDepth > 0.0 && upOrRightInBounds.x && upOrRightInBounds.y);\n' +
+ ' float useUpOrRight = float(upOrRightLogDepth > 0.0 && upOrRightInBounds.x && upOrRightInBounds.y);\n' +
' float useDownOrLeft = float(useUpOrRight == 0.0);\n' +
-
- ' vec3 upOrRightEC = getEyeCoordinate3FromWindowCoordordinate(glFragCoordXY + positiveOffset, upOrRightDepth);\n' +
- ' vec3 downOrLeftEC = getEyeCoordinate3FromWindowCoordordinate(glFragCoordXY - positiveOffset, downOrLeftDepth);\n' +
+ ' vec3 upOrRightEC = getEyeCoordinate3FromWindowCoordinate(glFragCoordXY + positiveOffset, upOrRightLogDepth);\n' +
+ ' vec3 downOrLeftEC = getEyeCoordinate3FromWindowCoordinate(glFragCoordXY - positiveOffset, downOrLeftLogDepth);\n' +
' return (upOrRightEC - (eyeCoordinate.xyz / eyeCoordinate.w)) * useUpOrRight + ((eyeCoordinate.xyz / eyeCoordinate.w) - downOrLeftEC) * useDownOrLeft;\n' +
'}\n';
diff --git a/Source/Shaders/Builtin/Functions/reverseLogDepth.glsl b/Source/Shaders/Builtin/Functions/reverseLogDepth.glsl
index e8719f24a9b..c6033d6d878 100644
--- a/Source/Shaders/Builtin/Functions/reverseLogDepth.glsl
+++ b/Source/Shaders/Builtin/Functions/reverseLogDepth.glsl
@@ -3,7 +3,7 @@ float czm_reverseLogDepth(float logZ)
#ifdef LOG_DEPTH
float near = czm_currentFrustum.x;
float far = czm_currentFrustum.y;
- logZ = pow(2.0, logZ * log2(far + 1.0)) - 1.0;
+ logZ = pow(2.0, logZ * czm_log2FarPlusOne) - 1.0;
logZ = far * (1.0 - near / logZ) / (far - near);
#endif
return logZ;
diff --git a/Source/Shaders/Builtin/Functions/vertexLogDepth.glsl b/Source/Shaders/Builtin/Functions/vertexLogDepth.glsl
index 1a16d725f5c..d48609d6847 100644
--- a/Source/Shaders/Builtin/Functions/vertexLogDepth.glsl
+++ b/Source/Shaders/Builtin/Functions/vertexLogDepth.glsl
@@ -7,7 +7,7 @@ void czm_updatePositionDepth() {
#if defined(LOG_DEPTH) && !defined(DISABLE_GL_POSITION_LOG_DEPTH)
v_logPositionEC = (czm_inverseProjection * gl_Position).xyz;
- gl_Position.z = log2(max(1e-6, 1.0 + gl_Position.w)) * czm_logFarDistance - 1.0;
+ gl_Position.z = log2(max(1e-6, 1.0 + gl_Position.w)) * czm_log2FarDistance - 1.0;
gl_Position.z *= gl_Position.w;
#endif
}
diff --git a/Source/Shaders/Builtin/Functions/writeLogDepth.glsl b/Source/Shaders/Builtin/Functions/writeLogDepth.glsl
index 49d01bd2e72..b9511ef4b8e 100644
--- a/Source/Shaders/Builtin/Functions/writeLogDepth.glsl
+++ b/Source/Shaders/Builtin/Functions/writeLogDepth.glsl
@@ -19,9 +19,9 @@ varying float v_logZ;
void czm_writeLogDepth(float logZ)
{
#if defined(GL_EXT_frag_depth) && defined(LOG_DEPTH) && !defined(DISABLE_LOG_DEPTH_FRAGMENT_WRITE)
- float halfLogFarDistance = czm_logFarDistance * 0.5;
+ float halfLogFarDistance = czm_log2FarDistance * 0.5;
float depth = log2(logZ);
- if (depth < log2(czm_currentFrustum.x)) {
+ if (depth < czm_log2NearDistance) {
discard;
}
gl_FragDepthEXT = depth * halfLogFarDistance;
diff --git a/Specs/Renderer/AutomaticUniformSpec.js b/Specs/Renderer/AutomaticUniformSpec.js
index f439c7e1af6..25778ed564f 100644
--- a/Specs/Renderer/AutomaticUniformSpec.js
+++ b/Specs/Renderer/AutomaticUniformSpec.js
@@ -1307,10 +1307,32 @@ defineSuite([
}).contextToRender();
});
- it('has czm_logFarDistance', function() {
+ it('has czm_log2FarDistance', function() {
var fs =
'void main() {' +
- ' gl_FragColor = vec4(czm_logFarDistance == (2.0 / log2(czm_currentFrustum.y + 1.0)));' +
+ ' gl_FragColor = vec4(czm_log2FarDistance == (2.0 / log2(czm_currentFrustum.y + 1.0)));' +
+ '}';
+ expect({
+ context : context,
+ fragmentShader : fs
+ }).contextToRender();
+ });
+
+ it('has czm_log2FarPlusOne', function() {
+ var fs =
+ 'void main() {' +
+ ' gl_FragColor = vec4(czm_log2FarPlusOne == log2(czm_currentFrustum.y + 1.0));' +
+ '}';
+ expect({
+ context : context,
+ fragmentShader : fs
+ }).contextToRender();
+ });
+
+ it('has czm_log2NearDistance', function() {
+ var fs =
+ 'void main() {' +
+ ' gl_FragColor = vec4(czm_log2NearDistance == log2(czm_currentFrustum.x));' +
'}';
expect({
context : context,
From 0844b9d52ba8c9abe4d7bb1b4731be832258bfd6 Mon Sep 17 00:00:00 2001
From: Kangning Li x
, y
, width
,
- * and height
properties in an vec4
's x
, y
, z
,
- * and w
components, respectively.
- *
- * @alias czm_viewport
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform vec4 czm_viewport;
- *
- * // 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({
- size : 1,
- datatype : WebGLConstants.FLOAT_VEC4,
- getValue : function(uniformState) {
- return uniformState.viewportCartesian4;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 4x4 orthographic projection matrix that
- * transforms window coordinates to clip coordinates. Clip coordinates is the
- * coordinate system for a vertex shader's gl_Position
output.
- *
- * This transform is useful when a vertex shader inputs or manipulates window coordinates
- * as done by {@link BillboardCollection}.
- *
- * Do not confuse {@link czm_viewportTransformation} with czm_viewportOrthographic
.
- * The former transforms from normalized device coordinates to window coordinates; the later transforms
- * from window coordinates to clip coordinates, and is often used to assign to gl_Position
.
- *
- * @alias czm_viewportOrthographic
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat4 czm_viewportOrthographic;
- *
- * // Example
- * gl_Position = czm_viewportOrthographic * vec4(windowPosition, 0.0, 1.0);
- *
- * @see UniformState#viewportOrthographic
- * @see czm_viewport
- * @see czm_viewportTransformation
- * @see BillboardCollection
- */
- czm_viewportOrthographic : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT4,
- getValue : function(uniformState) {
- return uniformState.viewportOrthographic;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 4x4 transformation matrix that
- * transforms normalized device coordinates to window coordinates. The context's
- * full viewport is used, and the depth range is assumed to be near = 0
- * and far = 1
.
- *
- * This transform is useful when there is a need to manipulate window coordinates
- * in a vertex shader as done by {@link BillboardCollection}. In many cases,
- * this matrix will not be used directly; instead, {@link czm_modelToWindowCoordinates}
- * will be used to transform directly from model to window coordinates.
- *
- * Do not confuse czm_viewportTransformation
with {@link czm_viewportOrthographic}.
- * The former transforms from normalized device coordinates to window coordinates; the later transforms
- * from window coordinates to clip coordinates, and is often used to assign to gl_Position
.
- *
- * @alias czm_viewportTransformation
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat4 czm_viewportTransformation;
- *
- * // Use czm_viewportTransformation as part of the
- * // transform from model to window coordinates.
- * 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
- * @see czm_modelToWindowCoordinates
- * @see BillboardCollection
- */
- czm_viewportTransformation : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT4,
- getValue : function(uniformState) {
- return uniformState.viewportTransformation;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing the depth after
- * only the globe has been rendered and packed into an RGBA texture.
- *
- * @private
- *
- * @alias czm_globeDepthTexture
- * @glslUniform
- *
- * @example
- * // GLSL declaration
- * uniform sampler2D czm_globeDepthTexture;
- *
- * // Get the depth at the current fragment
- * vec2 coords = gl_FragCoord.xy / czm_viewport.zw;
- * float depth = czm_unpackDepth(texture2D(czm_globeDepthTexture, coords));
- */
- czm_globeDepthTexture : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.SAMPLER_2D,
- getValue : function(uniformState) {
- return uniformState.globeDepthTexture;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 4x4 model transformation matrix that
- * transforms model coordinates to world coordinates.
- *
- * @alias czm_model
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat4 czm_model;
- *
- * // Example
- * vec4 worldPosition = czm_model * modelPosition;
- *
- * @see UniformState#model
- * @see czm_inverseModel
- * @see czm_modelView
- * @see czm_modelViewProjection
- */
- czm_model : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT4,
- getValue : function(uniformState) {
- return uniformState.model;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 4x4 model transformation matrix that
- * transforms world coordinates to model coordinates.
- *
- * @alias czm_inverseModel
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat4 czm_inverseModel;
- *
- * // Example
- * vec4 modelPosition = czm_inverseModel * worldPosition;
- *
- * @see UniformState#inverseModel
- * @see czm_model
- * @see czm_inverseModelView
- */
- czm_inverseModel : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT4,
- getValue : function(uniformState) {
- return uniformState.inverseModel;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 4x4 view transformation matrix that
- * transforms world coordinates to eye coordinates.
- *
- * @alias czm_view
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat4 czm_view;
- *
- * // Example
- * vec4 eyePosition = czm_view * worldPosition;
- *
- * @see UniformState#view
- * @see czm_viewRotation
- * @see czm_modelView
- * @see czm_viewProjection
- * @see czm_modelViewProjection
- * @see czm_inverseView
- */
- czm_view : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT4,
- getValue : function(uniformState) {
- return uniformState.view;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 4x4 view transformation matrix that
- * transforms 3D world coordinates to eye coordinates. In 3D mode, this is identical to
- * {@link czm_view}, but in 2D and Columbus View it represents the view matrix
- * as if the camera were at an equivalent location in 3D mode. This is useful for lighting
- * 2D and Columbus View in the same way that 3D is lit.
- *
- * @alias czm_view3D
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat4 czm_view3D;
- *
- * // Example
- * vec4 eyePosition3D = czm_view3D * worldPosition3D;
- *
- * @see UniformState#view3D
- * @see czm_view
- */
- czm_view3D : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT4,
- getValue : function(uniformState) {
- return uniformState.view3D;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 3x3 view rotation matrix that
- * transforms vectors in world coordinates to eye coordinates.
- *
- * @alias czm_viewRotation
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat3 czm_viewRotation;
- *
- * // Example
- * vec3 eyeVector = czm_viewRotation * worldVector;
- *
- * @see UniformState#viewRotation
- * @see czm_view
- * @see czm_inverseView
- * @see czm_inverseViewRotation
- */
- czm_viewRotation : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT3,
- getValue : function(uniformState) {
- return uniformState.viewRotation;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 3x3 view rotation matrix that
- * transforms vectors in 3D world coordinates to eye coordinates. In 3D mode, this is identical to
- * {@link czm_viewRotation}, but in 2D and Columbus View it represents the view matrix
- * as if the camera were at an equivalent location in 3D mode. This is useful for lighting
- * 2D and Columbus View in the same way that 3D is lit.
- *
- * @alias czm_viewRotation3D
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat3 czm_viewRotation3D;
- *
- * // Example
- * vec3 eyeVector = czm_viewRotation3D * worldVector;
- *
- * @see UniformState#viewRotation3D
- * @see czm_viewRotation
- */
- czm_viewRotation3D : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT3,
- getValue : function(uniformState) {
- return uniformState.viewRotation3D;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 4x4 transformation matrix that
- * transforms from eye coordinates to world coordinates.
- *
- * @alias czm_inverseView
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat4 czm_inverseView;
- *
- * // Example
- * vec4 worldPosition = czm_inverseView * eyePosition;
- *
- * @see UniformState#inverseView
- * @see czm_view
- * @see czm_inverseNormal
- */
- czm_inverseView : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT4,
- getValue : function(uniformState) {
- return uniformState.inverseView;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 4x4 transformation matrix that
- * transforms from 3D eye coordinates to world coordinates. In 3D mode, this is identical to
- * {@link czm_inverseView}, but in 2D and Columbus View it represents the inverse view matrix
- * as if the camera were at an equivalent location in 3D mode. This is useful for lighting
- * 2D and Columbus View in the same way that 3D is lit.
- *
- * @alias czm_inverseView3D
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat4 czm_inverseView3D;
- *
- * // Example
- * vec4 worldPosition = czm_inverseView3D * eyePosition;
- *
- * @see UniformState#inverseView3D
- * @see czm_inverseView
- */
- czm_inverseView3D : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT4,
- getValue : function(uniformState) {
- return uniformState.inverseView3D;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 3x3 rotation matrix that
- * transforms vectors from eye coordinates to world coordinates.
- *
- * @alias czm_inverseViewRotation
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat3 czm_inverseViewRotation;
- *
- * // Example
- * vec4 worldVector = czm_inverseViewRotation * eyeVector;
- *
- * @see UniformState#inverseView
- * @see czm_view
- * @see czm_viewRotation
- * @see czm_inverseViewRotation
- */
- czm_inverseViewRotation : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT3,
- getValue : function(uniformState) {
- return uniformState.inverseViewRotation;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 3x3 rotation matrix that
- * transforms vectors from 3D eye coordinates to world coordinates. In 3D mode, this is identical to
- * {@link czm_inverseViewRotation}, but in 2D and Columbus View it represents the inverse view matrix
- * as if the camera were at an equivalent location in 3D mode. This is useful for lighting
- * 2D and Columbus View in the same way that 3D is lit.
- *
- * @alias czm_inverseViewRotation3D
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat3 czm_inverseViewRotation3D;
- *
- * // Example
- * vec4 worldVector = czm_inverseViewRotation3D * eyeVector;
- *
- * @see UniformState#inverseView3D
- * @see czm_inverseViewRotation
- */
- czm_inverseViewRotation3D : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT3,
- getValue : function(uniformState) {
- return uniformState.inverseViewRotation3D;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 4x4 projection transformation matrix that
- * transforms eye coordinates to clip coordinates. Clip coordinates is the
- * coordinate system for a vertex shader's gl_Position
output.
- *
- * @alias czm_projection
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat4 czm_projection;
- *
- * // Example
- * gl_Position = czm_projection * eyePosition;
- *
- * @see UniformState#projection
- * @see czm_viewProjection
- * @see czm_modelViewProjection
- * @see czm_infiniteProjection
- */
- czm_projection : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT4,
- getValue : function(uniformState) {
- return uniformState.projection;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 4x4 inverse projection transformation matrix that
- * transforms from clip coordinates to eye coordinates. Clip coordinates is the
- * coordinate system for a vertex shader's gl_Position
output.
- *
- * @alias czm_inverseProjection
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat4 czm_inverseProjection;
- *
- * // Example
- * vec4 eyePosition = czm_inverseProjection * clipPosition;
- *
- * @see UniformState#inverseProjection
- * @see czm_projection
- */
- czm_inverseProjection : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT4,
- getValue : function(uniformState) {
- return uniformState.inverseProjection;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 4x4 projection transformation matrix with the far plane at infinity,
- * that transforms eye coordinates to clip coordinates. Clip coordinates is the
- * coordinate system for a vertex shader's gl_Position
output. An infinite far plane is used
- * in algorithms like shadow volumes and GPU ray casting with proxy geometry to ensure that triangles
- * are not clipped by the far plane.
- *
- * @alias czm_infiniteProjection
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat4 czm_infiniteProjection;
- *
- * // Example
- * gl_Position = czm_infiniteProjection * eyePosition;
- *
- * @see UniformState#infiniteProjection
- * @see czm_projection
- * @see czm_modelViewInfiniteProjection
- */
- czm_infiniteProjection : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT4,
- getValue : function(uniformState) {
- return uniformState.infiniteProjection;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 4x4 model-view transformation matrix that
- * transforms model coordinates to eye coordinates.
- *
- * Positions should be transformed to eye coordinates using czm_modelView
and
- * normals should be transformed using {@link czm_normal}.
- *
- * @alias czm_modelView
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat4 czm_modelView;
- *
- * // Example
- * vec4 eyePosition = czm_modelView * modelPosition;
- *
- * // 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
- * @see czm_modelViewProjection
- * @see czm_normal
- */
- czm_modelView : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT4,
- getValue : function(uniformState) {
- return uniformState.modelView;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 4x4 model-view transformation matrix that
- * transforms 3D model coordinates to eye coordinates. In 3D mode, this is identical to
- * {@link czm_modelView}, but in 2D and Columbus View it represents the model-view matrix
- * as if the camera were at an equivalent location in 3D mode. This is useful for lighting
- * 2D and Columbus View in the same way that 3D is lit.
- *
- * Positions should be transformed to eye coordinates using czm_modelView3D
and
- * normals should be transformed using {@link czm_normal3D}.
- *
- * @alias czm_modelView3D
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat4 czm_modelView3D;
- *
- * // Example
- * vec4 eyePosition = czm_modelView3D * modelPosition;
- *
- * // The above is equivalent to, but more efficient than:
- * vec4 eyePosition = czm_view3D * czm_model * modelPosition;
- *
- * @see UniformState#modelView3D
- * @see czm_modelView
- */
- czm_modelView3D : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT4,
- getValue : function(uniformState) {
- return uniformState.modelView3D;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 4x4 model-view transformation matrix that
- * transforms model coordinates, relative to the eye, to eye coordinates. This is used
- * in conjunction with {@link czm_translateRelativeToEye}.
- *
- * @alias czm_modelViewRelativeToEye
- * @glslUniform
- *
- * @example
- * // GLSL declaration
- * uniform mat4 czm_modelViewRelativeToEye;
- *
- * // Example
- * attribute vec3 positionHigh;
- * attribute vec3 positionLow;
- *
- * void main()
- * {
- * vec4 p = czm_translateRelativeToEye(positionHigh, positionLow);
- * gl_Position = czm_projection * (czm_modelViewRelativeToEye * p);
- * }
- *
- * @see czm_modelViewProjectionRelativeToEye
- * @see czm_translateRelativeToEye
- * @see EncodedCartesian3
- */
- czm_modelViewRelativeToEye : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT4,
- getValue : function(uniformState) {
- return uniformState.modelViewRelativeToEye;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 4x4 transformation matrix that
- * transforms from eye coordinates to model coordinates.
- *
- * @alias czm_inverseModelView
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat4 czm_inverseModelView;
- *
- * // Example
- * vec4 modelPosition = czm_inverseModelView * eyePosition;
- *
- * @see UniformState#inverseModelView
- * @see czm_modelView
- */
- czm_inverseModelView : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT4,
- getValue : function(uniformState) {
- return uniformState.inverseModelView;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 4x4 transformation matrix that
- * transforms from eye coordinates to 3D model coordinates. In 3D mode, this is identical to
- * {@link czm_inverseModelView}, but in 2D and Columbus View it represents the inverse model-view matrix
- * as if the camera were at an equivalent location in 3D mode. This is useful for lighting
- * 2D and Columbus View in the same way that 3D is lit.
- *
- * @alias czm_inverseModelView3D
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat4 czm_inverseModelView3D;
- *
- * // Example
- * vec4 modelPosition = czm_inverseModelView3D * eyePosition;
- *
- * @see UniformState#inverseModelView
- * @see czm_inverseModelView
- * @see czm_modelView3D
- */
- czm_inverseModelView3D : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT4,
- getValue : function(uniformState) {
- return uniformState.inverseModelView3D;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 4x4 view-projection transformation matrix that
- * transforms world coordinates to clip coordinates. Clip coordinates is the
- * coordinate system for a vertex shader's gl_Position
output.
- *
- * @alias czm_viewProjection
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat4 czm_viewProjection;
- *
- * // Example
- * vec4 gl_Position = czm_viewProjection * czm_model * modelPosition;
- *
- * // 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
- * @see czm_modelViewProjection
- * @see czm_inverseViewProjection
- */
- czm_viewProjection : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT4,
- getValue : function(uniformState) {
- return uniformState.viewProjection;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 4x4 view-projection transformation matrix that
- * transforms clip coordinates to world coordinates. Clip coordinates is the
- * coordinate system for a vertex shader's gl_Position
output.
- *
- * @alias czm_inverseViewProjection
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat4 czm_inverseViewProjection;
- *
- * // Example
- * vec4 worldPosition = czm_inverseViewProjection * clipPosition;
- *
- * @see UniformState#inverseViewProjection
- * @see czm_viewProjection
- */
- czm_inverseViewProjection : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT4,
- getValue : function(uniformState) {
- return uniformState.inverseViewProjection;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 4x4 model-view-projection transformation matrix that
- * transforms model coordinates to clip coordinates. Clip coordinates is the
- * coordinate system for a vertex shader's gl_Position
output.
- *
- * @alias czm_modelViewProjection
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat4 czm_modelViewProjection;
- *
- * // Example
- * vec4 gl_Position = czm_modelViewProjection * modelPosition;
- *
- * // 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
- * @see czm_projection
- * @see czm_modelView
- * @see czm_viewProjection
- * @see czm_modelViewInfiniteProjection
- * @see czm_inverseModelViewProjection
- */
- czm_modelViewProjection : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT4,
- getValue : function(uniformState) {
- return uniformState.modelViewProjection;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 4x4 inverse model-view-projection transformation matrix that
- * transforms clip coordinates to model coordinates. Clip coordinates is the
- * coordinate system for a vertex shader's gl_Position
output.
- *
- * @alias czm_inverseModelViewProjection
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat4 czm_inverseModelViewProjection;
- *
- * // Example
- * vec4 modelPosition = czm_inverseModelViewProjection * clipPosition;
- *
- * @see UniformState#modelViewProjection
- * @see czm_modelViewProjection
- */
- czm_inverseModelViewProjection : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT4,
- getValue : function(uniformState) {
- return uniformState.inverseModelViewProjection;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 4x4 model-view-projection transformation matrix that
- * transforms model coordinates, relative to the eye, to clip coordinates. Clip coordinates is the
- * coordinate system for a vertex shader's gl_Position
output. This is used in
- * conjunction with {@link czm_translateRelativeToEye}.
- *
- * @alias czm_modelViewProjectionRelativeToEye
- * @glslUniform
- *
- * @example
- * // GLSL declaration
- * uniform mat4 czm_modelViewProjectionRelativeToEye;
- *
- * // Example
- * attribute vec3 positionHigh;
- * attribute vec3 positionLow;
- *
- * void main()
- * {
- * vec4 p = czm_translateRelativeToEye(positionHigh, positionLow);
- * gl_Position = czm_modelViewProjectionRelativeToEye * p;
- * }
- *
- * @see czm_modelViewRelativeToEye
- * @see czm_translateRelativeToEye
- * @see EncodedCartesian3
- */
- czm_modelViewProjectionRelativeToEye : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT4,
- getValue : function(uniformState) {
- return uniformState.modelViewProjectionRelativeToEye;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 4x4 model-view-projection transformation matrix that
- * transforms model coordinates to clip coordinates. Clip coordinates is the
- * coordinate system for a vertex shader's gl_Position
output. The projection matrix places
- * the far plane at infinity. This is useful in algorithms like shadow volumes and GPU ray casting with
- * proxy geometry to ensure that triangles are not clipped by the far plane.
- *
- * @alias czm_modelViewInfiniteProjection
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat4 czm_modelViewInfiniteProjection;
- *
- * // Example
- * vec4 gl_Position = czm_modelViewInfiniteProjection * modelPosition;
- *
- * // 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
- * @see czm_infiniteProjection
- * @see czm_modelViewProjection
- */
- czm_modelViewInfiniteProjection : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT4,
- getValue : function(uniformState) {
- return uniformState.modelViewInfiniteProjection;
- }
- }),
-
- /**
- * An automatic GLSL uniform that indicates if the current camera is orthographic in 3D.
- *
- * @alias czm_orthographicIn3D
- * @see UniformState#orthographicIn3D
- */
- czm_orthographicIn3D : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT,
- getValue : function(uniformState) {
- return uniformState.orthographicIn3D ? 1 : 0;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 3x3 normal transformation matrix that
- * transforms normal vectors in model coordinates to eye coordinates.
- *
- * Positions should be transformed to eye coordinates using {@link czm_modelView} and
- * normals should be transformed using czm_normal
.
- *
- * @alias czm_normal
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat3 czm_normal;
- *
- * // Example
- * vec3 eyeNormal = czm_normal * normal;
- *
- * @see UniformState#normal
- * @see czm_inverseNormal
- * @see czm_modelView
- */
- czm_normal : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT3,
- getValue : function(uniformState) {
- return uniformState.normal;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 3x3 normal transformation matrix that
- * transforms normal vectors in 3D model coordinates to eye coordinates.
- * In 3D mode, this is identical to
- * {@link czm_normal}, but in 2D and Columbus View it represents the normal transformation
- * matrix as if the camera were at an equivalent location in 3D mode. This is useful for lighting
- * 2D and Columbus View in the same way that 3D is lit.
- *
- * Positions should be transformed to eye coordinates using {@link czm_modelView3D} and
- * normals should be transformed using czm_normal3D
.
- *
- * @alias czm_normal3D
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat3 czm_normal3D;
- *
- * // Example
- * vec3 eyeNormal = czm_normal3D * normal;
- *
- * @see UniformState#normal3D
- * @see czm_normal
- */
- czm_normal3D : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT3,
- getValue : function(uniformState) {
- return uniformState.normal3D;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 3x3 normal transformation matrix that
- * transforms normal vectors in eye coordinates to model coordinates. This is
- * the opposite of the transform provided by {@link czm_normal}.
- *
- * @alias czm_inverseNormal
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat3 czm_inverseNormal;
- *
- * // Example
- * vec3 normalMC = czm_inverseNormal * normalEC;
- *
- * @see UniformState#inverseNormal
- * @see czm_normal
- * @see czm_modelView
- * @see czm_inverseView
- */
- czm_inverseNormal : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT3,
- getValue : function(uniformState) {
- return uniformState.inverseNormal;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 3x3 normal transformation matrix that
- * transforms normal vectors in eye coordinates to 3D model coordinates. This is
- * the opposite of the transform provided by {@link czm_normal}.
- * In 3D mode, this is identical to
- * {@link czm_inverseNormal}, but in 2D and Columbus View it represents the inverse normal transformation
- * matrix as if the camera were at an equivalent location in 3D mode. This is useful for lighting
- * 2D and Columbus View in the same way that 3D is lit.
- *
- * @alias czm_inverseNormal3D
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat3 czm_inverseNormal3D;
- *
- * // Example
- * vec3 normalMC = czm_inverseNormal3D * normalEC;
- *
- * @see UniformState#inverseNormal3D
- * @see czm_inverseNormal
- */
- czm_inverseNormal3D : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT3,
- getValue : function(uniformState) {
- return uniformState.inverseNormal3D;
- }
- }),
-
- /**
- * An automatic GLSL uniform containing height (x
) and height squared (y
)
- * of the eye (camera) in the 2D scene in meters.
- *
- * @alias czm_eyeHeight2D
- * @glslUniform
- *
- * @see UniformState#eyeHeight2D
- */
- czm_eyeHeight2D : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_VEC2,
- getValue : function(uniformState) {
- return uniformState.eyeHeight2D;
- }
- }),
-
- /**
- * An automatic GLSL uniform containing the near distance (x
) and the far distance (y
)
- * of the frustum defined by the camera. This is the largest possible frustum, not an individual
- * frustum used for multi-frustum rendering.
- *
- * @alias czm_entireFrustum
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform vec2 czm_entireFrustum;
- *
- * // Example
- * float frustumLength = czm_entireFrustum.y - czm_entireFrustum.x;
- *
- * @see UniformState#entireFrustum
- * @see czm_currentFrustum
- */
- czm_entireFrustum : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_VEC2,
- getValue : function(uniformState) {
- return uniformState.entireFrustum;
- }
- }),
+ // this check must use typeof, not defined, because defined doesn't work with undeclared variables.
+ if (typeof WebGLRenderingContext === 'undefined') {
+ return {};
+ }
- /**
- * An automatic GLSL uniform containing the near distance (x
) and the far distance (y
)
- * of the frustum defined by the camera. This is the individual
- * frustum used for multi-frustum rendering.
- *
- * @alias czm_currentFrustum
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform vec2 czm_currentFrustum;
- *
- * // Example
- * float frustumLength = czm_currentFrustum.y - czm_currentFrustum.x;
- *
- * @see UniformState#currentFrustum
- * @see czm_entireFrustum
- */
- czm_currentFrustum : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_VEC2,
- getValue : function(uniformState) {
- return uniformState.currentFrustum;
+ var datatypeToGlsl = {};
+ datatypeToGlsl[WebGLConstants.FLOAT] = 'float';
+ datatypeToGlsl[WebGLConstants.FLOAT_VEC2] = 'vec2';
+ datatypeToGlsl[WebGLConstants.FLOAT_VEC3] = 'vec3';
+ datatypeToGlsl[WebGLConstants.FLOAT_VEC4] = 'vec4';
+ datatypeToGlsl[WebGLConstants.INT] = 'int';
+ datatypeToGlsl[WebGLConstants.INT_VEC2] = 'ivec2';
+ datatypeToGlsl[WebGLConstants.INT_VEC3] = 'ivec3';
+ datatypeToGlsl[WebGLConstants.INT_VEC4] = 'ivec4';
+ datatypeToGlsl[WebGLConstants.BOOL] = 'bool';
+ datatypeToGlsl[WebGLConstants.BOOL_VEC2] = 'bvec2';
+ datatypeToGlsl[WebGLConstants.BOOL_VEC3] = 'bvec3';
+ datatypeToGlsl[WebGLConstants.BOOL_VEC4] = 'bvec4';
+ datatypeToGlsl[WebGLConstants.FLOAT_MAT2] = 'mat2';
+ datatypeToGlsl[WebGLConstants.FLOAT_MAT3] = 'mat3';
+ datatypeToGlsl[WebGLConstants.FLOAT_MAT4] = 'mat4';
+ datatypeToGlsl[WebGLConstants.SAMPLER_2D] = 'sampler2D';
+ datatypeToGlsl[WebGLConstants.SAMPLER_CUBE] = 'samplerCube';
+
+ AutomaticUniform.prototype.getDeclaration = function(name) {
+ var declaration = 'uniform ' + datatypeToGlsl[this._datatype] + ' ' + name;
+
+ var size = this._size;
+ if (size === 1) {
+ declaration += ';';
+ } else {
+ declaration += '[' + size.toString() + '];';
}
- }),
- /**
- * The distances to the frustum planes. The top, bottom, left and right distances are
- * the x, y, z, and w components, respectively.
- *
- * @alias czm_frustumPlanes
- * @glslUniform
- */
- czm_frustumPlanes : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_VEC4,
- getValue : function(uniformState) {
- return uniformState.frustumPlanes;
- }
- }),
+ return declaration;
+ };
/**
- * The log2 of the current frustums far plane. Used for computing the log depth.
- *
- * @alias czm_log2FarDistance
- * @glslUniform
- *
* @private
*/
- czm_log2FarDistance : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT,
- getValue : function(uniformState) {
- return uniformState.logFarDistance;
- }
- }),
-
- /**
- * An automatic GLSL uniform containing log2 of the far distance + 1.0.
- * This is used when reversing log depth computations.
- *
- * @alias czm_log2FarPlusOne
- * @glslUniform
- */
- czm_log2FarPlusOne : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT,
- getValue : function(uniformState) {
- return CesiumMath.log2(uniformState.currentFrustum.y + 1.0);
- }
- }),
-
- /**
- * An automatic GLSL uniform containing log2 of the near distance.
- * This is used when writing log depth in the fragment shader.
- *
- * @alias czm_log2NearDistance
- * @glslUniform
- */
- czm_log2NearDistance : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT,
- getValue : function(uniformState) {
- return CesiumMath.log2(uniformState.currentFrustum.x);
- }
- }),
-
- /**
- * An automatic GLSL uniform representing the sun position in world coordinates.
- *
- * @alias czm_sunPositionWC
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform vec3 czm_sunPositionWC;
- *
- * @see UniformState#sunPositionWC
- * @see czm_sunPositionColumbusView
- * @see czm_sunDirectionWC
- */
- czm_sunPositionWC : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_VEC3,
- getValue : function(uniformState) {
- return uniformState.sunPositionWC;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing the sun position in Columbus view world coordinates.
- *
- * @alias czm_sunPositionColumbusView
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform vec3 czm_sunPositionColumbusView;
- *
- * @see UniformState#sunPositionColumbusView
- * @see czm_sunPositionWC
- */
- czm_sunPositionColumbusView : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_VEC3,
- getValue : function(uniformState) {
- return uniformState.sunPositionColumbusView;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing the normalized direction to the sun in eye coordinates.
- * This is commonly used for directional lighting computations.
- *
- * @alias czm_sunDirectionEC
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform vec3 czm_sunDirectionEC;
- *
- * // Example
- * float diffuse = max(dot(czm_sunDirectionEC, normalEC), 0.0);
- *
- * @see UniformState#sunDirectionEC
- * @see czm_moonDirectionEC
- * @see czm_sunDirectionWC
- */
- czm_sunDirectionEC : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_VEC3,
- getValue : function(uniformState) {
- return uniformState.sunDirectionEC;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing the normalized direction to the sun in world coordinates.
- * This is commonly used for directional lighting computations.
- *
- * @alias czm_sunDirectionWC
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform vec3 czm_sunDirectionWC;
- *
- * @see UniformState#sunDirectionWC
- * @see czm_sunPositionWC
- * @see czm_sunDirectionEC
- */
- czm_sunDirectionWC : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_VEC3,
- getValue : function(uniformState) {
- return uniformState.sunDirectionWC;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing the normalized direction to the moon in eye coordinates.
- * This is commonly used for directional lighting computations.
- *
- * @alias czm_moonDirectionEC
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform vec3 czm_moonDirectionEC;
- *
- * // Example
- * float diffuse = max(dot(czm_moonDirectionEC, normalEC), 0.0);
- *
- * @see UniformState#moonDirectionEC
- * @see czm_sunDirectionEC
- */
- czm_moonDirectionEC : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_VEC3,
- getValue : function(uniformState) {
- return uniformState.moonDirectionEC;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing the high bits of the camera position in model
- * coordinates. This is used for GPU RTE to eliminate jittering artifacts when rendering
- * as described in {@link http://blogs.agi.com/insight3d/index.php/2008/09/03/precisions-precisions/|Precisions, Precisions}.
- *
- * @alias czm_encodedCameraPositionMCHigh
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform vec3 czm_encodedCameraPositionMCHigh;
- *
- * @see czm_encodedCameraPositionMCLow
- * @see czm_modelViewRelativeToEye
- * @see czm_modelViewProjectionRelativeToEye
- */
- czm_encodedCameraPositionMCHigh : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_VEC3,
- getValue : function(uniformState) {
- return uniformState.encodedCameraPositionMCHigh;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing the low bits of the camera position in model
- * coordinates. This is used for GPU RTE to eliminate jittering artifacts when rendering
- * as described in {@link http://blogs.agi.com/insight3d/index.php/2008/09/03/precisions-precisions/|Precisions, Precisions}.
- *
- * @alias czm_encodedCameraPositionMCLow
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform vec3 czm_encodedCameraPositionMCLow;
- *
- * @see czm_encodedCameraPositionMCHigh
- * @see czm_modelViewRelativeToEye
- * @see czm_modelViewProjectionRelativeToEye
- */
- czm_encodedCameraPositionMCLow : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_VEC3,
- getValue : function(uniformState) {
- return uniformState.encodedCameraPositionMCLow;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing the position of the viewer (camera) in world coordinates.
- *
- * @alias czm_viewerPositionWC
- * @glslUniform
- *
- * @example
- * // GLSL declaration
- * uniform vec3 czm_viewerPositionWC;
- */
- czm_viewerPositionWC : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_VEC3,
- getValue : function(uniformState) {
- return Matrix4.getTranslation(uniformState.inverseView, viewerPositionWCScratch);
- }
- }),
-
- /**
- * An automatic GLSL uniform representing the frame number. This uniform is automatically incremented
- * every frame.
- *
- * @alias czm_frameNumber
- * @glslUniform
- *
- * @example
- * // GLSL declaration
- * uniform float czm_frameNumber;
- */
- czm_frameNumber : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT,
- getValue : function(uniformState) {
- return uniformState.frameState.frameNumber;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing the current morph transition time between
- * 2D/Columbus View and 3D, with 0.0 being 2D or Columbus View and 1.0 being 3D.
- *
- * @alias czm_morphTime
- * @glslUniform
- *
- * @example
- * // GLSL declaration
- * uniform float czm_morphTime;
- *
- * // Example
- * vec4 p = czm_columbusViewMorph(position2D, position3D, czm_morphTime);
- */
- czm_morphTime : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT,
- getValue : function(uniformState) {
- return uniformState.frameState.morphTime;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing the current {@link SceneMode}, expressed
- * as a float.
- *
- * @alias czm_sceneMode
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform float czm_sceneMode;
- *
- * // Example
- * if (czm_sceneMode == czm_sceneMode2D)
- * {
- * eyeHeightSq = czm_eyeHeight2D.y;
- * }
- *
- * @see czm_sceneMode2D
- * @see czm_sceneModeColumbusView
- * @see czm_sceneMode3D
- * @see czm_sceneModeMorphing
- */
- czm_sceneMode : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT,
- getValue : function(uniformState) {
- return uniformState.frameState.mode;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing the current rendering pass.
- *
- * @alias czm_pass
- * @glslUniform
- *
- * @example
- * // GLSL declaration
- * uniform float czm_pass;
- *
- * // Example
- * if ((czm_pass == czm_passTranslucent) && isOpaque())
- * {
- * gl_Position *= 0.0; // Cull opaque geometry in the translucent pass
- * }
- */
- czm_pass : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT,
- getValue : function(uniformState) {
- return uniformState.pass;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing the current scene background color.
- *
- * @alias czm_backgroundColor
- * @glslUniform
- *
- * @example
- * // GLSL declaration
- * uniform vec4 czm_backgroundColor;
- *
- * // Example: If the given color's RGB matches the background color, invert it.
- * vec4 adjustColorForContrast(vec4 color)
- * {
- * if (czm_backgroundColor.rgb == color.rgb)
- * {
- * color.rgb = vec3(1.0) - color.rgb;
- * }
- *
- * return color;
- * }
- */
- czm_backgroundColor : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_VEC4,
- getValue : function(uniformState) {
- return uniformState.backgroundColor;
- }
- }),
-
- /**
- * An automatic GLSL uniform containing the BRDF look up texture used for image-based lighting computations.
- *
- * @alias czm_brdfLut
- * @glslUniform
- *
- * @example
- * // GLSL declaration
- * uniform sampler2D czm_brdfLut;
- *
- * // Example: For a given roughness and NdotV value, find the material's BRDF information in the red and green channels
- * float roughness = 0.5;
- * float NdotV = dot(normal, view);
- * vec2 brdfLut = texture2D(czm_brdfLut, vec2(NdotV, 1.0 - roughness)).rg;
- */
- czm_brdfLut : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.SAMPLER_2D,
- getValue : function(uniformState) {
- return uniformState.brdfLut;
- }
- }),
-
- /**
- * An automatic GLSL uniform containing the environment map used within the scene.
- *
- * @alias czm_environmentMap
- * @glslUniform
- *
- * @example
- * // GLSL declaration
- * uniform samplerCube czm_environmentMap;
- *
- * // Example: Create a perfect reflection of the environment map on a model
- * float reflected = reflect(view, normal);
- * vec4 reflectedColor = textureCube(czm_environmentMap, reflected);
- */
- czm_environmentMap : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.SAMPLER_CUBE,
- getValue : function(uniformState) {
- return uniformState.environmentMap;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing a 3x3 rotation matrix that transforms
- * from True Equator Mean Equinox (TEME) axes to the pseudo-fixed axes at the current scene time.
- *
- * @alias czm_temeToPseudoFixed
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform mat3 czm_temeToPseudoFixed;
- *
- * // Example
- * vec3 pseudoFixed = czm_temeToPseudoFixed * teme;
- *
- * @see UniformState#temeToPseudoFixedMatrix
- * @see Transforms.computeTemeToPseudoFixedMatrix
- */
- czm_temeToPseudoFixed : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_MAT3,
- getValue : function(uniformState) {
- return uniformState.temeToPseudoFixedMatrix;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing the ratio of canvas coordinate space to canvas pixel space.
- *
- * @alias czm_resolutionScale
- * @glslUniform
- *
- * @example
- * uniform float czm_resolutionScale;
- */
- czm_resolutionScale : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT,
- getValue : function(uniformState) {
- return uniformState.resolutionScale;
- }
- }),
-
- /**
- * An automatic GLSL uniform scalar used to mix a color with the fog color based on the distance to the camera.
- *
- * @alias czm_fogDensity
- * @glslUniform
- *
- * @see czm_fog
- */
- czm_fogDensity : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT,
- getValue : function(uniformState) {
- return uniformState.fogDensity;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing the splitter position to use when rendering imagery layers with a splitter.
- * This will be in pixel coordinates relative to the canvas.
- *
- * @alias czm_imagerySplitPosition
- * @glslUniform
- *
- *
- * @example
- * // GLSL declaration
- * uniform float czm_imagerySplitPosition;
- */
- czm_imagerySplitPosition : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT,
- getValue : function(uniformState) {
- return uniformState.imagerySplitPosition;
- }
- }),
-
- /**
- * An automatic GLSL uniform scalar representing the geometric tolerance per meter
- *
- * @alias czm_geometricToleranceOverMeter
- * @glslUniform
- */
- czm_geometricToleranceOverMeter : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT,
- getValue : function(uniformState) {
- return uniformState.geometricToleranceOverMeter;
- }
- }),
-
- /**
- * An automatic GLSL uniform representing the distance from the camera at which to disable the depth test of billboards, labels and points
- * to, for example, prevent clipping against terrain. When set to zero, the depth test should always be applied. When less than zero,
- * the depth test should never be applied.
- *
- * @alias czm_minimumDisableDepthTestDistance
- * @glslUniform
- */
- czm_minimumDisableDepthTestDistance : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT,
- getValue : function(uniformState) {
- return uniformState.minimumDisableDepthTestDistance;
- }
- }),
-
- /**
- * An automatic GLSL uniform that will be the highlight color of unclassified 3D Tiles.
- *
- * @alias czm_invertClassificationColor
- * @glslUniform
- */
- czm_invertClassificationColor : new AutomaticUniform({
- size : 1,
- datatype : WebGLConstants.FLOAT_VEC4,
- getValue : function(uniformState) {
- return uniformState.invertClassificationColor;
- }
- })
-};
-
-return AutomaticUniforms;
+ var AutomaticUniforms = {
+ /**
+ * An automatic GLSL uniform containing the viewport's x
, y
, width
,
+ * and height
properties in an vec4
's x
, y
, z
,
+ * and w
components, respectively.
+ *
+ * @alias czm_viewport
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform vec4 czm_viewport;
+ *
+ * // 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({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_VEC4,
+ getValue : function(uniformState) {
+ return uniformState.viewportCartesian4;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 4x4 orthographic projection matrix that
+ * transforms window coordinates to clip coordinates. Clip coordinates is the
+ * coordinate system for a vertex shader's gl_Position
output.
+ *
+ * This transform is useful when a vertex shader inputs or manipulates window coordinates
+ * as done by {@link BillboardCollection}.
+ *
+ * Do not confuse {@link czm_viewportTransformation} with czm_viewportOrthographic
.
+ * The former transforms from normalized device coordinates to window coordinates; the later transforms
+ * from window coordinates to clip coordinates, and is often used to assign to gl_Position
.
+ *
+ * @alias czm_viewportOrthographic
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat4 czm_viewportOrthographic;
+ *
+ * // Example
+ * gl_Position = czm_viewportOrthographic * vec4(windowPosition, 0.0, 1.0);
+ *
+ * @see UniformState#viewportOrthographic
+ * @see czm_viewport
+ * @see czm_viewportTransformation
+ * @see BillboardCollection
+ */
+ czm_viewportOrthographic : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT4,
+ getValue : function(uniformState) {
+ return uniformState.viewportOrthographic;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 4x4 transformation matrix that
+ * transforms normalized device coordinates to window coordinates. The context's
+ * full viewport is used, and the depth range is assumed to be near = 0
+ * and far = 1
.
+ *
+ * This transform is useful when there is a need to manipulate window coordinates
+ * in a vertex shader as done by {@link BillboardCollection}. In many cases,
+ * this matrix will not be used directly; instead, {@link czm_modelToWindowCoordinates}
+ * will be used to transform directly from model to window coordinates.
+ *
+ * Do not confuse czm_viewportTransformation
with {@link czm_viewportOrthographic}.
+ * The former transforms from normalized device coordinates to window coordinates; the later transforms
+ * from window coordinates to clip coordinates, and is often used to assign to gl_Position
.
+ *
+ * @alias czm_viewportTransformation
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat4 czm_viewportTransformation;
+ *
+ * // Use czm_viewportTransformation as part of the
+ * // transform from model to window coordinates.
+ * 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
+ * @see czm_modelToWindowCoordinates
+ * @see BillboardCollection
+ */
+ czm_viewportTransformation : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT4,
+ getValue : function(uniformState) {
+ return uniformState.viewportTransformation;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing the depth after
+ * only the globe has been rendered and packed into an RGBA texture.
+ *
+ * @private
+ *
+ * @alias czm_globeDepthTexture
+ * @glslUniform
+ *
+ * @example
+ * // GLSL declaration
+ * uniform sampler2D czm_globeDepthTexture;
+ *
+ * // Get the depth at the current fragment
+ * vec2 coords = gl_FragCoord.xy / czm_viewport.zw;
+ * float depth = czm_unpackDepth(texture2D(czm_globeDepthTexture, coords));
+ */
+ czm_globeDepthTexture : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.SAMPLER_2D,
+ getValue : function(uniformState) {
+ return uniformState.globeDepthTexture;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 4x4 model transformation matrix that
+ * transforms model coordinates to world coordinates.
+ *
+ * @alias czm_model
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat4 czm_model;
+ *
+ * // Example
+ * vec4 worldPosition = czm_model * modelPosition;
+ *
+ * @see UniformState#model
+ * @see czm_inverseModel
+ * @see czm_modelView
+ * @see czm_modelViewProjection
+ */
+ czm_model : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT4,
+ getValue : function(uniformState) {
+ return uniformState.model;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 4x4 model transformation matrix that
+ * transforms world coordinates to model coordinates.
+ *
+ * @alias czm_inverseModel
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat4 czm_inverseModel;
+ *
+ * // Example
+ * vec4 modelPosition = czm_inverseModel * worldPosition;
+ *
+ * @see UniformState#inverseModel
+ * @see czm_model
+ * @see czm_inverseModelView
+ */
+ czm_inverseModel : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT4,
+ getValue : function(uniformState) {
+ return uniformState.inverseModel;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 4x4 view transformation matrix that
+ * transforms world coordinates to eye coordinates.
+ *
+ * @alias czm_view
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat4 czm_view;
+ *
+ * // Example
+ * vec4 eyePosition = czm_view * worldPosition;
+ *
+ * @see UniformState#view
+ * @see czm_viewRotation
+ * @see czm_modelView
+ * @see czm_viewProjection
+ * @see czm_modelViewProjection
+ * @see czm_inverseView
+ */
+ czm_view : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT4,
+ getValue : function(uniformState) {
+ return uniformState.view;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 4x4 view transformation matrix that
+ * transforms 3D world coordinates to eye coordinates. In 3D mode, this is identical to
+ * {@link czm_view}, but in 2D and Columbus View it represents the view matrix
+ * as if the camera were at an equivalent location in 3D mode. This is useful for lighting
+ * 2D and Columbus View in the same way that 3D is lit.
+ *
+ * @alias czm_view3D
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat4 czm_view3D;
+ *
+ * // Example
+ * vec4 eyePosition3D = czm_view3D * worldPosition3D;
+ *
+ * @see UniformState#view3D
+ * @see czm_view
+ */
+ czm_view3D : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT4,
+ getValue : function(uniformState) {
+ return uniformState.view3D;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 3x3 view rotation matrix that
+ * transforms vectors in world coordinates to eye coordinates.
+ *
+ * @alias czm_viewRotation
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat3 czm_viewRotation;
+ *
+ * // Example
+ * vec3 eyeVector = czm_viewRotation * worldVector;
+ *
+ * @see UniformState#viewRotation
+ * @see czm_view
+ * @see czm_inverseView
+ * @see czm_inverseViewRotation
+ */
+ czm_viewRotation : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT3,
+ getValue : function(uniformState) {
+ return uniformState.viewRotation;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 3x3 view rotation matrix that
+ * transforms vectors in 3D world coordinates to eye coordinates. In 3D mode, this is identical to
+ * {@link czm_viewRotation}, but in 2D and Columbus View it represents the view matrix
+ * as if the camera were at an equivalent location in 3D mode. This is useful for lighting
+ * 2D and Columbus View in the same way that 3D is lit.
+ *
+ * @alias czm_viewRotation3D
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat3 czm_viewRotation3D;
+ *
+ * // Example
+ * vec3 eyeVector = czm_viewRotation3D * worldVector;
+ *
+ * @see UniformState#viewRotation3D
+ * @see czm_viewRotation
+ */
+ czm_viewRotation3D : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT3,
+ getValue : function(uniformState) {
+ return uniformState.viewRotation3D;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 4x4 transformation matrix that
+ * transforms from eye coordinates to world coordinates.
+ *
+ * @alias czm_inverseView
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat4 czm_inverseView;
+ *
+ * // Example
+ * vec4 worldPosition = czm_inverseView * eyePosition;
+ *
+ * @see UniformState#inverseView
+ * @see czm_view
+ * @see czm_inverseNormal
+ */
+ czm_inverseView : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT4,
+ getValue : function(uniformState) {
+ return uniformState.inverseView;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 4x4 transformation matrix that
+ * transforms from 3D eye coordinates to world coordinates. In 3D mode, this is identical to
+ * {@link czm_inverseView}, but in 2D and Columbus View it represents the inverse view matrix
+ * as if the camera were at an equivalent location in 3D mode. This is useful for lighting
+ * 2D and Columbus View in the same way that 3D is lit.
+ *
+ * @alias czm_inverseView3D
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat4 czm_inverseView3D;
+ *
+ * // Example
+ * vec4 worldPosition = czm_inverseView3D * eyePosition;
+ *
+ * @see UniformState#inverseView3D
+ * @see czm_inverseView
+ */
+ czm_inverseView3D : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT4,
+ getValue : function(uniformState) {
+ return uniformState.inverseView3D;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 3x3 rotation matrix that
+ * transforms vectors from eye coordinates to world coordinates.
+ *
+ * @alias czm_inverseViewRotation
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat3 czm_inverseViewRotation;
+ *
+ * // Example
+ * vec4 worldVector = czm_inverseViewRotation * eyeVector;
+ *
+ * @see UniformState#inverseView
+ * @see czm_view
+ * @see czm_viewRotation
+ * @see czm_inverseViewRotation
+ */
+ czm_inverseViewRotation : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT3,
+ getValue : function(uniformState) {
+ return uniformState.inverseViewRotation;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 3x3 rotation matrix that
+ * transforms vectors from 3D eye coordinates to world coordinates. In 3D mode, this is identical to
+ * {@link czm_inverseViewRotation}, but in 2D and Columbus View it represents the inverse view matrix
+ * as if the camera were at an equivalent location in 3D mode. This is useful for lighting
+ * 2D and Columbus View in the same way that 3D is lit.
+ *
+ * @alias czm_inverseViewRotation3D
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat3 czm_inverseViewRotation3D;
+ *
+ * // Example
+ * vec4 worldVector = czm_inverseViewRotation3D * eyeVector;
+ *
+ * @see UniformState#inverseView3D
+ * @see czm_inverseViewRotation
+ */
+ czm_inverseViewRotation3D : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT3,
+ getValue : function(uniformState) {
+ return uniformState.inverseViewRotation3D;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 4x4 projection transformation matrix that
+ * transforms eye coordinates to clip coordinates. Clip coordinates is the
+ * coordinate system for a vertex shader's gl_Position
output.
+ *
+ * @alias czm_projection
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat4 czm_projection;
+ *
+ * // Example
+ * gl_Position = czm_projection * eyePosition;
+ *
+ * @see UniformState#projection
+ * @see czm_viewProjection
+ * @see czm_modelViewProjection
+ * @see czm_infiniteProjection
+ */
+ czm_projection : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT4,
+ getValue : function(uniformState) {
+ return uniformState.projection;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 4x4 inverse projection transformation matrix that
+ * transforms from clip coordinates to eye coordinates. Clip coordinates is the
+ * coordinate system for a vertex shader's gl_Position
output.
+ *
+ * @alias czm_inverseProjection
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat4 czm_inverseProjection;
+ *
+ * // Example
+ * vec4 eyePosition = czm_inverseProjection * clipPosition;
+ *
+ * @see UniformState#inverseProjection
+ * @see czm_projection
+ */
+ czm_inverseProjection : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT4,
+ getValue : function(uniformState) {
+ return uniformState.inverseProjection;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 4x4 projection transformation matrix with the far plane at infinity,
+ * that transforms eye coordinates to clip coordinates. Clip coordinates is the
+ * coordinate system for a vertex shader's gl_Position
output. An infinite far plane is used
+ * in algorithms like shadow volumes and GPU ray casting with proxy geometry to ensure that triangles
+ * are not clipped by the far plane.
+ *
+ * @alias czm_infiniteProjection
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat4 czm_infiniteProjection;
+ *
+ * // Example
+ * gl_Position = czm_infiniteProjection * eyePosition;
+ *
+ * @see UniformState#infiniteProjection
+ * @see czm_projection
+ * @see czm_modelViewInfiniteProjection
+ */
+ czm_infiniteProjection : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT4,
+ getValue : function(uniformState) {
+ return uniformState.infiniteProjection;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 4x4 model-view transformation matrix that
+ * transforms model coordinates to eye coordinates.
+ *
+ * Positions should be transformed to eye coordinates using czm_modelView
and
+ * normals should be transformed using {@link czm_normal}.
+ *
+ * @alias czm_modelView
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat4 czm_modelView;
+ *
+ * // Example
+ * vec4 eyePosition = czm_modelView * modelPosition;
+ *
+ * // 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
+ * @see czm_modelViewProjection
+ * @see czm_normal
+ */
+ czm_modelView : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT4,
+ getValue : function(uniformState) {
+ return uniformState.modelView;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 4x4 model-view transformation matrix that
+ * transforms 3D model coordinates to eye coordinates. In 3D mode, this is identical to
+ * {@link czm_modelView}, but in 2D and Columbus View it represents the model-view matrix
+ * as if the camera were at an equivalent location in 3D mode. This is useful for lighting
+ * 2D and Columbus View in the same way that 3D is lit.
+ *
+ * Positions should be transformed to eye coordinates using czm_modelView3D
and
+ * normals should be transformed using {@link czm_normal3D}.
+ *
+ * @alias czm_modelView3D
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat4 czm_modelView3D;
+ *
+ * // Example
+ * vec4 eyePosition = czm_modelView3D * modelPosition;
+ *
+ * // The above is equivalent to, but more efficient than:
+ * vec4 eyePosition = czm_view3D * czm_model * modelPosition;
+ *
+ * @see UniformState#modelView3D
+ * @see czm_modelView
+ */
+ czm_modelView3D : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT4,
+ getValue : function(uniformState) {
+ return uniformState.modelView3D;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 4x4 model-view transformation matrix that
+ * transforms model coordinates, relative to the eye, to eye coordinates. This is used
+ * in conjunction with {@link czm_translateRelativeToEye}.
+ *
+ * @alias czm_modelViewRelativeToEye
+ * @glslUniform
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat4 czm_modelViewRelativeToEye;
+ *
+ * // Example
+ * attribute vec3 positionHigh;
+ * attribute vec3 positionLow;
+ *
+ * void main()
+ * {
+ * vec4 p = czm_translateRelativeToEye(positionHigh, positionLow);
+ * gl_Position = czm_projection * (czm_modelViewRelativeToEye * p);
+ * }
+ *
+ * @see czm_modelViewProjectionRelativeToEye
+ * @see czm_translateRelativeToEye
+ * @see EncodedCartesian3
+ */
+ czm_modelViewRelativeToEye : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT4,
+ getValue : function(uniformState) {
+ return uniformState.modelViewRelativeToEye;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 4x4 transformation matrix that
+ * transforms from eye coordinates to model coordinates.
+ *
+ * @alias czm_inverseModelView
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat4 czm_inverseModelView;
+ *
+ * // Example
+ * vec4 modelPosition = czm_inverseModelView * eyePosition;
+ *
+ * @see UniformState#inverseModelView
+ * @see czm_modelView
+ */
+ czm_inverseModelView : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT4,
+ getValue : function(uniformState) {
+ return uniformState.inverseModelView;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 4x4 transformation matrix that
+ * transforms from eye coordinates to 3D model coordinates. In 3D mode, this is identical to
+ * {@link czm_inverseModelView}, but in 2D and Columbus View it represents the inverse model-view matrix
+ * as if the camera were at an equivalent location in 3D mode. This is useful for lighting
+ * 2D and Columbus View in the same way that 3D is lit.
+ *
+ * @alias czm_inverseModelView3D
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat4 czm_inverseModelView3D;
+ *
+ * // Example
+ * vec4 modelPosition = czm_inverseModelView3D * eyePosition;
+ *
+ * @see UniformState#inverseModelView
+ * @see czm_inverseModelView
+ * @see czm_modelView3D
+ */
+ czm_inverseModelView3D : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT4,
+ getValue : function(uniformState) {
+ return uniformState.inverseModelView3D;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 4x4 view-projection transformation matrix that
+ * transforms world coordinates to clip coordinates. Clip coordinates is the
+ * coordinate system for a vertex shader's gl_Position
output.
+ *
+ * @alias czm_viewProjection
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat4 czm_viewProjection;
+ *
+ * // Example
+ * vec4 gl_Position = czm_viewProjection * czm_model * modelPosition;
+ *
+ * // 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
+ * @see czm_modelViewProjection
+ * @see czm_inverseViewProjection
+ */
+ czm_viewProjection : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT4,
+ getValue : function(uniformState) {
+ return uniformState.viewProjection;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 4x4 view-projection transformation matrix that
+ * transforms clip coordinates to world coordinates. Clip coordinates is the
+ * coordinate system for a vertex shader's gl_Position
output.
+ *
+ * @alias czm_inverseViewProjection
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat4 czm_inverseViewProjection;
+ *
+ * // Example
+ * vec4 worldPosition = czm_inverseViewProjection * clipPosition;
+ *
+ * @see UniformState#inverseViewProjection
+ * @see czm_viewProjection
+ */
+ czm_inverseViewProjection : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT4,
+ getValue : function(uniformState) {
+ return uniformState.inverseViewProjection;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 4x4 model-view-projection transformation matrix that
+ * transforms model coordinates to clip coordinates. Clip coordinates is the
+ * coordinate system for a vertex shader's gl_Position
output.
+ *
+ * @alias czm_modelViewProjection
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat4 czm_modelViewProjection;
+ *
+ * // Example
+ * vec4 gl_Position = czm_modelViewProjection * modelPosition;
+ *
+ * // 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
+ * @see czm_projection
+ * @see czm_modelView
+ * @see czm_viewProjection
+ * @see czm_modelViewInfiniteProjection
+ * @see czm_inverseModelViewProjection
+ */
+ czm_modelViewProjection : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT4,
+ getValue : function(uniformState) {
+ return uniformState.modelViewProjection;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 4x4 inverse model-view-projection transformation matrix that
+ * transforms clip coordinates to model coordinates. Clip coordinates is the
+ * coordinate system for a vertex shader's gl_Position
output.
+ *
+ * @alias czm_inverseModelViewProjection
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat4 czm_inverseModelViewProjection;
+ *
+ * // Example
+ * vec4 modelPosition = czm_inverseModelViewProjection * clipPosition;
+ *
+ * @see UniformState#modelViewProjection
+ * @see czm_modelViewProjection
+ */
+ czm_inverseModelViewProjection : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT4,
+ getValue : function(uniformState) {
+ return uniformState.inverseModelViewProjection;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 4x4 model-view-projection transformation matrix that
+ * transforms model coordinates, relative to the eye, to clip coordinates. Clip coordinates is the
+ * coordinate system for a vertex shader's gl_Position
output. This is used in
+ * conjunction with {@link czm_translateRelativeToEye}.
+ *
+ * @alias czm_modelViewProjectionRelativeToEye
+ * @glslUniform
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat4 czm_modelViewProjectionRelativeToEye;
+ *
+ * // Example
+ * attribute vec3 positionHigh;
+ * attribute vec3 positionLow;
+ *
+ * void main()
+ * {
+ * vec4 p = czm_translateRelativeToEye(positionHigh, positionLow);
+ * gl_Position = czm_modelViewProjectionRelativeToEye * p;
+ * }
+ *
+ * @see czm_modelViewRelativeToEye
+ * @see czm_translateRelativeToEye
+ * @see EncodedCartesian3
+ */
+ czm_modelViewProjectionRelativeToEye : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT4,
+ getValue : function(uniformState) {
+ return uniformState.modelViewProjectionRelativeToEye;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 4x4 model-view-projection transformation matrix that
+ * transforms model coordinates to clip coordinates. Clip coordinates is the
+ * coordinate system for a vertex shader's gl_Position
output. The projection matrix places
+ * the far plane at infinity. This is useful in algorithms like shadow volumes and GPU ray casting with
+ * proxy geometry to ensure that triangles are not clipped by the far plane.
+ *
+ * @alias czm_modelViewInfiniteProjection
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat4 czm_modelViewInfiniteProjection;
+ *
+ * // Example
+ * vec4 gl_Position = czm_modelViewInfiniteProjection * modelPosition;
+ *
+ * // 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
+ * @see czm_infiniteProjection
+ * @see czm_modelViewProjection
+ */
+ czm_modelViewInfiniteProjection : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT4,
+ getValue : function(uniformState) {
+ return uniformState.modelViewInfiniteProjection;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform that indicates if the current camera is orthographic in 3D.
+ *
+ * @alias czm_orthographicIn3D
+ * @see UniformState#orthographicIn3D
+ */
+ czm_orthographicIn3D : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT,
+ getValue : function(uniformState) {
+ return uniformState.orthographicIn3D ? 1 : 0;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 3x3 normal transformation matrix that
+ * transforms normal vectors in model coordinates to eye coordinates.
+ *
+ * Positions should be transformed to eye coordinates using {@link czm_modelView} and
+ * normals should be transformed using czm_normal
.
+ *
+ * @alias czm_normal
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat3 czm_normal;
+ *
+ * // Example
+ * vec3 eyeNormal = czm_normal * normal;
+ *
+ * @see UniformState#normal
+ * @see czm_inverseNormal
+ * @see czm_modelView
+ */
+ czm_normal : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT3,
+ getValue : function(uniformState) {
+ return uniformState.normal;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 3x3 normal transformation matrix that
+ * transforms normal vectors in 3D model coordinates to eye coordinates.
+ * In 3D mode, this is identical to
+ * {@link czm_normal}, but in 2D and Columbus View it represents the normal transformation
+ * matrix as if the camera were at an equivalent location in 3D mode. This is useful for lighting
+ * 2D and Columbus View in the same way that 3D is lit.
+ *
+ * Positions should be transformed to eye coordinates using {@link czm_modelView3D} and
+ * normals should be transformed using czm_normal3D
.
+ *
+ * @alias czm_normal3D
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat3 czm_normal3D;
+ *
+ * // Example
+ * vec3 eyeNormal = czm_normal3D * normal;
+ *
+ * @see UniformState#normal3D
+ * @see czm_normal
+ */
+ czm_normal3D : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT3,
+ getValue : function(uniformState) {
+ return uniformState.normal3D;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 3x3 normal transformation matrix that
+ * transforms normal vectors in eye coordinates to model coordinates. This is
+ * the opposite of the transform provided by {@link czm_normal}.
+ *
+ * @alias czm_inverseNormal
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat3 czm_inverseNormal;
+ *
+ * // Example
+ * vec3 normalMC = czm_inverseNormal * normalEC;
+ *
+ * @see UniformState#inverseNormal
+ * @see czm_normal
+ * @see czm_modelView
+ * @see czm_inverseView
+ */
+ czm_inverseNormal : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT3,
+ getValue : function(uniformState) {
+ return uniformState.inverseNormal;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 3x3 normal transformation matrix that
+ * transforms normal vectors in eye coordinates to 3D model coordinates. This is
+ * the opposite of the transform provided by {@link czm_normal}.
+ * In 3D mode, this is identical to
+ * {@link czm_inverseNormal}, but in 2D and Columbus View it represents the inverse normal transformation
+ * matrix as if the camera were at an equivalent location in 3D mode. This is useful for lighting
+ * 2D and Columbus View in the same way that 3D is lit.
+ *
+ * @alias czm_inverseNormal3D
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat3 czm_inverseNormal3D;
+ *
+ * // Example
+ * vec3 normalMC = czm_inverseNormal3D * normalEC;
+ *
+ * @see UniformState#inverseNormal3D
+ * @see czm_inverseNormal
+ */
+ czm_inverseNormal3D : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT3,
+ getValue : function(uniformState) {
+ return uniformState.inverseNormal3D;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform containing height (x
) and height squared (y
)
+ * of the eye (camera) in the 2D scene in meters.
+ *
+ * @alias czm_eyeHeight2D
+ * @glslUniform
+ *
+ * @see UniformState#eyeHeight2D
+ */
+ czm_eyeHeight2D : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_VEC2,
+ getValue : function(uniformState) {
+ return uniformState.eyeHeight2D;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform containing the near distance (x
) and the far distance (y
)
+ * of the frustum defined by the camera. This is the largest possible frustum, not an individual
+ * frustum used for multi-frustum rendering.
+ *
+ * @alias czm_entireFrustum
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform vec2 czm_entireFrustum;
+ *
+ * // Example
+ * float frustumLength = czm_entireFrustum.y - czm_entireFrustum.x;
+ *
+ * @see UniformState#entireFrustum
+ * @see czm_currentFrustum
+ */
+ czm_entireFrustum : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_VEC2,
+ getValue : function(uniformState) {
+ return uniformState.entireFrustum;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform containing the near distance (x
) and the far distance (y
)
+ * of the frustum defined by the camera. This is the individual
+ * frustum used for multi-frustum rendering.
+ *
+ * @alias czm_currentFrustum
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform vec2 czm_currentFrustum;
+ *
+ * // Example
+ * float frustumLength = czm_currentFrustum.y - czm_currentFrustum.x;
+ *
+ * @see UniformState#currentFrustum
+ * @see czm_entireFrustum
+ */
+ czm_currentFrustum : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_VEC2,
+ getValue : function(uniformState) {
+ return uniformState.currentFrustum;
+ }
+ }),
+
+ /**
+ * The distances to the frustum planes. The top, bottom, left and right distances are
+ * the x, y, z, and w components, respectively.
+ *
+ * @alias czm_frustumPlanes
+ * @glslUniform
+ */
+ czm_frustumPlanes : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_VEC4,
+ getValue : function(uniformState) {
+ return uniformState.frustumPlanes;
+ }
+ }),
+
+ /**
+ * The log2 of the current frustums far plane. Used for computing the log depth.
+ *
+ * @alias czm_log2FarDistance
+ * @glslUniform
+ *
+ * @private
+ */
+ czm_log2FarDistance : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT,
+ getValue : function(uniformState) {
+ return uniformState.logFarDistance;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform containing log2 of the far distance + 1.0.
+ * This is used when reversing log depth computations.
+ *
+ * @alias czm_log2FarPlusOne
+ * @glslUniform
+ */
+ czm_log2FarPlusOne : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT,
+ getValue : function(uniformState) {
+ return CesiumMath.log2(uniformState.currentFrustum.y + 1.0);
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform containing log2 of the near distance.
+ * This is used when writing log depth in the fragment shader.
+ *
+ * @alias czm_log2NearDistance
+ * @glslUniform
+ */
+ czm_log2NearDistance : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT,
+ getValue : function(uniformState) {
+ return CesiumMath.log2(uniformState.currentFrustum.x);
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing the sun position in world coordinates.
+ *
+ * @alias czm_sunPositionWC
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform vec3 czm_sunPositionWC;
+ *
+ * @see UniformState#sunPositionWC
+ * @see czm_sunPositionColumbusView
+ * @see czm_sunDirectionWC
+ */
+ czm_sunPositionWC : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_VEC3,
+ getValue : function(uniformState) {
+ return uniformState.sunPositionWC;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing the sun position in Columbus view world coordinates.
+ *
+ * @alias czm_sunPositionColumbusView
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform vec3 czm_sunPositionColumbusView;
+ *
+ * @see UniformState#sunPositionColumbusView
+ * @see czm_sunPositionWC
+ */
+ czm_sunPositionColumbusView : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_VEC3,
+ getValue : function(uniformState) {
+ return uniformState.sunPositionColumbusView;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing the normalized direction to the sun in eye coordinates.
+ * This is commonly used for directional lighting computations.
+ *
+ * @alias czm_sunDirectionEC
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform vec3 czm_sunDirectionEC;
+ *
+ * // Example
+ * float diffuse = max(dot(czm_sunDirectionEC, normalEC), 0.0);
+ *
+ * @see UniformState#sunDirectionEC
+ * @see czm_moonDirectionEC
+ * @see czm_sunDirectionWC
+ */
+ czm_sunDirectionEC : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_VEC3,
+ getValue : function(uniformState) {
+ return uniformState.sunDirectionEC;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing the normalized direction to the sun in world coordinates.
+ * This is commonly used for directional lighting computations.
+ *
+ * @alias czm_sunDirectionWC
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform vec3 czm_sunDirectionWC;
+ *
+ * @see UniformState#sunDirectionWC
+ * @see czm_sunPositionWC
+ * @see czm_sunDirectionEC
+ */
+ czm_sunDirectionWC : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_VEC3,
+ getValue : function(uniformState) {
+ return uniformState.sunDirectionWC;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing the normalized direction to the moon in eye coordinates.
+ * This is commonly used for directional lighting computations.
+ *
+ * @alias czm_moonDirectionEC
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform vec3 czm_moonDirectionEC;
+ *
+ * // Example
+ * float diffuse = max(dot(czm_moonDirectionEC, normalEC), 0.0);
+ *
+ * @see UniformState#moonDirectionEC
+ * @see czm_sunDirectionEC
+ */
+ czm_moonDirectionEC : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_VEC3,
+ getValue : function(uniformState) {
+ return uniformState.moonDirectionEC;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing the high bits of the camera position in model
+ * coordinates. This is used for GPU RTE to eliminate jittering artifacts when rendering
+ * as described in {@link http://blogs.agi.com/insight3d/index.php/2008/09/03/precisions-precisions/|Precisions, Precisions}.
+ *
+ * @alias czm_encodedCameraPositionMCHigh
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform vec3 czm_encodedCameraPositionMCHigh;
+ *
+ * @see czm_encodedCameraPositionMCLow
+ * @see czm_modelViewRelativeToEye
+ * @see czm_modelViewProjectionRelativeToEye
+ */
+ czm_encodedCameraPositionMCHigh : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_VEC3,
+ getValue : function(uniformState) {
+ return uniformState.encodedCameraPositionMCHigh;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing the low bits of the camera position in model
+ * coordinates. This is used for GPU RTE to eliminate jittering artifacts when rendering
+ * as described in {@link http://blogs.agi.com/insight3d/index.php/2008/09/03/precisions-precisions/|Precisions, Precisions}.
+ *
+ * @alias czm_encodedCameraPositionMCLow
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform vec3 czm_encodedCameraPositionMCLow;
+ *
+ * @see czm_encodedCameraPositionMCHigh
+ * @see czm_modelViewRelativeToEye
+ * @see czm_modelViewProjectionRelativeToEye
+ */
+ czm_encodedCameraPositionMCLow : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_VEC3,
+ getValue : function(uniformState) {
+ return uniformState.encodedCameraPositionMCLow;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing the position of the viewer (camera) in world coordinates.
+ *
+ * @alias czm_viewerPositionWC
+ * @glslUniform
+ *
+ * @example
+ * // GLSL declaration
+ * uniform vec3 czm_viewerPositionWC;
+ */
+ czm_viewerPositionWC : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_VEC3,
+ getValue : function(uniformState) {
+ return Matrix4.getTranslation(uniformState.inverseView, viewerPositionWCScratch);
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing the frame number. This uniform is automatically incremented
+ * every frame.
+ *
+ * @alias czm_frameNumber
+ * @glslUniform
+ *
+ * @example
+ * // GLSL declaration
+ * uniform float czm_frameNumber;
+ */
+ czm_frameNumber : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT,
+ getValue : function(uniformState) {
+ return uniformState.frameState.frameNumber;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing the current morph transition time between
+ * 2D/Columbus View and 3D, with 0.0 being 2D or Columbus View and 1.0 being 3D.
+ *
+ * @alias czm_morphTime
+ * @glslUniform
+ *
+ * @example
+ * // GLSL declaration
+ * uniform float czm_morphTime;
+ *
+ * // Example
+ * vec4 p = czm_columbusViewMorph(position2D, position3D, czm_morphTime);
+ */
+ czm_morphTime : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT,
+ getValue : function(uniformState) {
+ return uniformState.frameState.morphTime;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing the current {@link SceneMode}, expressed
+ * as a float.
+ *
+ * @alias czm_sceneMode
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform float czm_sceneMode;
+ *
+ * // Example
+ * if (czm_sceneMode == czm_sceneMode2D)
+ * {
+ * eyeHeightSq = czm_eyeHeight2D.y;
+ * }
+ *
+ * @see czm_sceneMode2D
+ * @see czm_sceneModeColumbusView
+ * @see czm_sceneMode3D
+ * @see czm_sceneModeMorphing
+ */
+ czm_sceneMode : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT,
+ getValue : function(uniformState) {
+ return uniformState.frameState.mode;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing the current rendering pass.
+ *
+ * @alias czm_pass
+ * @glslUniform
+ *
+ * @example
+ * // GLSL declaration
+ * uniform float czm_pass;
+ *
+ * // Example
+ * if ((czm_pass == czm_passTranslucent) && isOpaque())
+ * {
+ * gl_Position *= 0.0; // Cull opaque geometry in the translucent pass
+ * }
+ */
+ czm_pass : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT,
+ getValue : function(uniformState) {
+ return uniformState.pass;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing the current scene background color.
+ *
+ * @alias czm_backgroundColor
+ * @glslUniform
+ *
+ * @example
+ * // GLSL declaration
+ * uniform vec4 czm_backgroundColor;
+ *
+ * // Example: If the given color's RGB matches the background color, invert it.
+ * vec4 adjustColorForContrast(vec4 color)
+ * {
+ * if (czm_backgroundColor.rgb == color.rgb)
+ * {
+ * color.rgb = vec3(1.0) - color.rgb;
+ * }
+ *
+ * return color;
+ * }
+ */
+ czm_backgroundColor : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_VEC4,
+ getValue : function(uniformState) {
+ return uniformState.backgroundColor;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform containing the BRDF look up texture used for image-based lighting computations.
+ *
+ * @alias czm_brdfLut
+ * @glslUniform
+ *
+ * @example
+ * // GLSL declaration
+ * uniform sampler2D czm_brdfLut;
+ *
+ * // Example: For a given roughness and NdotV value, find the material's BRDF information in the red and green channels
+ * float roughness = 0.5;
+ * float NdotV = dot(normal, view);
+ * vec2 brdfLut = texture2D(czm_brdfLut, vec2(NdotV, 1.0 - roughness)).rg;
+ */
+ czm_brdfLut : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.SAMPLER_2D,
+ getValue : function(uniformState) {
+ return uniformState.brdfLut;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform containing the environment map used within the scene.
+ *
+ * @alias czm_environmentMap
+ * @glslUniform
+ *
+ * @example
+ * // GLSL declaration
+ * uniform samplerCube czm_environmentMap;
+ *
+ * // Example: Create a perfect reflection of the environment map on a model
+ * float reflected = reflect(view, normal);
+ * vec4 reflectedColor = textureCube(czm_environmentMap, reflected);
+ */
+ czm_environmentMap : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.SAMPLER_CUBE,
+ getValue : function(uniformState) {
+ return uniformState.environmentMap;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing a 3x3 rotation matrix that transforms
+ * from True Equator Mean Equinox (TEME) axes to the pseudo-fixed axes at the current scene time.
+ *
+ * @alias czm_temeToPseudoFixed
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform mat3 czm_temeToPseudoFixed;
+ *
+ * // Example
+ * vec3 pseudoFixed = czm_temeToPseudoFixed * teme;
+ *
+ * @see UniformState#temeToPseudoFixedMatrix
+ * @see Transforms.computeTemeToPseudoFixedMatrix
+ */
+ czm_temeToPseudoFixed : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_MAT3,
+ getValue : function(uniformState) {
+ return uniformState.temeToPseudoFixedMatrix;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing the ratio of canvas coordinate space to canvas pixel space.
+ *
+ * @alias czm_resolutionScale
+ * @glslUniform
+ *
+ * @example
+ * uniform float czm_resolutionScale;
+ */
+ czm_resolutionScale : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT,
+ getValue : function(uniformState) {
+ return uniformState.resolutionScale;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform scalar used to mix a color with the fog color based on the distance to the camera.
+ *
+ * @alias czm_fogDensity
+ * @glslUniform
+ *
+ * @see czm_fog
+ */
+ czm_fogDensity : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT,
+ getValue : function(uniformState) {
+ return uniformState.fogDensity;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing the splitter position to use when rendering imagery layers with a splitter.
+ * This will be in pixel coordinates relative to the canvas.
+ *
+ * @alias czm_imagerySplitPosition
+ * @glslUniform
+ *
+ *
+ * @example
+ * // GLSL declaration
+ * uniform float czm_imagerySplitPosition;
+ */
+ czm_imagerySplitPosition : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT,
+ getValue : function(uniformState) {
+ return uniformState.imagerySplitPosition;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform scalar representing the geometric tolerance per meter
+ *
+ * @alias czm_geometricToleranceOverMeter
+ * @glslUniform
+ */
+ czm_geometricToleranceOverMeter : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT,
+ getValue : function(uniformState) {
+ return uniformState.geometricToleranceOverMeter;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform representing the distance from the camera at which to disable the depth test of billboards, labels and points
+ * to, for example, prevent clipping against terrain. When set to zero, the depth test should always be applied. When less than zero,
+ * the depth test should never be applied.
+ *
+ * @alias czm_minimumDisableDepthTestDistance
+ * @glslUniform
+ */
+ czm_minimumDisableDepthTestDistance : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT,
+ getValue : function(uniformState) {
+ return uniformState.minimumDisableDepthTestDistance;
+ }
+ }),
+
+ /**
+ * An automatic GLSL uniform that will be the highlight color of unclassified 3D Tiles.
+ *
+ * @alias czm_invertClassificationColor
+ * @glslUniform
+ */
+ czm_invertClassificationColor : new AutomaticUniform({
+ size : 1,
+ datatype : WebGLConstants.FLOAT_VEC4,
+ getValue : function(uniformState) {
+ return uniformState.invertClassificationColor;
+ }
+ })
+ };
+
+ return AutomaticUniforms;
});
diff --git a/Source/Scene/ClassificationPrimitive.js b/Source/Scene/ClassificationPrimitive.js
index 2bbe9461f25..450cb78bfb8 100644
--- a/Source/Scene/ClassificationPrimitive.js
+++ b/Source/Scene/ClassificationPrimitive.js
@@ -1,23 +1,12 @@
define([
- '../Core/Cartesian2',
- '../Core/Cartesian3',
- '../Core/Cartographic',
- '../Core/Math',
- '../Core/Check',
'../Core/ColorGeometryInstanceAttribute',
'../Core/combine',
- '../Core/ComponentDatatype',
'../Core/defaultValue',
'../Core/defined',
'../Core/defineProperties',
'../Core/destroyObject',
'../Core/DeveloperError',
- '../Core/EncodedCartesian3',
'../Core/GeometryInstance',
- '../Core/GeometryInstanceAttribute',
- '../Core/Matrix2',
- '../Core/Rectangle',
- '../Core/WebGLConstants',
'../Core/isArray',
'../Renderer/DrawCommand',
'../Renderer/Pass',
@@ -30,34 +19,21 @@ define([
'./BlendingState',
'./ClassificationType',
'./DepthFunction',
- './Material',
- './MaterialAppearance',
'./PerInstanceColorAppearance',
'./Primitive',
'./SceneMode',
- './ShadowVolumeAppearanceShader',
+ './ShadowVolumeAppearance',
'./StencilFunction',
'./StencilOperation'
], function(
- Cartesian2,
- Cartesian3,
- Cartographic,
- CesiumMath,
- Check,
ColorGeometryInstanceAttribute,
combine,
- ComponentDatatype,
defaultValue,
defined,
defineProperties,
destroyObject,
DeveloperError,
- EncodedCartesian3,
GeometryInstance,
- GeometryInstanceAttribute,
- Matrix2,
- Rectangle,
- WebGLConstants,
isArray,
DrawCommand,
Pass,
@@ -70,12 +46,10 @@ define([
BlendingState,
ClassificationType,
DepthFunction,
- Material,
- MaterialAppearance,
PerInstanceColorAppearance,
Primitive,
SceneMode,
- ShadowVolumeAppearanceShader,
+ ShadowVolumeAppearance,
StencilFunction,
StencilOperation) {
'use strict';
@@ -89,6 +63,9 @@ define([
* {@link Material} and {@link RenderState}. Roughly, the geometry instance defines the structure and placement,
* and the appearance defines the visual characteristics. Decoupling geometry and appearance allows us to mix
* and match most of them and add a new geometry or appearance independently of each other.
+ * Only the {@link PerInstanceColorAppearance} is supported at this time when using ClassificationPrimitive directly.
+ * For full {@link Appearance} support use {@link GroundPrimitive} instead.
+ *
* true
, geometry vertices are optimized for the pre and post-vertex-shader caches.
* @param {Boolean} [options.interleave=false] When true
, geometry vertex attributes are interleaved, which can slightly improve rendering performance but increases load time.
@@ -786,7 +793,18 @@ define([
this._minHeight = this._minTerrainHeight * exaggeration;
this._maxHeight = this._maxTerrainHeight * exaggeration;
- // Determine whether to add spherical or planar extent attributes
+ // Determine whether to add spherical or planar extent attributes for computing texture coordinates.
+ // This depends on the size of the GeometryInstances.
+
+ // If all the GeometryInstances have the same per-instance color,
+ // don't bother with texture coordinates at all.
+ var allSameColor = false;
+ var color;
+ var attributes;
+ if (length > 0 && defined(instances[0].attributes) && defined(instances[0].attributes.color)) {
+ color = instances[0].attributes.color;
+ allSameColor = true;
+ }
var usePlanarExtents = true;
for (i = 0; i < length; ++i) {
instance = instances[i];
@@ -794,7 +812,10 @@ define([
rectangle = getRectangle(frameState, geometry);
if (ShadowVolumeAppearance.shouldUseSphericalCoordinates(rectangle)) {
usePlanarExtents = false;
- break;
+ }
+ attributes = instance.attributes;
+ if (defined(color) && defined(attributes) && defined(attributes.color)) {
+ allSameColor = allSameColor && ColorGeometryInstanceAttribute.equals(color, attributes.color);
}
}
@@ -804,12 +825,15 @@ define([
instanceType = geometry.constructor;
rectangle = getRectangle(frameState, geometry);
- var attributes;
- if (usePlanarExtents) {
- attributes = ShadowVolumeAppearance.getPlanarTextureCoordinateAttributes(rectangle, ellipsoid, frameState.mapProjection, this._maxHeight, geometry._stRotation);
+ if (!allSameColor) {
+ if (usePlanarExtents) {
+ attributes = ShadowVolumeAppearance.getPlanarTextureCoordinateAttributes(rectangle, ellipsoid, frameState.mapProjection, this._maxHeight, geometry._stRotation);
+ } else {
+ attributes = ShadowVolumeAppearance.getSphericalExtentGeometryInstanceAttributes(rectangle, ellipsoid, frameState.mapProjection, geometry._stRotation);
+ }
} else {
- attributes = ShadowVolumeAppearance.getSphericalExtentGeometryInstanceAttributes(rectangle, ellipsoid, frameState.mapProjection, geometry._stRotation);
+ attributes = {};
}
var instanceAttributes = instance.attributes;
@@ -931,5 +955,20 @@ define([
return destroyObject(this);
};
+ /**
+ * Checks if the given Scene supports materials on GroundPrimitives.
+ * Materials on GroundPrimitives require support for the WEBGL_depth_texture extension.
+ *
+ * @param {Scene} scene The current scene.
+ * @returns {Boolean} Whether or not the current scene supports materials on GroundPrimitives.
+ */
+ GroundPrimitive.supportsMaterials = function(scene) {
+ //>>includeStart('debug', pragmas.debug);
+ Check.typeOf.object('scene', scene);
+ //>>includeEnd('debug');
+
+ return scene.frameState.context.depthTexture;
+ };
+
return GroundPrimitive;
});
diff --git a/Specs/DataSources/GeometryVisualizerSpec.js b/Specs/DataSources/GeometryVisualizerSpec.js
index f2c35ededa9..0f51eccf215 100644
--- a/Specs/DataSources/GeometryVisualizerSpec.js
+++ b/Specs/DataSources/GeometryVisualizerSpec.js
@@ -840,4 +840,71 @@ defineSuite([
visualizer.destroy();
});
});
+
+ it('batches ground entities by identical color if ground entity materials are not supported', function() {
+ spyOn(GroundPrimitive, 'supportsMaterials').and.callFake(function() {
+ return false;
+ });
+ var entities = new EntityCollection();
+ var visualizer = new GeometryVisualizer(scene, entities, scene.primitives, scene.groundPrimitives);
+
+ var blueColor = Color.BLUE.withAlpha(0.5);
+ entities.add({
+ position : new Cartesian3(1, 2, 3),
+ ellipse : {
+ semiMajorAxis : 2,
+ semiMinorAxis : 1,
+ material : blueColor
+ }
+ });
+
+ return pollToPromise(function() {
+ scene.initializeFrame();
+ var isUpdated = visualizer.update(time);
+ scene.render(time);
+ return isUpdated;
+ }).then(function() {
+ expect(scene.groundPrimitives.length).toEqual(1);
+
+ entities.add({
+ position : new Cartesian3(12, 34, 45),
+ ellipse : {
+ semiMajorAxis : 2,
+ semiMinorAxis : 1,
+ material : blueColor
+ }
+ });
+
+ return pollToPromise(function() {
+ scene.initializeFrame();
+ var isUpdated = visualizer.update(time);
+ scene.render(time);
+ return isUpdated;
+ });
+ }).then(function() {
+ expect(scene.groundPrimitives.length).toEqual(1);
+
+ entities.add({
+ position : new Cartesian3(123, 456, 789),
+ ellipse : {
+ semiMajorAxis : 2,
+ semiMinorAxis : 1,
+ material : Color.BLUE.withAlpha(0.6)
+ }
+ });
+
+ return pollToPromise(function() {
+ scene.initializeFrame();
+ var isUpdated = visualizer.update(time);
+ scene.render(time);
+ return isUpdated;
+ });
+ }).then(function() {
+ expect(scene.groundPrimitives.length).toEqual(2);
+
+ entities.removeAll();
+ visualizer.destroy();
+ });
+ });
+
}, 'WebGL');
diff --git a/Specs/DataSources/StaticGroundGeometryColorBatchSpec.js b/Specs/DataSources/StaticGroundGeometryColorBatchSpec.js
new file mode 100644
index 00000000000..32d95f9f05f
--- /dev/null
+++ b/Specs/DataSources/StaticGroundGeometryColorBatchSpec.js
@@ -0,0 +1,239 @@
+defineSuite([
+ 'DataSources/StaticGroundGeometryColorBatch',
+ 'Core/Cartesian3',
+ 'Core/Color',
+ 'Core/DistanceDisplayCondition',
+ 'Core/JulianDate',
+ 'Core/Math',
+ 'Core/TimeInterval',
+ 'Core/TimeIntervalCollection',
+ 'DataSources/CallbackProperty',
+ 'DataSources/ColorMaterialProperty',
+ 'DataSources/EllipseGeometryUpdater',
+ 'DataSources/Entity',
+ 'DataSources/TimeIntervalCollectionProperty',
+ 'Scene/ClassificationType',
+ 'Scene/GroundPrimitive',
+ 'Specs/createScene',
+ 'Specs/pollToPromise'
+ ], function(
+ StaticGroundGeometryColorBatch,
+ Cartesian3,
+ Color,
+ DistanceDisplayCondition,
+ JulianDate,
+ CesiumMath,
+ TimeInterval,
+ TimeIntervalCollection,
+ CallbackProperty,
+ ColorMaterialProperty,
+ EllipseGeometryUpdater,
+ Entity,
+ TimeIntervalCollectionProperty,
+ ClassificationType,
+ GroundPrimitive,
+ createScene,
+ pollToPromise) {
+ 'use strict';
+
+ var time = JulianDate.now();
+ var scene;
+ beforeAll(function() {
+ scene = createScene();
+
+ return GroundPrimitive.initializeTerrainHeights();
+ });
+
+ afterAll(function() {
+ scene.destroyForSpecs();
+
+ // Leave ground primitive uninitialized
+ GroundPrimitive._initialized = false;
+ GroundPrimitive._initPromise = undefined;
+ GroundPrimitive._terrainHeights = undefined;
+ });
+
+ function computeKey(color) {
+ var ui8 = new Uint8Array(color);
+ var ui32 = new Uint32Array(ui8.buffer);
+ return ui32[0];
+ }
+
+ it('updates color attribute after rebuilding primitive', function() {
+ if (!GroundPrimitive.isSupported(scene)) {
+ return;
+ }
+
+ var batch = new StaticGroundGeometryColorBatch(scene.groundPrimitives, ClassificationType.BOTH);
+ var entity = new Entity({
+ position : new Cartesian3(1234, 5678, 9101112),
+ ellipse : {
+ semiMajorAxis : 2,
+ semiMinorAxis : 1,
+ show : new CallbackProperty(function() {
+ return true;
+ }, false),
+ material : Color.RED
+ }
+ });
+
+ var updater = new EllipseGeometryUpdater(entity, scene);
+ batch.add(time, updater);
+
+ return pollToPromise(function() {
+ scene.initializeFrame();
+ var isUpdated = batch.update(time);
+ scene.render(time);
+ return isUpdated;
+ }).then(function() {
+ expect(scene.groundPrimitives.length).toEqual(1);
+ var primitive = scene.groundPrimitives.get(0);
+ var attributes = primitive.getGeometryInstanceAttributes(entity);
+ var red = [255, 0, 0, 255];
+ var redKey = computeKey(red);
+ expect(attributes.color).toEqual(red);
+
+ // Verify we have 1 batch with the key for red
+ expect(batch._batches.length).toEqual(1);
+ expect(batch._batches.contains(redKey)).toBe(true);
+ expect(batch._batches.get(redKey).key).toEqual(redKey);
+
+ entity.ellipse.material = Color.GREEN;
+ updater._onEntityPropertyChanged(entity, 'ellipse');
+ batch.remove(updater);
+ batch.add(time, updater);
+ return pollToPromise(function() {
+ scene.initializeFrame();
+ var isUpdated = batch.update(time);
+ scene.render(time);
+ return isUpdated;
+ }).then(function() {
+ expect(scene.groundPrimitives.length).toEqual(1);
+ var primitive = scene.groundPrimitives.get(0);
+ var attributes = primitive.getGeometryInstanceAttributes(entity);
+ var green = [0, 128, 0, 255];
+ var greenKey = computeKey(green);
+ expect(attributes.color).toEqual(green);
+
+ // Verify we have 1 batch with the key for green
+ expect(batch._batches.length).toEqual(1);
+ expect(batch._batches.contains(greenKey)).toBe(true);
+ expect(batch._batches.get(greenKey).key).toEqual(greenKey);
+
+ batch.removeAllPrimitives();
+ });
+ });
+ });
+
+ it('updates with sampled distance display condition out of range', function() {
+ var validTime = JulianDate.fromIso8601('2018-02-14T04:10:00+1100');
+ var ddc = new TimeIntervalCollectionProperty();
+ ddc.intervals.addInterval(TimeInterval.fromIso8601({
+ iso8601: '2018-02-14T04:00:00+1100/2018-02-14T04:15:00+1100',
+ data: new DistanceDisplayCondition(1.0, 2.0)
+ }));
+ var entity = new Entity({
+ availability: new TimeIntervalCollection([TimeInterval.fromIso8601({iso8601: '2018-02-14T04:00:00+1100/2018-02-14T04:30:00+1100'})]),
+ position : new Cartesian3(1234, 5678, 9101112),
+ ellipse: {
+ semiMajorAxis : 2,
+ semiMinorAxis : 1,
+ material: Color.RED,
+ distanceDisplayCondition: ddc
+ }
+ });
+
+ var batch = new StaticGroundGeometryColorBatch(scene.groundPrimitives, ClassificationType.BOTH);
+
+ var updater = new EllipseGeometryUpdater(entity, scene);
+ batch.add(validTime, updater);
+
+ return pollToPromise(function() {
+ scene.initializeFrame();
+ var isUpdated = batch.update(validTime);
+ scene.render(validTime);
+ return isUpdated;
+ }).then(function() {
+ expect(scene.groundPrimitives.length).toEqual(1);
+ var primitive = scene.groundPrimitives.get(0);
+ var attributes = primitive.getGeometryInstanceAttributes(entity);
+ expect(attributes.distanceDisplayCondition).toEqualEpsilon([1.0, 2.0], CesiumMath.EPSILON6);
+
+ batch.update(time);
+ scene.render(time);
+
+ primitive = scene.groundPrimitives.get(0);
+ attributes = primitive.getGeometryInstanceAttributes(entity);
+ expect(attributes.distanceDisplayCondition).toEqual([0.0, Infinity]);
+
+ batch.removeAllPrimitives();
+ });
+ });
+
+ it('shows only one primitive while rebuilding primitive', function() {
+ if (!GroundPrimitive.isSupported(scene)) {
+ return;
+ }
+
+ var batch = new StaticGroundGeometryColorBatch(scene.groundPrimitives, ClassificationType.BOTH);
+ function buildEntity() {
+ return new Entity({
+ position : new Cartesian3(1234, 5678, 9101112),
+ ellipse : {
+ semiMajorAxis : 2,
+ semiMinorAxis : 1,
+ height : 0,
+ outline : true,
+ outlineColor : Color.RED.withAlpha(0.5)
+ }
+ });
+ }
+
+ function renderScene() {
+ scene.initializeFrame();
+ var isUpdated = batch.update(time);
+ scene.render(time);
+ return isUpdated;
+ }
+
+ var entity1 = buildEntity();
+ var entity2 = buildEntity();
+
+ var updater1 = new EllipseGeometryUpdater(entity1, scene);
+ var updater2 = new EllipseGeometryUpdater(entity2, scene);
+
+ batch.add(time, updater1);
+ return pollToPromise(renderScene)
+ .then(function() {
+ expect(scene.groundPrimitives.length).toEqual(1);
+ var primitive = scene.groundPrimitives.get(0);
+ expect(primitive.show).toBeTruthy();
+ })
+ .then(function() {
+ batch.add(time, updater2);
+ })
+ .then(function() {
+ return pollToPromise(function() {
+ renderScene();
+ return scene.groundPrimitives.length === 2;
+ });
+ })
+ .then(function() {
+ var showCount = 0;
+ expect(scene.groundPrimitives.length).toEqual(2);
+ showCount += !!scene.groundPrimitives.get(0).show;
+ showCount += !!scene.groundPrimitives.get(1).show;
+ expect(showCount).toEqual(1);
+ })
+ .then(function() {
+ return pollToPromise(renderScene);
+ })
+ .then(function() {
+ expect(scene.groundPrimitives.length).toEqual(1);
+ var primitive = scene.groundPrimitives.get(0);
+ expect(primitive.show).toBeTruthy();
+
+ batch.removeAllPrimitives();
+ });
+ });
+});
diff --git a/Specs/Scene/GroundPrimitiveSpec.js b/Specs/Scene/GroundPrimitiveSpec.js
index 04e240ef418..ea0a1b404cc 100644
--- a/Specs/Scene/GroundPrimitiveSpec.js
+++ b/Specs/Scene/GroundPrimitiveSpec.js
@@ -464,7 +464,7 @@ defineSuite([
});
it('renders small GeometryInstances with texture', function() {
- if (!GroundPrimitive.isSupported(scene)) {
+ if (!GroundPrimitive.isSupported(scene) || !GroundPrimitive.supportsMaterials(scene)) {
return;
}
@@ -495,7 +495,7 @@ defineSuite([
});
it('renders large GeometryInstances with texture', function() {
- if (!GroundPrimitive.isSupported(scene)) {
+ if (!GroundPrimitive.isSupported(scene) || !GroundPrimitive.supportsMaterials(scene)) {
return;
}
From 606188015f753f67efbf3a3305c1cc08d34d11c4 Mon Sep 17 00:00:00 2001
From: Kangning Li Loading...
%!Efg=^BMl#|(Ybo&jp%1W
zvlu7JSQEAMwNyymD{9`kSZ6$AnQJm&j=NIU>nnX;mU5z=O%yVElWnmlbe5IL?|v-bQk&k7jxw;#_}r
Loading...
D1@>)s0;!&K16hv
zayd0UJAaVrSVBmdL+)
zP>j2Ym%}me=6X2&B8+fuxFc7fB3je!Lg-FSpf^yfPhG6ZjP!d4;1~KReB?S4N=*>Q
z8T{?vc7H6KU;DO}a?HEBO5dQB^#Y_@e+@TwACHeyA%M7bx#Ph*Hii8b#h!vtJauY
z3MozmNV9LYXcWmN*f^D%ELo-bw1-wS&{tw>HBqzqed^}@=BbPG^`>FzPu#;YDj=NU
z?5@h~8h;en#X&Vpm9)8awc