Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 19 additions & 5 deletions examples/webgpu_postprocessing_bloom_emissive.html
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
<script type="module">

import * as THREE from 'three/webgpu';
import { pass, mrt, output, emissive } from 'three/tsl';
import { pass, mrt, output, emissive, vec4 } from 'three/tsl';
import { bloom } from 'three/addons/tsl/display/BloomNode.js';

import { HDRLoader } from 'three/addons/loaders/HDRLoader.js';
Expand Down Expand Up @@ -92,10 +92,24 @@
//

const scenePass = pass( scene, camera );
scenePass.setMRT( mrt( {
output,
emissive
} ) );

// set up MRT with emissive

const mrtNode = mrt( {
output: output,
emissive: vec4( emissive, output.a )
} );

mrtNode.setBlendMode( 'emissive', new THREE.BlendMode( THREE.NormalBlending ) );

scenePass.setMRT( mrtNode );

// optimize the bandwidth

const emissiveTexture = scenePass.getTexture( 'emissive' );
emissiveTexture.type = THREE.UnsignedByteType;

//

const outputPass = scenePass.getTextureNode().toInspector( 'Color' );
const emissivePass = scenePass.getTextureNode( 'emissive' ).toInspector( 'Emissive' );
Expand Down
1 change: 1 addition & 0 deletions src/Three.WebGPU.Nodes.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export { default as NodeObjectLoader } from './loaders/nodes/NodeObjectLoader.js
export { default as NodeMaterialLoader } from './loaders/nodes/NodeMaterialLoader.js';
export { default as InspectorBase } from './renderers/common/InspectorBase.js';
export { default as CanvasTarget } from './renderers/common/CanvasTarget.js';
export { default as BlendMode } from './renderers/common/BlendMode.js';
export { ClippingGroup } from './objects/ClippingGroup.js';
export * from './nodes/Nodes.js';
import * as TSL from './nodes/TSL.js';
Expand Down
1 change: 1 addition & 0 deletions src/Three.WebGPU.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export { default as NodeObjectLoader } from './loaders/nodes/NodeObjectLoader.js
export { default as NodeMaterialLoader } from './loaders/nodes/NodeMaterialLoader.js';
export { default as InspectorBase } from './renderers/common/InspectorBase.js';
export { default as CanvasTarget } from './renderers/common/CanvasTarget.js';
export { default as BlendMode } from './renderers/common/BlendMode.js';
export { ClippingGroup } from './objects/ClippingGroup.js';
export * from './nodes/Nodes.js';
import * as TSL from './nodes/TSL.js';
Expand Down
8 changes: 8 additions & 0 deletions src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,14 @@ export const MultiplyBlending = 4;
*/
export const CustomBlending = 5;

/**
* Represents material blending.
*
* @type {number}
* @constant
*/
export const MaterialBlending = 6;

/**
* A `source + destination` blending equation.
*
Expand Down
48 changes: 47 additions & 1 deletion src/nodes/core/MRTNode.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import OutputStructNode from './OutputStructNode.js';
import { nodeProxy, vec4 } from '../tsl/TSLBase.js';
import { MaterialBlending, NoBlending } from '../../constants.js';
import BlendMode from '../../renderers/common/BlendMode.js';

// Predefined blend modes for MRT nodes.
const _noBlending = /**@__PURE__*/ new BlendMode( NoBlending );
const _materialBlending = /**@__PURE__*/ new BlendMode( MaterialBlending );

/**
* Returns the MRT texture index for the given name.
Expand Down Expand Up @@ -63,6 +69,15 @@ class MRTNode extends OutputStructNode {
*/
this.outputNodes = outputNodes;

/**
* A dictionary storing the blend modes for each output.
*
* @type {Object<string, BlendMode>}
*/
this.blendModes = {
output: _materialBlending
};

/**
* This flag can be used for type testing.
*
Expand All @@ -74,6 +89,33 @@ class MRTNode extends OutputStructNode {

}

/**
* Sets the blend mode for the given output name.
*
* @param {string} name - The name of the output.
* @param {BlendMode} blend - The blending mode.
* @return {MRTNode} The current MRT node.
*/
setBlendMode( name, blend ) {

this.blendModes[ name ] = blend;

return this;

}

/**
* Returns the blend mode for the given output name.
*
* @param {string} name - The name of the output.
* @return {BlendMode} The blend mode.
*/
getBlendMode( name ) {

return this.blendModes[ name ] || _noBlending;

}

