|
28 | 28 | import * as THREE from 'three'; |
29 | 29 | import { timerLocal, vec2, uv, texture, mix, checker, normalLocal, positionLocal, color, oscSine, attribute, MeshBasicNodeMaterial, PointsNodeMaterial, LineBasicNodeMaterial } from 'three/nodes'; |
30 | 30 |
|
31 | | - import { DDSLoader } from 'three/addons/loaders/DDSLoader.js'; |
| 31 | + import { KTX2Loader } from 'three/addons/loaders/KTX2Loader.js'; |
32 | 32 |
|
33 | 33 | import WebGPU from 'three/addons/capabilities/WebGPU.js'; |
34 | 34 | import WebGPURenderer from 'three/addons/renderers/webgpu/WebGPURenderer.js'; |
|
39 | 39 |
|
40 | 40 | init(); |
41 | 41 |
|
42 | | - function init() { |
| 42 | + async function init() { |
43 | 43 |
|
44 | 44 | if ( WebGPU.isAvailable() === false ) { |
45 | 45 |
|
|
55 | 55 | scene = new THREE.Scene(); |
56 | 56 | scene.background = new THREE.Color( 0x222222 ); |
57 | 57 |
|
| 58 | + // |
| 59 | + |
| 60 | + renderer = new WebGPURenderer( { requiredFeatures: [ 'texture-compression-bc', 'texture-compression-astc' ] } ); |
| 61 | + renderer.setPixelRatio( window.devicePixelRatio ); |
| 62 | + renderer.setSize( window.innerWidth, window.innerHeight ); |
| 63 | + renderer.setAnimationLoop( animate ); |
| 64 | + document.body.appendChild( renderer.domElement ); |
| 65 | + await renderer.init(); |
| 66 | + |
58 | 67 | // textures |
59 | 68 |
|
60 | 69 | const textureLoader = new THREE.TextureLoader(); |
|
67 | 76 | textureDisplace.wrapS = THREE.RepeatWrapping; |
68 | 77 | textureDisplace.wrapT = THREE.RepeatWrapping; |
69 | 78 |
|
70 | | - // compressed texture |
| 79 | + const ktxLoader = new KTX2Loader() |
| 80 | + .setTranscoderPath( 'jsm/libs/basis/' ) |
| 81 | + .detectSupport( renderer ); |
71 | 82 |
|
72 | | - const ddsLoader = new DDSLoader(); |
73 | | - const dxt5Texture = ddsLoader.load( './textures/compressed/explosion_dxt5_mip.dds' ); |
| 83 | + const ktxTexture = await ktxLoader.loadAsync( './textures/compressed/sample_uastc_zstd.ktx2' ); |
74 | 84 |
|
75 | 85 | // box mesh |
76 | 86 |
|
|
114 | 124 | const geometryPlane = new THREE.PlaneGeometry(); |
115 | 125 | const materialPlane = new MeshBasicNodeMaterial(); |
116 | 126 | materialPlane.colorNode = texture( createDataTexture() ).add( color( 0x0000FF ) ); |
117 | | - materialPlane.opacityNode = texture( dxt5Texture ).a; |
118 | 127 | materialPlane.transparent = true; |
119 | 128 |
|
120 | 129 | const plane = new THREE.Mesh( geometryPlane, materialPlane ); |
|
124 | 133 | // compressed texture |
125 | 134 |
|
126 | 135 | const materialCompressed = new MeshBasicNodeMaterial(); |
127 | | - materialCompressed.colorNode = texture( dxt5Texture ); |
| 136 | + materialCompressed.colorNode = texture( ktxTexture ); |
128 | 137 | materialCompressed.emissiveNode = oscSine().mix( color( 0x663300 ), color( 0x0000FF ) ); |
129 | 138 | materialCompressed.alphaTestNode = oscSine(); |
130 | 139 | materialCompressed.transparent = true; |
131 | 140 |
|
132 | | - const boxCompressed = new THREE.Mesh( geometryBox, materialCompressed ); |
133 | | - boxCompressed.position.set( - 2, 1, 0 ); |
134 | | - scene.add( boxCompressed ); |
| 141 | + const geo = flipY( new THREE.PlaneGeometry() ); |
| 142 | + const planeCompressed = new THREE.Mesh( geo, materialCompressed ); |
| 143 | + planeCompressed.position.set( - 2, 1, 0 ); |
| 144 | + scene.add( planeCompressed ); |
135 | 145 |
|
136 | 146 | // points |
137 | 147 |
|
|
171 | 181 | line.position.set( 2, 1, 0 ); |
172 | 182 | scene.add( line ); |
173 | 183 |
|
174 | | - // |
175 | | - |
176 | | - renderer = new WebGPURenderer( { requiredFeatures: [ 'texture-compression-bc' ] } ); |
177 | | - renderer.setPixelRatio( window.devicePixelRatio ); |
178 | | - renderer.setSize( window.innerWidth, window.innerHeight ); |
179 | | - renderer.setAnimationLoop( animate ); |
180 | | - document.body.appendChild( renderer.domElement ); |
181 | | - |
182 | 184 | window.addEventListener( 'resize', onWindowResize ); |
183 | 185 |
|
184 | 186 | } |
|
194 | 196 |
|
195 | 197 | function animate() { |
196 | 198 |
|
197 | | - box.rotation.x += 0.01; |
198 | | - box.rotation.y += 0.02; |
| 199 | + if ( box ) { |
| 200 | + |
| 201 | + box.rotation.x += 0.01; |
| 202 | + box.rotation.y += 0.02; |
| 203 | + |
| 204 | + } |
199 | 205 |
|
200 | 206 | renderer.render( scene, camera ); |
201 | 207 |
|
|
232 | 238 |
|
233 | 239 | } |
234 | 240 |
|
| 241 | + /** Correct UVs to be compatible with `flipY=false` textures. */ |
| 242 | + function flipY( geometry ) { |
| 243 | + |
| 244 | + const uv = geometry.attributes.uv; |
| 245 | + |
| 246 | + for ( let i = 0; i < uv.count; i ++ ) { |
| 247 | + |
| 248 | + uv.setY( i, 1 - uv.getY( i ) ); |
| 249 | + |
| 250 | + } |
| 251 | + |
| 252 | + return geometry; |
| 253 | + |
| 254 | + } |
| 255 | + |
235 | 256 | </script> |
236 | 257 | </body> |
237 | 258 | </html> |
0 commit comments