diff --git a/examples/files.json b/examples/files.json
index 0173905083689c..6341bfa5de2e2f 100644
--- a/examples/files.json
+++ b/examples/files.json
@@ -485,6 +485,7 @@
"webgpu_volume_cloud",
"webgpu_volume_lighting",
"webgpu_volume_lighting_rectarea",
+ "webgpu_volume_lighting_traa",
"webgpu_volume_perlin",
"webgpu_water",
"webgpu_xr_rollercoaster",
diff --git a/examples/jsm/tsl/display/RetroPassNode.js b/examples/jsm/tsl/display/RetroPassNode.js
index 2f6a9cb10e463f..bcf42e8b9de77d 100644
--- a/examples/jsm/tsl/display/RetroPassNode.js
+++ b/examples/jsm/tsl/display/RetroPassNode.js
@@ -1,5 +1,5 @@
-import { MeshBasicNodeMaterial, PassNode, UnsignedByteType, NearestFilter } from 'three/webgpu';
-import { float, vec2, vec4, Fn, uv, varying, cameraProjectionMatrix, cameraViewMatrix, positionWorld, screenSize, materialColor, replaceDefaultUV } from 'three/tsl';
+import { MeshBasicNodeMaterial, PassNode, UnsignedByteType, NearestFilter, CubeMapNode, MeshPhongNodeMaterial } from 'three/webgpu';
+import { float, vec2, vec4, Fn, uv, varying, cameraProjectionMatrix, cameraViewMatrix, positionWorld, screenSize, materialColor, uint, texture, uniform, context, reflectVector } from 'three/tsl';
const _affineUv = varying( vec2() );
const _w = varying( float() );
@@ -50,7 +50,8 @@ class RetroPassNode extends PassNode {
super( PassNode.COLOR, scene, camera );
const {
- affineDistortion = null
+ affineDistortion = null,
+ filterTextures = false
} = options;
this.setResolutionScale( .25 );
@@ -61,6 +62,8 @@ class RetroPassNode extends PassNode {
this.affineDistortionNode = affineDistortion;
+ this.filterTextures = filterTextures;
+
this._materialCache = new Map();
}
@@ -80,36 +83,125 @@ class RetroPassNode extends PassNode {
renderer.setRenderObjectFunction( ( object, scene, camera, geometry, material, ...params ) => {
- let retroMaterial = this._materialCache.get( material );
+ const retroMaterialData = this._materialCache.get( material );
+
+ let retroMaterial;
+
+ if ( retroMaterialData === undefined || retroMaterialData.version !== material.version ) {
+
+ if ( retroMaterialData !== undefined ) {
+
+ retroMaterialData.material.dispose();
+
+ }
+
+ if ( material.isMeshBasicMaterial || material.isMeshBasicNodeMaterial ) {
+
+ retroMaterial = new MeshBasicNodeMaterial();
- if ( retroMaterial === undefined ) {
+ } else {
- retroMaterial = new MeshBasicNodeMaterial();
+ retroMaterial = new MeshPhongNodeMaterial();
+
+ }
retroMaterial.colorNode = material.colorNode || null;
retroMaterial.opacityNode = material.opacityNode || null;
retroMaterial.positionNode = material.positionNode || null;
retroMaterial.vertexNode = material.vertexNode || _clipSpaceRetro;
+ let colorNode = material.colorNode || materialColor;
+
+ if ( material.isMeshStandardNodeMaterial || material.isMeshStandardMaterial ) {
+
+ const envMap = material.envMap || scene.environment;
+
+ if ( envMap ) {
+
+ const reflection = new CubeMapNode( texture( envMap ) );
+
+ let metalness;
+
+ if ( material.metalnessNode ) {
+
+ metalness = material.metalnessNode;
+
+ } else {
+
+ metalness = uniform( material.metalness ).onRenderUpdate( ( { material } ) => material.metalness );
+
+ if ( material.metalnessMap ) {
+
+ const textureUniform = texture( material.metalnessMap ).onRenderUpdate( ( { material } ) => material.metalnessMap );
+
+ metalness = metalness.mul( textureUniform.b );
+
+ }
+
+ }
+
+ colorNode = metalness.mix( colorNode, reflection );
+
+ }
+
+ }
+
+ retroMaterial.colorNode = colorNode;
+
+ //
+
+ const contextData = {};
+
if ( this.affineDistortionNode ) {
- retroMaterial.colorNode = replaceDefaultUV( () => {
+ contextData.getUV = ( texture ) => {
+
+ let finalUV;
+
+ if ( texture.isCubeTextureNode ) {
- return this.affineDistortionNode.mix( uv(), _affineUv.div( _w ) );
+ finalUV = reflectVector;
- }, retroMaterial.colorNode || materialColor );
+ } else {
+
+ finalUV = this.affineDistortionNode.mix( uv(), _affineUv.div( _w ) );
+
+ }
+
+ return finalUV;
+
+ };
}
- this._materialCache.set( material, retroMaterial );
+ if ( this.filterTextures !== true ) {
+
+ contextData.getTextureLevel = () => uint( 0 );
+
+ }
+
+ retroMaterial.contextNode = context( contextData );
+
+ //
+
+ this._materialCache.set( material, {
+ material: retroMaterial,
+ version: material.version
+ } );
+
+ } else {
+
+ retroMaterial = retroMaterialData.material;
}
- retroMaterial.map = material.map;
- retroMaterial.color = material.color;
- retroMaterial.opacity = material.opacity;
- retroMaterial.transparent = material.transparent;
- retroMaterial.side = material.side;
+ for ( const property in material ) {
+
+ if ( retroMaterial[ property ] === undefined ) continue;
+
+ retroMaterial[ property ] = material[ property ];
+
+ }
renderer.renderObject( object, scene, camera, geometry, retroMaterial, ...params );
@@ -131,7 +223,12 @@ class RetroPassNode extends PassNode {
super.dispose();
- this._materialCache.forEach( material => material.dispose() );
+ this._materialCache.forEach( ( data ) => {
+
+ data.material.dispose();
+
+ } );
+
this._materialCache.clear();
}
diff --git a/examples/screenshots/webgpu_postprocessing_retro.jpg b/examples/screenshots/webgpu_postprocessing_retro.jpg
index 1585d761881f50..39626e76a86680 100644
Binary files a/examples/screenshots/webgpu_postprocessing_retro.jpg and b/examples/screenshots/webgpu_postprocessing_retro.jpg differ
diff --git a/examples/screenshots/webgpu_volume_lighting_traa.jpg b/examples/screenshots/webgpu_volume_lighting_traa.jpg
new file mode 100644
index 00000000000000..00898d2d2f9b1e
Binary files /dev/null and b/examples/screenshots/webgpu_volume_lighting_traa.jpg differ
diff --git a/examples/webgpu_postprocessing_retro.html b/examples/webgpu_postprocessing_retro.html
index 0b64507a806465..75377766b97b5d 100644
--- a/examples/webgpu_postprocessing_retro.html
+++ b/examples/webgpu_postprocessing_retro.html
@@ -35,7 +35,7 @@
+
+
+
+