0beqz / three-billboard-reflection

Performant plane reflections in three.js r139
MIT License
112 stars 11 forks source link

# Billboard Reflection Implements performant reflections for simple planes in three.js. \ \ The name derives from billboards for which this technique can ideally be used as seen in the Unreal Engine 3: Samaritan Demo. The benefit of this technique is that any mesh with any orientation can reflect these planes correctly. \ \

Installation

The build (UMD and module version) is located in the /dist directory.

Usage

import BillboardReflection from "./BillboardReflection"

let billboardReflection = new BillboardReflection()

billboardReflection.create(billboardMesh)
billboardReflection.create(otherBillboardMesh, options)

mesh.material.onBeforeCompile = shader => billboardReflection.enableReflection(shader)

This will make mesh reflect billboardMesh and otherBillboardMesh.

Options

Options for BillboardReflection.create(mesh, options)

Default values:

{
    rayFalloff: 0,
    color: undefined, // will use reflecting mesh's color if undefined
    opacity: undefined, // will use reflecting mesh's opacity if undefined
    visible: undefined // will use reflecting mesh's visibility if undefined
}

Description:


Options for BillboardReflection.enableReflection(shader, options)

Default values:

{
    roughnessMapBlur: true,
    roughnessMapBlurIntensity: 0.85,

    roughness: undefined, // will use reflecting mesh's roughness if undefined
    envMapIntensity: undefined // will use reflecting mesh's envMapIntensity if undefined
}

Description:

Reflection for just a texture and matrix

If your reflecting objects are not meshes (e.g. all billboards are batched into a single mesh) then you can use a texture and a matrix to create reflections for each billboard:

let position = new Vector3(1, 0, 0)
let rotation = new Quaternion().setFromEuler(new Euler(0, 1, 0))
let scale = new Vector3(1, 1, 1)

let matrix = new Matrix4().compose(position, rotation, scale)

billboardReflection.createFromTextureAndMatrix(texture, matrix)

This will give the same reflection as a mesh at the given position with the given rotation and scale.

Limitations

There are limitations regarding roughness and occlusion due to performance reasons.

Roughness

Proper roughness support is missing so reflections aren't blurred on rough surfaces but fade out. If there's a roughness map then blur is achieved through using low-res mipmaps of a billboard texture for rough spots which gives acceptable results when there aren't too many rough spots. This does not work for video textures as these don't have mipmaps.

If your material has a roughness map but you don't want to use blur, then you can have it toggled off like so:

material.onBeforeCompile = shader => billboardReflection.enableReflection(shader, { roughnessMapBlur: false })

This will now only make the reflection fade out for higher roughness values.

Occlusion

There's no occlusion check for reflections so they can be visible behind other meshes. This can be counteracted by giving these meshes reflections too or increasing the reflection's fallOff value.

References

Papers and articles

Slides

Credits

Algorithm

Demo Scene