1+ <!DOCTYPE html>
2+ < html lang ="en ">
3+ < head >
4+ < title > three.js webgpu - materials - bpcem</ title >
5+ < meta charset ="utf-8 ">
6+ < meta name ="viewport " content ="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0 ">
7+ < link type ="text/css " rel ="stylesheet " href ="main.css ">
8+ </ head >
9+ < body >
10+
11+ < div id ="info ">
12+ < a href ="https://threejs.org " target ="_blank " rel ="noopener "> three.js</ a > - webgpu - box projected cube environment mapping (BPCEM)< br />
13+ </ div >
14+
15+ < script type ="importmap ">
16+ {
17+ "imports" : {
18+ "three" : "../build/three.webgpu.js" ,
19+ "three/tsl" : "../build/three.webgpu.js" ,
20+ "three/addons/" : "./jsm/"
21+ }
22+ }
23+ </ script >
24+
25+
26+ < script type ="module ">
27+
28+ import * as THREE from 'three' ;
29+ import { bumpMap , float , getParallaxCorrectNormal , pmremTexture , reflectVector , texture , uniform , vec3 } from 'three/tsl' ;
30+
31+ import { GUI } from 'three/addons/libs/lil-gui.module.min.js' ;
32+ import { OrbitControls } from 'three/addons/controls/OrbitControls.js' ;
33+ import { RectAreaLightHelper } from 'three/addons/helpers/RectAreaLightHelper.js' ;
34+ import { RectAreaLightTexturesLib } from 'three/addons/lights/RectAreaLightTexturesLib.js' ;
35+
36+ let camera , scene , renderer ;
37+
38+ let controls , cubeCamera ;
39+
40+ let groundPlane , wallMat ;
41+
42+ init ( ) ;
43+
44+ function init ( ) {
45+
46+ THREE . RectAreaLightNode . setLTC ( RectAreaLightTexturesLib . init ( ) ) ;
47+
48+ // scene
49+
50+ scene = new THREE . Scene ( ) ;
51+
52+ // camera
53+
54+ camera = new THREE . PerspectiveCamera ( 45 , window . innerWidth / window . innerHeight , 0.1 , 1000 ) ;
55+ camera . position . set ( 0 , 200 , - 200 ) ;
56+
57+ // cube camera for environment map
58+
59+ const renderTarget = new THREE . WebGLCubeRenderTarget ( 512 ) ;
60+ renderTarget . texture . type = THREE . HalfFloatType ;
61+ renderTarget . texture . minFilter = THREE . LinearMipmapLinearFilter ;
62+ renderTarget . texture . magFilter = THREE . LinearFilter ;
63+ renderTarget . texture . generateMipmaps = true ;
64+ renderTarget . texture . mapping = THREE . CubeReflectionMapping ;
65+
66+ cubeCamera = new THREE . CubeCamera ( 1 , 1000 , renderTarget ) ;
67+ cubeCamera . position . set ( 0 , - 100 , 0 ) ;
68+
69+ // ground floor ( with box projected environment mapping )
70+
71+ const loader = new THREE . TextureLoader ( ) ;
72+ const rMap = loader . load ( 'textures/lava/lavatile.jpg' ) ;
73+ rMap . wrapS = THREE . RepeatWrapping ;
74+ rMap . wrapT = THREE . RepeatWrapping ;
75+ rMap . repeat . set ( 2 , 1 ) ;
76+
77+ const roughnessUniform = uniform ( 0.25 ) ;
78+
79+ const defaultMat = new THREE . MeshStandardNodeMaterial ( ) ;
80+ defaultMat . envNode = pmremTexture ( renderTarget . texture ) ;
81+ defaultMat . roughnessNode = texture ( rMap ) . mul ( roughnessUniform ) ;
82+ defaultMat . metalnessNode = float ( 1 ) ;
83+
84+ const boxProjectedMat = new THREE . MeshStandardNodeMaterial ( ) ;
85+ boxProjectedMat . envNode = pmremTexture ( renderTarget . texture , getParallaxCorrectNormal ( reflectVector , vec3 ( 200 , 100 , 100 ) , vec3 ( 0 , - 50 , 0 ) ) ) ;
86+ boxProjectedMat . roughnessNode = texture ( rMap ) . mul ( roughnessUniform ) ;
87+ boxProjectedMat . metalnessNode = float ( 1 ) ;
88+
89+ groundPlane = new THREE . Mesh ( new THREE . PlaneGeometry ( 200 , 100 , 100 ) , boxProjectedMat ) ;
90+ groundPlane . rotateX ( - Math . PI / 2 ) ;
91+ groundPlane . position . set ( 0 , - 49 , 0 ) ;
92+ scene . add ( groundPlane ) ;
93+
94+ // walls
95+
96+ const diffuseTex = loader . load ( 'textures/brick_diffuse.jpg' ) ;
97+ diffuseTex . colorSpace = THREE . SRGBColorSpace ;
98+ const bumpTex = loader . load ( 'textures/brick_bump.jpg' ) ;
99+
100+ wallMat = new THREE . MeshStandardNodeMaterial ( ) ;
101+
102+ wallMat . colorNode = texture ( diffuseTex ) ;
103+ wallMat . normalNode = bumpMap ( texture ( bumpTex ) , float ( 5 ) ) ;
104+
105+ const planeGeo = new THREE . PlaneGeometry ( 100 , 100 ) ;
106+
107+ const planeBack1 = new THREE . Mesh ( planeGeo , wallMat ) ;
108+ planeBack1 . position . z = - 50 ;
109+ planeBack1 . position . x = - 50 ;
110+ scene . add ( planeBack1 ) ;
111+
112+ const planeBack2 = new THREE . Mesh ( planeGeo , wallMat ) ;
113+ planeBack2 . position . z = - 50 ;
114+ planeBack2 . position . x = 50 ;
115+ scene . add ( planeBack2 ) ;
116+
117+ const planeFront1 = new THREE . Mesh ( planeGeo , wallMat ) ;
118+ planeFront1 . position . z = 50 ;
119+ planeFront1 . position . x = - 50 ;
120+ planeFront1 . rotateY ( Math . PI ) ;
121+ scene . add ( planeFront1 ) ;
122+
123+ const planeFront2 = new THREE . Mesh ( planeGeo , wallMat ) ;
124+ planeFront2 . position . z = 50 ;
125+ planeFront2 . position . x = 50 ;
126+ planeFront2 . rotateY ( Math . PI ) ;
127+ scene . add ( planeFront2 ) ;
128+
129+ const planeRight = new THREE . Mesh ( planeGeo , wallMat ) ;
130+ planeRight . position . x = 100 ;
131+ planeRight . rotateY ( - Math . PI / 2 ) ;
132+ scene . add ( planeRight ) ;
133+
134+ const planeLeft = new THREE . Mesh ( planeGeo , wallMat ) ;
135+ planeLeft . position . x = - 100 ;
136+ planeLeft . rotateY ( Math . PI / 2 ) ;
137+ scene . add ( planeLeft ) ;
138+
139+ // area lights
140+
141+ const width = 50 ;
142+ const height = 50 ;
143+ const intensity = 5 ;
144+
145+ const blueRectLight = new THREE . RectAreaLight ( 0x9aaeff , intensity , width , height ) ;
146+ blueRectLight . position . set ( - 99 , 5 , 0 ) ;
147+ blueRectLight . lookAt ( 0 , 5 , 0 ) ;
148+ scene . add ( blueRectLight ) ;
149+
150+ const blueRectLightHelper = new RectAreaLightHelper ( blueRectLight , 0xffffff ) ;
151+ blueRectLight . add ( blueRectLightHelper ) ;
152+
153+ const redRectLight = new THREE . RectAreaLight ( 0xf3aaaa , intensity , width , height ) ;
154+ redRectLight . position . set ( 99 , 5 , 0 ) ;
155+ redRectLight . lookAt ( 0 , 5 , 0 ) ;
156+ scene . add ( redRectLight ) ;
157+
158+ const redRectLightHelper = new RectAreaLightHelper ( redRectLight , 0xffffff ) ;
159+ redRectLight . add ( redRectLightHelper ) ;
160+
161+ // renderer
162+
163+ renderer = new THREE . WebGPURenderer ( { antialias : true } ) ;
164+ renderer . setPixelRatio ( window . devicePixelRatio ) ;
165+ renderer . setSize ( window . innerWidth , window . innerHeight ) ;
166+ renderer . setAnimationLoop ( animate ) ;
167+ document . body . appendChild ( renderer . domElement ) ;
168+
169+ window . addEventListener ( 'resize' , onWindowResize ) ;
170+
171+ // controls
172+
173+ controls = new OrbitControls ( camera , renderer . domElement ) ;
174+ controls . target . set ( 0 , - 10 , 0 ) ;
175+ controls . maxDistance = 400 ;
176+ controls . minDistance = 10 ;
177+ controls . update ( ) ;
178+
179+ // gui
180+
181+ const gui = new GUI ( ) ;
182+ const params = {
183+ 'box projected' : true
184+ } ;
185+ gui . add ( params , 'box projected' ) . onChange ( ( value ) => {
186+
187+ groundPlane . material = ( value ) ? boxProjectedMat : defaultMat ;
188+
189+ } ) ;
190+ gui . add ( roughnessUniform , 'value' , 0 , 1 ) . name ( 'roughness' ) ;
191+
192+ }
193+
194+ function onWindowResize ( ) {
195+
196+ camera . aspect = window . innerWidth / window . innerHeight ;
197+ camera . updateProjectionMatrix ( ) ;
198+
199+ renderer . setSize ( window . innerWidth , window . innerHeight ) ;
200+
201+ }
202+
203+ function updateCubeMap ( ) {
204+
205+ groundPlane . visible = false ;
206+
207+ cubeCamera . position . copy ( groundPlane . position ) ;
208+
209+ cubeCamera . update ( renderer , scene ) ;
210+
211+ groundPlane . visible = true ;
212+
213+ }
214+
215+ function animate ( ) {
216+
217+ updateCubeMap ( ) ;
218+
219+ renderer . render ( scene , camera ) ;
220+
221+ }
222+
223+ </ script >
224+
225+ </ body >
226+ </ html >
0 commit comments