diff --git a/src/renderers/common/Constants.js b/src/renderers/common/Constants.js index dae2803e2b1fc2..b552356c491edc 100644 --- a/src/renderers/common/Constants.js +++ b/src/renderers/common/Constants.js @@ -8,8 +8,3 @@ export const AttributeType = { // size of a chunk in bytes (STD140 layout) export const GPU_CHUNK_BYTES = 16; - -// @TODO: Move to src/constants.js - -export const BlendColorFactor = 211; -export const OneMinusBlendColorFactor = 212; diff --git a/src/renderers/webgl-fallback/utils/WebGLState.js b/src/renderers/webgl-fallback/utils/WebGLState.js index beae95be961b5b..611de66dc084c3 100644 --- a/src/renderers/webgl-fallback/utils/WebGLState.js +++ b/src/renderers/webgl-fallback/utils/WebGLState.js @@ -4,9 +4,11 @@ import { AdditiveBlending, SubtractiveBlending, MultiplyBlending, SubtractEquation, ReverseSubtractEquation, MinEquation, MaxEquation, ZeroFactor, OneFactor, SrcColorFactor, SrcAlphaFactor, SrcAlphaSaturateFactor, DstColorFactor, DstAlphaFactor, OneMinusSrcColorFactor, OneMinusSrcAlphaFactor, OneMinusDstColorFactor, OneMinusDstAlphaFactor, + ConstantColorFactor, OneMinusConstantColorFactor, ConstantAlphaFactor, OneMinusConstantAlphaFactor, NeverDepth, AlwaysDepth, LessDepth, LessEqualDepth, EqualDepth, GreaterEqualDepth, GreaterDepth, NotEqualDepth, MaterialBlending } from '../../../constants.js'; +import { Color } from '../../../math/Color.js'; import { Vector4 } from '../../../math/Vector4.js'; import { error, ReversedDepthFuncs, warnOnce } from '../../../utils.js'; @@ -62,6 +64,8 @@ class WebGLState { this.currentBlendDst = null; this.currentBlendSrcAlpha = null; this.currentBlendDstAlpha = null; + this.currentBlendColor = new Color( 0, 0, 0 ); + this.currentBlendAlpha = 0; this.currentPremultipledAlpha = null; this.currentPolygonOffsetFactor = null; this.currentPolygonOffsetUnits = null; @@ -124,7 +128,11 @@ class WebGLState { [ OneMinusSrcColorFactor ]: gl.ONE_MINUS_SRC_COLOR, [ OneMinusSrcAlphaFactor ]: gl.ONE_MINUS_SRC_ALPHA, [ OneMinusDstColorFactor ]: gl.ONE_MINUS_DST_COLOR, - [ OneMinusDstAlphaFactor ]: gl.ONE_MINUS_DST_ALPHA + [ OneMinusDstAlphaFactor ]: gl.ONE_MINUS_DST_ALPHA, + [ ConstantColorFactor ]: gl.CONSTANT_COLOR, + [ OneMinusConstantColorFactor ]: gl.ONE_MINUS_CONSTANT_COLOR, + [ ConstantAlphaFactor ]: gl.CONSTANT_ALPHA, + [ OneMinusConstantAlphaFactor ]: gl.ONE_MINUS_CONSTANT_ALPHA }; const scissorParam = gl.getParameter( gl.SCISSOR_BOX ); @@ -426,7 +434,7 @@ class WebGLState { * Defines the blending. * * This method caches the state so `gl.blendEquation()`, `gl.blendEquationSeparate()`, - * `gl.blendFunc()` and `gl.blendFuncSeparate()` are only called when necessary. + * `gl.blendFunc()`, `gl.blendFuncSeparate()` and `gl.blendColor()` are only called when necessary. * * @param {number} blending - The blending type. * @param {number} blendEquation - The blending equation. @@ -435,9 +443,11 @@ class WebGLState { * @param {number} blendEquationAlpha - Only relevant for custom blending. The blending equation for alpha. * @param {number} blendSrcAlpha - Only relevant for custom blending. The alpha source blending factor. * @param {number} blendDstAlpha - Only relevant for custom blending. The alpha destination blending factor. + * @param {Color} blendColor - Only relevant for custom blending. The RGB values of the constant blend color. + * @param {number} blendAlpha - Only relevant for custom blending. The alpha value of the constant blend color. * @param {boolean} premultipliedAlpha - Whether premultiplied alpha is enabled or not. */ - setBlending( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, premultipliedAlpha ) { + setBlending( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, blendColor, blendAlpha, premultipliedAlpha ) { const { gl } = this; @@ -568,6 +578,15 @@ class WebGLState { } + if ( blendColor.equals( this.currentBlendColor ) === false || blendAlpha !== this.currentBlendAlpha ) { + + gl.blendColor( blendColor.r, blendColor.g, blendColor.b, blendAlpha ); + + this.currentBlendColor.copy( blendColor ); + this.currentBlendAlpha = blendAlpha; + + } + this.currentBlending = blending; this.currentPremultipledAlpha = false; @@ -917,7 +936,7 @@ class WebGLState { ( material.blending === NormalBlending && material.transparent === false ) ? this.setBlending( NoBlending ) - : this.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha ); + : this.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.blendColor, material.blendAlpha, material.premultipliedAlpha ); this.setDepthFunc( material.depthFunc ); this.setDepthTest( material.depthTest ); @@ -1444,6 +1463,8 @@ class WebGLState { this.currentBlendDst = null; this.currentBlendSrcAlpha = null; this.currentBlendDstAlpha = null; + this.currentBlendColor.set( 0, 0, 0 ); + this.currentBlendAlpha = 0; this.currentPremultipledAlpha = null; this.currentPolygonOffsetFactor = null; this.currentPolygonOffsetUnits = null; diff --git a/src/renderers/webgpu/WebGPUBackend.js b/src/renderers/webgpu/WebGPUBackend.js index d3240855849123..3dba9f86059e4c 100644 --- a/src/renderers/webgpu/WebGPUBackend.js +++ b/src/renderers/webgpu/WebGPUBackend.js @@ -13,7 +13,8 @@ import WebGPUCapabilities from './utils/WebGPUCapabilities.js'; import WebGPUPipelineUtils from './utils/WebGPUPipelineUtils.js'; import WebGPUTextureUtils from './utils/WebGPUTextureUtils.js'; -import { WebGPUCoordinateSystem, TimestampQuery, REVISION, HalfFloatType, Compatibility } from '../../constants.js'; +import { WebGPUCoordinateSystem, TimestampQuery, REVISION, HalfFloatType, Compatibility, CustomBlending } from '../../constants.js'; +import { Color } from '../../math/Color.js'; import WebGPUTimestampQueryPool from './utils/WebGPUTimestampQueryPool.js'; import { error } from '../../utils.js'; @@ -32,6 +33,7 @@ import GPUTextureViewDescriptor from './descriptors/GPUTextureViewDescriptor.js' import GPUExtent3D from './descriptors/GPUExtent3D.js'; const _clearValue = { r: 0, g: 0, b: 0, a: 1 }; +const _blendConstant = { r: 0, g: 0, b: 0, a: 0 }; const _bufferDescriptor = new GPUBufferDescriptor(); const _commandEncoderDescriptor = new GPUCommandEncoderDescriptor(); const _computePassDescriptor = new GPUComputePassDescriptor(); @@ -1122,9 +1124,31 @@ class WebGPUBackend extends Backend { renderContextData.descriptor = descriptor; renderContextData.encoder = encoder; - renderContextData.currentSets = { attributes: {}, bindingGroups: [], pipeline: null, index: null }; renderContextData.renderBundles = []; + this._resetRenderContextData( renderContextData ); + + } + + /** + * Resets the state cache of the given render context data. + * + * A new render pass encoder starts with a blend constant and a stencil reference + * of zero so the cached values must be reset as well. + * + * @private + * @param {Object} renderContextData - The render context data. + */ + _resetRenderContextData( renderContextData ) { + + renderContextData.currentSets = { attributes: {}, bindingGroups: [], pipeline: null, index: null }; + + if ( renderContextData.currentBlendColor === undefined ) renderContextData.currentBlendColor = new Color(); + + renderContextData.currentBlendColor.setRGB( 0, 0, 0 ); + renderContextData.currentBlendAlpha = 0; + renderContextData.currentStencilRef = 0; + } /** @@ -2062,6 +2086,29 @@ class WebGPUBackend extends Backend { } + // blend constant + + if ( material.blending === CustomBlending && passEncoderGPU.setBlendConstant !== undefined ) { + + const blendColor = material.blendColor; + const blendAlpha = material.blendAlpha; + + if ( blendColor.equals( renderContextData.currentBlendColor ) === false || blendAlpha !== renderContextData.currentBlendAlpha ) { + + _blendConstant.r = blendColor.r; + _blendConstant.g = blendColor.g; + _blendConstant.b = blendColor.b; + _blendConstant.a = blendAlpha; + + passEncoderGPU.setBlendConstant( _blendConstant ); + + renderContextData.currentBlendColor.copy( blendColor ); + renderContextData.currentBlendAlpha = blendAlpha; + + } + + } + if ( object.isBatchedMesh === true ) { const starts = object._multiDrawStarts; @@ -3095,7 +3142,8 @@ class WebGPUBackend extends Backend { if ( renderContext.stencil ) descriptor.depthStencilAttachment.stencilLoadOp = GPULoadOp.Load; renderContextData.currentPass = encoder.beginRenderPass( descriptor ); - renderContextData.currentSets = { attributes: {}, bindingGroups: [], pipeline: null, index: null }; + + this._resetRenderContextData( renderContextData ); if ( renderContext.viewport ) { diff --git a/src/renderers/webgpu/utils/WebGPUPipelineUtils.js b/src/renderers/webgpu/utils/WebGPUPipelineUtils.js index 0e130371451f47..802f98b6e061d4 100644 --- a/src/renderers/webgpu/utils/WebGPUPipelineUtils.js +++ b/src/renderers/webgpu/utils/WebGPUPipelineUtils.js @@ -1,5 +1,3 @@ -import { BlendColorFactor, OneMinusBlendColorFactor, } from '../../common/Constants.js'; - import { GPUFrontFace, GPUCullMode, GPUColorWriteFlags, GPUCompareFunction, GPUBlendFactor, GPUBlendOperation, GPUIndexFormat, GPUStencilOperation, GPUPrimitiveTopology } from './WebGPUConstants.js'; @@ -10,6 +8,7 @@ import { NoBlending, NormalBlending, AdditiveBlending, SubtractiveBlending, MultiplyBlending, CustomBlending, MaterialBlending, ZeroFactor, OneFactor, SrcColorFactor, OneMinusSrcColorFactor, SrcAlphaFactor, OneMinusSrcAlphaFactor, DstColorFactor, OneMinusDstColorFactor, DstAlphaFactor, OneMinusDstAlphaFactor, SrcAlphaSaturateFactor, + ConstantColorFactor, OneMinusConstantColorFactor, ConstantAlphaFactor, OneMinusConstantAlphaFactor, AddEquation, SubtractEquation, ReverseSubtractEquation, MinEquation, MaxEquation, KeepStencilOp, ZeroStencilOp, ReplaceStencilOp, InvertStencilOp, IncrementStencilOp, DecrementStencilOp, IncrementWrapStencilOp, DecrementWrapStencilOp, NeverStencilFunc, AlwaysStencilFunc, LessStencilFunc, LessEqualStencilFunc, EqualStencilFunc, GreaterEqualStencilFunc, GreaterStencilFunc, NotEqualStencilFunc @@ -714,11 +713,13 @@ class WebGPUPipelineUtils { blendFactor = GPUBlendFactor.SrcAlphaSaturated; break; - case BlendColorFactor: + case ConstantColorFactor: + case ConstantAlphaFactor: // WebGPU has no dedicated constant alpha blend factors blendFactor = GPUBlendFactor.Constant; break; - case OneMinusBlendColorFactor: + case OneMinusConstantColorFactor: + case OneMinusConstantAlphaFactor: // WebGPU has no dedicated constant alpha blend factors blendFactor = GPUBlendFactor.OneMinusConstant; break;