diff --git a/common/changes/@bentley/imodeljs-frontend/fix-edge-and-polyline-z_2021-03-29-16-18.json b/common/changes/@bentley/imodeljs-frontend/fix-edge-and-polyline-z_2021-03-29-16-18.json new file mode 100644 index 000000000000..738a223a90e8 --- /dev/null +++ b/common/changes/@bentley/imodeljs-frontend/fix-edge-and-polyline-z_2021-03-29-16-18.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "packageName": "@bentley/imodeljs-frontend", + "comment": "fixed z for edges and polylines when extended behind the eye", + "type": "none" + } + ], + "packageName": "@bentley/imodeljs-frontend", + "email": "36053767+MarcNeely@users.noreply.github.com" +} \ No newline at end of file diff --git a/core/frontend/src/render/webgl/glsl/Edge.ts b/core/frontend/src/render/webgl/glsl/Edge.ts index 24c447f5d82e..f4d6b71eb709 100644 --- a/core/frontend/src/render/webgl/glsl/Edge.ts +++ b/core/frontend/src/render/webgl/glsl/Edge.ts @@ -16,7 +16,7 @@ import { addShaderFlags } from "./Common"; import { addWhiteOnWhiteReversal } from "./Fragment"; import { addAdjustWidth, addLineCode } from "./Polyline"; import { octDecodeNormal } from "./Surface"; -import { addLineWeight, addModelViewMatrix, addNormalMatrix, addProjectionMatrix } from "./Vertex"; +import { addLineWeight, addModelViewMatrix, addModelViewProjectionMatrix, addNormalMatrix, addProjectionMatrix } from "./Vertex"; import { addModelToWindowCoordinates, addViewport } from "./Viewport"; const decodeEndPointAndQuadIndices = ` @@ -62,16 +62,15 @@ const computePosition = ` vec4 other = g_otherPos; float miterAdjust = 0.0; float weight = computeLineWeight(); - float clipDist; - g_windowPos = modelToWindowCoordinates(rawPos, other, clipDist); + vec4 pos; + g_windowPos = modelToWindowCoordinates(rawPos, other, pos, v_eyeSpace); if (g_windowPos.w == 0.0) // Clipped out. return g_windowPos; - vec4 clipPos = rawPos + clipDist * (other - rawPos); - vec4 pos = MAT_MVP * clipPos; - - vec4 projOther = modelToWindowCoordinates(other, rawPos, clipDist); + vec4 otherPos; + vec3 otherMvPos; + vec4 projOther = modelToWindowCoordinates(other, rawPos, otherPos, otherMvPos); g_windowDir = projOther.xy - g_windowPos.xy; @@ -117,9 +116,10 @@ function createBase(isSilhouette: boolean, instanced: IsInstanced, isAnimated: I vert.addGlobal("lineCodeEyePos", VariableType.Vec4); vert.addGlobal("lineCodeDist", VariableType.Float, "0.0"); - addModelToWindowCoordinates(vert); // adds u_mvp, u_viewportTransformation + addModelToWindowCoordinates(vert); // adds u_mvp, u_viewportTransformation, and sets g_eyeSpace addProjectionMatrix(vert); addLineCode(builder, lineCodeArgs); + builder.addVarying("v_eyeSpace", VariableType.Vec3); vert.set(VertexShaderComponent.ComputePosition, computePosition); builder.addVarying("v_lnInfo", VariableType.Vec4); addAdjustWidth(vert); @@ -131,6 +131,7 @@ function createBase(isSilhouette: boolean, instanced: IsInstanced, isAnimated: I if (isSilhouette) { addNormalMatrix(vert); + addModelViewProjectionMatrix(vert); vert.set(VertexShaderComponent.CheckForEarlyDiscard, checkForSilhouetteDiscard); vert.addFunction(octDecodeNormal); } diff --git a/core/frontend/src/render/webgl/glsl/Polyline.ts b/core/frontend/src/render/webgl/glsl/Polyline.ts index 0bf4be8cc281..a52471ecd614 100644 --- a/core/frontend/src/render/webgl/glsl/Polyline.ts +++ b/core/frontend/src/render/webgl/glsl/Polyline.ts @@ -196,6 +196,7 @@ function addCommon(prog: ProgramBuilder) { addLineWeight(vert); vert.addGlobal("miterAdjust", VariableType.Float, "0.0"); + prog.addVarying("v_eyeSpace", VariableType.Vec3); vert.set(VertexShaderComponent.ComputePosition, computePosition); prog.addVarying("v_lnInfo", VariableType.Vec4); addAdjustWidth(vert); @@ -232,14 +233,11 @@ const computePosition = ` v_lnInfo = vec4(0.0, 0.0, 0.0, 0.0); // init and set flag to false vec4 next = g_nextPos; - float clipDist; - g_windowPos = modelToWindowCoordinates(rawPos, next, clipDist); + vec4 pos; + g_windowPos = modelToWindowCoordinates(rawPos, next, pos, v_eyeSpace); if (g_windowPos.w == 0.0) return g_windowPos; - vec4 clipPos = rawPos + clipDist * (next - rawPos); - vec4 pos = MAT_MVP * clipPos; - float param = a_param; float weight = computeLineWeight(); float scale = 1.0, directionScale = 1.0; @@ -257,7 +255,9 @@ const computePosition = ` param -= kNegatePerp; } - vec4 projNext = modelToWindowCoordinates(next, rawPos, clipDist); + vec4 otherPos; + vec3 otherMvPos; + vec4 projNext = modelToWindowCoordinates(next, rawPos, otherPos, otherMvPos); g_windowDir = projNext.xy - g_windowPos.xy; if (param < kJointBase) { @@ -269,7 +269,7 @@ const computePosition = ` if (kNone != param) { vec2 delta = vec2(0.0); vec4 prev = g_prevPos; - vec4 projPrev = modelToWindowCoordinates(prev, rawPos, clipDist); + vec4 projPrev = modelToWindowCoordinates(prev, rawPos, otherPos, otherMvPos); vec2 prevDir = g_windowPos.xy - projPrev.xy; float thisLength = sqrt(g_windowDir.x * g_windowDir.x + g_windowDir.y * g_windowDir.y); const float s_minNormalizeLength = 1.0E-5; // avoid normalizing zero length vectors. diff --git a/core/frontend/src/render/webgl/glsl/Viewport.ts b/core/frontend/src/render/webgl/glsl/Viewport.ts index c00f4bdc7897..39a5b04ae3d0 100644 --- a/core/frontend/src/render/webgl/glsl/Viewport.ts +++ b/core/frontend/src/render/webgl/glsl/Viewport.ts @@ -8,7 +8,7 @@ import { ShaderBuilder, VariableType, VertexShaderBuilder } from "../ShaderBuilder"; import { addRenderPass } from "./RenderPass"; -import { addModelViewProjectionMatrix } from "./Vertex"; +import { addModelViewMatrix, addProjectionMatrix } from "./Vertex"; /** @internal */ export function addViewport(shader: ShaderBuilder) { @@ -29,10 +29,12 @@ export function addViewportTransformation(shader: ShaderBuilder) { } const modelToWindowCoordinates = ` -vec4 modelToWindowCoordinates(vec4 position, vec4 next, out float clipDist) { - clipDist = 0.0; +vec4 modelToWindowCoordinates(vec4 position, vec4 next, out vec4 clippedMvpPos, out vec3 clippedMvPos) { if (kRenderPass_ViewOverlay == u_renderPass || kRenderPass_Background == u_renderPass) { - vec4 q = MAT_MVP * position; + vec4 q = MAT_MV * position; + clippedMvPos = q.xyz; + q = u_proj * q; + clippedMvpPos = q; q.xyz /= q.w; q.xyz = (u_viewportTransformation * vec4(q.xyz, 1.0)).xyz; return q; @@ -40,21 +42,23 @@ vec4 modelToWindowCoordinates(vec4 position, vec4 next, out float clipDist) { // Negative values are in front of the camera (visible). float s_maxZ = -u_frustum.x; // use -near (front) plane for segment drop test since u_frustum's near & far are pos. - vec4 q = MAT_MV * position; // eye coordinates. + vec4 q = MAT_MV * position; // eye coordinates. vec4 n = MAT_MV * next; if (q.z > s_maxZ) { if (n.z > s_maxZ) - return vec4(0.0, 0.0, 1.0, 0.0); // Entire segment behind eye. + return vec4(0.0, 0.0, 1.0, 0.0); // Entire segment behind front clip plane. - clipDist = (s_maxZ - q.z) / (n.z - q.z); + float t = (s_maxZ - q.z) / (n.z - q.z); - q.x += clipDist * (n.x - q.x); - q.y += clipDist * (n.y - q.y); - q.z = s_maxZ; // q.z + (s_maxZ - q.z) * (s_maxZ - q.z) / n.z - q.z + q.x += t * (n.x - q.x); + q.y += t * (n.y - q.y); + q.z = s_maxZ; // q.z + (s_maxZ - q.z) / (n.z - q.z) * (n.z - q.z) = s_maxZ } + clippedMvPos = q.xyz; q = u_proj * q; + clippedMvpPos = q; q.xyz /= q.w; // normalized device coords q.xyz = (u_viewportTransformation * vec4(q.xyz, 1.0)).xyz; // window coords return q; @@ -63,7 +67,8 @@ vec4 modelToWindowCoordinates(vec4 position, vec4 next, out float clipDist) { /** @internal */ export function addModelToWindowCoordinates(vert: VertexShaderBuilder) { - addModelViewProjectionMatrix(vert); + addModelViewMatrix(vert); + addProjectionMatrix(vert); addViewportTransformation(vert); addRenderPass(vert); vert.addFunction(modelToWindowCoordinates);