Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nonlocatable classification #732

Merged
merged 5 commits into from
Feb 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"changes": [
{
"packageName": "@bentley/imodeljs-frontend",
"comment": "implemented nonlocatable for planar classifiers",
"type": "none"
}
],
"packageName": "@bentley/imodeljs-frontend",
"email": "36053767+MarcNeely@users.noreply.github.com"
}
3 changes: 2 additions & 1 deletion core/frontend/src/render/webgl/PlanarClassifier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,8 @@ export class PlanarClassifier extends RenderPlanarClassifier implements RenderMe
return;

// TBD - Refine resolution calculation -- increase height based on viewing angle.
const requiredHeight = Math.max(context.target.viewRect.width, context.target.viewRect.height);
// But make sure that we don't make it larger than the hardware supports, keeping in mind that we will be doubling the height later.
const requiredHeight = Math.min(Math.max(context.target.viewRect.width, context.target.viewRect.height), System.instance.capabilities.maxTextureSize / 2);
const requiredWidth = requiredHeight;

if (requiredWidth !== this._width || requiredHeight !== this._height)
Expand Down
18 changes: 11 additions & 7 deletions core/frontend/src/render/webgl/glsl/FeatureSymbology.ts
Original file line number Diff line number Diff line change
Expand Up @@ -277,9 +277,11 @@ function addEmphasisFlags(builder: ShaderBuilder): void {
builder.addBitFlagConstant("kEmphBit_Hilite", 0);
builder.addBitFlagConstant("kEmphBit_Emphasize", 1);
builder.addBitFlagConstant("kEmphBit_Flash", 2);
builder.addBitFlagConstant("kEmphBit_NonLocatable", 3);
builder.addConstant("kEmphFlag_Hilite", VariableType.Float, "1.0");
builder.addConstant("kEmphFlag_Emphasize", VariableType.Float, "2.0");
builder.addConstant("kEmphFlag_Flash", VariableType.Float, "4.0");
builder.addConstant("kEmphFlag_NonLocatable", VariableType.Float, "8.0");
}

function addHiliteSettings(frag: FragmentShaderBuilder, wantFlashMode: boolean): void {
Expand Down Expand Up @@ -487,6 +489,12 @@ function addBatchId(builder: ShaderBuilder) {
}, VariablePrecision.High);
}

const computeIdVert = `v_feature_id = addUInt32s(u_batch_id, vec4(g_featureIndex, 0.0)) / 255.0;`;
const computeIdFrag = `
vec4 featureIndex = vec4(floor(v_feature_index + 0.5), 0.0);
feature_id = addUInt32s(u_batch_id, featureIndex) / 255.0;
`;

