diff --git a/examples/jsm/nodes/accessors/CubeTextureNode.js b/examples/jsm/nodes/accessors/CubeTextureNode.js index 542080a5a28f95..c89bb449d22bc5 100644 --- a/examples/jsm/nodes/accessors/CubeTextureNode.js +++ b/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; + + } } diff --git a/examples/jsm/renderers/common/nodes/Nodes.js b/examples/jsm/renderers/common/nodes/Nodes.js index 68046076c79021..d019ab008e269d 100644 --- a/examples/jsm/renderers/common/nodes/Nodes.js +++ b/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 { diff --git a/examples/jsm/renderers/webgl/WebGLBackend.js b/examples/jsm/renderers/webgl/WebGLBackend.js index a3e5ff0caf39af..08b2903f238b52 100644 --- a/examples/jsm/renderers/webgl/WebGLBackend.js +++ b/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 ) { diff --git a/examples/jsm/renderers/webgl/nodes/GLSLNodeBuilder.js b/examples/jsm/renderers/webgl/nodes/GLSLNodeBuilder.js index e05aeb648ebf7e..b5ebe7b44d4f47 100644 --- a/examples/jsm/renderers/webgl/nodes/GLSLNodeBuilder.js +++ b/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`; diff --git a/examples/jsm/renderers/webgl/utils/WebGLAttributeUtils.js b/examples/jsm/renderers/webgl/utils/WebGLAttributeUtils.js index 4dadb63b8e34d5..a1441ff264dcbe 100644 --- a/examples/jsm/renderers/webgl/utils/WebGLAttributeUtils.js +++ b/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; diff --git a/examples/jsm/renderers/webgl/utils/WebGLTextureUtils.js b/examples/jsm/renderers/webgl/utils/WebGLTextureUtils.js index 55a970df2e8d29..863b679a3d1b23 100644 --- a/examples/jsm/renderers/webgl/utils/WebGLTextureUtils.js +++ b/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 ) { diff --git a/examples/webgpu_cubemap_dynamic.html b/examples/webgpu_cubemap_dynamic.html index a454d477a40758..8099ef3dde12fd 100644 --- a/examples/webgpu_cubemap_dynamic.html +++ b/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' ); } diff --git a/examples/webgpu_loader_gltf.html b/examples/webgpu_loader_gltf.html index 4adbff3ab95ac6..c171984dd3446b 100644 --- a/examples/webgpu_loader_gltf.html +++ b/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' ); } diff --git a/examples/webgpu_loader_gltf_iridescence.html b/examples/webgpu_loader_gltf_iridescence.html index 53d12e4ea538ee..f73ad6054195ee 100644 --- a/examples/webgpu_loader_gltf_iridescence.html +++ b/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' ); } diff --git a/examples/webgpu_loader_gltf_sheen.html b/examples/webgpu_loader_gltf_sheen.html index fcafbff7c99c62..3f6158ee28ad79 100644 --- a/examples/webgpu_loader_gltf_sheen.html +++ b/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' ); } diff --git a/test/e2e/puppeteer.js b/test/e2e/puppeteer.js index d45d0b0f18f5e8..bdc5b132c817b9 100644 --- a/test/e2e/puppeteer.js +++ b/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',