Skip to content

Commit

Permalink
feat(enhancement): Adds the depth buffer to the reflector component (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
emmelleppi authored Jan 31, 2021
1 parent 0271cb1 commit 1479f50
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 7 deletions.
3 changes: 3 additions & 0 deletions .storybook/stories/Reflector.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ function ReflectorScene() {
mirror={0.5}
rotation={[-Math.PI / 2, 0, Math.PI / 2]}
blur={[400, 100]}
minDepthThreshold={0.5}
maxDepthThreshold={1}
depthScale={1}
>
{(Material, props) => <Material color="#a0a0a0" metalness={0.5} normalScale={[1, 1]} {...props} />}
</Reflector>
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -621,6 +621,9 @@ Easily add reflections and/or blur to a planar surface. This reflector can also
resolution={256} // Off-buffer resolution, lower=faster, higher=better quality
args={[1, 1]} // PlaneBufferGeometry arguments
mirror={0.5} // Mirror environment, 0 = texture colors, 1 = pick up env colors
minDepthThreshold={0.5} // Lower edge for the depthTexture interpolation (default = 0)
maxDepthThreshold={1} // Upper edge for the depthTexture interpolation (default = 0)
depthScale={1} // Scale the depth factor (0 = no depth, default = 1)
>
{(Material, props) => <Material {...props}>}
</Reflector>
Expand Down
31 changes: 30 additions & 1 deletion src/core/Reflector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import {
Mesh,
LinearFilter,
WebGLRenderTarget,
DepthTexture,
DepthFormat,
UnsignedShortType,
} from 'three'
import { useFrame, useThree, extend } from 'react-three-fiber'
import { BlurPass } from '../materials/BlurPass'
Expand All @@ -23,6 +26,9 @@ export type ReflectorProps = Omit<JSX.IntrinsicElements['mesh'], 'args' | 'child
blur?: [number, number] | number
args?: [number, number]
mirror: number
minDepthThreshold?: number
maxDepthThreshold?: number
depthScale?: number
children: {
(
Component: React.ElementType<JSX.IntrinsicElements['meshReflectorMaterial']>,
Expand All @@ -47,6 +53,9 @@ export function Reflector({
resolution = 256,
blur = [0, 0],
args = [1, 1],
minDepthThreshold = 0,
maxDepthThreshold = 1,
depthScale = 1,
mirror,
children,
...props
Expand Down Expand Up @@ -127,19 +136,39 @@ export function Reflector({
encoding: gl.outputEncoding,
}
const fbo1 = new WebGLRenderTarget(resolution, resolution, parameters)
fbo1.depthBuffer = true
fbo1.depthTexture = new DepthTexture(resolution, resolution)
fbo1.depthTexture.format = DepthFormat
fbo1.depthTexture.type = UnsignedShortType
const fbo2 = new WebGLRenderTarget(resolution, resolution, parameters)
const blurpass = new BlurPass({ gl, resolution, width: blur[0], height: blur[1] })
const reflectorProps = {
mirror,
textureMatrix,
mixBlur,
tDiffuse: fbo1.texture,
tDepth: fbo1.depthTexture,
tDiffuseBlur: fbo2.texture,
hasBlur,
mixStrength,
minDepthThreshold,
maxDepthThreshold,
depthScale,
}
return [fbo1, fbo2, blurpass, reflectorProps]
}, [gl, blur, textureMatrix, resolution, mirror, hasBlur, mixBlur, mixStrength])
}, [
gl,
blur,
textureMatrix,
resolution,
mirror,
hasBlur,
mixBlur,
mixStrength,
minDepthThreshold,
maxDepthThreshold,
depthScale,
])

useFrame(() => {
meshRef.current.visible = false
Expand Down
62 changes: 56 additions & 6 deletions src/materials/ReflectorMaterial.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,17 @@ import { Matrix4, MeshStandardMaterial, Texture } from 'three'
type UninitializedUniform<Value> = { value: Value | null }

export class MeshReflectorMaterial extends MeshStandardMaterial {
private _tDepth: UninitializedUniform<Texture> = { value: null }
private _tDiffuse: UninitializedUniform<Texture> = { value: null }
private _tDiffuseBlur: UninitializedUniform<Texture> = { value: null }
private _textureMatrix: UninitializedUniform<Matrix4> = { value: null }
private _hasBlur: { value: boolean } = { value: false }
private _mirror: { value: number } = { value: 0.0 }
private _mixBlur: { value: number } = { value: 0.0 }
private _blurStrength: { value: number } = { value: 0.5 }
private _minDepthThreshold: { value: number } = { value: 0 }
private _maxDepthThreshold: { value: number } = { value: 1 }
private _depthScale: { value: number } = { value: 1 }

constructor(parameters = {}) {
super(parameters)
Expand All @@ -18,11 +22,15 @@ export class MeshReflectorMaterial extends MeshStandardMaterial {
onBeforeCompile(shader) {
shader.uniforms.hasBlur = this._hasBlur
shader.uniforms.tDiffuse = this._tDiffuse
shader.uniforms.tDepth = this._tDepth
shader.uniforms.tDiffuseBlur = this._tDiffuseBlur
shader.uniforms.textureMatrix = this._textureMatrix
shader.uniforms.mirror = this._mirror
shader.uniforms.mixBlur = this._mixBlur
shader.uniforms.mixStrength = this._blurStrength
shader.uniforms.minDepthThreshold = this._minDepthThreshold
shader.uniforms.maxDepthThreshold = this._maxDepthThreshold
shader.uniforms.depthScale = this._depthScale
shader.vertexShader = `
uniform mat4 textureMatrix;
varying vec4 my_vUv;
Expand All @@ -36,29 +44,44 @@ export class MeshReflectorMaterial extends MeshStandardMaterial {
shader.fragmentShader = `
uniform sampler2D tDiffuse;
uniform sampler2D tDiffuseBlur;
uniform sampler2D tDepth;
uniform float cameraNear;
uniform float cameraFar;
uniform bool hasBlur;
uniform float mixBlur;
uniform float mirror;
uniform float mixStrength;
varying vec4 my_vUv;
uniform float minDepthThreshold;
uniform float maxDepthThreshold;
uniform float depthScale;
varying vec4 my_vUv;
${shader.fragmentShader}`
shader.fragmentShader = shader.fragmentShader.replace(
'#include <emissivemap_fragment>',
`#include <emissivemap_fragment>
vec4 depth = texture2DProj(tDepth, my_vUv );
vec4 base = texture2DProj(tDiffuse, my_vUv);
vec4 blur = texture2DProj(tDiffuseBlur, my_vUv);
float depthFactor = smoothstep(minDepthThreshold, maxDepthThreshold, 1.0-(depth.r * depth.a));
depthFactor *= depthScale;
depthFactor = min(1.0, depthFactor);
float reflectorRoughnessFactor = roughness;
#ifdef USE_ROUGHNESSMAP
vec4 reflectorTexelRoughness = texture2D( roughnessMap, vUv );
reflectorRoughnessFactor *= reflectorTexelRoughness.g;
#endif
vec4 tColor = base;
vec4 merge = vec4(0.0,0.0,0.0,1.0);
if (hasBlur) {
float blurFactor = min(1.0, mixBlur * reflectorRoughnessFactor);
tColor = mix(base, blur, blurFactor);
merge = mix(merge, blur, min(1.0, mixBlur * reflectorRoughnessFactor));
}
diffuseColor.rgb = diffuseColor.rgb * (1.0 - min(1.0, mirror)) + tColor.rgb * mixStrength;
diffuseColor = sRGBToLinear(diffuseColor);`
merge += mix(merge, base, depthFactor);
diffuseColor.rgb = diffuseColor.rgb * ((1.0 - min(1.0, mirror)) + merge.rgb * mixStrength);
diffuseColor = sRGBToLinear(diffuseColor);
`
)
}
get tDiffuse(): Texture | null {
Expand All @@ -67,6 +90,12 @@ export class MeshReflectorMaterial extends MeshStandardMaterial {
set tDiffuse(v: Texture | null) {
this._tDiffuse.value = v
}
get tDepth(): Texture | null {
return this._tDepth.value
}
set tDepth(v: Texture | null) {
this._tDepth.value = v
}
get tDiffuseBlur(): Texture | null {
return this._tDiffuseBlur.value
}
Expand Down Expand Up @@ -103,6 +132,24 @@ export class MeshReflectorMaterial extends MeshStandardMaterial {
set mixStrength(v: number) {
this._blurStrength.value = v
}
get minDepthThreshold(): number {
return this._minDepthThreshold.value
}
set minDepthThreshold(v: number) {
this._minDepthThreshold.value = v
}
get maxDepthThreshold(): number {
return this._maxDepthThreshold.value
}
set maxDepthThreshold(v: number) {
this._maxDepthThreshold.value = v
}
get depthScale(): number {
return this._depthScale.value
}
set depthScale(v: number) {
this._depthScale.value = v
}
}

export type MeshReflectorMaterialImpl = {
Expand All @@ -113,4 +160,7 @@ export type MeshReflectorMaterialImpl = {
tDiffuse: Texture
tDiffuseBlur: Texture
hasBlur: boolean
minDepthThreshold: number
maxDepthThreshold: number
depthScale: number
} & JSX.IntrinsicElements['meshStandardMaterial']

1 comment on commit 1479f50

@vercel
Copy link

@vercel vercel bot commented on 1479f50 Jan 31, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.