/** @internal */
export function addFeatureId(builder: ProgramBuilder, computeInFrag: boolean) {
const vert = builder.vert;
Expand All @@ -495,20 +503,15 @@ export function addFeatureId(builder: ProgramBuilder, computeInFrag: boolean) {
if (!computeInFrag) {
vert.addFunction(addUInt32s);
addBatchId(vert);
const computeId = `v_feature_id = addUInt32s(u_batch_id, vec4(g_featureIndex, 0.0)) / 255.0;`;
builder.addInlineComputedVarying("v_feature_id", VariableType.Vec4, computeId);
builder.addInlineComputedVarying("v_feature_id", VariableType.Vec4, computeIdVert);

frag.addInitializer("feature_id = v_feature_id;");
} else {
frag.addFunction(addUInt32s);
builder.addInlineComputedVarying("v_feature_index", VariableType.Vec3, "v_feature_index = g_featureIndex;");

addBatchId(frag);
const computeId = `
vec4 featureIndex = vec4(floor(v_feature_index + 0.5), 0.0);
feature_id = addUInt32s(u_batch_id, featureIndex) / 255.0;
`;
frag.addInitializer(computeId);
frag.addInitializer(computeIdFrag);
}
}

Expand Down Expand Up @@ -600,6 +603,7 @@ const computeFeatureOverrides = `
return; // nothing overridden for this feature

bool nonLocatable = (u_shaderFlags[kShaderBit_IgnoreNonLocatable] ? nthFeatureBitSet(flags, kOvrBit_NonLocatable) : false);
v_feature_emphasis += kEmphFlag_NonLocatable * float(nthFeatureBitSet(flags, kOvrBit_NonLocatable));
bool invisible = nthFeatureBitSet(flags, kOvrBit_Visibility);
feature_invisible = invisible || nonLocatable;
if (feature_invisible)
Expand Down
2 changes: 1 addition & 1 deletion core/frontend/src/render/webgl/glsl/Fragment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ const assignPickBufferOutputsMP = `
else
FragColor = output2;
`;
const reassignFeatureId = "output1 = overrideFeatureId(output1);";
const reassignFeatureId = " output1 = overrideFeatureId(output1);";

/** @internal */
export function addPickBufferOutputs(frag: FragmentShaderBuilder): void {
Expand Down
52 changes: 44 additions & 8 deletions core/frontend/src/render/webgl/glsl/PlanarClassification.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { TextureUnit } from "../RenderFlags";
import { FragmentShaderComponent, ProgramBuilder, ShaderBuilder, VariableType } from "../ShaderBuilder";
import { IsThematic } from "../TechniqueFlags";
import { Texture2DHandle } from "../Texture";
import { addUInt32s } from "./Common";
import { addShaderFlags, addUInt32s } from "./Common";
import { addClassifierFlash } from "./FeatureSymbology";
import { addWindowToTexCoords } from "./Fragment";
import { addInstancedRtcMatrix } from "./Vertex";
Expand Down Expand Up @@ -52,6 +52,15 @@ const applyPlanarClassificationColor = `
}

vec4 colorTexel = TEXTURE(s_pClassSampler, vec2(classPos.x, classPos.y / 2.0));
if (colorTexel.b >= 0.5) {
if (u_shaderFlags[kShaderBit_IgnoreNonLocatable]) {
discard;
return vec4(0.0);
}
colorTexel.b = (colorTexel.b * 255.0 - 128.0) / 127.0;
} else {
colorTexel.b *= 255.0 / 127.0;
}
bool isClassified = colorTexel.r + colorTexel.g + colorTexel.b + colorTexel.a > 0.0;
float param = isClassified ? u_pClassColorParams.x : u_pClassColorParams.y;
if (kClassifierDisplay_Off == param)
Expand Down Expand Up @@ -102,6 +111,15 @@ const applyPlanarClassificationColorForThematic = `
}

vec4 colorTexel = TEXTURE(s_pClassSampler, vec2(classPos.x, classPos.y / 2.0));
if (colorTexel.b >= 0.5) {
if (u_shaderFlags[kShaderBit_IgnoreNonLocatable]) {
discard;
return vec4(0.0);
}
colorTexel.b = (colorTexel.b * 255.0 - 128.0) / 127.0;
} else {
colorTexel.b *= 255.0 / 127.0;
}
bool isClassified = colorTexel.r + colorTexel.g + colorTexel.b + colorTexel.a > 0.0;
float param = isClassified ? u_pClassColorParams.x : u_pClassColorParams.y;
if (kClassifierDisplay_Off == param)
Expand Down Expand Up @@ -248,6 +266,8 @@ export function addColorPlanarClassifier(builder: ProgramBuilder, translucent: b
frag.addFunction(volClassOpaqueColor);
}

addShaderFlags(builder);

frag.set(FragmentShaderComponent.ApplyPlanarClassifier, (isThematic === IsThematic.No) ? applyPlanarClassificationColor : applyPlanarClassificationColorForThematic);
}

Expand Down Expand Up @@ -286,24 +306,39 @@ export function addHilitePlanarClassifier(builder: ProgramBuilder, supportTextur
frag.set(FragmentShaderComponent.ComputeBaseColor, supportTextures ? computeClassifiedSurfaceHiliteColor : computeClassifiedHiliteColor);
}

// NonLocatable flag is put in upper bit of blue component when drawing the classification texture.
const encodeNonLocatableWithFeatures = `
vec4 encodeNonLocatable(vec4 clr) {
float encoded_b = (floor(clr.b * 127.0) + float(extractNthBit(floor(v_feature_emphasis + 0.5), kEmphBit_NonLocatable)) * 128.0) / 255.0;
return vec4(clr.r, clr.g, encoded_b, clr.a);
}
`;

const encodeNonLocatable = `
vec4 encodeNonLocatable(vec4 clr) {
float encoded_b = floor(clr.b * 127.0) / 255.0;
return vec4(clr.r, clr.g, encoded_b, clr.a);
}
`;

const overrideClassifierColorPrelude = `
if (0.0 == u_planarClassifierInsideMode)
return currentColor;