/**
* Returns `true` if the MRT node has an output with the given name.
*
Expand Down Expand Up @@ -107,8 +149,12 @@ class MRTNode extends OutputStructNode {
merge( mrtNode ) {

const outputs = { ...this.outputNodes, ...mrtNode.outputNodes };
const blendings = { ...this.blendModes, ...mrtNode.blendModes };

const mrtTarget = mrt( outputs );
mrtTarget.blendings = blendings;

return mrt( outputs );
return mrtTarget;

}

Expand Down
20 changes: 10 additions & 10 deletions src/nodes/utils/DebugNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,21 +42,21 @@ class DebugNode extends TempNode {
const callback = this.callback;
const snippet = this.node.build( builder );

const title = '--- TSL debug - ' + builder.shaderStage + ' shader ---';
const border = '-'.repeat( title.length );

let code = '';
code += '// #' + title + '#\n';
code += builder.flow.code.replace( /^\t/mg, '' ) + '\n';
code += '/* ... */ ' + snippet + ' /* ... */\n';
code += '// #' + border + '#\n';

if ( callback !== null ) {

callback( builder, code );
callback( builder, snippet );

} else {

const title = '--- TSL debug - ' + builder.shaderStage + ' shader ---';
const border = '-'.repeat( title.length );

let code = '';
code += '// #' + title + '#\n';
code += builder.flow.code.replace( /^\t/mg, '' ) + '\n';
code += '/* ... */ ' + snippet + ' /* ... */\n';
code += '// #' + border + '#\n';

log( code );

}
Expand Down
143 changes: 143 additions & 0 deletions src/renderers/common/BlendMode.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
import { NormalBlending, AddEquation, SrcAlphaFactor, OneMinusSrcAlphaFactor } from '../../constants.js';

