diff --git a/src/nodes/accessors/CubeTextureNode.js b/src/nodes/accessors/CubeTextureNode.js index c04c9a1b0fd29c..1dafe17d25d67d 100644 --- a/src/nodes/accessors/CubeTextureNode.js +++ b/src/nodes/accessors/CubeTextureNode.js @@ -47,13 +47,19 @@ class CubeTextureNode extends TextureNode { } /** - * Overwrites the default implementation to return a fixed value `'cubeTexture'`. + * Overwrites the default implementation to return the appropriate cube texture type. * * @param {NodeBuilder} builder - The current node builder. * @return {string} The input type. */ getInputType( /*builder*/ ) { + if ( this.value.isDepthTexture === true ) { + + return 'cubeDepthTexture'; + + } + return 'cubeTexture'; } @@ -105,6 +111,19 @@ class CubeTextureNode extends TextureNode { const texture = this.value; + // Depth textures (shadow maps) - no environment rotation, Y flip for WebGPU + if ( texture.isDepthTexture === true ) { + + if ( builder.renderer.coordinateSystem === WebGPUCoordinateSystem ) { + + return vec3( uvNode.x, uvNode.y.negate(), uvNode.z ); + + } + + return uvNode; + + } + if ( builder.renderer.coordinateSystem === WebGPUCoordinateSystem || ! texture.isRenderTargetTexture ) { uvNode = vec3( uvNode.x.negate(), uvNode.yz ); diff --git a/src/nodes/lighting/PointShadowNode.js b/src/nodes/lighting/PointShadowNode.js index 6f5f03c2b9e2b1..e809ed8af747da 100644 --- a/src/nodes/lighting/PointShadowNode.js +++ b/src/nodes/lighting/PointShadowNode.js @@ -2,165 +2,66 @@ import ShadowNode from './ShadowNode.js'; import { uniform } from '../core/UniformNode.js'; import { float, vec2, If, Fn, nodeObject } from '../tsl/TSLBase.js'; import { reference } from '../accessors/ReferenceNode.js'; -import { texture } from '../accessors/TextureNode.js'; -import { max, abs, sign } from '../math/MathNode.js'; -import { sub, div } from '../math/OperatorNode.js'; +import { cubeTexture } from '../accessors/CubeTextureNode.js'; import { renderGroup } from '../core/UniformGroupNode.js'; import { Matrix4 } from '../../math/Matrix4.js'; -import { Vector2 } from '../../math/Vector2.js'; import { Vector3 } from '../../math/Vector3.js'; -import { Vector4 } from '../../math/Vector4.js'; import { Color } from '../../math/Color.js'; -import { BasicShadowMap } from '../../constants.js'; +import { BasicShadowMap, LessCompare, WebGPUCoordinateSystem } from '../../constants.js'; +import { CubeDepthTexture } from '../../textures/CubeDepthTexture.js'; const _clearColor = /*@__PURE__*/ new Color(); const _projScreenMatrix = /*@__PURE__*/ new Matrix4(); const _lightPositionWorld = /*@__PURE__*/ new Vector3(); const _lookTarget = /*@__PURE__*/ new Vector3(); -// These viewports map a cube-map onto a 2D texture with the -// following orientation: -// -// xzXZ -// y Y -// -// X - Positive x direction -// x - Negative x direction -// Y - Positive y direction -// y - Negative y direction -// Z - Positive z direction -// z - Negative z direction - -const _frameExtents = /*@__PURE__*/ new Vector2( 4, 2 ); - -const _viewports = [ - // positive X - /*@__PURE__*/ new Vector4( 2, 1, 1, 1 ), - // negative X - /*@__PURE__*/ new Vector4( 0, 1, 1, 1 ), - // positive Z - /*@__PURE__*/ new Vector4( 3, 1, 1, 1 ), - // negative Z - /*@__PURE__*/ new Vector4( 1, 1, 1, 1 ), - // positive Y - /*@__PURE__*/ new Vector4( 3, 0, 1, 1 ), - // negative Y - /*@__PURE__*/ new Vector4( 1, 0, 1, 1 ) +// Cube map face directions and up vectors for point light shadows +// Face order: +X, -X, +Y, -Y, +Z, -Z +// WebGPU coordinate system - Y faces swapped to match texture sampling convention +const _cubeDirectionsWebGPU = [ + /*@__PURE__*/ new Vector3( 1, 0, 0 ), /*@__PURE__*/ new Vector3( - 1, 0, 0 ), /*@__PURE__*/ new Vector3( 0, - 1, 0 ), + /*@__PURE__*/ new Vector3( 0, 1, 0 ), /*@__PURE__*/ new Vector3( 0, 0, 1 ), /*@__PURE__*/ new Vector3( 0, 0, - 1 ) ]; -const _cubeDirections = [ - /*@__PURE__*/ new Vector3( 1, 0, 0 ), /*@__PURE__*/ new Vector3( - 1, 0, 0 ), /*@__PURE__*/ new Vector3( 0, 0, 1 ), - /*@__PURE__*/ new Vector3( 0, 0, - 1 ), /*@__PURE__*/ new Vector3( 0, 1, 0 ), /*@__PURE__*/ new Vector3( 0, - 1, 0 ) +const _cubeUpsWebGPU = [ + /*@__PURE__*/ new Vector3( 0, - 1, 0 ), /*@__PURE__*/ new Vector3( 0, - 1, 0 ), /*@__PURE__*/ new Vector3( 0, 0, - 1 ), + /*@__PURE__*/ new Vector3( 0, 0, 1 ), /*@__PURE__*/ new Vector3( 0, - 1, 0 ), /*@__PURE__*/ new Vector3( 0, - 1, 0 ) ]; -const _cubeUps = [ - /*@__PURE__*/ new Vector3( 0, 1, 0 ), /*@__PURE__*/ new Vector3( 0, 1, 0 ), /*@__PURE__*/ new Vector3( 0, 1, 0 ), - /*@__PURE__*/ new Vector3( 0, 1, 0 ), /*@__PURE__*/ new Vector3( 0, 0, 1 ), /*@__PURE__*/ new Vector3( 0, 0, - 1 ) +// WebGL coordinate system - standard OpenGL convention +const _cubeDirectionsWebGL = [ + /*@__PURE__*/ new Vector3( 1, 0, 0 ), /*@__PURE__*/ new Vector3( - 1, 0, 0 ), /*@__PURE__*/ new Vector3( 0, 1, 0 ), + /*@__PURE__*/ new Vector3( 0, - 1, 0 ), /*@__PURE__*/ new Vector3( 0, 0, 1 ), /*@__PURE__*/ new Vector3( 0, 0, - 1 ) ]; -// cubeToUV() maps a 3D direction vector suitable for cube texture mapping to a 2D -// vector suitable for 2D texture mapping. This code uses the following layout for the -// 2D texture: -// -// xzXZ -// y Y -// -// Y - Positive y direction -// y - Negative y direction -// X - Positive x direction -// x - Negative x direction -// Z - Positive z direction -// z - Negative z direction -// -// Source and test bed: -// https://gist.github.com/tschw/da10c43c467ce8afd0c4 - -export const cubeToUV = /*@__PURE__*/ Fn( ( [ pos, texelSizeY ] ) => { - - const v = pos.toVar(); - - // Number of texels to avoid at the edge of each square - - const absV = abs( v ); - - // Intersect unit cube - - const scaleToCube = div( 1.0, max( absV.x, max( absV.y, absV.z ) ) ); - absV.mulAssign( scaleToCube ); - - // Apply scale to avoid seams - - // two texels less per square (one texel will do for NEAREST) - v.mulAssign( scaleToCube.mul( texelSizeY.mul( 2 ).oneMinus() ) ); - - // Unwrap - - // space: -1 ... 1 range for each square - // - // #X## dim := ( 4 , 2 ) - // # # center := ( 1 , 1 ) - - const planar = vec2( v.xy ).toVar(); - - const almostATexel = texelSizeY.mul( 1.5 ); - const almostOne = almostATexel.oneMinus(); - - If( absV.z.greaterThanEqual( almostOne ), () => { - - If( v.z.greaterThan( 0.0 ), () => { - - planar.x.assign( sub( 4.0, v.x ) ); - - } ); - - } ).ElseIf( absV.x.greaterThanEqual( almostOne ), () => { - - const signX = sign( v.x ); - planar.x.assign( v.z.mul( signX ).add( signX.mul( 2.0 ) ) ); - - } ).ElseIf( absV.y.greaterThanEqual( almostOne ), () => { - - const signY = sign( v.y ); - planar.x.assign( v.x.add( signY.mul( 2.0 ) ).add( 2.0 ) ); - planar.y.assign( v.z.mul( signY ).sub( 2.0 ) ); - - } ); - - // Transform to UV space - - // scale := 0.5 / dim - // translate := ( center + 0.5 ) / dim - return vec2( 0.125, 0.25 ).mul( planar ).add( vec2( 0.375, 0.75 ) ).flipY(); - -} ).setLayout( { - name: 'cubeToUV', - type: 'vec2', - inputs: [ - { name: 'pos', type: 'vec3' }, - { name: 'texelSizeY', type: 'float' } - ] -} ); +const _cubeUpsWebGL = [ + /*@__PURE__*/ new Vector3( 0, - 1, 0 ), /*@__PURE__*/ new Vector3( 0, - 1, 0 ), /*@__PURE__*/ new Vector3( 0, 0, 1 ), + /*@__PURE__*/ new Vector3( 0, 0, - 1 ), /*@__PURE__*/ new Vector3( 0, - 1, 0 ), /*@__PURE__*/ new Vector3( 0, - 1, 0 ) +]; -export const BasicPointShadowFilter = /*@__PURE__*/ Fn( ( { depthTexture, bd3D, dp, texelSize } ) => { +export const BasicPointShadowFilter = /*@__PURE__*/ Fn( ( { depthTexture, bd3D, dp } ) => { - return texture( depthTexture, cubeToUV( bd3D, texelSize.y ) ).compare( dp ); + return cubeTexture( depthTexture, bd3D ).compare( dp ); } ); -export const PointShadowFilter = /*@__PURE__*/ Fn( ( { depthTexture, bd3D, dp, texelSize, shadow } ) => { +export const PointShadowFilter = /*@__PURE__*/ Fn( ( { depthTexture, bd3D, dp, shadow } ) => { const radius = reference( 'radius', 'float', shadow ).setGroup( renderGroup ); - const offset = vec2( - 1.0, 1.0 ).mul( radius ).mul( texelSize.y ); - - return texture( depthTexture, cubeToUV( bd3D.add( offset.xyy ), texelSize.y ) ).compare( dp ) - .add( texture( depthTexture, cubeToUV( bd3D.add( offset.yyy ), texelSize.y ) ).compare( dp ) ) - .add( texture( depthTexture, cubeToUV( bd3D.add( offset.xyx ), texelSize.y ) ).compare( dp ) ) - .add( texture( depthTexture, cubeToUV( bd3D.add( offset.yyx ), texelSize.y ) ).compare( dp ) ) - .add( texture( depthTexture, cubeToUV( bd3D, texelSize.y ) ).compare( dp ) ) - .add( texture( depthTexture, cubeToUV( bd3D.add( offset.xxy ), texelSize.y ) ).compare( dp ) ) - .add( texture( depthTexture, cubeToUV( bd3D.add( offset.yxy ), texelSize.y ) ).compare( dp ) ) - .add( texture( depthTexture, cubeToUV( bd3D.add( offset.xxx ), texelSize.y ) ).compare( dp ) ) - .add( texture( depthTexture, cubeToUV( bd3D.add( offset.yxx ), texelSize.y ) ).compare( dp ) ) + const mapSize = reference( 'mapSize', 'vec2', shadow ).setGroup( renderGroup ); + + const texelSize = float( 1 ).div( mapSize.x ); + const offset = vec2( - 1.0, 1.0 ).mul( radius ).mul( texelSize ); + + return cubeTexture( depthTexture, bd3D.add( offset.xyy ) ).compare( dp ) + .add( cubeTexture( depthTexture, bd3D.add( offset.yyy ) ).compare( dp ) ) + .add( cubeTexture( depthTexture, bd3D.add( offset.xyx ) ).compare( dp ) ) + .add( cubeTexture( depthTexture, bd3D.add( offset.yyx ) ).compare( dp ) ) + .add( cubeTexture( depthTexture, bd3D ).compare( dp ) ) + .add( cubeTexture( depthTexture, bd3D.add( offset.xxy ) ).compare( dp ) ) + .add( cubeTexture( depthTexture, bd3D.add( offset.yxy ) ).compare( dp ) ) + .add( cubeTexture( depthTexture, bd3D.add( offset.xxx ) ).compare( dp ) ) + .add( cubeTexture( depthTexture, bd3D.add( offset.yxx ) ).compare( dp ) ) .mul( 1.0 / 9.0 ); } ); @@ -175,7 +76,6 @@ const pointShadowFilter = /*@__PURE__*/ Fn( ( { filterFn, depthTexture, shadowCo const cameraNearLocal = uniform( 'float' ).setGroup( renderGroup ).onRenderUpdate( () => shadow.camera.near ); const cameraFarLocal = uniform( 'float' ).setGroup( renderGroup ).onRenderUpdate( () => shadow.camera.far ); const bias = reference( 'bias', 'float', shadow ).setGroup( renderGroup ); - const mapSize = uniform( shadow.mapSize ).setGroup( renderGroup ); const result = float( 1.0 ).toVar(); @@ -185,12 +85,11 @@ const pointShadowFilter = /*@__PURE__*/ Fn( ( { filterFn, depthTexture, shadowCo const dp = lightToPositionLength.sub( cameraNearLocal ).div( cameraFarLocal.sub( cameraNearLocal ) ).toVar(); // need to clamp? dp.addAssign( bias ); - // bd3D = base direction 3D + // bd3D = base direction 3D (direction from light to fragment) const bd3D = lightToPosition.normalize(); - const texelSize = vec2( 1.0 ).div( mapSize.mul( vec2( 4.0, 2.0 ) ) ); - // percentage-closer filtering - result.assign( filterFn( { depthTexture, bd3D, dp, texelSize, shadow } ) ); + // percentage-closer filtering using cube texture sampling + result.assign( filterFn( { depthTexture, bd3D, dp, shadow } ) ); } ); @@ -198,10 +97,6 @@ const pointShadowFilter = /*@__PURE__*/ Fn( ( { filterFn, depthTexture, shadowCo } ); -const _viewport = /*@__PURE__*/ new Vector4(); -const _viewportSize = /*@__PURE__*/ new Vector2(); -const _shadowMapSize = /*@__PURE__*/ new Vector2(); - /** * Represents the shadow implementation for point light nodes. @@ -261,15 +156,35 @@ class PointShadowNode extends ShadowNode { * @param {NodeBuilder} builder - A reference to the current node builder. * @param {Object} inputs - A configuration object that defines the shadow filtering. * @param {Function} inputs.filterFn - This function defines the filtering type of the shadow map e.g. PCF. - * @param {Texture} inputs.shadowTexture - A reference to the shadow map's texture. - * @param {DepthTexture} inputs.depthTexture - A reference to the shadow map's texture data. + * @param {DepthTexture} inputs.depthTexture - A reference to the shadow map's depth texture. * @param {Node} inputs.shadowCoord - Shadow coordinates which are used to sample from the shadow map. * @param {LightShadow} inputs.shadow - The light shadow. * @return {Node} The result node of the shadow filtering. */ - setupShadowFilter( builder, { filterFn, shadowTexture, depthTexture, shadowCoord, shadow } ) { + setupShadowFilter( builder, { filterFn, depthTexture, shadowCoord, shadow } ) { + + return pointShadowFilter( { filterFn, depthTexture, shadowCoord, shadow } ); + + } + + /** + * Overwrites the default implementation to create a CubeRenderTarget with CubeDepthTexture. + * + * @param {LightShadow} shadow - The light shadow object. + * @param {NodeBuilder} builder - A reference to the current node builder. + * @return {Object} An object containing the shadow map and depth texture. + */ + setupRenderTarget( shadow, builder ) { + + const depthTexture = new CubeDepthTexture( shadow.mapSize.width ); + depthTexture.name = 'PointShadowDepthTexture'; + depthTexture.compareFunction = LessCompare; - return pointShadowFilter( { filterFn, shadowTexture, depthTexture, shadowCoord, shadow } ); + const shadowMap = builder.createCubeRenderTarget( shadow.mapSize.width ); + shadowMap.texture.name = 'PointShadowMap'; + shadowMap.depthTexture = depthTexture; + + return { shadowMap, depthTexture }; } @@ -287,12 +202,12 @@ class PointShadowNode extends ShadowNode { const camera = shadow.camera; const shadowMatrix = shadow.matrix; - _shadowMapSize.copy( shadow.mapSize ); - _shadowMapSize.multiply( _frameExtents ); - - shadowMap.setSize( _shadowMapSize.width, _shadowMapSize.height ); + // Select cube directions/ups based on coordinate system + const isWebGPU = renderer.coordinateSystem === WebGPUCoordinateSystem; + const cubeDirections = isWebGPU ? _cubeDirectionsWebGPU : _cubeDirectionsWebGL; + const cubeUps = isWebGPU ? _cubeUpsWebGPU : _cubeUpsWebGL; - _viewportSize.copy( shadow.mapSize ); + shadowMap.setSize( shadow.mapSize.width, shadow.mapSize.width ); // @@ -303,23 +218,13 @@ class PointShadowNode extends ShadowNode { renderer.autoClear = false; renderer.setClearColor( shadow.clearColor, shadow.clearAlpha ); - renderer.clear(); - - for ( let vp = 0; vp < 6; vp ++ ) { - - const viewport = _viewports[ vp ]; - - const x = _viewportSize.x * viewport.x; - const y = _shadowMapSize.y - _viewportSize.y - ( _viewportSize.y * viewport.y ); - _viewport.set( - x, - y, - _viewportSize.x * viewport.z, - _viewportSize.y * viewport.w - ); + // Render each cube face + for ( let face = 0; face < 6; face ++ ) { - shadowMap.viewport.copy( _viewport ); + // Set render target to the specific cube face + renderer.setRenderTarget( shadowMap, face ); + renderer.clear(); // Update shadow camera matrices for this face @@ -336,8 +241,8 @@ class PointShadowNode extends ShadowNode { camera.position.copy( _lightPositionWorld ); _lookTarget.copy( camera.position ); - _lookTarget.add( _cubeDirections[ vp ] ); - camera.up.copy( _cubeUps[ vp ] ); + _lookTarget.add( cubeDirections[ face ] ); + camera.up.copy( cubeUps[ face ] ); camera.lookAt( _lookTarget ); camera.updateMatrixWorld(); @@ -350,7 +255,7 @@ class PointShadowNode extends ShadowNode { const currentSceneName = scene.name; - scene.name = `Point Light Shadow [ ${ light.name || 'ID: ' + light.id } ] - Face ${ vp + 1 }`; + scene.name = `Point Light Shadow [ ${ light.name || 'ID: ' + light.id } ] - Face ${ face + 1 }`; renderer.render( scene, camera ); diff --git a/src/nodes/lighting/ShadowNode.js b/src/nodes/lighting/ShadowNode.js index 8d6f3fa6963433..3436c520eb8d04 100644 --- a/src/nodes/lighting/ShadowNode.js +++ b/src/nodes/lighting/ShadowNode.js @@ -2,6 +2,7 @@ import ShadowBaseNode, { shadowPositionWorld } from './ShadowBaseNode.js'; import { float, vec2, vec3, int, Fn, nodeObject } from '../tsl/TSLBase.js'; import { reference } from '../accessors/ReferenceNode.js'; import { texture, textureLoad } from '../accessors/TextureNode.js'; +import { cubeTexture } from '../accessors/CubeTextureNode.js'; import { normalWorld } from '../accessors/Normal.js'; import { mix, sqrt } from '../math/MathNode.js'; import { add } from '../math/OperatorNode.js'; @@ -516,11 +517,22 @@ class ShadowNode extends ShadowBaseNode { const shadowNode = this.setupShadowFilter( builder, { filterFn, shadowTexture: shadowMap.texture, depthTexture: shadowDepthTexture, shadowCoord, shadow, depthLayer: this.depthLayer } ); - let shadowColor = texture( shadowMap.texture, shadowCoord ); + let shadowColor; - if ( depthTexture.isArrayTexture ) { + if ( shadowMap.texture.isCubeTexture ) { - shadowColor = shadowColor.depth( this.depthLayer ); + // For cube shadow maps (point lights), use cubeTexture with vec3 coordinates + shadowColor = cubeTexture( shadowMap.texture, shadowCoord.xyz ); + + } else { + + shadowColor = texture( shadowMap.texture, shadowCoord ); + + if ( depthTexture.isArrayTexture ) { + + shadowColor = shadowColor.depth( this.depthLayer ); + + } } @@ -535,6 +547,12 @@ class ShadowNode extends ShadowBaseNode { return shadowOutput.toInspector( `${ inspectName } / Color`, () => { + if ( this.shadowMap.texture.isCubeTexture ) { + + return cubeTexture( this.shadowMap.texture ); + + } + return texture( this.shadowMap.texture ); } ).toInspector( `${ inspectName } / Depth`, () => { diff --git a/src/renderers/webgl-fallback/WebGLBackend.js b/src/renderers/webgl-fallback/WebGLBackend.js index 03bf06d182bfd9..167ef97af0cb0f 100644 --- a/src/renderers/webgl-fallback/WebGLBackend.js +++ b/src/renderers/webgl-fallback/WebGLBackend.js @@ -2151,6 +2151,12 @@ class WebGLBackend extends Backend { gl.framebufferTextureLayer( gl.FRAMEBUFFER, depthStyle, textureData.textureGPU, 0, layer ); + } else if ( descriptor.depthTexture.isCubeTexture ) { + + const cubeFace = this.renderer._activeCubeFace; + + gl.framebufferTexture2D( gl.FRAMEBUFFER, depthStyle, gl.TEXTURE_CUBE_MAP_POSITIVE_X + cubeFace, textureData.textureGPU, 0 ); + } else { gl.framebufferTexture2D( gl.FRAMEBUFFER, depthStyle, gl.TEXTURE_2D, textureData.textureGPU, 0 ); diff --git a/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js b/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js index 6e1d58f512b571..5453b739ea081f 100644 --- a/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js +++ b/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js @@ -621,6 +621,13 @@ ${ flowData.code } if ( shaderStage === 'fragment' ) { + // Cube shadow maps use vec4(direction, compareValue) + if ( texture.isCubeTexture ) { + + return `texture( ${ textureProperty }, vec4( ${ uvSnippet }, ${ compareSnippet } ) )`; + + } + if ( depthSnippet ) { if ( offsetSnippet ) { @@ -743,6 +750,10 @@ ${ flowData.code } snippet = `samplerCube ${ uniform.name };`; + } else if ( uniform.type === 'cubeDepthTexture' ) { + + snippet = `samplerCubeShadow ${ uniform.name };`; + } else if ( uniform.type === 'buffer' ) { const bufferNode = uniform.node; @@ -1549,7 +1560,7 @@ void main() { uniformGPU = new NodeSampledTexture( uniformNode.name, uniformNode.node, group ); bindings.push( uniformGPU ); - } else if ( type === 'cubeTexture' ) { + } else if ( type === 'cubeTexture' || type === 'cubeDepthTexture' ) { uniformGPU = new NodeSampledCubeTexture( uniformNode.name, uniformNode.node, group ); bindings.push( uniformGPU ); diff --git a/src/renderers/webgpu/WebGPUBackend.js b/src/renderers/webgpu/WebGPUBackend.js index 93cdc4cc9f6a93..10e92f45c92628 100644 --- a/src/renderers/webgpu/WebGPUBackend.js +++ b/src/renderers/webgpu/WebGPUBackend.js @@ -519,7 +519,7 @@ class WebGPUBackend extends Backend { const depthTextureData = this.get( renderContext.depthTexture ); const options = {}; - if ( renderContext.depthTexture.isArrayTexture ) { + if ( renderContext.depthTexture.isArrayTexture || renderContext.depthTexture.isCubeTexture ) { options.dimension = GPUTextureViewDimension.TwoD; options.arrayLayerCount = 1; diff --git a/src/renderers/webgpu/nodes/WGSLNodeBuilder.js b/src/renderers/webgpu/nodes/WGSLNodeBuilder.js index 0b11a860d7a157..bde04dd82d9dfa 100644 --- a/src/renderers/webgpu/nodes/WGSLNodeBuilder.js +++ b/src/renderers/webgpu/nodes/WGSLNodeBuilder.js @@ -802,7 +802,7 @@ class WGSLNodeBuilder extends NodeBuilder { const name = node.name; const type = node.type; - if ( type === 'texture' || type === 'cubeTexture' || type === 'storageTexture' || type === 'texture3D' ) { + if ( type === 'texture' || type === 'cubeTexture' || type === 'cubeDepthTexture' || type === 'storageTexture' || type === 'texture3D' ) { return name; @@ -928,7 +928,7 @@ class WGSLNodeBuilder extends NodeBuilder { const bindings = this.getBindGroupArray( groupName, shaderStage ); - if ( type === 'texture' || type === 'cubeTexture' || type === 'storageTexture' || type === 'texture3D' ) { + if ( type === 'texture' || type === 'cubeTexture' || type === 'cubeDepthTexture' || type === 'storageTexture' || type === 'texture3D' ) { let texture = null; @@ -946,7 +946,7 @@ class WGSLNodeBuilder extends NodeBuilder { } - } else if ( type === 'cubeTexture' ) { + } else if ( type === 'cubeTexture' || type === 'cubeDepthTexture' ) { texture = new NodeSampledCubeTexture( uniformNode.name, uniformNode.node, group, access ); @@ -1714,7 +1714,7 @@ ${ flowData.code } const groupName = uniform.groupNode.name; const uniformIndexes = this.bindingsIndexes[ groupName ]; - if ( uniform.type === 'texture' || uniform.type === 'cubeTexture' || uniform.type === 'storageTexture' || uniform.type === 'texture3D' ) { + if ( uniform.type === 'texture' || uniform.type === 'cubeTexture' || uniform.type === 'cubeDepthTexture' || uniform.type === 'storageTexture' || uniform.type === 'texture3D' ) { const texture = uniform.node.value; @@ -1744,7 +1744,11 @@ ${ flowData.code } } - if ( texture.isCubeTexture === true ) { + if ( texture.isCubeTexture === true && texture.isDepthTexture === true ) { + + textureType = 'texture_depth_cube'; + + } else if ( texture.isCubeTexture === true ) { textureType = 'texture_cube';