فهرست منبع

WebGPURenderer: Support to `.backgroundNode` (#24213)

* beautify matrix columns

* add support to .onBeforeRender()

* add support to .backgroundNode

* add .backgroundNode to examples

* cleanup

* cleanup

* remove brightness, rename contrast to intensity

* fix get empty image[0]
sunag 3 سال پیش
والد
کامیت
f30599ed21

+ 2 - 1
examples/jsm/nodes/utils/MaxMipLevelNode.js

@@ -15,7 +15,8 @@ class MaxMipLevelNode extends UniformNode {
 
 	update() {
 
-		const image = this.texture.images && this.texture.images.length > 0 ? this.texture.images[ 0 ].image || this.texture.images[ 0 ] : this.texture.image;
+		const images = this.texture.images;
+		const image = ( images && images.length > 0 ) ? ( images[ 0 ]?.image || images[ 0 ] ) : this.texture.image;
 
 		if ( image?.width !== undefined ) {
 

+ 40 - 3
examples/jsm/renderers/webgpu/WebGPUBackground.js

@@ -1,5 +1,7 @@
 import { GPULoadOp, GPUStoreOp } from './constants.js';
-import { Color } from 'three';
+import { Color, Mesh, BoxGeometry, BackSide } from 'three';
+import { context, transformDirection, positionWorld, modelWorldMatrix } from 'three-nodes/Nodes.js';
+import MeshBasicNodeMaterial from 'three-nodes/materials/MeshBasicNodeMaterial.js';
 
 let _clearAlpha;
 const _clearColor = new Color();
@@ -10,6 +12,8 @@ class WebGPUBackground {
 
 		this.renderer = renderer;
 
+		this.boxMesh = null;
+
 		this.forceClear = false;
 
 	}
@@ -20,10 +24,11 @@ class WebGPUBackground {
 
 	}
 
-	update( scene ) {
+	update( renderList, scene ) {
 
 		const renderer = this.renderer;
-		const background = ( scene.isScene === true ) ? scene.background : null;
+		const background = ( scene.isScene === true ) ? scene.backgroundNode || scene.background : null;
+
 		let forceClear = this.forceClear;
 
 		if ( background === null ) {
@@ -41,6 +46,38 @@ class WebGPUBackground {
 			_clearAlpha = 1;
 			forceClear = true;
 
+		} else if ( background.isNode === true ) {
+
+			_clearColor.copy( renderer._clearColor );
+			_clearAlpha = renderer._clearAlpha;
+
+			let boxMesh = this.boxMesh;
+
+			if ( boxMesh === null ) {
+
+				const colorNode = context( background, {
+					uvNode: transformDirection( positionWorld, modelWorldMatrix )
+				} );
+
+				const nodeMaterial = new MeshBasicNodeMaterial();
+				nodeMaterial.colorNode = colorNode;
+				nodeMaterial.side = BackSide;
+				nodeMaterial.depthTest = false;
+				nodeMaterial.depthWrite = false;
+				nodeMaterial.fog = false;
+
+				this.boxMesh = boxMesh = new Mesh( new BoxGeometry( 1, 1, 1 ), nodeMaterial );
+
+				boxMesh.onBeforeRender = function ( renderer, scene, camera ) {
+
+					this.matrixWorld.copyPosition( camera.matrixWorld );
+
+				};
+
+			}
+
+			renderList.unshift( boxMesh, boxMesh.geometry, boxMesh.material, 0, 0, null );
+
 		} else {
 
 			console.error( 'THREE.WebGPURenderer: Unsupported background configuration.', background );

+ 8 - 6
examples/jsm/renderers/webgpu/WebGPURenderer.js

@@ -48,10 +48,10 @@ Matrix4.prototype.makeOrthographic = function ( left, right, top, bottom, near,
 	const y = ( top + bottom ) * h;
 	const z = near * p;
 
-	te[ 0 ] = 2 * w;	te[ 4 ] = 0;	te[ 8 ] = 0;	te[ 12 ] = - x;
-	te[ 1 ] = 0;	te[ 5 ] = 2 * h;	te[ 9 ] = 0;	te[ 13 ] = - y;
-	te[ 2 ] = 0;	te[ 6 ] = 0;	te[ 10 ] = - 1 * p;	te[ 14 ] = - z;
-	te[ 3 ] = 0;	te[ 7 ] = 0;	te[ 11 ] = 0;	te[ 15 ] = 1;
+	te[ 0 ] = 2 * w;	te[ 4 ] = 0;		te[ 8 ] = 0;		te[ 12 ] = - x;
+	te[ 1 ] = 0;		te[ 5 ] = 2 * h;	te[ 9 ] = 0;		te[ 13 ] = - y;
+	te[ 2 ] = 0;		te[ 6 ] = 0;		te[ 10 ] = - 1 * p;	te[ 14 ] = - z;
+	te[ 3 ] = 0;		te[ 7 ] = 0;		te[ 11 ] = 0;		te[ 15 ] = 1;
 
 	return this;
 
@@ -282,7 +282,7 @@ class WebGPURenderer {
 
 		//
 
-		this._background.update( scene );
+		this._background.update( this._currentRenderList, scene );
 
 		// start render pass
 
@@ -768,7 +768,9 @@ class WebGPURenderer {
 			// @TODO: Add support for multiple materials per object. This will require to extract
 			// the material from the renderItem object and pass it with its group data to _renderObject().
 
-			const object = renderItem.object;
+			const { object, geometry, material, group } = renderItem;
+
+			object.onBeforeRender( this, scene, camera, geometry, material, group );
 
 			object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
 			object.normalMatrix.getNormalMatrix( object.modelViewMatrix );

+ 28 - 16
examples/webgpu_cubemap_adjustments.html

@@ -32,7 +32,7 @@
 			import * as THREE from 'three';
 			import * as Nodes from 'three-nodes/Nodes.js';
 
-			import { uniform, mix, cubeTexture, mul, reference, add, positionWorld, normalWorld, saturate, saturation, hue, reflectCube } from 'three-nodes/Nodes.js';
+			import { uniform, mix, cubeTexture, mul, reference, add, positionWorld, normalWorld, modelWorldMatrix, transformDirection, saturate, saturation, hue, reflectCube, context } from 'three-nodes/Nodes.js';
 
 			import WebGPU from './jsm/capabilities/WebGPU.js';
 			import WebGPURenderer from './jsm/renderers/webgpu/WebGPURenderer.js';
@@ -92,33 +92,41 @@
 				const adjustments = {
 					mix: 0,
 					procedural: 0,
-					brightness: 0,
-					contrast: 1,
+					intensity: 1,
 					hue: 0,
 					saturation: 1
 				};
 
 				const mixNode = reference( 'mix', 'float', adjustments );
 				const proceduralNode = reference( 'procedural', 'float', adjustments );
-				const brightnessNode = reference( 'brightness', 'float', adjustments );
-				const contrastNode = reference( 'contrast', 'float', adjustments );
+				const intensityNode = reference( 'intensity', 'float', adjustments );
 				const hueNode = reference( 'hue', 'float', adjustments );
 				const saturationNode = reference( 'saturation', 'float', adjustments );
 
 				const rotateY1Matrix = new THREE.Matrix4();
 				const rotateY2Matrix = new THREE.Matrix4();
 
-				const custom1UV = mul( reflectCube, uniform( rotateY1Matrix ) );
-				const custom2UV = mul( reflectCube, uniform( rotateY2Matrix ) );
+				const getEnvironmentNode = ( reflectNode ) => {
 
-				const mixCubeMaps = mix( cubeTexture( cube1Texture, custom1UV ), cubeTexture( cube2Texture, custom2UV ), saturate( add( positionWorld.y, mixNode ) ) );
-				const proceduralEnv = mix( mixCubeMaps, normalWorld, proceduralNode );
-				const brightnessFilter = add( proceduralEnv, brightnessNode );
-				const contrastFilter = mul( brightnessFilter, contrastNode );
-				const hueFilter = hue( contrastFilter, hueNode );
-				const saturationFilter = saturation( hueFilter, saturationNode );
+					const custom1UV = mul( reflectNode.xyz, uniform( rotateY1Matrix ) );
+					const custom2UV = mul( reflectNode.xyz, uniform( rotateY2Matrix ) );
 
-				scene.environmentNode = saturationFilter;
+					const mixCubeMaps = mix( cubeTexture( cube1Texture, custom1UV ), cubeTexture( cube2Texture, custom2UV ), saturate( add( positionWorld.y, mixNode ) ) );
+					const proceduralEnv = mix( mixCubeMaps, normalWorld, proceduralNode );
+					const intensityFilter = mul( proceduralEnv, intensityNode );
+					const hueFilter = hue( intensityFilter, hueNode );
+
+					return saturation( hueFilter, saturationNode );
+
+				}
+
+				const blurNode = uniform( 0 );
+
+				scene.environmentNode = getEnvironmentNode( reflectCube );
+
+				scene.backgroundNode = context( getEnvironmentNode( transformDirection( positionWorld, modelWorldMatrix ) ), {
+					levelNode : blurNode // @TODO: currently it uses mipmaps value, I think it should be replaced for [0,1]
+				} );
 
 				// scene objects
 
@@ -161,6 +169,11 @@
 
 				const gui = new GUI();
 
+				gui.add( { blurBackground: blurNode.value }, 'blurBackground', 0, 10, 0.01 ).onChange( value => {
+
+					blurNode.value = value;
+
+				} );
 				gui.add( { offsetCube1: 0 }, 'offsetCube1', 0, Math.PI * 2, 0.01 ).onChange( value => {
 
 					rotateY1Matrix.makeRotationY( value );
@@ -173,8 +186,7 @@
 				} );
 				gui.add( adjustments, 'mix', - 1, 2, 0.01 );
 				gui.add( adjustments, 'procedural', 0, 1, 0.01 );
-				gui.add( adjustments, 'brightness', 0, 1, 0.01 );
-				gui.add( adjustments, 'contrast', 0, 3, 0.01 );
+				gui.add( adjustments, 'intensity', 0, 5, 0.01 );
 				gui.add( adjustments, 'hue', 0, Math.PI * 2, 0.01 );
 				gui.add( adjustments, 'saturation', 0, 2, 0.01 );
 

+ 9 - 5
examples/webgpu_cubemap_mix.html

@@ -32,7 +32,7 @@
 			import * as THREE from 'three';
 			import * as Nodes from 'three-nodes/Nodes.js';
 
-			import { mix, oscSine, timerLocal } from 'three-nodes/Nodes.js';
+			import { mix, oscSine, timerLocal, cubeTexture, context, float } from 'three-nodes/Nodes.js';
 
 			import WebGPU from './jsm/capabilities/WebGPU.js';
 			import WebGPURenderer from './jsm/renderers/webgpu/WebGPURenderer.js';
@@ -65,13 +65,13 @@
 				scene = new THREE.Scene();
 
 				const rgbmUrls = [ 'px.png', 'nx.png', 'py.png', 'ny.png', 'pz.png', 'nz.png' ];
-				const cubeTexture = new RGBMLoader()
+				const cube1Texture = new RGBMLoader()
 					.setMaxRange( 16 )
 					.setPath( './textures/cube/pisaRGBM16/' )
 					.loadCubemap( rgbmUrls );
 
-				cubeTexture.generateMipmaps = true;
-				cubeTexture.minFilter = THREE.LinearMipmapLinearFilter;
+				cube1Texture.generateMipmaps = true;
+				cube1Texture.minFilter = THREE.LinearMipmapLinearFilter;
 
 				const cube2Urls = [ 'dark-s_px.jpg', 'dark-s_nx.jpg', 'dark-s_py.jpg', 'dark-s_ny.jpg', 'dark-s_pz.jpg', 'dark-s_nz.jpg' ];
 				const cube2Texture = new THREE.CubeTextureLoader()
@@ -81,7 +81,11 @@
 				cube2Texture.generateMipmaps = true;
 				cube2Texture.minFilter = THREE.LinearMipmapLinearFilter;
 
-				scene.environmentNode = mix( new Nodes.CubeTextureNode( cube2Texture ), new Nodes.CubeTextureNode( cubeTexture ), oscSine( timerLocal( .1 ) ) );
+				scene.environmentNode = mix( cubeTexture( cube2Texture ), cubeTexture( cube1Texture ), oscSine( timerLocal( .1 ) ) );
+
+				scene.backgroundNode = context( scene.environmentNode, {
+					levelNode : float( 9 ) // @TODO: currently it uses mipmaps value, I think it should be replaced for [0,1]
+				} );
 
 				const loader = new GLTFLoader().setPath( 'models/gltf/DamagedHelmet/glTF/' );
 				loader.load( 'DamagedHelmet.gltf', function ( gltf ) {

+ 1 - 1
examples/webgpu_loader_gltf.html

@@ -73,8 +73,8 @@
 				cubeTexture.generateMipmaps = true;
 				cubeTexture.minFilter = THREE.LinearMipmapLinearFilter;
 
-				//scene.backgroundNode = texture;
 				scene.environmentNode = new Nodes.CubeTextureNode( cubeTexture );
+				scene.backgroundNode = scene.environmentNode;
 
 				const loader = new GLTFLoader().setPath( 'models/gltf/DamagedHelmet/glTF/' );
 				loader.load( 'DamagedHelmet.gltf', function ( gltf ) {