if (0.0 == currentColor.a)
return vec4(0.0, 0.0, 1.0, 0.5);
return encodeNonLocatable(vec4(0.0, 0.0, 1.0, 0.5));
`;

const overrideClassifierEmphasis = `
if (kClassifierDisplay_Element != u_planarClassifierInsideMode) {
float emph = floor(v_feature_emphasis + 0.5);
if (0.0 != emph)
return vec4(extractNthBit(emph, kEmphBit_Hilite), extractNthBit(emph, kEmphBit_Flash), 0.0, 0.5);
return encodeNonLocatable(vec4(extractNthBit(emph, kEmphBit_Hilite), extractNthBit(emph, kEmphBit_Flash), 0.0, 0.5));
}
`;

const overrideClassifierColorPostlude = `
return currentColor;
return encodeNonLocatable(currentColor);
`;

const overrideClassifierWithFeatures = overrideClassifierColorPrelude + overrideClassifierEmphasis + overrideClassifierColorPostlude;
Expand All @@ -314,22 +349,22 @@ const overrideClassifierColorPreludeForThematic = `
return currentColor;

if (0.0 == currentColor.a)
return vec4(0.0, 0.0, 1.0, 0.5);
return encodeNonLocatable(vec4(0.0, 0.0, 1.0, 0.5));

bool isElem = kClassifierDisplay_Element == u_planarClassifierInsideMode;
`;

const overrideClassifierEmphasisForThematic = `
float emph = floor(v_feature_emphasis + 0.5);
if (0.0 != emph)
return vec4(extractNthBit(emph, kEmphBit_Hilite), extractNthBit(emph, kEmphBit_Flash), isElem ? currentColor.a : 0.0, isElem ? 1.0 : 0.5);
return encodeNonLocatable(vec4(extractNthBit(emph, kEmphBit_Hilite), extractNthBit(emph, kEmphBit_Flash), isElem ? currentColor.a : 0.0, isElem ? 1.0 : 0.5));
else if (kClassifierDisplay_Element == u_planarClassifierInsideMode)
return vec4(0.0, 0.0, currentColor.a, 1.0);
return encodeNonLocatable(vec4(0.0, 0.0, currentColor.a, 1.0));
`;

// Thematic classifiers use alpha of 1 to blend; we just want thematic colors to largely win out except when selecting and flashing classifiers.
const overrideClassifierColorPostludeClipForThematic = `
return isElem ? vec4(0.0, 0.0, 1.0, 1.0) : currentColor;
return encodeNonLocatable(isElem ? vec4(0.0, 0.0, 1.0, 1.0) : currentColor);
`;

const overrideClassifierWithFeaturesForThematic = overrideClassifierColorPreludeForThematic + overrideClassifierEmphasisForThematic + overrideClassifierColorPostlude;
Expand All @@ -353,6 +388,7 @@ export function addOverrideClassifierColor(builder: ProgramBuilder, isThematic:
});

const haveOverrides = undefined !== builder.frag.find("v_feature_emphasis");
builder.frag.addFunction(haveOverrides ? encodeNonLocatableWithFeatures : encodeNonLocatable);
if (isThematic === IsThematic.No)
builder.frag.set(FragmentShaderComponent.OverrideColor, haveOverrides ? overrideClassifierWithFeatures : overrideClassifierForClip);
else
Expand Down