瀏覽代碼

WebGPURenderer: Render Pass ID and Double Pass (#26333)

* WebGPURenderer: NS RenderObject and Double Pass

* Example `webgpu_backdrop_area`: Move to DoubleSide

* namespace to pass id

* namespace -> passId
sunag 2 年之前
父節點
當前提交
872ad803db

+ 21 - 14
examples/jsm/renderers/common/RenderObjects.js

@@ -2,33 +2,33 @@ import DataMap from './DataMap.js';
 import ChainMap from './ChainMap.js';
 import RenderObject from './RenderObject.js';
 
-class RenderObjects extends ChainMap {
+class RenderObjects {
 
 	constructor( renderer, nodes, geometries, pipelines, info ) {
 
-		super();
-
 		this.renderer = renderer;
 		this.nodes = nodes;
 		this.geometries = geometries;
 		this.pipelines = pipelines;
 		this.info = info;
 
+		this.chainMaps = {};
 		this.dataMap = new DataMap();
 
 	}
 
-	get( object, material, scene, camera, lightsNode ) {
+	get( object, material, scene, camera, lightsNode, passId ) {
 
+		const chainMap = this.getChainMap( passId );
 		const chainArray = [ object, material, scene, camera, lightsNode ];
 
-		let renderObject = super.get( chainArray );
+		let renderObject = chainMap.get( chainArray );
 
 		if ( renderObject === undefined ) {
 
-			renderObject = this.createRenderObject( this.nodes, this.geometries, this.renderer, object, material, scene, camera, lightsNode );
+			renderObject = this.createRenderObject( this.nodes, this.geometries, this.renderer, object, material, scene, camera, lightsNode, passId );
 
-			this.set( chainArray, renderObject );
+			chainMap.set( chainArray, renderObject );
 
 		} else {
 
@@ -49,29 +49,36 @@ class RenderObjects extends ChainMap {
 
 	}
 
-	dispose() {
+	getChainMap( passId = 'default' ) {
 
-		super.dispose();
+		return this.chainMaps[ passId ] || ( this.chainMaps[ passId ] = new ChainMap() );
+
+	}
 
-		this.dataMap.clear();
+	dispose() {
+
+		this.chainMaps = {};
+		this.dataMap = new DataMap();
 
 	}
 
-	createRenderObject( nodes, geometries, renderer, object, material, scene, camera, lightsNode ) {
+	createRenderObject( nodes, geometries, renderer, object, material, scene, camera, lightsNode, passId ) {
 
+		const chainMap = this.getChainMap( passId );
+		const dataMap = this.dataMap;
 		const renderObject = new RenderObject( nodes, geometries, renderer, object, material, scene, camera, lightsNode );
 
-		const data = this.dataMap.get( renderObject );
+		const data = dataMap.get( renderObject );
 		data.cacheKey = renderObject.getCacheKey();
 
 		renderObject.onDispose = () => {
 
-			this.dataMap.delete( renderObject );
+			dataMap.delete( renderObject );
 
 			this.pipelines.delete( renderObject );
 			this.nodes.delete( renderObject );
 
-			this.delete( renderObject.getChainArray() );
+			chainMap.delete( renderObject.getChainArray() );
 
 		};
 

+ 36 - 6
examples/jsm/renderers/common/Renderer.js

@@ -10,7 +10,7 @@ import RenderContexts from './RenderContexts.js';
 import Textures from './Textures.js';
 import Background from './Background.js';
 import Nodes from './nodes/Nodes.js';
-import { Frustum, Matrix4, Vector2, Vector3, Vector4, Color, SRGBColorSpace, NoToneMapping } from 'three';
+import { Frustum, Matrix4, Vector2, Vector3, Vector4, Color, DoubleSide, BackSide, FrontSide, SRGBColorSpace, NoToneMapping } from 'three';
 
 const _drawingBufferSize = new Vector2();
 const _screen = new Vector4();
@@ -805,17 +805,47 @@ class Renderer {
 
 		//
 
-		const renderObject = this._objects.get( object, material, scene, camera, lightsNode );
-		renderObject.context = this._currentRenderContext;
+		object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
+		object.normalMatrix.getNormalMatrix( object.modelViewMatrix );
 
 		//
 
-		this._nodes.updateBefore( renderObject );
+		material.onBeforeRender( this, scene, camera, geometry, material, group );
 
 		//
 
-		object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
-		object.normalMatrix.getNormalMatrix( object.modelViewMatrix );
+		if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) {
+
+			material.side = BackSide;
+			this._renderObjectDirect( object, scene, camera, geometry, material, group, lightsNode, 'backSide' ); // create backSide pass id
+
+			material.side = FrontSide;
+			this._renderObjectDirect( object, scene, camera, geometry, material, group, lightsNode ); // use default pass id
+
+			material.side = DoubleSide;
+
+		} else {
+
+			this._renderObjectDirect( object, scene, camera, geometry, material, group, lightsNode );
+
+		}
+
+		//
+
+		object.onAfterRender( this, scene, camera, geometry, material, group );
+
+	}
+
+	_renderObjectDirect( object, scene, camera, geometry, material, group, lightsNode, passId ) {
+
+		//
+
+		const renderObject = this._objects.get( object, material, scene, camera, lightsNode, passId );
+		renderObject.context = this._currentRenderContext;
+
+		//
+
+		this._nodes.updateBefore( renderObject );
 
 		//
 

+ 6 - 11
examples/webgpu_backdrop_area.html

@@ -86,16 +86,19 @@
 				volumeMaterial.backdropNode = viewportSharedTexture();
 				volumeMaterial.backdropAlphaNode = depthAlphaNode;
 				volumeMaterial.transparent = true;
+				volumeMaterial.side = THREE.DoubleSide;
 
 				const depthMaterial = new MeshBasicNodeMaterial();
 				depthMaterial.backdropNode = depthAlphaNode;
 				depthMaterial.transparent = true;
+				depthMaterial.side = THREE.DoubleSide;
 
 				const bicubicMaterial = new MeshBasicNodeMaterial();
 				bicubicMaterial.backdropNode = viewportMipTexture().bicubic( 5 ); // @TODO: Move to alpha value [ 0, 1 ]
 				bicubicMaterial.backdropAlphaNode = checker( uv().mul( 3 ).mul( modelScale.xy ) );
 				bicubicMaterial.opacityNode = bicubicMaterial.backdropAlphaNode;
 				bicubicMaterial.transparent = true;
+				bicubicMaterial.side = THREE.DoubleSide;
 
 				const pixelMaterial = new MeshBasicNodeMaterial();
 				pixelMaterial.backdropNode = viewportSharedTexture( viewportTopLeft.mul( 100 ).floor().div( 100 ) );
@@ -105,15 +108,8 @@
 
 				const box = new THREE.Mesh( new THREE.BoxGeometry( 2, 2, 2 ), volumeMaterial );
 				box.position.set( 0, 1, 0 );
-				//box.material.side = THREE.DoubleSide; // @TODO: Needed add support to material.forceSinglePass = false;
 				scene.add( box );
 
-				const boxBack = new THREE.Mesh( new THREE.BoxGeometry( 2, 2, 2 ).scale( - 1, - 1, - 1 ), volumeMaterial );
-				boxBack.position.set( 0, 1, 0 );
-				boxBack.renderOrder = - 1;
-				boxBack.visible = false;
-				scene.add( boxBack );
-
 				const floor = new THREE.Mesh( new THREE.BoxGeometry( 1.99, .01, 1.99 ), new MeshBasicNodeMaterial( { color: 0x333333 } ) );
 				floor.position.set( 0, 0, 0 );
 				scene.add( floor );
@@ -146,12 +142,11 @@
 				const gui = new GUI();
 				const options = { material: 'volume' };
 
-				gui.add( box.scale, 'x', 0.1, 2, 0.01 ).onChange( () => boxBack.scale.copy( box.scale ) );
-				gui.add( box.scale, 'z', 0.1, 2, 0.01 ).onChange( () => boxBack.scale.copy( box.scale ) );
+				gui.add( box.scale, 'x', 0.1, 2, 0.01 );
+				gui.add( box.scale, 'z', 0.1, 2, 0.01 );
 				gui.add( options, 'material', Object.keys( materials ) ).onChange( name => {
 
-					box.material = boxBack.material = materials[ name ];
-					boxBack.visible = ( name === 'bicubic' );
+					box.material = materials[ name ];
 
 				} );