1import { ExpoWebGLRenderingContext, GLView } from 'expo-gl'; 2import * as React from 'react'; 3import { StyleSheet, View } from 'react-native'; 4import { 5 AmbientLight, 6 BasicShadowMap, 7 BoxGeometry, 8 CameraHelper, 9 DirectionalLight, 10 DirectionalLightHelper, 11 DoubleSide, 12 Mesh, 13 MeshPhongMaterial, 14 MeshStandardMaterial, 15 PerspectiveCamera, 16 PlaneBufferGeometry, 17 Scene, 18 WebGLRenderer, 19} from 'three'; 20 21export default function GLThreeDepthStencilBuffer() { 22 const animationFrameId = React.useRef(-1); 23 24 React.useEffect(() => { 25 return () => { 26 if (animationFrameId.current >= 0) { 27 cancelAnimationFrame(animationFrameId.current); 28 } 29 }; 30 }, []); 31 32 const onContextCreate = React.useCallback(async (gl: ExpoWebGLRenderingContext) => { 33 const renderer = new WebGLRenderer({ 34 context: gl, 35 }); 36 renderer.shadowMap.enabled = true; 37 renderer.shadowMap.type = BasicShadowMap; 38 39 renderer.setSize(gl.drawingBufferWidth, gl.drawingBufferHeight); 40 renderer.setClearColor(0xffffff, 1.0); 41 renderer.shadowMap.enabled = true; 42 43 // Standard Camera 44 const camera = new PerspectiveCamera( 45 70, 46 gl.drawingBufferWidth / gl.drawingBufferHeight, 47 0.1, 48 1000 49 ); 50 camera.position.set(10, 10, 0); 51 camera.lookAt(0, 0, 0); 52 53 const scene = new Scene(); 54 55 scene.add(new AmbientLight(0xffffff, 0.5)); 56 57 // Three's lights use depth and stencil buffers. 58 const light = new DirectionalLight(0xffffff, 0.5); 59 light.position.set(0, 6, 0); 60 light.castShadow = true; 61 light.shadow.camera.left = -1; 62 light.shadow.camera.right = 1; 63 light.shadow.camera.top = -1; 64 light.shadow.camera.bottom = 1; 65 scene.add(light); 66 67 const shadowHelper = new DirectionalLightHelper(light, 2, 0x0000ff); 68 scene.add(shadowHelper); 69 70 // Create a plane that receives shadows (but does not cast them). 71 const planeGeometry = new PlaneBufferGeometry(10, 10, 32, 32); 72 const planeMaterial = new MeshStandardMaterial({ 73 color: 0x00ff00, 74 side: DoubleSide, 75 }); 76 77 const plane = new Mesh(planeGeometry, planeMaterial); 78 plane.receiveShadow = true; 79 plane.rotation.x = Math.PI / 2; 80 plane.position.y = -2; 81 scene.add(plane); 82 83 const cube = new Mesh( 84 new BoxGeometry(1.2, 1.2, 1.2), 85 new MeshPhongMaterial({ 86 color: 0xffff00, 87 }) 88 ); 89 cube.castShadow = true; 90 cube.receiveShadow = true; 91 cube.renderOrder = 3; 92 scene.add(cube); 93 94 const another = new Mesh( 95 new BoxGeometry(1.4, 1.4, 1.4), 96 new MeshPhongMaterial({ 97 color: 0xff0000, 98 }) 99 ); 100 another.position.set(0, 2, 0); 101 another.castShadow = true; 102 another.receiveShadow = true; 103 another.renderOrder = 1; 104 scene.add(another); 105 106 const helper = new CameraHelper(light.shadow.camera); 107 scene.add(helper); 108 109 const animate = () => { 110 animationFrameId.current = requestAnimationFrame(animate); 111 112 cube.rotation.x += 0.01; 113 cube.rotation.y += 0.01; 114 renderer.render(scene, camera); 115 gl.endFrameEXP(); 116 }; 117 118 animate(); 119 renderer.render(scene, camera); 120 gl.endFrameEXP(); 121 }, []); 122 123 return ( 124 <View style={styles.flex}> 125 <GLView style={styles.flex} onContextCreate={onContextCreate} /> 126 </View> 127 ); 128} 129 130GLThreeDepthStencilBuffer.title = 'three.js depth and stencil buffer'; 131 132const styles = StyleSheet.create({ 133 flex: { 134 flex: 1, 135 }, 136}); 137