/**
* Represents blending configuration.
*
* This class encapsulates all blending-related properties that control how
* a material's colors are combined with the colors already in the frame buffer.
*/
class BlendMode {

/**
* Constructs a new blending configuration.
*
* @param {(NoBlending|NormalBlending|AdditiveBlending|SubtractiveBlending|MultiplyBlending|CustomBlending|MaterialBlending)} [blending=NormalBlending] - The blending mode.
*/
constructor( blending = NormalBlending ) {

/**
* Defines the blending type.
*
* It must be set to `CustomBlending` if custom blending properties like
* {@link BlendMode#blendSrc}, {@link BlendMode#blendDst} or {@link BlendMode#blendEquation}
* should have any effect.
*
* @type {(NoBlending|NormalBlending|AdditiveBlending|SubtractiveBlending|MultiplyBlending|CustomBlending|MaterialBlending)}
* @default NormalBlending
*/
this.blending = blending;

/**
* Defines the blending source factor.
*
* This determines how the source (incoming) fragment color is factored before being added
* to the destination (existing) fragment color in the frame buffer.
*
* @type {(ZeroFactor|OneFactor|SrcColorFactor|OneMinusSrcColorFactor|SrcAlphaFactor|OneMinusSrcAlphaFactor|DstAlphaFactor|OneMinusDstAlphaFactor|DstColorFactor|OneMinusDstColorFactor|SrcAlphaSaturateFactor|ConstantColorFactor|OneMinusConstantColorFactor|ConstantAlphaFactor|OneMinusConstantAlphaFactor)}
* @default SrcAlphaFactor
*/
this.blendSrc = SrcAlphaFactor;

/**
* Defines the blending destination factor.
*
* This determines how the destination (existing) fragment color in the frame buffer
* is factored before being combined with the source (incoming) fragment color.
*
* @type {(ZeroFactor|OneFactor|SrcColorFactor|OneMinusSrcColorFactor|SrcAlphaFactor|OneMinusSrcAlphaFactor|DstAlphaFactor|OneMinusDstAlphaFactor|DstColorFactor|OneMinusDstColorFactor|SrcAlphaSaturateFactor|ConstantColorFactor|OneMinusConstantColorFactor|ConstantAlphaFactor|OneMinusConstantAlphaFactor)}
* @default OneMinusSrcAlphaFactor
*/
this.blendDst = OneMinusSrcAlphaFactor;

/**
* Defines the blending equation.
*
* This determines how the source and destination colors are combined.
*
* @type {(AddEquation|SubtractEquation|ReverseSubtractEquation|MinEquation|MaxEquation)}
* @default AddEquation
*/
this.blendEquation = AddEquation;

/**
* Defines the blending source alpha factor.
*
* When set, this allows separate control of the alpha channel's source blending factor.
* If `null`, {@link BlendMode#blendSrc} is used for the alpha channel as well.
*
* @type {?(ZeroFactor|OneFactor|SrcColorFactor|OneMinusSrcColorFactor|SrcAlphaFactor|OneMinusSrcAlphaFactor|DstAlphaFactor|OneMinusDstAlphaFactor|DstColorFactor|OneMinusDstColorFactor|SrcAlphaSaturateFactor|ConstantColorFactor|OneMinusConstantColorFactor|ConstantAlphaFactor|OneMinusConstantAlphaFactor)}
* @default null
*/
this.blendSrcAlpha = null;

/**
* Defines the blending destination alpha factor.
*
* When set, this allows separate control of the alpha channel's destination blending factor.
* If `null`, {@link BlendMode#blendDst} is used for the alpha channel as well.
*
* @type {?(ZeroFactor|OneFactor|SrcColorFactor|OneMinusSrcColorFactor|SrcAlphaFactor|OneMinusSrcAlphaFactor|DstAlphaFactor|OneMinusDstAlphaFactor|DstColorFactor|OneMinusDstColorFactor|SrcAlphaSaturateFactor|ConstantColorFactor|OneMinusConstantColorFactor|ConstantAlphaFactor|OneMinusConstantAlphaFactor)}
* @default null
*/
this.blendDstAlpha = null;

/**
* Defines the blending equation of the alpha channel.
*
* When set, this allows separate control of the alpha channel's blending equation.
* If `null`, {@link BlendMode#blendEquation} is used for the alpha channel as well.
*
* @type {?(AddEquation|SubtractEquation|ReverseSubtractEquation|MinEquation|MaxEquation)}
* @default null
*/
this.blendEquationAlpha = null;

/**
* Defines whether to premultiply the alpha (transparency) value.
*
* If `true`, the RGB color of the texture or material is multiplied by its alpha value.
* This is useful for transparent textures/materials where the color data
* should already include the transparency information.
*
* @type {boolean}
* @default false
*/
this.premultiplyAlpha = false;

}

/**
* Copies the blending properties from the given source to this instance.
*
* @param {BlendMode} source - The blending configuration to copy from.
* @return {BlendMode} A reference to this instance.
*/
copy( source ) {

this.blending = source.blending;
this.blendSrc = source.blendSrc;
this.blendDst = source.blendDst;
this.blendEquation = source.blendEquation;
this.blendSrcAlpha = source.blendSrcAlpha;
this.blendDstAlpha = source.blendDstAlpha;
this.blendEquationAlpha = source.blendEquationAlpha;
this.premultiplyAlpha = source.premultiplyAlpha;

return this;

}

/**
* Returns a clone of this blending configuration.
*
* @return {BlendMode} A new Blending instance with the same properties.
*/
clone() {

return new this.constructor().copy( this );

}

}

export default BlendMode;
8 changes: 8 additions & 0 deletions src/renderers/common/RenderContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ class RenderContext {
*/
this.id = _id ++;

/**
* The MRT configuration.
*
* @type {?MRTNode}
* @default null
*/
this.mrt = null;

/**
* Whether the current active framebuffer has a color attachment.
*
Expand Down
3 changes: 2 additions & 1 deletion src/renderers/common/RenderContexts.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,9 @@ class RenderContexts {
if ( renderState === undefined ) {

renderState = new RenderContext();
renderState.mrt = mrt;

this._renderContexts[ renderStateKey ] = renderState;
this._renderContexts[ renderStateKey ] = renderState;

}

Expand Down
4 changes: 2 additions & 2 deletions src/renderers/webgl-fallback/WebGLBackend.js
Original file line number Diff line number Diff line change
Expand Up @@ -958,9 +958,9 @@ class WebGLBackend extends Backend {

state.setMaterial( material, frontFaceCW, hardwareClippingPlanes );

if ( context.textures !== null && context.textures.length > 1 ) {
if ( context.mrt !== null && context.textures !== null ) {

state.setMRTBlending( context.textures );
state.setMRTBlending( context.textures, context.mrt, material );

}

Expand Down
Loading