@itwin/core-frontend
Version:
iTwin.js frontend components
108 lines (105 loc) • 4.77 kB
JavaScript
/*---------------------------------------------------------------------------------------------
* 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
*/
import { assert } from "@itwin/core-bentley";
import { AttributeMap } from "../AttributeMap";
import { ProgramBuilder } from "../ShaderBuilder";
import { addUniformHiliter } from "./FeatureSymbology";
import { addColorPlanarClassifier, addFeaturePlanarClassifier, addHilitePlanarClassifier } from "./PlanarClassification";
import { addModelViewProjectionMatrix } from "./Vertex";
import { addViewportTransformation } from "./Viewport";
import { addThematicDisplay } from "./Thematic";
import { addTexture } from "./Surface";
import { assignFragColor } from "./Fragment";
// Revert components if color format is BGR instead of RGB.
const computeColor = `
return u_pointCloud.y == 1.0 ? vec4(a_color.b, a_color.g, a_color.r, 1.0) : vec4(a_color, 1.0);
`;
const computeBaseColor = "return v_color;";
// Round the point unless drawing square points.
const roundPointDiscard = `
if (u_pointCloudSettings.w == 1.0)
return false;
vec2 pointXY = (2.0 * gl_PointCoord - 1.0);
return dot(pointXY, pointXY) > 1.0;
`;
const checkForClassifiedDiscard = "return baseColor.a == 0.0;";
const computePosition = `
gl_PointSize = 1.0;
vec4 pos = MAT_MVP * rawPos;
if (u_pointCloudSettings.x > 0.0) {
// Size is specified in pixels.
gl_PointSize = u_pointCloudSettings.x;
return pos;
}
// Point size is in meters (voxel size).
if (pos.w <= 0.0) {
// Cannot perform perspective divide below.
return pos;
}
// Convert voxel size in meters into pixel size, then compute pixel size, taking perspective into account.
mat4 toView = u_viewportTransformation * MAT_MVP;
float scale = length(toView[0].xyz);
gl_PointSize = -u_pointCloudSettings.x * clamp(u_pointCloud.x * scale / pos.w, u_pointCloudSettings.y, u_pointCloudSettings.z);
return pos;
`;
function createBuilder() {
const builder = new ProgramBuilder(AttributeMap.findAttributeMap(2 /* TechniqueId.PointCloud */, false));
const vert = builder.vert;
addViewportTransformation(vert);
vert.set(10 /* VertexShaderComponent.ComputePosition */, computePosition);
addModelViewProjectionMatrix(vert);
builder.frag.set(0 /* FragmentShaderComponent.CheckForEarlyDiscard */, roundPointDiscard);
// Uniforms based on the PointCloudDisplaySettings.
builder.addUniform("u_pointCloudSettings", 5 /* VariableType.Vec4 */, (prog) => {
prog.addGraphicUniform("u_pointCloudSettings", (uniform, params) => {
params.target.uniforms.realityModel.pointCloud.bind(uniform);
});
});
// Uniforms based on the PointCloudGeometry.
builder.vert.addUniform("u_pointCloud", 3 /* VariableType.Vec2 */, (prog) => {
prog.addGraphicUniform("u_pointCloud", (uniform, params) => {
assert(params.geometry.asPointCloud !== undefined);
scratchPointCloud[0] = params.geometry.asPointCloud.voxelSize;
scratchPointCloud[1] = params.geometry.asPointCloud.colorIsBgr ? 1 : 0;
uniform.setUniform2fv(scratchPointCloud);
});
});
return builder;
}
const scratchPointCloud = new Float32Array([0, 0]);
/** @internal */
export function createPointCloudBuilder(classified, featureMode, thematic) {
const builder = createBuilder();
builder.addVarying("v_color", 5 /* VariableType.Vec4 */);
builder.vert.set(5 /* VertexShaderComponent.ComputeBaseColor */, computeColor);
builder.frag.set(1 /* FragmentShaderComponent.ComputeBaseColor */, computeBaseColor);
if (classified) {
addColorPlanarClassifier(builder, false, thematic);
builder.frag.set(4 /* FragmentShaderComponent.CheckForDiscard */, checkForClassifiedDiscard);
if (0 /* FeatureMode.None */ !== featureMode)
addFeaturePlanarClassifier(builder);
}
if (1 /* IsThematic.Yes */ === thematic) {
addThematicDisplay(builder, true);
addTexture(builder, 0 /* IsAnimated.No */, 1 /* IsThematic.Yes */, true, false, false);
}
return builder;
}
/** @internal */
export function createPointCloudHiliter(classified) {
const builder = createBuilder();
if (classified) {
addHilitePlanarClassifier(builder, false);
builder.frag.set(18 /* FragmentShaderComponent.AssignFragData */, assignFragColor);
}
else {
addUniformHiliter(builder);
}
return builder;
}
//# sourceMappingURL=PointCloud.js.map