2
0
Эх сурвалжийг харах

WebGPURenderer: Support WebGLCubeRenderTarget (#27071)

* cube render targets

* implemenet destroyAttribute()

* replicate WebGPU texture filtering

* missed ;

* allow tests to run

* reinstate flip

* add missing ;

* repair damage

---------

Co-authored-by: aardgoose <[email protected]>
aardgoose 1 жил өмнө
parent
commit
7a12ec3c1d

+ 12 - 1
examples/jsm/nodes/accessors/CubeTextureNode.js

@@ -2,6 +2,7 @@ import TextureNode from './TextureNode.js';
 import { reflectVector } from './ReflectVectorNode.js';
 import { addNodeClass } from '../core/Node.js';
 import { addNodeElement, nodeProxy, vec3 } from '../shadernode/ShaderNode.js';
+import { WebGPUCoordinateSystem } from 'three';
 
 class CubeTextureNode extends TextureNode {
 
@@ -29,7 +30,17 @@ class CubeTextureNode extends TextureNode {
 
 	setupUV( builder, uvNode ) {
 
-		return vec3( uvNode.x.negate(), uvNode.yz );
+		const texture = this.value;
+
+		if ( builder.renderer.coordinateSystem === WebGPUCoordinateSystem || ! texture.isRenderTargetTexture ) {
+
+			return vec3( uvNode.x.negate(), uvNode.yz );
+
+		} else {
+
+			return uvNode;
+
+		}
 
 	}
 

+ 1 - 0
examples/jsm/renderers/common/nodes/Nodes.js

@@ -314,6 +314,7 @@ class Nodes extends DataMap {
 					if ( background.mapping === EquirectangularReflectionMapping || background.mapping === EquirectangularRefractionMapping ) {
 
 						nodeUV = equirectUV();
+						background.flipY = false;
 
 					} else {
 

+ 63 - 17
examples/jsm/renderers/webgl/WebGLBackend.js

@@ -10,6 +10,7 @@ import WebGLTextureUtils from './utils/WebGLTextureUtils.js';
 import WebGLExtensions from './utils/WebGLExtensions.js';
 import WebGLCapabilities from './utils/WebGLCapabilities.js';
 import { GLFeatureName } from './utils/WebGLConstants.js';
+
 //
 
 class WebGLBackend extends Backend {
@@ -115,6 +116,24 @@ class WebGLBackend extends Backend {
 		const renderContextData = this.get( renderContext );
 		const previousContext = renderContextData.previousContext;
 
+		const textures = renderContext.textures;
+
+		if ( textures !== null ) {
+
+			for ( let i = 0; i < textures.length; i ++ ) {
+
+				const texture = textures[ i ];
+
+				if ( texture.generateMipmaps ) {
+
+					this.generateMipmaps( texture );
+
+				}
+
+			}
+
+		}
+
 		this._currentContext = previousContext;
 
 
@@ -809,9 +828,9 @@ class WebGLBackend extends Backend {
 
 	}
 
-	destroyAttribute( /*attribute*/ ) {
+	destroyAttribute( attribute ) {
 
-		console.warn( 'Abstract class.' );
+		this.attributeUtils.destroyAttribute( attribute );
 
 	}
 
@@ -855,18 +874,36 @@ class WebGLBackend extends Backend {
 
 		const { gl, state } = this;
 
-		let fb = null;
 		let currentFrameBuffer = null;
 
 		if ( renderContext.textures !== null ) {
 
-			const renderTargetContextData = this.get( renderContext.renderTarget );
-			const { samples } = renderContext.renderTarget;
+			const renderTarget = renderContext.renderTarget;
+			const renderTargetContextData = this.get( renderTarget );
+			const { samples } = renderTarget;
+			const cubeFace = this.renderer._activeCubeFace;
+			const isCube = renderTarget.isWebGLCubeRenderTarget === true;
 
-			fb = renderTargetContextData.framebuffer;
 			let msaaFb = renderTargetContextData.msaaFrameBuffer;
 			let depthRenderbuffer = renderTargetContextData.depthRenderbuffer;
 
+			let fb;
+
+			if ( isCube ) {
+
+				if ( renderTargetContextData.cubeFramebuffers === undefined ) {
+
+					renderTargetContextData.cubeFramebuffers = [];
+
+				}
+
+				fb = renderTargetContextData.cubeFramebuffers[ cubeFace ];
+
+			} else {
+
+				fb = renderTargetContextData.framebuffer;
+
+			}
 
 			if ( fb === undefined ) {
 
@@ -876,16 +913,30 @@ class WebGLBackend extends Backend {
 
 				const textures = renderContext.textures;
 
-				for ( let i = 0; i < textures.length; i ++ ) {
+				if ( isCube ) {
 
-					const texture = textures[ i ];
-					const textureData = this.get( texture );
-					textureData.renderTarget = renderContext.renderTarget;
+					renderTargetContextData.cubeFramebuffers[ cubeFace ] = fb;
+					const { textureGPU } = this.get( textures[ 0 ] );
 
-					const attachment = gl.COLOR_ATTACHMENT0 + i;
+					gl.framebufferTexture2D( gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_CUBE_MAP_POSITIVE_X + cubeFace, textureGPU, 0 );
+
+				} else {
 
+					for ( let i = 0; i < textures.length; i ++ ) {
 
-					gl.framebufferTexture2D( gl.FRAMEBUFFER, attachment, gl.TEXTURE_2D, textureData.textureGPU, 0 );
+						const texture = textures[ i ];
+						const textureData = this.get( texture );
+						textureData.renderTarget = renderContext.renderTarget;
+
+						const attachment = gl.COLOR_ATTACHMENT0 + i;
+
+						gl.framebufferTexture2D( gl.FRAMEBUFFER, attachment, gl.TEXTURE_2D, textureData.textureGPU, 0 );
+
+					}
+
+					renderTargetContextData.framebuffer = fb;
+
+					state.drawBuffers( renderContext, fb );
 
 				}
 
@@ -897,11 +948,6 @@ class WebGLBackend extends Backend {
 
 				}
 
-
-				renderTargetContextData.framebuffer = fb;
-
-				state.drawBuffers( renderContext, fb );
-
 			}
 
 			if ( samples > 0 ) {

+ 1 - 5
examples/jsm/renderers/webgl/nodes/GLSLNodeBuilder.js

@@ -99,11 +99,7 @@ ${ flowData.code }
 
 	generateTexture( texture, textureProperty, uvSnippet, depthSnippet ) {
 
-		if ( texture.isTextureCube ) {
-
-			return `textureCube( ${ textureProperty }, ${ uvSnippet } )`;
-
-		} else if ( texture.isDepthTexture ) {
+		if ( texture.isDepthTexture ) {
 
 			return `texture( ${ textureProperty }, ${ uvSnippet } ).x`;
 

+ 19 - 0
examples/jsm/renderers/webgl/utils/WebGLAttributeUtils.js

@@ -134,6 +134,25 @@ class WebGLAttributeUtils {
 
 	}
 
+	destroyAttribute( attribute ) {
+
+		const backend = this.backend;
+		const { gl } = backend;
+
+		if ( attribute.isInterleavedBufferAttribute ) {
+
+			backend.delete( attribute.data );
+
+		}
+
+		const attributeData = backend.get( attribute );
+
+		gl.deleteBuffer( attributeData.bufferGPU );
+
+		backend.delete( attribute );
+
+	}
+
 	async getArrayBufferAsync( attribute ) {
 
 		const backend = this.backend;

+ 6 - 1
examples/jsm/renderers/webgl/utils/WebGLTextureUtils.js

@@ -184,7 +184,12 @@ class WebGLTextureUtils {
 		}
 
 		gl.texParameteri( textureType, gl.TEXTURE_MAG_FILTER, filterToGL[ texture.magFilter ] );
-		gl.texParameteri( textureType, gl.TEXTURE_MIN_FILTER, filterToGL[ texture.minFilter ] );
+
+
+		// follow WebGPU backend mapping for texture filtering
+		const minFilter = texture.minFilter === LinearFilter ? LinearMipmapLinearFilter : texture.minFilter;
+
+		gl.texParameteri( textureType, gl.TEXTURE_MIN_FILTER, filterToGL[ minFilter ] );
 
 		if ( texture.compareFunction ) {
 

+ 4 - 2
examples/webgpu_cubemap_dynamic.html

@@ -31,6 +31,8 @@
 			import * as Nodes from 'three/nodes';
 
 			import WebGPU from 'three/addons/capabilities/WebGPU.js';
+			import WebGL from 'three/addons/capabilities/WebGL.js';
+
 			import WebGPURenderer from 'three/addons/renderers/webgpu/WebGPURenderer.js';
 
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
@@ -50,11 +52,11 @@
 
 			function init() {
 
-				if ( WebGPU.isAvailable() === false ) {
+				if ( WebGPU.isAvailable() === false && WebGL.isWebGL2Available() === false ) {
 
 					document.body.appendChild( WebGPU.getErrorMessage() );
 
-					throw new Error( 'No WebGPU support' );
+					throw new Error( 'No WebGPU or WebGL2 support' );
 
 				}
 

+ 4 - 2
examples/webgpu_loader_gltf.html

@@ -29,6 +29,8 @@
 			import * as THREE from 'three';
 
 			import WebGPU from 'three/addons/capabilities/WebGPU.js';
+			import WebGL from 'three/addons/capabilities/WebGL.js';
+
 			import WebGPURenderer from 'three/addons/renderers/webgpu/WebGPURenderer.js';
 
 			import { RGBELoader } from 'three/addons/loaders/RGBELoader.js';
@@ -43,11 +45,11 @@
 
 			function init() {
 
-				if ( WebGPU.isAvailable() === false ) {
+				if ( WebGPU.isAvailable() === false && WebGL.isWebGL2Available() === false ) {
 
 					document.body.appendChild( WebGPU.getErrorMessage() );
 
-					throw new Error( 'No WebGPU support' );
+					throw new Error( 'No WebGPU or WebGL2 support' );
 
 				}
 

+ 4 - 2
examples/webgpu_loader_gltf_iridescence.html

@@ -28,6 +28,8 @@
 			import * as THREE from 'three';
 
 			import WebGPU from 'three/addons/capabilities/WebGPU.js';
+			import WebGL from 'three/addons/capabilities/WebGL.js';
+
 			import WebGPURenderer from 'three/addons/renderers/webgpu/WebGPURenderer.js';
 
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
@@ -44,11 +46,11 @@
 
 			async function init() {
 
-				if ( WebGPU.isAvailable() === false ) {
+				if ( WebGPU.isAvailable() === false && WebGL.isWebGL2Available() === false ) {
 
 					document.body.appendChild( WebGPU.getErrorMessage() );
 
-					throw new Error( 'No WebGPU support' );
+					throw new Error( 'No WebGPU or WebGL2 support' );
 
 				}
 

+ 4 - 2
examples/webgpu_loader_gltf_sheen.html

@@ -32,6 +32,8 @@
 			import * as THREE from 'three';
 
 			import WebGPU from 'three/addons/capabilities/WebGPU.js';
+			import WebGL from 'three/addons/capabilities/WebGL.js';
+
 			import WebGPURenderer from 'three/addons/renderers/webgpu/WebGPURenderer.js';
 
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
@@ -46,11 +48,11 @@
 
 			function init() {
 
-				if ( WebGPU.isAvailable() === false ) {
+				if ( WebGPU.isAvailable() === false && WebGL.isWebGL2Available() === false ) {
 
 					document.body.appendChild( WebGPU.getErrorMessage() );
 
-					throw new Error( 'No WebGPU support' );
+					throw new Error( 'No WebGPU or WebGL2 support' );
 
 				}
 

+ 0 - 4
test/e2e/puppeteer.js

@@ -117,11 +117,7 @@ const exceptionList = [
 	'webgpu_compute_points',
 	'webgpu_compute_texture',
 	'webgpu_compute_texture_pingpong',
-	'webgpu_cubemap_dynamic',
-	'webgpu_loader_gltf',
 	'webgpu_loader_gltf_compressed',
-	'webgpu_loader_gltf_iridescence',
-	'webgpu_loader_gltf_sheen',
 	'webgpu_materials',
 	'webgpu_portal',
 	'webgpu_sandbox',