Skip to content

Commit 7a4eeae

Browse files
endankegithub-actions[bot]
authored andcommitted
Allow mixed rendering of translucent and fully opaque meshes
GitOrigin-RevId: 312409bf7fc439565228b2e5a76a03ab817d5623
1 parent cdb43c4 commit 7a4eeae

File tree

1 file changed

+30
-18
lines changed

1 file changed

+30
-18
lines changed

3d-style/render/draw_model.ts

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ type SortedMesh = {
5555
worldViewProjection: mat4;
5656
nodeModelMatrix: mat4;
5757
isLightMesh: boolean;
58+
modelOpacity: number;
5859
materialOverride?: MaterialOverride;
5960
modelColor?: [number, number, number, number];
6061
};
@@ -164,7 +165,7 @@ function setupMeshDraw(definesValues: Array<string>, dynamicBuffers: Array<Verte
164165
}
165166

166167
function drawMesh(sortedMesh: SortedMesh, painter: Painter, layer: ModelStyleLayer, modelParameters: ModelParameters, stencilMode: StencilMode, colorMode: ColorMode) {
167-
const opacity = layer.paint.get('model-opacity').constantOr(1.0);
168+
const opacity = sortedMesh.modelOpacity;
168169

169170
assert(opacity > 0);
170171
const context = painter.context;
@@ -295,7 +296,7 @@ export function prepare(layer: ModelStyleLayer, sourceCache: SourceCache, painte
295296
}
296297
}
297298

298-
function prepareMeshes(painter: Painter, node: ModelNode, modelMatrix: mat4, projectionMatrix: mat4, modelIndex: number, transparentMeshes: Array<SortedMesh>, opaqueMeshes: Array<SortedMesh>, materialOverrides: ModelMaterialOverrides, modelColorMix?: [number, number, number, number]) {
299+
function prepareMeshes(painter: Painter, node: ModelNode, modelMatrix: mat4, projectionMatrix: mat4, modelIndex: number, transparentMeshes: Array<SortedMesh>, opaqueMeshes: Array<SortedMesh>, materialOverrides: ModelMaterialOverrides, modelOpacity: number, modelColorMix?: [number, number, number, number]) {
299300

300301
const transform = painter.transform;
301302

@@ -317,21 +318,21 @@ function prepareMeshes(painter: Painter, node: ModelNode, modelMatrix: mat4, pro
317318
if (materialOverride && materialOverride.opacity <= 0) continue;
318319

319320
if (mesh.material.alphaMode !== 'BLEND') {
320-
const opaqueMesh: SortedMesh = {mesh, depth: 0.0, modelIndex, worldViewProjection, nodeModelMatrix, isLightMesh, materialOverride, modelColor: modelColorMix};
321+
const opaqueMesh: SortedMesh = {mesh, depth: 0.0, modelIndex, worldViewProjection, nodeModelMatrix, isLightMesh, materialOverride, modelOpacity, modelColor: modelColorMix};
321322
opaqueMeshes.push(opaqueMesh);
322323
continue;
323324
}
324325

325326
const centroidPos = vec3.transformMat4([], mesh.centroid, worldViewProjection);
326327
// Filter meshes behind the camera if in perspective mode
327328
if (!transform.isOrthographic && centroidPos[2] <= 0.0) continue;
328-
const transparentMesh: SortedMesh = {mesh, depth: centroidPos[2], modelIndex, worldViewProjection, nodeModelMatrix, isLightMesh, materialOverride, modelColor: modelColorMix};
329+
const transparentMesh: SortedMesh = {mesh, depth: centroidPos[2], modelIndex, worldViewProjection, nodeModelMatrix, isLightMesh, materialOverride, modelOpacity, modelColor: modelColorMix};
329330
transparentMeshes.push(transparentMesh);
330331
}
331332
}
332333
if (node.children) {
333334
for (const child of node.children) {
334-
prepareMeshes(painter, child, modelMatrix, projectionMatrix, modelIndex, transparentMeshes, opaqueMeshes, materialOverrides, modelColorMix);
335+
prepareMeshes(painter, child, modelMatrix, projectionMatrix, modelIndex, transparentMeshes, opaqueMeshes, materialOverrides, modelOpacity, modelColorMix);
335336
}
336337
}
337338
}
@@ -485,6 +486,7 @@ function drawModels(painter: Painter, sourceCache: SourceCache, layer: ModelStyl
485486
const rotation = layer.paint.get('model-rotation').evaluate(modelFeature, modelFeatureState);
486487
const scale = layer.paint.get('model-scale').evaluate(modelFeature, modelFeatureState);
487488
const translation = layer.paint.get('model-translation').evaluate(modelFeature, modelFeatureState);
489+
const modelOpacity = layer.paint.get('model-opacity').evaluate(modelFeature, modelFeatureState);
488490

489491
evaluateFeatureStateForNodeOverrides(layer, model.id, modelFeatureState, model.featureProperties, model.nodeOverrideNames, model.nodeOverrides);
490492
evaluateFeatureStateForMaterialOverrides(layer, model.id, modelFeatureState, model.featureProperties, model.materialOverrideNames, model.materialOverrides);
@@ -505,7 +507,7 @@ function drawModels(painter: Painter, sourceCache: SourceCache, layer: ModelStyl
505507
const modelParameters = {zScaleMatrix, negCameraPosMatrix};
506508
modelParametersVector.push(modelParameters);
507509
for (const node of model.nodes) {
508-
prepareMeshes(painter, node, model.matrix, painter.transform.expandedFarZProjMatrix, modelIndex, transparentMeshes, opaqueMeshes, model.materialOverrides);
510+
prepareMeshes(painter, node, model.matrix, painter.transform.expandedFarZProjMatrix, modelIndex, transparentMeshes, opaqueMeshes, model.materialOverrides, modelOpacity);
509511
}
510512
modelIndex++;
511513
}
@@ -527,25 +529,33 @@ function drawModels(painter: Painter, sourceCache: SourceCache, layer: ModelStyl
527529
return;
528530
}
529531

530-
drawSortedMeshes(painter, layer, opacity, transparentMeshes, opaqueMeshes, modelParametersVector);
532+
drawSortedMeshes(painter, layer, transparentMeshes, opaqueMeshes, modelParametersVector);
531533

532534
cleanup();
533535
}
534536

