diff --git a/examples/jsm/tsl/display/SSGINode.js b/examples/jsm/tsl/display/SSGINode.js index 9202ef841fa9c7..26a139d1d8632f 100644 --- a/examples/jsm/tsl/display/SSGINode.js +++ b/examples/jsm/tsl/display/SSGINode.js @@ -1,5 +1,5 @@ -import { HalfFloatType, RenderTarget, Vector2, TempNode, QuadMesh, NodeMaterial, RendererUtils, MathUtils } from 'three/webgpu'; -import { clamp, normalize, reference, Fn, NodeUpdateType, uniform, vec4, passTexture, uv, logarithmicDepthToViewZ, viewZToPerspectiveDepth, getViewPosition, screenCoordinate, float, sub, fract, dot, vec2, rand, vec3, Loop, mul, PI, cos, sin, uint, cross, acos, sign, pow, luminance, If, max, abs, Break, sqrt, HALF_PI, div, ceil, shiftRight, convertToTexture, bool, getNormalFromDepth, countOneBits, interleavedGradientNoise } from 'three/tsl'; +import { RenderTarget, Vector2, TempNode, QuadMesh, NodeMaterial, RendererUtils, MathUtils, RGBFormat, RedFormat, UnsignedInt101111Type, UnsignedByteType } from 'three/webgpu'; +import { clamp, normalize, reference, Fn, NodeUpdateType, uniform, vec4, passTexture, uv, logarithmicDepthToViewZ, viewZToPerspectiveDepth, getViewPosition, screenCoordinate, float, sub, fract, dot, vec2, rand, vec3, Loop, mul, PI, cos, sin, uint, cross, acos, sign, pow, luminance, If, max, abs, Break, sqrt, HALF_PI, div, ceil, shiftRight, convertToTexture, bool, getNormalFromDepth, countOneBits, interleavedGradientNoise, property, outputStruct } from 'three/tsl'; const _quadMesh = /*@__PURE__*/ new QuadMesh(); const _size = /*@__PURE__*/ new Vector2(); @@ -267,13 +267,23 @@ class SSGINode extends TempNode { this._camera = camera; /** - * The render target the GI is rendered into. + * The render target the effect is rendered into. The first texture holds the GI, + * the second one the AO. * * @private * @type {RenderTarget} */ - this._ssgiRenderTarget = new RenderTarget( 1, 1, { depthBuffer: false, type: HalfFloatType } ); - this._ssgiRenderTarget.texture.name = 'SSGI'; + this._ssgiRenderTarget = new RenderTarget( 1, 1, { depthBuffer: false, count: 2 } ); + + const aoTexture = this._ssgiRenderTarget.textures[ 0 ]; + aoTexture.name = 'SSGI.AO'; + aoTexture.type = UnsignedByteType; + aoTexture.format = RedFormat; + + const giTexture = this._ssgiRenderTarget.textures[ 1 ]; + giTexture.name = 'SSGI.GI'; + giTexture.type = UnsignedInt101111Type; + giTexture.format = RGBFormat; /** * The material that is used to render the effect. @@ -285,23 +295,42 @@ class SSGINode extends TempNode { this._material.name = 'SSGI'; /** - * The result of the effect is represented as a separate texture node. + * The AO result of the effect is represented as a separate texture node. + * + * @private + * @type {PassTextureNode} + */ + this._aoNode = passTexture( this, this._ssgiRenderTarget.textures[ 0 ] ); + + /** + * The GI result of the effect is represented as a separate texture node. * * @private * @type {PassTextureNode} */ - this._textureNode = passTexture( this, this._ssgiRenderTarget.texture ); + this._giNode = passTexture( this, this._ssgiRenderTarget.textures[ 1 ] ); } /** - * Returns the result of the effect as a texture node. + * Returns the AO result of the effect as a texture node. * - * @return {PassTextureNode} A texture node that represents the result of the effect. + * @return {PassTextureNode} A texture node that represents the AO result of the effect. */ - getTextureNode() { + getAONode() { - return this._textureNode; + return this._aoNode; + + } + + /** + * Returns the GI result of the effect as a texture node. + * + * @return {PassTextureNode} A texture node that represents the GI result of the effect. + */ + getGINode() { + + return this._giNode; } @@ -357,9 +386,9 @@ class SSGINode extends TempNode { _quadMesh.material = this._material; _quadMesh.name = 'SSGI'; - // clear + // clear (white for the AO attachement) - renderer.setClearColor( 0x000000, 1 ); + renderer.setClearColor( 0xffffff, 1 ); // gi @@ -380,6 +409,14 @@ class SSGINode extends TempNode { */ setup( builder ) { + const renderer = builder.renderer; + + if ( renderer.backend.isWebGPUBackend === true && renderer.hasFeature( 'rg11b10ufloat-renderable' ) === false ) { + + console.error( 'THREE.SSGINode: The device does not support the "rg11b10ufloat-renderable" feature which is required for SSGI.' ); + + } + const uvNode = uv(); const MAX_RAY = uint( 32 ); const globalOccludedBitfield = uint( 0 ); @@ -519,6 +556,11 @@ class SSGINode extends TempNode { } ); + const aoField = property( 'float' ); + const giField = property( 'vec3' ); + + const outputNode = outputStruct( aoField, giField ); + const gi = Fn( () => { const depth = sampleDepth( uvNode ).toVar(); @@ -599,16 +641,20 @@ class SSGINode extends TempNode { const scale = currentLuminance.greaterThan( maxLuminance ).select( maxLuminance.div( currentLuminance ), float( 1 ) ); color.mulAssign( scale ); - return vec4( color, ao ); + aoField.assign( ao ); + giField.assign( color ); + + return vec4( 0 ); } ); - this._material.fragmentNode = gi().context( builder.getSharedContext() ); + this._material.colorNode = gi().context( builder.getSharedContext() ); + this._material.outputNode = outputNode; this._material.needsUpdate = true; // - return this._textureNode; + return this._aoNode; } diff --git a/examples/webgpu_postprocessing_ssgi.html b/examples/webgpu_postprocessing_ssgi.html index 33aa2cf12759cc..555da51624558c 100644 --- a/examples/webgpu_postprocessing_ssgi.html +++ b/examples/webgpu_postprocessing_ssgi.html @@ -118,10 +118,10 @@ // composite - const gi = giPass.rgb.toInspector( 'SSGI' ); - const ao = giPass.a.toInspector( 'AO' ); + const ao = giPass.getAONode().toInspector( 'SSGI.AO' ); + const gi = giPass.getGINode().toInspector( 'SSGI.GI' ); - const compositePass = vec4( add( scenePassColor.rgb.mul( ao ), ( scenePassDiffuse.rgb.mul( gi ) ) ), scenePassColor.a ); + const compositePass = vec4( add( scenePassColor.rgb.mul( ao.r ), ( scenePassDiffuse.rgb.mul( gi.rgb ) ) ), scenePassColor.a ); compositePass.name = 'Composite'; // traa diff --git a/examples/webgpu_postprocessing_ssgi_ballpool.html b/examples/webgpu_postprocessing_ssgi_ballpool.html index 2c8f7453ebbd4c..baabd6668013a6 100644 --- a/examples/webgpu_postprocessing_ssgi_ballpool.html +++ b/examples/webgpu_postprocessing_ssgi_ballpool.html @@ -137,11 +137,11 @@ // composite - const gi = giPass.rgb.toInspector( 'SSGI' ); - const ao = giPass.a.toInspector( 'AO' ); + const ao = giPass.getAONode().toInspector( 'SSGI.AO' ); + const gi = giPass.getGINode().toInspector( 'SSGI.GI' ); const compositePass = vec4( - add( scenePassColor.rgb.mul( ao ), scenePassDiffuse.rgb.mul( gi ) ), + add( scenePassColor.rgb.mul( ao.r ), scenePassDiffuse.rgb.mul( gi.rgb ) ), scenePassColor.a ); diff --git a/src/math/Matrix4.js b/src/math/Matrix4.js index f30cf4ec4e6764..fdac88099c0c24 100644 --- a/src/math/Matrix4.js +++ b/src/math/Matrix4.js @@ -655,7 +655,7 @@ class Matrix4 { * * For affine matrices (like an object's world matrix), this value equals the * full 4x4 {@link Matrix4#determinant} but is cheaper to compute. - * + * * Assumes the bottom row is [0, 0, 0, 1]. * * @return {number} The determinant of the matrix. diff --git a/src/renderers/webgl/WebGLPrograms.js b/src/renderers/webgl/WebGLPrograms.js index 9c50b355b83097..533954cf35d17d 100644 --- a/src/renderers/webgl/WebGLPrograms.js +++ b/src/renderers/webgl/WebGLPrograms.js @@ -108,10 +108,13 @@ function WebGLPrograms( renderer, environments, extensions, capabilities, bindin vertexShader = material.vertexShader; fragmentShader = material.fragmentShader; - _customShaders.update( material ); + const vertexShaderStage = _customShaders.getVertexShaderStage( material ); + const fragmentShaderStage = _customShaders.getFragmentShaderStage( material ); - customVertexShaderID = _customShaders.getVertexShaderID( material ); - customFragmentShaderID = _customShaders.getFragmentShaderID( material ); + _customShaders.update( material, vertexShaderStage, fragmentShaderStage ); + + customVertexShaderID = vertexShaderStage.id; + customFragmentShaderID = fragmentShaderStage.id; } diff --git a/src/renderers/webgl/WebGLShaderCache.js b/src/renderers/webgl/WebGLShaderCache.js index 4e0fffcbb035c5..01f83e287f62fd 100644 --- a/src/renderers/webgl/WebGLShaderCache.js +++ b/src/renderers/webgl/WebGLShaderCache.js @@ -9,13 +9,7 @@ class WebGLShaderCache { } - update( material ) { - - const vertexShader = material.vertexShader; - const fragmentShader = material.fragmentShader; - - const vertexShaderStage = this._getShaderStage( vertexShader ); - const fragmentShaderStage = this._getShaderStage( fragmentShader ); + update( material, vertexShaderStage, fragmentShaderStage ) { const materialShaders = this._getShaderCacheForMaterial( material ); @@ -55,15 +49,15 @@ class WebGLShaderCache { } - getVertexShaderID( material ) { + getVertexShaderStage( material ) { - return this._getShaderStage( material.vertexShader ).id; + return this._getShaderStage( material.vertexShader ); } - getFragmentShaderID( material ) { + getFragmentShaderStage( material ) { - return this._getShaderStage( material.fragmentShader ).id; + return this._getShaderStage( material.fragmentShader ); }