@itwin/core-frontend
Version:
iTwin.js frontend components
184 lines (176 loc) • 7.38 kB
JavaScript
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
* @module WebGL
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.unpackFloat = void 0;
exports.addClipping = addClipping;
const core_bentley_1 = require("@itwin/core-bentley");
const RenderFlags_1 = require("../RenderFlags");
const Common_1 = require("./Common");
const FeatureSymbology_1 = require("./FeatureSymbology");
const Translucency_1 = require("./Translucency");
const Vertex_1 = require("./Vertex");
const getClipPlaneFloat = `
vec4 getClipPlane(int index) {
return texelFetch(s_clipSampler, ivec2(0, index), 0);
}
`;
exports.unpackFloat = `
float unpackFloat(vec4 v) {
const float bias = 38.0;
v = floor(v * 255.0 + 0.5);
float temp = v.w / 2.0;
float exponent = floor(temp);
float sign = (temp - exponent) * 2.0;
exponent = exponent - bias;
sign = -(sign * 2.0 - 1.0);
float unpacked = dot(sign * v.xyz, vec3(1.0 / 256.0, 1.0 / 65536.0, 1.0 / 16777216.0)); // shift x right 8, y right 16 and z right 24
return unpacked * pow(10.0, exponent);
}
`;
const calcClipPlaneDist = `
float calcClipPlaneDist(vec3 camPos, vec4 plane) {
return dot(vec4(camPos, 1.0), plane);
}
`;
const applyClipPlanesLoop = `
for (int i = u_clipParams[0]; i < u_clipParams[1]; i++) {
`;
const applyClipPlanesLoopBody = `
vec4 plane = getClipPlane(i);
if (plane.x == 2.0) { // indicates start of new UnionOfConvexClipPlaneSets
if (numSetsClippedBy + int(clippedByCurrentPlaneSet) == numPlaneSets)
break;
numPlaneSets = 1;
numSetsClippedBy = 0;
clippedByCurrentPlaneSet = false;
} else if (plane.xyz == vec3(0.0)) { // indicates start of new clip plane set
numPlaneSets = numPlaneSets + 1;
numSetsClippedBy += int(clippedByCurrentPlaneSet);
clippedByCurrentPlaneSet = false;
} else if (!clippedByCurrentPlaneSet && calcClipPlaneDist(v_eyeSpace, plane) < 0.0) {
clippedByCurrentPlaneSet = true;
}
`;
const applyClipPlanesIntersectionLoopBody = `
if ((i <= u_clipParams[1] - 2) && (!clippedByCurrentPlaneSet)) {
//Obtaining closest point on plane to current frag in eyespace
vec3 pointOnPlane = v_eyeSpace - (abs(calcClipPlaneDist(v_eyeSpace, plane)) * plane.xyz);
//determining whether to colorize
if (distance(v_eyeSpace, pointOnPlane) <= (kFrustumType_Perspective == u_frustum.z ? -pointOnPlane.z * widthFactor : widthFactor)) {
colorizeIntersection = true;
}
}
}
//Need to pull this condition out of the loop for when there are multiple clip planes defined
if (colorizeIntersection && !clippedByCurrentPlaneSet) {
g_clipColor = u_clipIntersection.rgb;
return bvec2(true, true);
}
`;
const applyClipPlanesPrelude = `
int numPlaneSets = 1;
int numSetsClippedBy = 0;
bool clippedByCurrentPlaneSet = false;
bool colorizeIntersection = false;
if (u_colorizeIntersection) {
float widthFactor = u_pixelWidthFactor * 2.0 * u_clipIntersection.a;
${applyClipPlanesLoop}${applyClipPlanesLoopBody}${applyClipPlanesIntersectionLoopBody}
} else {
${applyClipPlanesLoop}${applyClipPlanesLoopBody} }\n
}
`;
const applyClipPlanesPostlude = `
numSetsClippedBy += int(clippedByCurrentPlaneSet);
if (numSetsClippedBy == numPlaneSets) {
if (u_outsideRgba.a > 0.0) {
g_clipColor = u_outsideRgba.rgb;
return bvec2(true,false);
} else {
discard;
}
} else if (u_insideRgba.a > 0.0) {
g_clipColor = u_insideRgba.rgb;
return bvec2(true,false);
}
return bvec2(false,false);
`;
const assignFragData = `
if (g_hasClipColor.y) {
vec4 output0 = vec4(g_clipColor, 1.0);
vec4 output1 = vec4(1.0, 1.0, 0.0, 1.0);
FragColor0 = output0;
FragColor1 = output1;
} else {
${Translucency_1.computeOutputs}
FragColor0 = output0;
FragColor1 = output1;
}
`;
const applyClipPlanes = applyClipPlanesPrelude + applyClipPlanesPostlude;
const clipParams = new Int32Array(3);
/** @internal */
function addClipping(prog) {
const frag = prog.frag;
const vert = prog.vert;
(0, Common_1.addEyeSpace)(prog);
prog.addUniform("u_outsideRgba", 5 /* VariableType.Vec4 */, (program) => {
program.addGraphicUniform("u_outsideRgba", (uniform, params) => {
params.target.uniforms.branch.clipStack.outsideColor.bind(uniform);
});
});
prog.addUniform("u_insideRgba", 5 /* VariableType.Vec4 */, (program) => {
program.addGraphicUniform("u_insideRgba", (uniform, params) => {
params.target.uniforms.branch.clipStack.insideColor.bind(uniform);
});
});
(0, Common_1.addFrustum)(prog);
(0, FeatureSymbology_1.addPixelWidthFactor)(frag);
(0, Vertex_1.addModelViewMatrix)(vert);
// [0] = index of first plane
// [1] = index of last plane (one past the end)
// [2] = texture height
prog.frag.addGlobal("g_hasClipColor", 11 /* VariableType.BVec2 */);
prog.addUniformArray("u_clipParams", 1 /* VariableType.Int */, 3, (program) => {
program.addGraphicUniform("u_clipParams", (uniform, params) => {
// Set this to false to visualize pre-shader culling of geometry.
const doClipping = true;
const stack = params.target.uniforms.branch.clipStack;
clipParams[0] = stack.startIndex;
clipParams[1] = stack.endIndex;
clipParams[2] = doClipping ? stack.textureHeight : 0;
(0, core_bentley_1.assert)(clipParams[2] > 0 || !doClipping);
uniform.setUniform1iv(clipParams);
});
});
prog.frag.addUniform("u_colorizeIntersection", 0 /* VariableType.Boolean */, (program) => {
program.addProgramUniform("u_colorizeIntersection", (uniform, params) => {
uniform.setUniform1i(params.target.uniforms.branch.clipStack.colorizeIntersection ? 1 : 0);
});
});
prog.frag.addUniform("u_clipIntersection", 5 /* VariableType.Vec4 */, (program) => {
program.addGraphicUniform("u_clipIntersection", (uniform, params) => {
params.target.uniforms.branch.clipStack.intersectionStyle.bind(uniform);
});
});
frag.addFunction(getClipPlaneFloat);
frag.addFunction(calcClipPlaneDist);
frag.addUniform("s_clipSampler", 8 /* VariableType.Sampler2D */, (program) => {
program.addGraphicUniform("s_clipSampler", (uniform, params) => {
const texture = params.target.uniforms.branch.clipStack.texture;
(0, core_bentley_1.assert)(texture !== undefined);
if (texture !== undefined)
texture.bindSampler(uniform, RenderFlags_1.TextureUnit.ClipVolume);
});
}, 3 /* VariablePrecision.High */);
frag.set(10 /* FragmentShaderComponent.ApplyClipping */, applyClipPlanes);
// modify translucent shaders
if (frag.findFunction(Translucency_1.computeAlphaWeight))
frag.set(18 /* FragmentShaderComponent.AssignFragData */, assignFragData);
}
//# sourceMappingURL=Clipping.js.map