From 7ccf29005e0c9a68d902d2f8886aab2f5855e6b5 Mon Sep 17 00:00:00 2001 From: sunag Date: Tue, 31 Mar 2026 10:49:24 -0300 Subject: [PATCH] improve support for output types --- src/materials/nodes/NodeMaterial.js | 10 +-- src/nodes/core/NodeBuilder.js | 64 +++++++++++++++++-- .../webgl-fallback/nodes/GLSLNodeBuilder.js | 6 +- src/renderers/webgpu/nodes/WGSLNodeBuilder.js | 16 ++++- .../webgpu/utils/WebGPUBindingUtils.js | 2 +- 5 files changed, 77 insertions(+), 21 deletions(-) diff --git a/src/materials/nodes/NodeMaterial.js b/src/materials/nodes/NodeMaterial.js index a6a736c6d2ac96..e67d2b74ce9b4a 100644 --- a/src/materials/nodes/NodeMaterial.js +++ b/src/materials/nodes/NodeMaterial.js @@ -592,15 +592,7 @@ class NodeMaterial extends Material { } else { - let fragmentNode = this.fragmentNode; - - if ( fragmentNode.isOutputStructNode !== true ) { - - fragmentNode = vec4( fragmentNode ); - - } - - resultNode = this.setupOutput( builder, fragmentNode ); + resultNode = this.setupOutput( builder, this.fragmentNode ); } diff --git a/src/nodes/core/NodeBuilder.js b/src/nodes/core/NodeBuilder.js index b76a701ad00693..539fc8c93504e5 100644 --- a/src/nodes/core/NodeBuilder.js +++ b/src/nodes/core/NodeBuilder.js @@ -23,7 +23,7 @@ import CubeRenderTarget from '../../renderers/common/CubeRenderTarget.js'; import BindGroup from '../../renderers/common/BindGroup.js'; -import { REVISION, IntType, UnsignedIntType, LinearFilter, LinearMipmapNearestFilter, NearestMipmapLinearFilter, LinearMipmapLinearFilter, NormalBlending } from '../../constants.js'; +import { REVISION, IntType, UnsignedIntType, LinearFilter, LinearMipmapNearestFilter, NearestMipmapLinearFilter, LinearMipmapLinearFilter, NormalBlending, RedFormat, RGFormat, RGBFormat, RedIntegerFormat, RGIntegerFormat, RGBIntegerFormat } from '../../constants.js'; import { RenderTarget } from '../../core/RenderTarget.js'; import { Color } from '../../math/Color.js'; import { Vector2 } from '../../math/Vector2.js'; @@ -534,6 +534,60 @@ class NodeBuilder { } + /** + * Returns the type of the color output based on the renderer's render target. + * + * @return {string} The type. + */ + getOutputType() { + + let type = 'vec4'; + + const renderTarget = this.renderer.getRenderTarget(); + + if ( renderTarget !== null ) { + + const renderTargetType = renderTarget.texture.type; + const renderTargetFormat = renderTarget.texture.format; + + let typeStr = 'vec'; + + if ( renderTargetType === IntType ) { + + typeStr = 'ivec'; + + } else if ( renderTargetType === UnsignedIntType ) { + + typeStr = 'uvec'; + + } + + if ( renderTargetFormat === RedFormat || renderTargetFormat === RedIntegerFormat ) { + + if ( renderTargetType === IntType ) type = 'int'; + else if ( renderTargetType === UnsignedIntType ) type = 'uint'; + else type = 'float'; + + } else if ( renderTargetFormat === RGFormat || renderTargetFormat === RGIntegerFormat ) { + + type = `${ typeStr }2`; + + } else if ( renderTargetFormat === RGBFormat || renderTargetFormat === RGBIntegerFormat ) { + + type = `${ typeStr }3`; + + } else { + + type = `${ typeStr }4`; + + } + + } + + return type; + + } + /** * Returns the output struct name which is required by * {@link OutputStructNode}. @@ -1468,12 +1522,10 @@ class NodeBuilder { const type = texture.type; - if ( texture.isDataTexture ) { + if ( texture.isDepthTexture === true ) return 'float'; - if ( type === IntType ) return 'int'; - if ( type === UnsignedIntType ) return 'uint'; - - } + if ( type === IntType ) return 'int'; + if ( type === UnsignedIntType ) return 'uint'; return 'float'; diff --git a/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js b/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js index 98fdf8702719f8..40ef3ad6b073a0 100644 --- a/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js +++ b/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js @@ -974,7 +974,7 @@ ${ flowData.code } if ( outputSnippet.length === 0 ) { - outputSnippet.push( 'layout( location = 0 ) out vec4 fragColor;' ); + outputSnippet.push( `layout( location = 0 ) out ${ this.getOutputType() } fragColor;` ); } @@ -1529,14 +1529,14 @@ void main() { if ( shaderStage === 'vertex' ) { flow += 'gl_Position = '; - flow += `${ flowSlotData.result };`; + flow += `${ this.format( flowSlotData.result, mainNode.getNodeType( this ), 'vec4' ) };`; } else if ( shaderStage === 'fragment' ) { if ( ! node.outputNode.isOutputStructNode ) { flow += 'fragColor = '; - flow += `${ flowSlotData.result };`; + flow += `${ this.format( flowSlotData.result, mainNode.getNodeType( this ), this.getOutputType() ) };`; } diff --git a/src/renderers/webgpu/nodes/WGSLNodeBuilder.js b/src/renderers/webgpu/nodes/WGSLNodeBuilder.js index 9aadc494186446..69e491468ec1f5 100644 --- a/src/renderers/webgpu/nodes/WGSLNodeBuilder.js +++ b/src/renderers/webgpu/nodes/WGSLNodeBuilder.js @@ -2126,7 +2126,7 @@ ${ flowData.code } } else { - let structSnippet = '\t@location( 0 ) color: vec4'; + let structSnippet = `\t@location( 0 ) color: ${ this.getOutputType() }`; const builtins = this.getBuiltins( 'output' ); @@ -2136,7 +2136,7 @@ ${ flowData.code } stageData.structs += this._getWGSLStruct( 'OutputStruct', structSnippet ); stageData.structs += '\nvar output : OutputStruct;'; - flow += `output.color = ${ flowSlotData.result };\n\n\treturn output;`; + flow += `output.color = ${ this.format( flowSlotData.result, mainNode.getNodeType( this ), this.getOutputType() ) };\n\n\treturn output;`; } @@ -2260,6 +2260,18 @@ ${ flowData.code } } + /** + * Returns the type of the color output based on the renderer's render target. + * + * @return {string} The WGSL type. + */ + getOutputType() { + + return this.getType( super.getOutputType() ); + + } + + /** * Whether the requested feature is available or not. * diff --git a/src/renderers/webgpu/utils/WebGPUBindingUtils.js b/src/renderers/webgpu/utils/WebGPUBindingUtils.js index 2f9488d22deacc..a5c33cec45a319 100644 --- a/src/renderers/webgpu/utils/WebGPUBindingUtils.js +++ b/src/renderers/webgpu/utils/WebGPUBindingUtils.js @@ -520,7 +520,7 @@ class WebGPUBindingUtils { } - } else if ( binding.texture.isDataTexture || binding.texture.isDataArrayTexture || binding.texture.isData3DTexture || binding.texture.isStorageTexture ) { + } else { const type = binding.texture.type;