From 83f30f1852c4c597a5380d28d3fc98e481a77cc2 Mon Sep 17 00:00:00 2001 From: Bruno de Oliveira Abinader Date: Thu, 23 Aug 2018 10:35:05 +0300 Subject: [PATCH] Counter-clockwise winding order for front-facing culling --- src/data/bucket/circle_bucket.js | 23 +++++++++++----------- src/data/bucket/fill_bucket.js | 5 +++-- src/data/bucket/line_bucket.js | 7 +++++-- src/data/bucket/symbol_bucket.js | 33 ++++++++++++++++++++------------ src/render/painter.js | 9 +++++++-- src/source/tile.js | 9 ++++++--- 6 files changed, 53 insertions(+), 33 deletions(-) diff --git a/src/data/bucket/circle_bucket.js b/src/data/bucket/circle_bucket.js index 425177bb8e4..39efaad33c0 100644 --- a/src/data/bucket/circle_bucket.js +++ b/src/data/bucket/circle_bucket.js @@ -121,23 +121,22 @@ class CircleBucket implements Bucke // this geometry will be of the Point type, and we'll derive // two triangles from it. - // - // ┌─────────┐ - // │ 3 2 │ - // │ │ - // │ 0 1 │ - // └─────────┘ + // ┌──────┐ + // │ 0 1 │ Counter-clockwise winding order: front-facing culling. + // │ │ Triangle 1: 0 => 2 => 1 + // │ 2 3 │ Triangle 2: 1 => 2 => 3 + // └──────┘ const segment = this.segments.prepareSegment(4, this.layoutVertexArray, this.indexArray); const index = segment.vertexLength; - addCircleVertex(this.layoutVertexArray, x, y, -1, -1); - addCircleVertex(this.layoutVertexArray, x, y, 1, -1); - addCircleVertex(this.layoutVertexArray, x, y, 1, 1); - addCircleVertex(this.layoutVertexArray, x, y, -1, 1); + addCircleVertex(this.layoutVertexArray, x, y, -1, -1); // 0 + addCircleVertex(this.layoutVertexArray, x, y, 1, -1); // 1 + addCircleVertex(this.layoutVertexArray, x, y, -1, 1); // 2 + addCircleVertex(this.layoutVertexArray, x, y, 1, 1); // 3 - this.indexArray.emplaceBack(index, index + 1, index + 2); - this.indexArray.emplaceBack(index, index + 3, index + 2); + this.indexArray.emplaceBack(index, index + 2, index + 1); + this.indexArray.emplaceBack(index + 1, index + 2, index + 3); segment.vertexLength += 4; segment.primitiveLength += 2; diff --git a/src/data/bucket/fill_bucket.js b/src/data/bucket/fill_bucket.js index b11865913ea..04f2209a0f8 100644 --- a/src/data/bucket/fill_bucket.js +++ b/src/data/bucket/fill_bucket.js @@ -151,10 +151,11 @@ class FillBucket implements Bucket { assert(indices.length % 3 === 0); for (let i = 0; i < indices.length; i += 3) { + // Counter-clockwise winding order: front-facing culling. this.indexArray.emplaceBack( triangleIndex + indices[i], - triangleIndex + indices[i + 1], - triangleIndex + indices[i + 2]); + triangleIndex + indices[i + 2], + triangleIndex + indices[i + 1]); } triangleSegment.vertexLength += numVertices; diff --git a/src/data/bucket/line_bucket.js b/src/data/bucket/line_bucket.js index 224c0e486ea..f360eb396d2 100644 --- a/src/data/bucket/line_bucket.js +++ b/src/data/bucket/line_bucket.js @@ -485,7 +485,8 @@ class LineBucket implements Bucket { addLineVertex(layoutVertexArray, currentVertex, extrude, round, false, endLeft, distance); this.e3 = segment.vertexLength++; if (this.e1 >= 0 && this.e2 >= 0) { - indexArray.emplaceBack(this.e1, this.e2, this.e3); + // Counter-clockwise winding order: front-facing culling. + indexArray.emplaceBack(this.e1, this.e3, this.e2); segment.primitiveLength++; } this.e1 = this.e2; @@ -496,6 +497,7 @@ class LineBucket implements Bucket { addLineVertex(layoutVertexArray, currentVertex, extrude, round, true, -endRight, distance); this.e3 = segment.vertexLength++; if (this.e1 >= 0 && this.e2 >= 0) { + // Counter-clockwise winding order: front-facing culling. indexArray.emplaceBack(this.e1, this.e2, this.e3); segment.primitiveLength++; } @@ -537,7 +539,8 @@ class LineBucket implements Bucket { addLineVertex(layoutVertexArray, currentVertex, extrude, false, lineTurnsLeft, 0, distance); this.e3 = segment.vertexLength++; if (this.e1 >= 0 && this.e2 >= 0) { - indexArray.emplaceBack(this.e1, this.e2, this.e3); + // Counter-clockwise winding order: front-facing culling. + indexArray.emplaceBack(this.e1, this.e3, this.e2); segment.primitiveLength++; } diff --git a/src/data/bucket/symbol_bucket.js b/src/data/bucket/symbol_bucket.js index d783c6bb7c4..38406774a57 100644 --- a/src/data/bucket/symbol_bucket.js +++ b/src/data/bucket/symbol_bucket.js @@ -499,7 +499,8 @@ class SymbolBucket implements Bucket { addDynamicAttributes(dynamicLayoutVertexArray, labelAnchor, 0); - indexArray.emplaceBack(index, index + 1, index + 2); + // Counter-clockwise winding order: front-facing culling. + indexArray.emplaceBack(index, index + 2, index + 1); indexArray.emplaceBack(index + 1, index + 2, index + 3); segment.vertexLength += 4; @@ -543,24 +544,30 @@ class SymbolBucket implements Bucket { const anchorX = symbolInstance.anchorX; const anchorY = symbolInstance.anchorY; - this._addCollisionDebugVertex(layoutVertexArray, collisionVertexArray, boxAnchorPoint, anchorX, anchorY, new Point(x1, y1)); - this._addCollisionDebugVertex(layoutVertexArray, collisionVertexArray, boxAnchorPoint, anchorX, anchorY, new Point(x2, y1)); - this._addCollisionDebugVertex(layoutVertexArray, collisionVertexArray, boxAnchorPoint, anchorX, anchorY, new Point(x2, y2)); - this._addCollisionDebugVertex(layoutVertexArray, collisionVertexArray, boxAnchorPoint, anchorX, anchorY, new Point(x1, y2)); + // ┌──────┐ + // │ 0 1 │ Counter-clockwise winding order: front-facing culling. + // │ │ Triangle 1: 0 => 2 => 1 + // │ 2 3 │ Triangle 2: 1 => 2 => 3 + // └──────┘ + this._addCollisionDebugVertex(layoutVertexArray, collisionVertexArray, boxAnchorPoint, anchorX, anchorY, new Point(x1, y1)); // 0 + this._addCollisionDebugVertex(layoutVertexArray, collisionVertexArray, boxAnchorPoint, anchorX, anchorY, new Point(x2, y1)); // 1 + this._addCollisionDebugVertex(layoutVertexArray, collisionVertexArray, boxAnchorPoint, anchorX, anchorY, new Point(x1, y2)); // 2 + this._addCollisionDebugVertex(layoutVertexArray, collisionVertexArray, boxAnchorPoint, anchorX, anchorY, new Point(x2, y2)); // 3 segment.vertexLength += 4; if (isCircle) { const indexArray: TriangleIndexArray = (arrays.indexArray: any); - indexArray.emplaceBack(index, index + 1, index + 2); - indexArray.emplaceBack(index, index + 2, index + 3); + // Counter-clockwise winding order: front-facing culling. + indexArray.emplaceBack(index, index + 2, index + 1); + indexArray.emplaceBack(index + 1, index + 2, index + 3); segment.primitiveLength += 2; } else { const indexArray: LineIndexArray = (arrays.indexArray: any); indexArray.emplaceBack(index, index + 1); - indexArray.emplaceBack(index + 1, index + 2); - indexArray.emplaceBack(index + 2, index + 3); - indexArray.emplaceBack(index + 3, index); + indexArray.emplaceBack(index + 1, index + 3); + indexArray.emplaceBack(index + 3, index + 2); + indexArray.emplaceBack(index + 2, index); segment.primitiveLength += 4; } @@ -655,7 +662,8 @@ class SymbolBucket implements Bucket { const endIndex = placedSymbol.vertexStartIndex + placedSymbol.numGlyphs * 4; for (let vertexIndex = placedSymbol.vertexStartIndex; vertexIndex < endIndex; vertexIndex += 4) { - this.text.indexArray.emplaceBack(vertexIndex, vertexIndex + 1, vertexIndex + 2); + // Counter-clockwise winding order: front-facing culling. + this.text.indexArray.emplaceBack(vertexIndex, vertexIndex + 2, vertexIndex + 1); this.text.indexArray.emplaceBack(vertexIndex + 1, vertexIndex + 2, vertexIndex + 3); } } @@ -715,7 +723,8 @@ class SymbolBucket implements Bucket { const placedIcon = this.icon.placedSymbolArray.get(i); if (placedIcon.numGlyphs) { const vertexIndex = placedIcon.vertexStartIndex; - this.icon.indexArray.emplaceBack(vertexIndex, vertexIndex + 1, vertexIndex + 2); + // Counter-clockwise winding order: front-facing culling. + this.icon.indexArray.emplaceBack(vertexIndex, vertexIndex + 2, vertexIndex + 1); this.icon.indexArray.emplaceBack(vertexIndex + 1, vertexIndex + 2, vertexIndex + 3); } } diff --git a/src/render/painter.js b/src/render/painter.js index cae8202c160..7041ab9bbde 100644 --- a/src/render/painter.js +++ b/src/render/painter.js @@ -199,8 +199,13 @@ class Painter { this.tileBorderIndexBuffer = context.createIndexBuffer(tileLineStripIndices); const quadTriangleIndices = new TriangleIndexArray(); - quadTriangleIndices.emplaceBack(0, 1, 2); - quadTriangleIndices.emplaceBack(2, 1, 3); + // ┌──────┐ + // │ 0 1 │ Counter-clockwise winding order: front-facing culling. + // │ │ Triangle 1: 0 => 2 => 1 + // │ 2 3 │ Triangle 2: 1 => 2 => 3 + // └──────┘ + quadTriangleIndices.emplaceBack(0, 2, 1); + quadTriangleIndices.emplaceBack(1, 2, 3); this.quadTriangleIndexBuffer = context.createIndexBuffer(quadTriangleIndices); const gl = this.context.gl; diff --git a/src/source/tile.js b/src/source/tile.js index ac54e9992df..7cdc09541f7 100644 --- a/src/source/tile.js +++ b/src/source/tile.js @@ -348,9 +348,12 @@ class Tile { maskedBoundsArray.emplaceBack(brVertex.x, brVertex.y, brVertex.x, brVertex.y); const offset = segment.vertexLength; - // 0, 1, 2 - // 1, 2, 3 - indexArray.emplaceBack(offset, offset + 1, offset + 2); + // ┌──────┐ + // │ 0 1 │ Counter-clockwise winding order: front-facing culling. + // │ │ Triangle 1: 0 => 2 => 1 + // │ 2 3 │ Triangle 2: 1 => 2 => 3 + // └──────┘ + indexArray.emplaceBack(offset, offset + 2, offset + 1); indexArray.emplaceBack(offset + 1, offset + 2, offset + 3); segment.vertexLength += 4;