-
Notifications
You must be signed in to change notification settings - Fork 719
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: Add ShadowAlpha * fix: Add note about artifacts in ShadowAlpha
- Loading branch information
1 parent
7dd1993
commit 6769989
Showing
4 changed files
with
183 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import * as React from 'react' | ||
|
||
import { Setup } from '../Setup' | ||
|
||
import { useFrame } from '@react-three/fiber' | ||
import { BufferGeometry, MeshStandardMaterial, type Mesh } from 'three' | ||
import { Icosahedron, Plane, ShadowAlpha } from '../../src' | ||
|
||
export default { | ||
title: 'Misc/ShadowAlpha', | ||
component: ShadowAlpha, | ||
decorators: [(storyFn) => <Setup lights={false}> {storyFn()}</Setup>], | ||
} | ||
|
||
function ShadowAlphaScene() { | ||
const mesh = React.useRef<Mesh<BufferGeometry, MeshStandardMaterial>>(null!) | ||
|
||
useFrame(({ clock }) => { | ||
const time = clock.elapsedTime | ||
mesh.current.material.opacity = Math.sin(time * 2) * 0.5 + 0.5 | ||
}) | ||
|
||
return ( | ||
<> | ||
<Icosahedron castShadow ref={mesh} args={[1, 2]} position-y={2}> | ||
<meshStandardMaterial color="lightblue" transparent /> | ||
<ShadowAlpha /> | ||
</Icosahedron> | ||
|
||
<Plane receiveShadow args={[4, 4]} rotation={[-Math.PI / 2, 0, 0]}> | ||
<meshStandardMaterial color="white" /> | ||
</Plane> | ||
|
||
<directionalLight castShadow position={[10, 40, 10]} /> | ||
<ambientLight intensity={0.5} /> | ||
</> | ||
) | ||
} | ||
|
||
export const ShadowAlphaSt = () => <ShadowAlphaScene /> | ||
ShadowAlphaSt.storyName = 'Default' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
/** | ||
* Integration and compilation: Faraz Shaikh (https://twitter.com/CantBeFaraz) | ||
* | ||
* Based on: | ||
* - https://gkjohnson.github.io/threejs-sandbox/screendoor-transparency/ by Garrett Johnson (https://github.com/gkjohnson) | ||
* | ||
* Note: | ||
* - Must depreciate in favor of https://github.com/mrdoob/three.js/issues/10600 when it's ready. | ||
*/ | ||
|
||
import { useFrame } from '@react-three/fiber' | ||
import * as React from 'react' | ||
import * as THREE from 'three' | ||
|
||
interface ShadowAlphaProps { | ||
opacity?: number | ||
alphaMap?: THREE.Texture | boolean | ||
} | ||
|
||
export function ShadowAlpha({ opacity, alphaMap }: ShadowAlphaProps) { | ||
const depthMaterialRef = React.useRef<THREE.MeshDepthMaterial>(null!) | ||
const distanceMaterialRef = React.useRef<THREE.MeshDistanceMaterial>(null!) | ||
|
||
const uShadowOpacity = React.useRef({ | ||
value: 1, | ||
}) | ||
|
||
const uAlphaMap = React.useRef({ | ||
value: null, | ||
}) | ||
|
||
const uHasAlphaMap = React.useRef({ | ||
value: false, | ||
}) | ||
|
||
React.useLayoutEffect(() => { | ||
depthMaterialRef.current.onBeforeCompile = distanceMaterialRef.current.onBeforeCompile = (shader) => { | ||
// Need to get the "void main" line dynamically because the lines for | ||
// MeshDistanceMaterial and MeshDepthMaterial are different 🤦♂️ | ||
const mainLineStart = shader.fragmentShader.indexOf('void main') | ||
let mainLine = '' | ||
let ch | ||
let i = mainLineStart | ||
while (ch !== '\n' && i < mainLineStart + 100) { | ||
ch = shader.fragmentShader.charAt(i) | ||
mainLine += ch | ||
i++ | ||
} | ||
mainLine = mainLine.trim() | ||
|
||
shader.vertexShader = shader.vertexShader.replace( | ||
'void main() {', | ||
` | ||
varying vec2 custom_vUv; | ||
void main() { | ||
custom_vUv = uv; | ||
` | ||
) | ||
|
||
shader.fragmentShader = shader.fragmentShader.replace( | ||
mainLine, | ||
` | ||
uniform float uShadowOpacity; | ||
uniform sampler2D uAlphaMap; | ||
uniform bool uHasAlphaMap; | ||
varying vec2 custom_vUv; | ||
float bayerDither2x2( vec2 v ) { | ||
return mod( 3.0 * v.y + 2.0 * v.x, 4.0 ); | ||
} | ||
float bayerDither4x4( vec2 v ) { | ||
vec2 P1 = mod( v, 2.0 ); | ||
vec2 P2 = mod( floor( 0.5 * v ), 2.0 ); | ||
return 4.0 * bayerDither2x2( P1 ) + bayerDither2x2( P2 ); | ||
} | ||
void main() { | ||
float alpha = | ||
uHasAlphaMap ? | ||
uShadowOpacity * texture2D(uAlphaMap, custom_vUv).x | ||
: uShadowOpacity; | ||
if( ( bayerDither4x4( floor( mod( gl_FragCoord.xy, 4.0 ) ) ) ) / 16.0 >= alpha ) discard; | ||
` | ||
) | ||
|
||
shader.uniforms['uShadowOpacity'] = uShadowOpacity.current | ||
shader.uniforms['uAlphaMap'] = uAlphaMap.current | ||
shader.uniforms['uHasAlphaMap'] = uHasAlphaMap.current | ||
} | ||
}, []) | ||
|
||
useFrame(() => { | ||
const parent = (depthMaterialRef.current as any).__r3f?.parent | ||
if (parent) { | ||
const parentMainMaterial = parent.material | ||
if (parentMainMaterial) { | ||
uShadowOpacity.current.value = opacity ?? parentMainMaterial.opacity | ||
|
||
if (alphaMap === false) { | ||
uAlphaMap.current.value = null | ||
uHasAlphaMap.current.value = false | ||
} else { | ||
uAlphaMap.current.value = alphaMap || parentMainMaterial.alphaMap | ||
uHasAlphaMap.current.value = !!uAlphaMap.current.value | ||
} | ||
} | ||
} | ||
}) | ||
|
||
return ( | ||
<> | ||
<meshDepthMaterial ref={depthMaterialRef} attach="customDepthMaterial" depthPacking={THREE.RGBADepthPacking} /> | ||
<meshDistanceMaterial ref={distanceMaterialRef} attach="customDistanceMaterial" /> | ||
</> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
6769989
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs:
drei – ./
drei-git-master-pmndrs.vercel.app
drei-pmndrs.vercel.app
drei.react-spring.io
drei.vercel.app
drei.pmnd.rs