535-
function drawSortedMeshes(painter: Painter, layer: ModelStyleLayer, opacity: number, transparentMeshes: Array<SortedMesh>, opaqueMeshes: Array<SortedMesh>, modelParametersVector: Array<ModelParameters>) {
536-
// Draw opaque meshes
537-
if (opacity === 1) {
538-
for (const opaqueMesh of opaqueMeshes) {
539-
drawMesh(opaqueMesh, painter, layer, modelParametersVector[opaqueMesh.modelIndex], StencilMode.disabled, painter.colorModeForRenderPass());
540-
}
541-
} else {
542-
for (const opaqueMesh of opaqueMeshes) {
537+
function drawSortedMeshes(painter: Painter, layer: ModelStyleLayer, transparentMeshes: Array<SortedMesh>, opaqueMeshes: Array<SortedMesh>, modelParametersVector: Array<ModelParameters>) {
538+
let needsStencilClear = false;
539+
540+
// Render opaque meshes first.
541+
// The per-feature model-opacity can be less than 1.0 even for opaque meshes.
542+
// In that case we need to render one extra pass to write into the depth buffer.
543+
for (const opaqueMesh of opaqueMeshes) {
544+
if (opaqueMesh.modelOpacity !== 1.0) {
543545
// If we have layer opacity draw with two passes opaque meshes
544546
drawMesh(opaqueMesh, painter, layer, modelParametersVector[opaqueMesh.modelIndex], StencilMode.disabled, ColorMode.disabled);
547+
needsStencilClear = true;
545548
}
546-
for (const opaqueMesh of opaqueMeshes) {
549+
}
550+
for (const opaqueMesh of opaqueMeshes) {
551+
if (opaqueMesh.modelOpacity !== 1.0) {
547552
drawMesh(opaqueMesh, painter, layer, modelParametersVector[opaqueMesh.modelIndex], painter.stencilModeFor3D(), painter.colorModeForRenderPass());
553+
} else {
554+
drawMesh(opaqueMesh, painter, layer, modelParametersVector[opaqueMesh.modelIndex], StencilMode.disabled, painter.colorModeForRenderPass());
548555
}
556+
}
557+
558+
if (needsStencilClear) {
549559
painter.resetStencilClippingMasks();
550560
}
551561

@@ -673,6 +683,8 @@ function drawVectorLayerModels(painter: Painter, source: SourceCache, layer: Mod
673683

674684
const layerIndex = painter.style.order.indexOf(layer.fqid);
675685

686+
const layerOpacity = layer.paint.get('model-opacity').constantOr(1.0);
687+
676688
for (const coord of coords) {
677689
const tile = source.getTile(coord);
678690
const bucket = tile.getBucket(layer) as ModelBucket | null | undefined;
@@ -776,7 +788,7 @@ function drawVectorLayerModels(painter: Painter, source: SourceCache, layer: Mod
776788
modelParametersVector.push(modelParameters);
777789

778790
for (const node of model.nodes) {
779-
prepareMeshes(painter, node, modelMatrix, painter.transform.expandedFarZProjMatrix, modelIndex, transparentMeshes, opaqueMeshes, model.materialOverrides, colorMix);
791+
prepareMeshes(painter, node, modelMatrix, painter.transform.expandedFarZProjMatrix, modelIndex, transparentMeshes, opaqueMeshes, model.materialOverrides, layerOpacity, colorMix);
780792
}
781793
++modelIndex;
782794
}
@@ -798,7 +810,7 @@ function drawVectorLayerModels(painter: Painter, source: SourceCache, layer: Mod
798810
drawShadowCaster(transparentMesh.mesh, transparentMesh.nodeModelMatrix, painter, layer);
799811
}
800812
} else {
801-
drawSortedMeshes(painter, layer, 1.0, transparentMeshes, opaqueMeshes, modelParametersVector);
813+
drawSortedMeshes(painter, layer, transparentMeshes, opaqueMeshes, modelParametersVector);
802814
}
803815

804816
}

0 commit comments

Comments
 (0)