@itwin/core-frontend
Version:
iTwin.js frontend components
172 lines (166 loc) • 7.92 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, expectDefined } from "@itwin/core-bentley";
import { TextureUnit } from "../RenderFlags";
import { Texture2DHandle } from "../Texture";
import { addWindowToTexCoords, assignFragColor } from "./Fragment";
import { createViewportQuadBuilder } from "./ViewportQuad";
function addHiliteSettings(frag) {
frag.addUniform("u_hilite_settings", 6 /* VariableType.Mat3 */, (prog) => {
prog.addProgramUniform("u_hilite_settings", (uniform, params) => {
params.target.uniforms.hilite.bindCompositeSettings(uniform);
});
});
frag.addUniform("u_hilite_width", 3 /* VariableType.Vec2 */, (prog) => {
prog.addProgramUniform("u_hilite_width", (uniform, params) => {
params.target.uniforms.hilite.bindCompositeWidths(uniform);
});
});
}
const readEdgePixel = `
vec2 readEdgePixel(float xOffset, float yOffset) {
vec2 t = windowCoordsToTexCoords(gl_FragCoord.xy + vec2(xOffset, yOffset));
return TEXTURE(u_hilite, t).xy;
}
`;
const computeNearbyHilites = `
vec2 computeNearbyHilites() {
float hiliteWidth = u_hilite_width.x;
float emphWidth = u_hilite_width.y;
float maxWidth = max(hiliteWidth, emphWidth);
if (0.0 == maxWidth)
return vec2(0.0);
vec2 nearest = vec2(0.0, 0.0);
for (int x = -1; x <= 1; x++)
for (int y = -1; y <= 1; y++)
if (0 != x || 0 != y)
nearest = nearest + readEdgePixel(float(x), float(y));
nearest = nearest * vec2(float(hiliteWidth > 0.0), float(emphWidth > 0.0));
if ((0.0 == nearest.x && hiliteWidth > 1.0) || (0.0 == nearest.y && emphWidth > 1.0)) {
vec2 farthest = vec2(0.0, 0.0);
for (int i = -2; i <= 2; i++) {
float f = float(i);
farthest = farthest + readEdgePixel(f, -2.0) + readEdgePixel(-2.0, f) + readEdgePixel(f, 2.0) + readEdgePixel(2.0, f);
}
farthest = farthest * vec2(float(hiliteWidth > 1.0), float(emphWidth > 1.0));
nearest = nearest + farthest;
}
return nearest;
}
`;
const computeOpaqueColor = `
vec4 computeOpaqueColor() {
vec4 opaque = TEXTURE(u_opaque, v_texCoord);
opaque.rgb *= computeAmbientOcclusion();
return opaque;
}
`;
const computeDefaultAmbientOcclusion = `\nfloat computeAmbientOcclusion() { return 1.0; }\n`;
const computeAmbientOcclusion = `\nfloat computeAmbientOcclusion() { return TEXTURE(u_occlusion, v_texCoord).r; }\n`;
const computeHiliteColor = "\nvec4 computeColor() { return computeOpaqueColor(); }\n";
const computeHiliteBaseColor = `
vec4 baseColor = computeColor();
vec2 flags = TEXTURE(u_hilite, v_texCoord).rg;
vec2 outline = computeNearbyHilites();
if (u_hilite_width.y < u_hilite_width.x) { // check for emphasis outline first if it is thinner
if (outline.y > 0.0 && flags.y == 0.0)
return vec4(u_hilite_settings[1], 1.0);
if (outline.x > 0.0 && flags.x == 0.0)
return vec4(u_hilite_settings[0], 1.0);
} else {
if (outline.x > 0.0 && flags.x == 0.0)
return vec4(u_hilite_settings[0], 1.0);
if (outline.y > 0.0 && flags.y == 0.0)
return vec4(u_hilite_settings[1], 1.0);
}
float hiliteMix = flags.x * u_hilite_settings[2][0];
float emphasisMix = flags.y * u_hilite_settings[2][1];
baseColor.rgb *= (1.0 - (hiliteMix + emphasisMix));
baseColor.rgb += u_hilite_settings[0] * hiliteMix;
baseColor.rgb += u_hilite_settings[1] * emphasisMix;
return baseColor;
`;
const computeTranslucentColor = `
vec4 computeColor() {
vec4 opaque = computeOpaqueColor();
vec4 accum = TEXTURE(u_accumulation, v_texCoord);
vec2 rg = TEXTURE(u_revealage, v_texCoord).rg;
vec4 transparent = vec4(accum.rgb / clamp(rg.r, 1e-4, 5e4), accum.a);
vec4 col = mix((1.0 - transparent.a) * transparent + transparent.a * opaque, vec4(u_clipIntersection.rgb, 1.0), rg.g);
return col;
}
`;
const computeTranslucentBaseColor = "return computeColor();";
const computeAmbientOcclusionBaseColor = "return computeOpaqueColor();";
/** @internal */
export function createCompositeProgram(flags, context) {
assert(0 /* CompositeFlags.None */ !== flags);
const wantHilite = 0 /* CompositeFlags.None */ !== (flags & 2 /* CompositeFlags.Hilite */);
const wantTranslucent = 0 /* CompositeFlags.None */ !== (flags & 1 /* CompositeFlags.Translucent */);
const wantOcclusion = 0 /* CompositeFlags.None */ !== (flags & 4 /* CompositeFlags.AmbientOcclusion */);
const builder = createViewportQuadBuilder(true);
const frag = builder.frag;
frag.addFunction(wantOcclusion ? computeAmbientOcclusion : computeDefaultAmbientOcclusion);
frag.addFunction(computeOpaqueColor);
frag.set(18 /* FragmentShaderComponent.AssignFragData */, assignFragColor);
frag.addUniform("u_opaque", 8 /* VariableType.Sampler2D */, (prog) => {
prog.addGraphicUniform("u_opaque", (uniform, params) => {
Texture2DHandle.bindSampler(uniform, params.geometry.opaque, TextureUnit.Zero);
});
});
if (wantHilite) {
addHiliteSettings(frag);
addWindowToTexCoords(frag);
frag.addFunction(readEdgePixel);
frag.addFunction(computeNearbyHilites);
frag.addUniform("u_hilite", 8 /* VariableType.Sampler2D */, (prog) => {
prog.addGraphicUniform("u_hilite", (uniform, params) => {
Texture2DHandle.bindSampler(uniform, params.geometry.hilite, TextureUnit.Three);
});
});
frag.set(1 /* FragmentShaderComponent.ComputeBaseColor */, computeHiliteBaseColor);
if (!wantTranslucent) {
frag.addFunction(computeHiliteColor);
}
}
if (wantTranslucent) {
frag.addUniform("u_accumulation", 8 /* VariableType.Sampler2D */, (prog) => {
prog.addGraphicUniform("u_accumulation", (uniform, params) => {
Texture2DHandle.bindSampler(uniform, params.geometry.accum, TextureUnit.One);
});
});
frag.addUniform("u_revealage", 8 /* VariableType.Sampler2D */, (prog) => {
prog.addGraphicUniform("u_revealage", (uniform, params) => {
Texture2DHandle.bindSampler(uniform, params.geometry.reveal, TextureUnit.Two);
});
});
builder.frag.addUniform("u_clipIntersection", 5 /* VariableType.Vec4 */, (program) => {
program.addGraphicUniform("u_clipIntersection", (uniform, params) => {
params.target.uniforms.branch.clipStack.intersectionStyle.bind(uniform);
});
});
frag.addFunction(computeTranslucentColor);
if (!wantHilite) {
frag.set(1 /* FragmentShaderComponent.ComputeBaseColor */, computeTranslucentBaseColor);
}
}
if (wantOcclusion) {
frag.addUniform("u_occlusion", 8 /* VariableType.Sampler2D */, (prog) => {
prog.addGraphicUniform("u_occlusion", (uniform, params) => {
Texture2DHandle.bindSampler(uniform, expectDefined(params.geometry.occlusion), TextureUnit.Four);
});
});
if (!wantHilite && !wantTranslucent)
frag.set(1 /* FragmentShaderComponent.ComputeBaseColor */, computeAmbientOcclusionBaseColor);
}
const flagString = (wantHilite ? "-Hilite" : "") + (wantTranslucent ? "-Translucent" : "") + (wantOcclusion ? "-Occlusion" : "");
builder.vert.headerComment = `//!V! CombineTextures${flagString}`;
builder.frag.headerComment = `//!F! CombineTextures${flagString}`;
return builder.buildProgram(context);
}
//# sourceMappingURL=Composite.js.map