cesium
Version:
CesiumJS is a JavaScript library for creating 3D globes and 2D maps in a web browser without a plugin.
162 lines (137 loc) • 7.55 kB
JavaScript
import Cartesian2 from '../Core/Cartesian2.js';
import Check from '../Core/Check.js';
import ClippingPlaneCollection from './ClippingPlaneCollection.js';
var textureResolutionScratch = new Cartesian2();
/**
* Gets the GLSL functions needed to retrieve clipping planes from a ClippingPlaneCollection's texture.
*
* @param {ClippingPlaneCollection} clippingPlaneCollection ClippingPlaneCollection with a defined texture.
* @param {Context} context The current rendering context.
* @returns {String} A string containing GLSL functions for retrieving clipping planes.
* @private
*/
function getClippingFunction(clippingPlaneCollection, context) {
//>>includeStart('debug', pragmas.debug);
Check.typeOf.object('clippingPlaneCollection', clippingPlaneCollection);
Check.typeOf.object('context', context);
//>>includeEnd('debug');
var unionClippingRegions = clippingPlaneCollection.unionClippingRegions;
var clippingPlanesLength = clippingPlaneCollection.length;
var usingFloatTexture = ClippingPlaneCollection.useFloatTexture(context);
var textureResolution = ClippingPlaneCollection.getTextureResolution(clippingPlaneCollection, context, textureResolutionScratch);
var width = textureResolution.x;
var height = textureResolution.y;
var functions = usingFloatTexture ? getClippingPlaneFloat(width, height) : getClippingPlaneUint8(width, height);
functions += '\n';
functions += unionClippingRegions ? clippingFunctionUnion(clippingPlanesLength) : clippingFunctionIntersect(clippingPlanesLength);
return functions;
}
function clippingFunctionUnion(clippingPlanesLength) {
var functionString =
'float clip(vec4 fragCoord, sampler2D clippingPlanes, mat4 clippingPlanesMatrix)\n' +
'{\n' +
' vec4 position = czm_windowToEyeCoordinates(fragCoord);\n' +
' vec3 clipNormal = vec3(0.0);\n' +
' vec3 clipPosition = vec3(0.0);\n' +
' float clipAmount;\n' + // For union planes, we want to get the min distance. So we set the initial value to the first plane distance in the loop below.
' float pixelWidth = czm_metersPerPixel(position);\n' +
' bool breakAndDiscard = false;\n' +
' for (int i = 0; i < ' + clippingPlanesLength + '; ++i)\n' +
' {\n' +
' vec4 clippingPlane = getClippingPlane(clippingPlanes, i, clippingPlanesMatrix);\n' +
' clipNormal = clippingPlane.xyz;\n' +
' clipPosition = -clippingPlane.w * clipNormal;\n' +
' float amount = dot(clipNormal, (position.xyz - clipPosition)) / pixelWidth;\n' +
' clipAmount = czm_branchFreeTernary(i == 0, amount, min(amount, clipAmount));\n' +
' if (amount <= 0.0)\n' +
' {\n' +
' breakAndDiscard = true;\n' +
' break;\n' + // HLSL compiler bug if we discard here: https://bugs.chromium.org/p/angleproject/issues/detail?id=1945#c6
' }\n' +
' }\n' +
' if (breakAndDiscard) {\n' +
' discard;\n' +
' }\n' +
' return clipAmount;\n' +
'}\n';
return functionString;
}
function clippingFunctionIntersect(clippingPlanesLength) {
var functionString =
'float clip(vec4 fragCoord, sampler2D clippingPlanes, mat4 clippingPlanesMatrix)\n' +
'{\n' +
' bool clipped = true;\n' +
' vec4 position = czm_windowToEyeCoordinates(fragCoord);\n' +
' vec3 clipNormal = vec3(0.0);\n' +
' vec3 clipPosition = vec3(0.0);\n' +
' float clipAmount = 0.0;\n' +
' float pixelWidth = czm_metersPerPixel(position);\n' +
' for (int i = 0; i < ' + clippingPlanesLength + '; ++i)\n' +
' {\n' +
' vec4 clippingPlane = getClippingPlane(clippingPlanes, i, clippingPlanesMatrix);\n' +
' clipNormal = clippingPlane.xyz;\n' +
' clipPosition = -clippingPlane.w * clipNormal;\n' +
' float amount = dot(clipNormal, (position.xyz - clipPosition)) / pixelWidth;\n' +
' clipAmount = max(amount, clipAmount);\n' +
' clipped = clipped && (amount <= 0.0);\n' +
' }\n' +
' if (clipped)\n' +
' {\n' +
' discard;\n' +
' }\n' +
' return clipAmount;\n' +
'}\n';
return functionString;
}
function getClippingPlaneFloat(width, height) {
var pixelWidth = 1.0 / width;
var pixelHeight = 1.0 / height;
var pixelWidthString = pixelWidth + '';
if (pixelWidthString.indexOf('.') === -1) {
pixelWidthString += '.0';
}
var pixelHeightString = pixelHeight + '';
if (pixelHeightString.indexOf('.') === -1) {
pixelHeightString += '.0';
}
var functionString =
'vec4 getClippingPlane(sampler2D packedClippingPlanes, int clippingPlaneNumber, mat4 transform)\n' +
'{\n' +
' int pixY = clippingPlaneNumber / ' + width + ';\n' +
' int pixX = clippingPlaneNumber - (pixY * ' + width + ');\n' +
' float u = (float(pixX) + 0.5) * ' + pixelWidthString + ';\n' + // sample from center of pixel
' float v = (float(pixY) + 0.5) * ' + pixelHeightString + ';\n' +
' vec4 plane = texture2D(packedClippingPlanes, vec2(u, v));\n' +
' return czm_transformPlane(plane, transform);\n' +
'}\n';
return functionString;
}
function getClippingPlaneUint8(width, height) {
var pixelWidth = 1.0 / width;
var pixelHeight = 1.0 / height;
var pixelWidthString = pixelWidth + '';
if (pixelWidthString.indexOf('.') === -1) {
pixelWidthString += '.0';
}
var pixelHeightString = pixelHeight + '';
if (pixelHeightString.indexOf('.') === -1) {
pixelHeightString += '.0';
}
var functionString =
'vec4 getClippingPlane(sampler2D packedClippingPlanes, int clippingPlaneNumber, mat4 transform)\n' +
'{\n' +
' int clippingPlaneStartIndex = clippingPlaneNumber * 2;\n' + // clipping planes are two pixels each
' int pixY = clippingPlaneStartIndex / ' + width + ';\n' +
' int pixX = clippingPlaneStartIndex - (pixY * ' + width + ');\n' +
' float u = (float(pixX) + 0.5) * ' + pixelWidthString + ';\n' + // sample from center of pixel
' float v = (float(pixY) + 0.5) * ' + pixelHeightString + ';\n' +
' vec4 oct32 = texture2D(packedClippingPlanes, vec2(u, v)) * 255.0;\n' +
' vec2 oct = vec2(oct32.x * 256.0 + oct32.y, oct32.z * 256.0 + oct32.w);\n' +
' vec4 plane;\n' +
' plane.xyz = czm_octDecode(oct, 65535.0);\n' +
' plane.w = czm_unpackFloat(texture2D(packedClippingPlanes, vec2(u + ' + pixelWidthString + ', v)));\n' +
' return czm_transformPlane(plane, transform);\n' +
'}\n';
return functionString;
}
export default getClippingFunction;