UNPKG

@itwin/core-frontend

Version:
184 lines (176 loc) • 7.38 kB
"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