Skip to content

Commit

Permalink
feat(troika-3d-ui): enable shadow casting by UI block bg/border layers
Browse files Browse the repository at this point in the history
  • Loading branch information
lojjic committed Mar 14, 2020
1 parent 294f341 commit d2c056c
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 13 deletions.
12 changes: 6 additions & 6 deletions packages/troika-3d-ui/src/facade/UIBlock3DFacade.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,8 @@ class UIBlock3DFacade extends Group3DFacade {
bgLayer.clipRect = _clipRectVec4
bgLayer.depthOffset = -flexNodeDepth
bgLayer.renderOrder = flexNodeDepth //TODO how can we make this play with the rest of the scene?
// bgLayer.castShadow = this.castShadow
// bgLayer.receiveShadow = this.receiveShadow
bgLayer.castShadow = this.castShadow
bgLayer.receiveShadow = this.receiveShadow
}
layers.children[0] = bgLayer

Expand All @@ -150,8 +150,8 @@ class UIBlock3DFacade extends Group3DFacade {
borderLayer.clipRect = _clipRectVec4
borderLayer.depthOffset = -flexNodeDepth - 1
borderLayer.renderOrder = flexNodeDepth + 0.1 //TODO how can we make this play with the rest of the scene?
// borderLayer.castShadow = this.castShadow
// borderLayer.receiveShadow = this.receiveShadow
borderLayer.castShadow = this.castShadow
borderLayer.receiveShadow = this.receiveShadow
}
layers.children[1] = borderLayer

Expand Down Expand Up @@ -189,8 +189,8 @@ class UIBlock3DFacade extends Group3DFacade {
textChild.material = this.textMaterial
textChild.depthOffset = -flexNodeDepth - 1
textChild.renderOrder = flexNodeDepth + 0.2
// textChild.castShadow = this.castShadow
// textChild.receiveShadow = this.receiveShadow
textChild.castShadow = this.castShadow
textChild.receiveShadow = this.receiveShadow
this.children = textChild //NOTE: text content will clobber any other defined children
} else {
// Convert any children specified as plain strings to nested text blocks; handy for JSX style
Expand Down
32 changes: 26 additions & 6 deletions packages/troika-3d-ui/src/facade/UIBlockLayer3DFacade.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,19 @@ const geometry = new PlaneBufferGeometry(1, 1).translate(0.5, -0.5, 0)
const defaultBgMaterial = new MeshBasicMaterial({color: 0})
const noclip = Object.freeze(new Vector4())

const shadowMaterialPropDefs = {
// Create and update materials for shadows upon request:
customDepthMaterial: {
get() {
return this.$facade._updateLayoutUniforms(this.material.getDepthMaterial())
}
},
customDistanceMaterial: {
get() {
return this.$facade._updateLayoutUniforms(this.material.getDistanceMaterial())
}
}
}

/**
* A single layer in a UI Block's rendering, e.g. background or border. All layers honor
Expand All @@ -18,6 +31,8 @@ class UIBlockLayer3DFacade extends Object3DFacade {
constructor(parent) {
const mesh = new Mesh(geometry, defaultBgMaterial)
mesh.frustumCulled = false //TODO moot if we make this an Instanceable, otherwise need to fix culling by transformed size
Object.defineProperties(mesh, shadowMaterialPropDefs)

super(parent, mesh)

this._colorObj = new Color()
Expand All @@ -41,19 +56,24 @@ class UIBlockLayer3DFacade extends Object3DFacade {
layerMaterial.polygonOffsetFactor = layerMaterial.polygonOffsetUnits = this.depthOffset || 0

// Set material uniform values
this._updateLayoutUniforms(layerMaterial)
if (color !== this._lastColor) {
this._colorObj.set(color)
this._lastColor = color
}

super.afterUpdate()
}

_updateLayoutUniforms(layerMaterial) {
const uniforms = layerMaterial.uniforms
uniforms.uTroikaBlockSize.value = this.size
uniforms.uTroikaCornerRadii.value = this.borderRadius
uniforms.uTroikaClipRect.value = this.clipRect || noclip
if (this.isBorder) {
uniforms.uTroikaBorderWidth.value = this.borderWidth
}
if (color !== this._lastColor) {
this._colorObj.set(color)
this._lastColor = color
}

super.afterUpdate()
return layerMaterial
}

getBoundingSphere() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,9 +133,16 @@ export function createUIBlockLayerDerivedMaterial(baseMaterial, isBorder) {
fragmentColorTransform: FRAGMENT_COLOR_TRANSFORM
})

// WebGLShadowMap reverses the side of the shadow material by default, which fails
// for planes, so here we force the `shadowSide` to always match the main side.
Object.defineProperty(material, 'shadowSide', {
get() {
return this.side
}
})

//force transparency - TODO is this reasonable?
material.transparent = true

return material
}
}

0 comments on commit d2c056c

Please sign in to comment.