Skip to content

Commit

Permalink
fix(troika-three-text): remove DoubleSide double draw hack in favor o…
Browse files Browse the repository at this point in the history
…f forceSinglePass flag
  • Loading branch information
lojjic committed Oct 12, 2024
1 parent 7f8c845 commit 7818d05
Show file tree
Hide file tree
Showing 5 changed files with 12 additions and 59 deletions.
14 changes: 7 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/troika-examples/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"react": "^16.14.0",
"react-dat-gui": "^4.0.0",
"react-dom": "^16.14.0",
"three": "^0.147.0",
"three": "^0.149.0",
"three-instanced-uniforms-mesh": "^0.50.0",
"three-line-2d": "^1.1.6",
"troika-2d": "^0.50.0",
Expand Down
35 changes: 1 addition & 34 deletions packages/troika-three-text/src/GlyphsGeometry.js
Original file line number Diff line number Diff line change
@@ -1,43 +1,17 @@
import {
Float32BufferAttribute,
BufferGeometry,
PlaneGeometry,
InstancedBufferGeometry,
InstancedBufferAttribute,
Sphere,
Box3,
DoubleSide,
BackSide,
} from 'three'

const templateGeometries = {}

function getTemplateGeometry(detail) {
let geom = templateGeometries[detail]
if (!geom) {
// Geometry is two planes back-to-back, which will always be rendered FrontSide only but
// appear as DoubleSide by default. FrontSide/BackSide are emulated using drawRange.
// We do it this way to avoid the performance hit of two draw calls for DoubleSide materials
// introduced by Three.js in r130 - see https://github.com/mrdoob/three.js/pull/21967
const front = new PlaneGeometry(1, 1, detail, detail)
const back = front.clone()
const frontAttrs = front.attributes
const backAttrs = back.attributes
const combined = new BufferGeometry()
const vertCount = frontAttrs.uv.count
for (let i = 0; i < vertCount; i++) {
backAttrs.position.array[i * 3] *= -1 // flip position x
backAttrs.normal.array[i * 3 + 2] *= -1 // flip normal z
}
['position', 'normal', 'uv'].forEach(name => {
combined.setAttribute(name, new Float32BufferAttribute(
[...frontAttrs[name].array, ...backAttrs[name].array],
frontAttrs[name].itemSize)
)
})
combined.setIndex([...front.index.array, ...back.index.array.map(n => n + vertCount)])
combined.translate(0.5, 0.5, 0)
geom = templateGeometries[detail] = combined
geom = templateGeometries[detail] = new PlaneGeometry(1, 1, detail, detail).translate(0.5, 0.5, 0)
}
return geom
}
Expand Down Expand Up @@ -103,13 +77,6 @@ class GlyphsGeometry extends InstancedBufferGeometry {
// No-op; we'll sync the boundingBox proactively when needed.
}

// Since our base geometry contains triangles for both front and back sides, we can emulate
// the "side" by restricting the draw range.
setSide(side) {
const verts = this.getIndex().count
this.setDrawRange(side === BackSide ? verts / 2 : 0, side === DoubleSide ? verts : verts / 2)
}

set detail(detail) {
if (detail !== this._detail) {
this._detail = detail
Expand Down
17 changes: 0 additions & 17 deletions packages/troika-three-text/src/Text.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import {
Color,
DoubleSide,
FrontSide,
Matrix4,
Mesh,
MeshBasicMaterial,
Expand Down Expand Up @@ -488,22 +487,6 @@ class Text extends Mesh {
if (material.isTroikaTextMaterial) {
this._prepareForRender(material)
}

// We need to force the material to FrontSide to avoid the double-draw-call performance hit
// introduced in Three.js r130: https://github.com/mrdoob/three.js/pull/21967 - The sidedness
// is instead applied via drawRange in the GlyphsGeometry.
material._hadOwnSide = material.hasOwnProperty('side')
this.geometry.setSide(material._actualSide = material.side)
material.side = FrontSide
}

onAfterRender(renderer, scene, camera, geometry, material, group) {
// Restore original material side
if (material._hadOwnSide) {
material.side = material._actualSide
} else {
delete material.side // back to inheriting from base material
}
}

/**
Expand Down
3 changes: 3 additions & 0 deletions packages/troika-three-text/src/TextDerivedMaterial.js
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,9 @@ export function createTextDerivedMaterial(baseMaterial) {
// Force transparency - TODO is this reasonable?
textMaterial.transparent = true

// Force single draw call when double-sided
textMaterial.forceSinglePass = true

Object.defineProperties(textMaterial, {
isTroikaTextMaterial: {value: true},

Expand Down

0 comments on commit 7818d05

Please sign in to comment.