diff --git a/examples/jsm/environments/RoomEnvironment.js b/examples/jsm/environments/RoomEnvironment.js index d22ddaf96ce86d..49867cd77eadd9 100644 --- a/examples/jsm/environments/RoomEnvironment.js +++ b/examples/jsm/environments/RoomEnvironment.js @@ -37,6 +37,7 @@ class RoomEnvironment extends Scene { super(); this.name = 'RoomEnvironment'; + this.position.y = - 3.5; const geometry = new BoxGeometry(); geometry.deleteAttribute( 'uv' ); diff --git a/examples/jsm/shaders/SSRShader.js b/examples/jsm/shaders/SSRShader.js index b124228eae5fb7..193bc3baf7ce2f 100644 --- a/examples/jsm/shaders/SSRShader.js +++ b/examples/jsm/shaders/SSRShader.js @@ -96,7 +96,7 @@ const SSRShader = { float x0=point.x,y0=point.y,z0=point.z; float x=planePoint.x,y=planePoint.y,z=planePoint.z; float d=-(a*x+b*y+c*z); - float distance=(a*x0+b*y0+c*z0+d)/sqrt(a*a+b*b+c*c); + float distance=a*x0+b*y0+c*z0+d; return distance; } float getDepth( const in vec2 uv ) { @@ -170,17 +170,17 @@ const SSRShader = { #endif d1=viewPositionToXY(d1viewPosition); - float totalLen=length(d1-d0); float xLen=d1.x-d0.x; float yLen=d1.y-d0.y; float totalStep=max(abs(xLen),abs(yLen)); float xSpan=xLen/totalStep; float ySpan=yLen/totalStep; - for(float i=0.;i=totalStep) break; vec2 xy=vec2(d0.x+i*xSpan,d0.y+i*ySpan); if(xy.x<0.||xy.x>resolution.x||xy.y<0.||xy.y>resolution.y) break; - float s=length(xy-d0)/totalLen; vec2 uv=xy/resolution; float d = getDepth(uv); @@ -221,7 +221,7 @@ const SSRShader = { if(hit){ vec3 vN=getViewNormal( uv ); - if(dot(viewReflectDir,vN)>=0.) continue; + if(dot(viewReflectDir,vN)>=0.) break; // treat backfaces as opaque float distance=pointPlaneDistance(vP,viewPosition,viewNormal); if(distance>maxDistance) break; float op=opacity; @@ -240,6 +240,7 @@ const SSRShader = { break; } } + s+=sStep; } } ` diff --git a/examples/jsm/tsl/display/SSRNode.js b/examples/jsm/tsl/display/SSRNode.js index b7696ea5893915..52eb39769492e4 100644 --- a/examples/jsm/tsl/display/SSRNode.js +++ b/examples/jsm/tsl/display/SSRNode.js @@ -1,5 +1,5 @@ import { HalfFloatType, RenderTarget, Vector2, RendererUtils, QuadMesh, TempNode, NodeMaterial, NodeUpdateType, LinearFilter, LinearMipmapLinearFilter } from 'three/webgpu'; -import { texture, reference, viewZToPerspectiveDepth, logarithmicDepthToViewZ, getScreenPosition, getViewPosition, sqrt, mul, div, cross, float, Continue, Break, Loop, int, max, abs, sub, If, dot, reflect, normalize, screenCoordinate, nodeObject, Fn, passTexture, uv, uniform, perspectiveDepthToViewZ, orthographicDepthToViewZ, vec2, vec3, vec4 } from 'three/tsl'; +import { texture, reference, viewZToPerspectiveDepth, logarithmicDepthToViewZ, getScreenPosition, getViewPosition, mul, div, cross, float, Break, Loop, int, max, abs, sub, If, dot, reflect, normalize, screenCoordinate, nodeObject, Fn, passTexture, uv, uniform, perspectiveDepthToViewZ, orthographicDepthToViewZ, vec2, vec3, vec4 } from 'three/tsl'; import { boxBlur } from './boxBlur.js'; const _quadMesh = /*@__PURE__*/ new QuadMesh(); @@ -400,9 +400,7 @@ class SSRNode extends TempNode { // http://paulbourke.net/geometry/pointlineplane/ const d = mul( planeNormal.x, planePoint.x ).add( mul( planeNormal.y, planePoint.y ) ).add( mul( planeNormal.z, planePoint.z ) ).negate().toVar(); - - const denominator = sqrt( mul( planeNormal.x, planeNormal.x, ).add( mul( planeNormal.y, planeNormal.y ) ).add( mul( planeNormal.z, planeNormal.z ) ) ).toVar(); - const distance = div( mul( planeNormal.x, point.x ).add( mul( planeNormal.y, point.y ) ).add( mul( planeNormal.z, point.z ) ).add( d ), denominator ); + const distance = mul( planeNormal.x, point.x ).add( mul( planeNormal.y, point.y ) ).add( mul( planeNormal.z, point.z ) ).add( d ); return distance; } ); @@ -481,9 +479,6 @@ class SSRNode extends TempNode { // below variables are used to control the raymarching process - // total length of the ray - const totalLen = d1.sub( d0 ).length().toVar(); - // offset in x and y direction const xLen = d1.x.sub( d0.x ).toVar(); const yLen = d1.y.sub( d0.y ).toVar(); @@ -491,7 +486,9 @@ class SSRNode extends TempNode { // determine the larger delta // The larger difference will help to determine how much to travel in the X and Y direction each iteration and // how many iterations are needed to travel the entire ray - const totalStep = int( max( abs( xLen ), abs( yLen ) ).mul( this.quality.clamp() ) ).toConst(); + // scale step count by distance - distant surfaces need less precision (0.5 to 1.0 multiplier) + const distanceFactor = float( 1 ).sub( depth.mul( 0.5 ) ).clamp( 0.5, 1 ); + const totalStep = int( max( abs( xLen ), abs( yLen ) ).mul( this.quality.clamp() ).mul( distanceFactor ) ).toConst(); // step sizes in the x and y directions const xSpan = xLen.div( totalStep ).toVar(); @@ -499,10 +496,14 @@ class SSRNode extends TempNode { const output = vec4( 0 ).toVar(); + // incremental interpolation factor + const sStep = float( 1 ).div( float( totalStep ) ); + const s = sStep.toVar(); // start at sStep since loop starts at i=1 + // the actual ray marching loop // starting from d0, the code gradually travels along the ray and looks for an intersection with the geometry. // it does not exceed d1 (the maximum ray extend) - Loop( totalStep, ( { i } ) => { + Loop( { start: int( 1 ), end: totalStep }, ( { i } ) => { // advance on the ray by computing a new position in screen coordinates const xy = vec2( d0.x.add( xSpan.mul( float( i ) ) ), d0.y.add( ySpan.mul( float( i ) ) ) ).toVar(); @@ -521,9 +522,6 @@ class SSRNode extends TempNode { const viewReflectRayZ = float( 0 ).toVar(); - // normalized distance between the current position xy and the starting point d0 - const s = xy.sub( d0 ).length().div( totalLen ); - // depending on the camera type, we now compute the z-coordinate of the reflected ray at the current step in view space If( this._isPerspectiveCamera, () => { @@ -559,9 +557,9 @@ class SSRNode extends TempNode { If( dot( viewReflectDir, vN ).greaterThanEqual( 0 ), () => { - // the reflected ray is pointing towards the same side as the fragment's normal (current ray position), - // which means it wouldn't reflect off the surface. The loop continues to the next step for the next ray sample. - Continue(); + // the reflected ray is hitting a backface (normal pointing away from ray), + // treat as opaque surface that blocks the ray + Break(); } ); @@ -596,6 +594,9 @@ class SSRNode extends TempNode { } ); + // advance interpolation factor + s.addAssign( sStep ); + } ); return output; diff --git a/examples/screenshots/misc_exporter_usdz.jpg b/examples/screenshots/misc_exporter_usdz.jpg index e9f0d1a2c9d866..f690c9bc6d3279 100644 Binary files a/examples/screenshots/misc_exporter_usdz.jpg and b/examples/screenshots/misc_exporter_usdz.jpg differ diff --git a/examples/screenshots/webgl_animation_keyframes.jpg b/examples/screenshots/webgl_animation_keyframes.jpg index 81643d66685710..94bf61cb3cb57e 100644 Binary files a/examples/screenshots/webgl_animation_keyframes.jpg and b/examples/screenshots/webgl_animation_keyframes.jpg differ diff --git a/examples/screenshots/webgl_batch_lod_bvh.jpg b/examples/screenshots/webgl_batch_lod_bvh.jpg index d093f594a84b8e..14c5780a879ef8 100644 Binary files a/examples/screenshots/webgl_batch_lod_bvh.jpg and b/examples/screenshots/webgl_batch_lod_bvh.jpg differ diff --git a/examples/screenshots/webgl_instancing_dynamic.jpg b/examples/screenshots/webgl_instancing_dynamic.jpg index c10413c0357a56..2ad100785a0c66 100644 Binary files a/examples/screenshots/webgl_instancing_dynamic.jpg and b/examples/screenshots/webgl_instancing_dynamic.jpg differ diff --git a/examples/screenshots/webgl_loader_gltf_animation_pointer.jpg b/examples/screenshots/webgl_loader_gltf_animation_pointer.jpg index 4cfac22861e0f9..b938a4b8f7a03d 100644 Binary files a/examples/screenshots/webgl_loader_gltf_animation_pointer.jpg and b/examples/screenshots/webgl_loader_gltf_animation_pointer.jpg differ diff --git a/examples/screenshots/webgl_loader_gltf_compressed.jpg b/examples/screenshots/webgl_loader_gltf_compressed.jpg index a3292fb4e72d3a..e9544d2a342556 100644 Binary files a/examples/screenshots/webgl_loader_gltf_compressed.jpg and b/examples/screenshots/webgl_loader_gltf_compressed.jpg differ diff --git a/examples/screenshots/webgl_loader_gltf_dispersion.jpg b/examples/screenshots/webgl_loader_gltf_dispersion.jpg index 4726be47eacd31..acd494db41735e 100644 Binary files a/examples/screenshots/webgl_loader_gltf_dispersion.jpg and b/examples/screenshots/webgl_loader_gltf_dispersion.jpg differ diff --git a/examples/screenshots/webgl_loader_gltf_sheen.jpg b/examples/screenshots/webgl_loader_gltf_sheen.jpg index 5e4f72b50a1a5f..db3459be454004 100644 Binary files a/examples/screenshots/webgl_loader_gltf_sheen.jpg and b/examples/screenshots/webgl_loader_gltf_sheen.jpg differ diff --git a/examples/screenshots/webgl_loader_ldraw.jpg b/examples/screenshots/webgl_loader_ldraw.jpg index 54fa76e1c98871..b055c6f2068225 100644 Binary files a/examples/screenshots/webgl_loader_ldraw.jpg and b/examples/screenshots/webgl_loader_ldraw.jpg differ diff --git a/examples/screenshots/webgl_loader_texture_lottie.jpg b/examples/screenshots/webgl_loader_texture_lottie.jpg index 2a84713143b904..13d731db3a1b9f 100644 Binary files a/examples/screenshots/webgl_loader_texture_lottie.jpg and b/examples/screenshots/webgl_loader_texture_lottie.jpg differ diff --git a/examples/screenshots/webgl_materials_alphahash.jpg b/examples/screenshots/webgl_materials_alphahash.jpg index 2c401565f7eb54..196a7af6c089f2 100644 Binary files a/examples/screenshots/webgl_materials_alphahash.jpg and b/examples/screenshots/webgl_materials_alphahash.jpg differ diff --git a/examples/screenshots/webgl_morphtargets_face.jpg b/examples/screenshots/webgl_morphtargets_face.jpg index 44edc24ad692ce..e3fce3fcdfbd25 100644 Binary files a/examples/screenshots/webgl_morphtargets_face.jpg and b/examples/screenshots/webgl_morphtargets_face.jpg differ diff --git a/examples/screenshots/webgl_morphtargets_webcam.jpg b/examples/screenshots/webgl_morphtargets_webcam.jpg index 7377236c1786a8..d7c8f263cb9f34 100644 Binary files a/examples/screenshots/webgl_morphtargets_webcam.jpg and b/examples/screenshots/webgl_morphtargets_webcam.jpg differ diff --git a/examples/screenshots/webgl_postprocessing_unreal_bloom_selective.jpg b/examples/screenshots/webgl_postprocessing_unreal_bloom_selective.jpg index a958904e9d5bef..a64a3f4d388fb8 100644 Binary files a/examples/screenshots/webgl_postprocessing_unreal_bloom_selective.jpg and b/examples/screenshots/webgl_postprocessing_unreal_bloom_selective.jpg differ diff --git a/examples/screenshots/webgpu_instance_path.jpg b/examples/screenshots/webgpu_instance_path.jpg index 6ffd97a4772f5c..e1305e868e6aa5 100644 Binary files a/examples/screenshots/webgpu_instance_path.jpg and b/examples/screenshots/webgpu_instance_path.jpg differ diff --git a/examples/screenshots/webgpu_materials_alphahash.jpg b/examples/screenshots/webgpu_materials_alphahash.jpg index af5618cd7d5f96..1839c5fde427bc 100644 Binary files a/examples/screenshots/webgpu_materials_alphahash.jpg and b/examples/screenshots/webgpu_materials_alphahash.jpg differ diff --git a/examples/screenshots/webgpu_morphtargets_face.jpg b/examples/screenshots/webgpu_morphtargets_face.jpg index 44edc24ad692ce..3468625cc7fea5 100644 Binary files a/examples/screenshots/webgpu_morphtargets_face.jpg and b/examples/screenshots/webgpu_morphtargets_face.jpg differ diff --git a/examples/screenshots/webgpu_postprocessing_ca.jpg b/examples/screenshots/webgpu_postprocessing_ca.jpg index a375e3ac38b9a7..f80e364de33e3b 100644 Binary files a/examples/screenshots/webgpu_postprocessing_ca.jpg and b/examples/screenshots/webgpu_postprocessing_ca.jpg differ diff --git a/examples/screenshots/webgpu_postprocessing_sobel.jpg b/examples/screenshots/webgpu_postprocessing_sobel.jpg index d8a1fcc6d0549e..21c674e1e8d21c 100644 Binary files a/examples/screenshots/webgpu_postprocessing_sobel.jpg and b/examples/screenshots/webgpu_postprocessing_sobel.jpg differ diff --git a/examples/screenshots/webgpu_postprocessing_ssr.jpg b/examples/screenshots/webgpu_postprocessing_ssr.jpg index 4edc959c18f853..dfd67848508591 100644 Binary files a/examples/screenshots/webgpu_postprocessing_ssr.jpg and b/examples/screenshots/webgpu_postprocessing_ssr.jpg differ diff --git a/examples/webgl_loader_gltf_compressed.html b/examples/webgl_loader_gltf_compressed.html index 49a70665841478..60212b77805cd4 100644 --- a/examples/webgl_loader_gltf_compressed.html +++ b/examples/webgl_loader_gltf_compressed.html @@ -59,7 +59,7 @@ scene = new THREE.Scene(); scene.background = new THREE.Color( 0xbbbbbb ); - scene.environment = pmremGenerator.fromScene( environment ).texture; + scene.environment = pmremGenerator.fromScene( environment, 0.04 ).texture; environment.dispose(); const grid = new THREE.GridHelper( 500, 10, 0xffffff, 0xffffff ); diff --git a/examples/webgl_loader_gltf_dispersion.html b/examples/webgl_loader_gltf_dispersion.html index 4e13a361c34e66..b059c119617d7a 100644 --- a/examples/webgl_loader_gltf_dispersion.html +++ b/examples/webgl_loader_gltf_dispersion.html @@ -56,7 +56,7 @@ scene = new THREE.Scene(); scene.backgroundBlurriness = 0.5; - const env = pmremGenerator.fromScene( environment ).texture; + const env = pmremGenerator.fromScene( environment, 0.04 ).texture; scene.background = env; scene.environment = env; environment.dispose(); diff --git a/examples/webgl_loader_gltf_sheen.html b/examples/webgl_loader_gltf_sheen.html index 277efc08a2213d..ed2b8dc08591a3 100644 --- a/examples/webgl_loader_gltf_sheen.html +++ b/examples/webgl_loader_gltf_sheen.html @@ -80,7 +80,7 @@ const pmremGenerator = new THREE.PMREMGenerator( renderer ); scene.background = new THREE.Color( 0xbbbbbb ); - scene.environment = pmremGenerator.fromScene( environment ).texture; + scene.environment = pmremGenerator.fromScene( environment, 0.04 ).texture; controls = new OrbitControls( camera, renderer.domElement ); controls.enableDamping = true; diff --git a/examples/webgl_loader_ldraw.html b/examples/webgl_loader_ldraw.html index 8a2e0d6f60b4db..49f1bf2b52c3cd 100644 --- a/examples/webgl_loader_ldraw.html +++ b/examples/webgl_loader_ldraw.html @@ -94,7 +94,7 @@ scene = new THREE.Scene(); scene.background = new THREE.Color( 0xdeebed ); - scene.environment = pmremGenerator.fromScene( new RoomEnvironment() ).texture; + scene.environment = pmremGenerator.fromScene( new RoomEnvironment(), 0.04 ).texture; controls = new OrbitControls( camera, renderer.domElement ); controls.enableDamping = true; diff --git a/examples/webgl_loader_texture_lottie.html b/examples/webgl_loader_texture_lottie.html index 017d3ff8b5ff26..32d62c8fe5c9e2 100644 --- a/examples/webgl_loader_texture_lottie.html +++ b/examples/webgl_loader_texture_lottie.html @@ -83,8 +83,8 @@ // texture = new THREE.TextureLoader().load( 'textures/uv_grid_directx.jpg' ); // texture.colorSpace = THREE.SRGBColorSpace; - const geometry = new RoundedBoxGeometry( 1, 1, 1, 7, 0.2 ); - const material = new THREE.MeshStandardMaterial( { roughness: 0.1, map: texture } ); + const geometry = new RoundedBoxGeometry( 1, 1, 1, 7, 0.1 ); + const material = new THREE.MeshStandardMaterial( { roughness: 0, map: texture } ); mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); @@ -94,12 +94,13 @@ renderer.setPixelRatio( window.devicePixelRatio ); renderer.setSize( window.innerWidth, window.innerHeight ); renderer.setAnimationLoop( animate ); + renderer.toneMapping = THREE.ACESFilmicToneMapping; document.body.appendChild( renderer.domElement ); const environment = new RoomEnvironment(); const pmremGenerator = new THREE.PMREMGenerator( renderer ); - scene.environment = pmremGenerator.fromScene( environment ).texture; + scene.environment = pmremGenerator.fromScene( environment, 0.04 ).texture; controls = new OrbitControls( camera, renderer.domElement ); controls.autoRotate = true; diff --git a/examples/webgl_materials_alphahash.html b/examples/webgl_materials_alphahash.html index dd79375a437d14..34f08bc67e998f 100644 --- a/examples/webgl_materials_alphahash.html +++ b/examples/webgl_materials_alphahash.html @@ -107,7 +107,7 @@ const environment = new RoomEnvironment(); const pmremGenerator = new THREE.PMREMGenerator( renderer ); - scene.environment = pmremGenerator.fromScene( environment ).texture; + scene.environment = pmremGenerator.fromScene( environment, 0.04 ).texture; environment.dispose(); // diff --git a/examples/webgl_morphtargets_face.html b/examples/webgl_morphtargets_face.html index 02b0c2b6ff0c78..f0c54250cc446f 100644 --- a/examples/webgl_morphtargets_face.html +++ b/examples/webgl_morphtargets_face.html @@ -106,7 +106,7 @@ const pmremGenerator = new THREE.PMREMGenerator( renderer ); scene.background = new THREE.Color( 0x666666 ); - scene.environment = pmremGenerator.fromScene( environment ).texture; + scene.environment = pmremGenerator.fromScene( environment, 0.04 ).texture; controls = new OrbitControls( camera, renderer.domElement ); controls.enableDamping = true; diff --git a/examples/webgl_morphtargets_webcam.html b/examples/webgl_morphtargets_webcam.html index a54f8fca03fd91..b2b7a403bc1588 100644 --- a/examples/webgl_morphtargets_webcam.html +++ b/examples/webgl_morphtargets_webcam.html @@ -32,7 +32,6 @@ import * as THREE from 'three'; import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; - import { RoomEnvironment } from 'three/addons/environments/RoomEnvironment.js'; import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'; import { KTX2Loader } from 'three/addons/loaders/KTX2Loader.js'; @@ -114,13 +113,10 @@ camera.position.z = 5; const scene = new THREE.Scene(); + scene.background = new THREE.Color( 0x666666 ); scene.scale.x = - 1; - const environment = new RoomEnvironment(); - const pmremGenerator = new THREE.PMREMGenerator( renderer ); - - scene.background = new THREE.Color( 0x666666 ); - scene.environment = pmremGenerator.fromScene( environment ).texture; + scene.add( new THREE.AmbientLight( 0xffffff, 5 ) ); const controls = new OrbitControls( camera, renderer.domElement ); @@ -144,6 +140,9 @@ const head = mesh.getObjectByName( 'mesh_2' ); head.material = new THREE.MeshNormalMaterial(); + const teeth = mesh.getObjectByName( 'mesh_3' ); + teeth.material = new THREE.MeshNormalMaterial(); + face = mesh.getObjectByName( 'mesh_2' ); eyeL = mesh.getObjectByName( 'eyeLeft' ); eyeR = mesh.getObjectByName( 'eyeRight' ); diff --git a/examples/webgpu_materials_alphahash.html b/examples/webgpu_materials_alphahash.html index 9a39df1db4c19c..da7f4df5a588ec 100644 --- a/examples/webgpu_materials_alphahash.html +++ b/examples/webgpu_materials_alphahash.html @@ -104,7 +104,7 @@ const environment = new RoomEnvironment(); const pmremGenerator = new THREE.PMREMGenerator( renderer ); - scene.environment = pmremGenerator.fromScene( environment ).texture; + scene.environment = pmremGenerator.fromScene( environment, 0.04 ).texture; environment.dispose(); // diff --git a/examples/webgpu_morphtargets_face.html b/examples/webgpu_morphtargets_face.html index 32bf76496a1415..e2da5449b117a8 100644 --- a/examples/webgpu_morphtargets_face.html +++ b/examples/webgpu_morphtargets_face.html @@ -69,7 +69,7 @@ const pmremGenerator = new THREE.PMREMGenerator( renderer ); scene.background = new THREE.Color( 0x666666 ); - scene.environment = pmremGenerator.fromScene( environment ).texture; + scene.environment = pmremGenerator.fromScene( environment, 0.04 ).texture; const ktx2Loader = await new KTX2Loader() .setTranscoderPath( 'jsm/libs/basis/' ) diff --git a/examples/webgpu_postprocessing_ao.html b/examples/webgpu_postprocessing_ao.html index 48ce5aa5ca6ccc..669aba98586583 100644 --- a/examples/webgpu_postprocessing_ao.html +++ b/examples/webgpu_postprocessing_ao.html @@ -96,7 +96,7 @@ const pmremGenerator = new THREE.PMREMGenerator( renderer ); scene.background = new THREE.Color( 0x666666 ); - scene.environment = pmremGenerator.fromScene( environment ).texture; + scene.environment = pmremGenerator.fromScene( environment, 0.04 ).texture; environment.dispose(); pmremGenerator.dispose(); diff --git a/examples/webgpu_postprocessing_sobel.html b/examples/webgpu_postprocessing_sobel.html index 80e5aa262be95c..2da8b33c62f16a 100644 --- a/examples/webgpu_postprocessing_sobel.html +++ b/examples/webgpu_postprocessing_sobel.html @@ -80,7 +80,7 @@ const environment = new RoomEnvironment(); const pmremGenerator = new THREE.PMREMGenerator( renderer ); - scene.environment = pmremGenerator.fromScene( environment ).texture; + scene.environment = pmremGenerator.fromScene( environment, 0.04 ).texture; pmremGenerator.dispose(); // diff --git a/examples/webgpu_postprocessing_ssr.html b/examples/webgpu_postprocessing_ssr.html index ef31aa7bf4a12a..3c0768d10102a9 100644 --- a/examples/webgpu_postprocessing_ssr.html +++ b/examples/webgpu_postprocessing_ssr.html @@ -120,7 +120,7 @@ const environment = new RoomEnvironment(); const pmremGenerator = new THREE.PMREMGenerator( renderer ); - scene.environment = pmremGenerator.fromScene( environment ).texture; + scene.environment = pmremGenerator.fromScene( environment, 0.04 ).texture; scene.environmentIntensity = 1.25; pmremGenerator.dispose(); diff --git a/package.json b/package.json index dd7e86801de452..c529453d42abe9 100644 --- a/package.json +++ b/package.json @@ -111,7 +111,6 @@ "puppeteer": "^24.25.0", "qunit": "^2.19.4", "rollup": "^4.6.0", - "rollup-plugin-filesize": "^10.0.0", "servez": "^2.2.4" }, "overrides": { diff --git a/src/core/Object3D.js b/src/core/Object3D.js index 6d71d16faa6696..c07fa3063ccf29 100644 --- a/src/core/Object3D.js +++ b/src/core/Object3D.js @@ -644,7 +644,7 @@ class Object3D extends EventDispatcher { } /** - * Converts the given vector from this 3D object's word space to local space. + * Converts the given vector from this 3D object's world space to local space. * * @param {Vector3} vector - The vector to convert. * @return {Vector3} The converted vector. diff --git a/test/e2e/puppeteer.js b/test/e2e/puppeteer.js index 466e802a678c35..0c8c12e1576273 100644 --- a/test/e2e/puppeteer.js +++ b/test/e2e/puppeteer.js @@ -1,9 +1,8 @@ import puppeteer from 'puppeteer'; -import express from 'express'; -import path from 'path'; import pixelmatch from 'pixelmatch'; import { Jimp } from 'jimp'; import * as fs from 'fs/promises'; +import server from './server.js'; const exceptionList = [ @@ -117,9 +116,7 @@ let browser; /* Launch server */ -const app = express(); -app.use( express.static( path.resolve() ) ); -const server = app.listen( port, main ); +server.listen( port, main ); process.on( 'SIGINT', async () => { diff --git a/test/e2e/server.js b/test/e2e/server.js new file mode 100644 index 00000000000000..c014058e6b3822 --- /dev/null +++ b/test/e2e/server.js @@ -0,0 +1,89 @@ +import http from 'http'; +import path from 'path'; +import { createReadStream, existsSync, statSync } from 'fs'; + +const mimeTypes = { + '.html': 'text/html', + '.js': 'application/javascript', + '.css': 'text/css', + '.json': 'application/json', + '.png': 'image/png', + '.jpg': 'image/jpeg', + '.gif': 'image/gif', + '.svg': 'image/svg+xml', + '.mp3': 'audio/mpeg', + '.mp4': 'video/mp4', + '.webm': 'video/webm', + '.ogv': 'video/ogg', + '.ogg': 'audio/ogg', + '.woff': 'font/woff', + '.woff2': 'font/woff2', + '.ttf': 'font/ttf', + '.glb': 'model/gltf-binary', + '.gltf': 'model/gltf+json', + '.hdr': 'application/octet-stream', + '.exr': 'application/octet-stream', + '.fbx': 'application/octet-stream', + '.bin': 'application/octet-stream', + '.cube': 'text/plain' +}; + +const rootDirectory = path.resolve(); + +const server = http.createServer( ( req, res ) => { + + const pathname = decodeURIComponent( req.url.split( '?' )[ 0 ] ); + const filePath = path.normalize( path.join( rootDirectory, pathname ) ); + + // Prevent path traversal attacks + if ( ! filePath.startsWith( rootDirectory ) ) { + + res.writeHead( 403 ); + res.end( 'Forbidden' ); + return; + + } + + if ( ! existsSync( filePath ) ) { + + res.writeHead( 404 ); + res.end( 'File not found' ); + return; + + } + + const ext = path.extname( filePath ).toLowerCase(); + const contentType = mimeTypes[ ext ] || 'application/octet-stream'; + const stat = statSync( filePath ); + const fileSize = stat.size; + const range = req.headers.range; + + if ( range ) { + + const parts = range.replace( /bytes=/, '' ).split( '-' ); + const start = parseInt( parts[ 0 ], 10 ); + const end = parts[ 1 ] ? parseInt( parts[ 1 ], 10 ) : fileSize - 1; + + res.writeHead( 206, { + 'Content-Range': `bytes ${start}-${end}/${fileSize}`, + 'Accept-Ranges': 'bytes', + 'Content-Length': end - start + 1, + 'Content-Type': contentType + } ); + + createReadStream( filePath, { start, end } ).pipe( res ); + + } else { + + res.writeHead( 200, { + 'Content-Length': fileSize, + 'Content-Type': contentType + } ); + + createReadStream( filePath ).pipe( res ); + + } + +} ); + +export default server; diff --git a/test/rollup.treeshake.config.js b/test/rollup.treeshake.config.js index 2c67f1660e74dc..dd70a3f39f71aa 100644 --- a/test/rollup.treeshake.config.js +++ b/test/rollup.treeshake.config.js @@ -1,7 +1,54 @@ +import { gzipSync } from 'zlib'; import resolve from '@rollup/plugin-node-resolve'; -import filesize from 'rollup-plugin-filesize'; import terser from '@rollup/plugin-terser'; +function filesize() { + + const green = '\x1b[1m\x1b[32m'; + const yellow = '\x1b[33m'; + const reset = '\x1b[0m'; + + return { + name: 'filesize', + writeBundle( options, bundle ) { + + for ( const [ , chunk ] of Object.entries( bundle ) ) { + + if ( chunk.code ) { + + const size = ( chunk.code.length / 1024 ).toFixed( 2 ) + ' KB'; + const gzipped = ( gzipSync( chunk.code ).length / 1024 ).toFixed( 2 ) + ' KB'; + const destination = options.file; + + const lines = [ + { label: 'Destination: ', value: destination }, + { label: 'Bundle Size: ', value: size }, + { label: 'Gzipped Size: ', value: gzipped } + ]; + + const maxLength = Math.max( ...lines.map( l => l.label.length + l.value.length ) ); + const width = maxLength + 6; + + console.log( `\n┌${'─'.repeat( width )}┐` ); + console.log( `│${' '.repeat( width )}│` ); + lines.forEach( ( { label, value } ) => { + + const padding = ' '.repeat( width - label.length - value.length - 3 ); + console.log( `│ ${green}${label}${yellow}${value}${reset}${padding}│` ); + + } ); + console.log( `│${' '.repeat( width )}│` ); + console.log( `└${'─'.repeat( width )}┘` ); + + } + + } + + } + }; + +} + export default [ { input: 'test/treeshake/index.js', @@ -20,9 +67,7 @@ export default [ plugins: [ resolve(), terser(), - filesize( { - showMinifiedSize: false, - } ) + filesize() ], output: [ { @@ -48,9 +93,7 @@ export default [ plugins: [ resolve(), terser(), - filesize( { - showMinifiedSize: false, - } ) + filesize() ], output: [ { @@ -76,9 +119,7 @@ export default [ plugins: [ resolve(), terser(), - filesize( { - showMinifiedSize: false, - } ) + filesize() ], output: [ {