添加关照、全局等高线、修改图层问题
This commit is contained in:
@ -0,0 +1,591 @@
|
||||
import { BlendColorFactor, OneMinusBlendColorFactor, } from '../../common/Constants.js';
|
||||
|
||||
import {
|
||||
GPUFrontFace, GPUCullMode, GPUColorWriteFlags, GPUCompareFunction, GPUBlendFactor, GPUBlendOperation, GPUIndexFormat, GPUStencilOperation
|
||||
} from './WebGPUConstants.js';
|
||||
|
||||
import {
|
||||
FrontSide, BackSide, DoubleSide,
|
||||
NeverDepth, AlwaysDepth, LessDepth, LessEqualDepth, EqualDepth, GreaterEqualDepth, GreaterDepth, NotEqualDepth,
|
||||
NoBlending, NormalBlending, AdditiveBlending, SubtractiveBlending, MultiplyBlending, CustomBlending,
|
||||
ZeroFactor, OneFactor, SrcColorFactor, OneMinusSrcColorFactor, SrcAlphaFactor, OneMinusSrcAlphaFactor, DstColorFactor,
|
||||
OneMinusDstColorFactor, DstAlphaFactor, OneMinusDstAlphaFactor, SrcAlphaSaturateFactor,
|
||||
AddEquation, SubtractEquation, ReverseSubtractEquation, MinEquation, MaxEquation,
|
||||
KeepStencilOp, ZeroStencilOp, ReplaceStencilOp, InvertStencilOp, IncrementStencilOp, DecrementStencilOp, IncrementWrapStencilOp, DecrementWrapStencilOp,
|
||||
NeverStencilFunc, AlwaysStencilFunc, LessStencilFunc, LessEqualStencilFunc, EqualStencilFunc, GreaterEqualStencilFunc, GreaterStencilFunc, NotEqualStencilFunc
|
||||
} from 'three';
|
||||
|
||||
class WebGPUPipelineUtils {
|
||||
|
||||
constructor( backend ) {
|
||||
|
||||
this.backend = backend;
|
||||
|
||||
}
|
||||
|
||||
createRenderPipeline( renderObject, promises ) {
|
||||
|
||||
const { object, material, geometry, pipeline } = renderObject;
|
||||
const { vertexProgram, fragmentProgram } = pipeline;
|
||||
|
||||
const backend = this.backend;
|
||||
const device = backend.device;
|
||||
const utils = backend.utils;
|
||||
|
||||
const pipelineData = backend.get( pipeline );
|
||||
const bindingsData = backend.get( renderObject.getBindings() );
|
||||
|
||||
// vertex buffers
|
||||
|
||||
const vertexBuffers = backend.attributeUtils.createShaderVertexBuffers( renderObject );
|
||||
|
||||
// blending
|
||||
|
||||
let blending;
|
||||
|
||||
if ( material.transparent === true && material.blending !== NoBlending ) {
|
||||
|
||||
blending = this._getBlending( material );
|
||||
|
||||
}
|
||||
|
||||
// stencil
|
||||
|
||||
let stencilFront = {};
|
||||
|
||||
if ( material.stencilWrite === true ) {
|
||||
|
||||
stencilFront = {
|
||||
compare: this._getStencilCompare( material ),
|
||||
failOp: this._getStencilOperation( material.stencilFail ),
|
||||
depthFailOp: this._getStencilOperation( material.stencilZFail ),
|
||||
passOp: this._getStencilOperation( material.stencilZPass )
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
const colorWriteMask = this._getColorWriteMask( material );
|
||||
|
||||
const targets = [];
|
||||
|
||||
if ( renderObject.context.textures !== null ) {
|
||||
|
||||
const textures = renderObject.context.textures;
|
||||
|
||||
for ( let i = 0; i < textures.length; i ++ ) {
|
||||
|
||||
const colorFormat = utils.getTextureFormatGPU( textures[ i ] );
|
||||
|
||||
targets.push( {
|
||||
format: colorFormat,
|
||||
blend: blending,
|
||||
writeMask: colorWriteMask
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
const colorFormat = utils.getCurrentColorFormat( renderObject.context );
|
||||
|
||||
targets.push( {
|
||||
format: colorFormat,
|
||||
blend: blending,
|
||||
writeMask: colorWriteMask
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
const vertexModule = backend.get( vertexProgram ).module;
|
||||
const fragmentModule = backend.get( fragmentProgram ).module;
|
||||
|
||||
const primitiveState = this._getPrimitiveState( object, geometry, material );
|
||||
const depthCompare = this._getDepthCompare( material );
|
||||
const depthStencilFormat = utils.getCurrentDepthStencilFormat( renderObject.context );
|
||||
let sampleCount = utils.getSampleCount( renderObject.context );
|
||||
|
||||
if ( sampleCount > 1 ) {
|
||||
|
||||
// WebGPU only supports power-of-two sample counts and 2 is not a valid value
|
||||
sampleCount = Math.pow( 2, Math.floor( Math.log2( sampleCount ) ) );
|
||||
|
||||
if ( sampleCount === 2 ) {
|
||||
|
||||
sampleCount = 4;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const pipelineDescriptor = {
|
||||
vertex: Object.assign( {}, vertexModule, { buffers: vertexBuffers } ),
|
||||
fragment: Object.assign( {}, fragmentModule, { targets } ),
|
||||
primitive: primitiveState,
|
||||
depthStencil: {
|
||||
format: depthStencilFormat,
|
||||
depthWriteEnabled: material.depthWrite,
|
||||
depthCompare: depthCompare,
|
||||
stencilFront: stencilFront,
|
||||
stencilBack: {}, // three.js does not provide an API to configure the back function (gl.stencilFuncSeparate() was never used)
|
||||
stencilReadMask: material.stencilFuncMask,
|
||||
stencilWriteMask: material.stencilWriteMask
|
||||
},
|
||||
multisample: {
|
||||
count: sampleCount,
|
||||
alphaToCoverageEnabled: material.alphaToCoverage
|
||||
},
|
||||
layout: device.createPipelineLayout( {
|
||||
bindGroupLayouts: [ bindingsData.layout ]
|
||||
} )
|
||||
};
|
||||
|
||||
if ( promises === null ) {
|
||||
|
||||
pipelineData.pipeline = device.createRenderPipeline( pipelineDescriptor );
|
||||
|
||||
} else {
|
||||
|
||||
const p = new Promise( ( resolve /*, reject*/ ) => {
|
||||
|
||||
device.createRenderPipelineAsync( pipelineDescriptor ).then( pipeline => {
|
||||
|
||||
pipelineData.pipeline = pipeline;
|
||||
resolve();
|
||||
|
||||
} );
|
||||
|
||||
} );
|
||||
|
||||
promises.push( p );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
createComputePipeline( pipeline, bindings ) {
|
||||
|
||||
const backend = this.backend;
|
||||
const device = backend.device;
|
||||
|
||||
const computeProgram = backend.get( pipeline.computeProgram ).module;
|
||||
|
||||
const pipelineGPU = backend.get( pipeline );
|
||||
const bindingsData = backend.get( bindings );
|
||||
|
||||
pipelineGPU.pipeline = device.createComputePipeline( {
|
||||
compute: computeProgram,
|
||||
layout: device.createPipelineLayout( {
|
||||
bindGroupLayouts: [ bindingsData.layout ]
|
||||
} )
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
_getBlending( material ) {
|
||||
|
||||
let color, alpha;
|
||||
|
||||
const blending = material.blending;
|
||||
|
||||
if ( blending === CustomBlending ) {
|
||||
|
||||
const blendSrcAlpha = material.blendSrcAlpha !== null ? material.blendSrcAlpha : GPUBlendFactor.One;
|
||||
const blendDstAlpha = material.blendDstAlpha !== null ? material.blendDstAlpha : GPUBlendFactor.Zero;
|
||||
const blendEquationAlpha = material.blendEquationAlpha !== null ? material.blendEquationAlpha : GPUBlendFactor.Add;
|
||||
|
||||
color = {
|
||||
srcFactor: this._getBlendFactor( material.blendSrc ),
|
||||
dstFactor: this._getBlendFactor( material.blendDst ),
|
||||
operation: this._getBlendOperation( material.blendEquation )
|
||||
};
|
||||
|
||||
alpha = {
|
||||
srcFactor: this._getBlendFactor( blendSrcAlpha ),
|
||||
dstFactor: this._getBlendFactor( blendDstAlpha ),
|
||||
operation: this._getBlendOperation( blendEquationAlpha )
|
||||
};
|
||||
|
||||
} else {
|
||||
|
||||
const premultipliedAlpha = material.premultipliedAlpha;
|
||||
|
||||
const setBlend = ( srcRGB, dstRGB, srcAlpha, dstAlpha ) => {
|
||||
|
||||
color = {
|
||||
srcFactor: srcRGB,
|
||||
dstFactor: dstRGB,
|
||||
operation: GPUBlendOperation.Add
|
||||
};
|
||||
|
||||
alpha = {
|
||||
srcFactor: srcAlpha,
|
||||
dstFactor: dstAlpha,
|
||||
operation: GPUBlendOperation.Add
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
if ( premultipliedAlpha ) {
|
||||
|
||||
switch ( blending ) {
|
||||
|
||||
case NormalBlending:
|
||||
setBlend( GPUBlendFactor.SrcAlpha, GPUBlendFactor.OneMinusSrcAlpha, GPUBlendFactor.One, GPUBlendFactor.OneMinusSrcAlpha );
|
||||
break;
|
||||
|
||||
case AdditiveBlending:
|
||||
setBlend( GPUBlendFactor.SrcAlpha, GPUBlendFactor.One, GPUBlendFactor.One, GPUBlendFactor.One );
|
||||
break;
|
||||
|
||||
case SubtractiveBlending:
|
||||
setBlend( GPUBlendFactor.Zero, GPUBlendFactor.OneMinusSrc, GPUBlendFactor.Zero, GPUBlendFactor.One );
|
||||
break;
|
||||
|
||||
case MultiplyBlending:
|
||||
setBlend( GPUBlendFactor.Zero, GPUBlendFactor.Src, GPUBlendFactor.Zero, GPUBlendFactor.SrcAlpha );
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
switch ( blending ) {
|
||||
|
||||
case NormalBlending:
|
||||
setBlend( GPUBlendFactor.SrcAlpha, GPUBlendFactor.OneMinusSrcAlpha, GPUBlendFactor.One, GPUBlendFactor.OneMinusSrcAlpha );
|
||||
break;
|
||||
|
||||
case AdditiveBlending:
|
||||
setBlend( GPUBlendFactor.SrcAlpha, GPUBlendFactor.One, GPUBlendFactor.SrcAlpha, GPUBlendFactor.One );
|
||||
break;
|
||||
|
||||
case SubtractiveBlending:
|
||||
setBlend( GPUBlendFactor.Zero, GPUBlendFactor.OneMinusSrc, GPUBlendFactor.Zero, GPUBlendFactor.One );
|
||||
break;
|
||||
|
||||
case MultiplyBlending:
|
||||
setBlend( GPUBlendFactor.Zero, GPUBlendFactor.Src, GPUBlendFactor.Zero, GPUBlendFactor.Src );
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( color !== undefined && alpha !== undefined ) {
|
||||
|
||||
return { color, alpha };
|
||||
|
||||
} else {
|
||||
|
||||
console.error( 'THREE.WebGPURenderer: Invalid blending: ', blending );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
_getBlendFactor( blend ) {
|
||||
|
||||
let blendFactor;
|
||||
|
||||
switch ( blend ) {
|
||||
|
||||
case ZeroFactor:
|
||||
blendFactor = GPUBlendFactor.Zero;
|
||||
break;
|
||||
|
||||
case OneFactor:
|
||||
blendFactor = GPUBlendFactor.One;
|
||||
break;
|
||||
|
||||
case SrcColorFactor:
|
||||
blendFactor = GPUBlendFactor.Src;
|
||||
break;
|
||||
|
||||
case OneMinusSrcColorFactor:
|
||||
blendFactor = GPUBlendFactor.OneMinusSrc;
|
||||
break;
|
||||
|
||||
case SrcAlphaFactor:
|
||||
blendFactor = GPUBlendFactor.SrcAlpha;
|
||||
break;
|
||||
|
||||
case OneMinusSrcAlphaFactor:
|
||||
blendFactor = GPUBlendFactor.OneMinusSrcAlpha;
|
||||
break;
|
||||
|
||||
case DstColorFactor:
|
||||
blendFactor = GPUBlendFactor.Dst;
|
||||
break;
|
||||
|
||||
case OneMinusDstColorFactor:
|
||||
blendFactor = GPUBlendFactor.OneMinusDstColor;
|
||||
break;
|
||||
|
||||
case DstAlphaFactor:
|
||||
blendFactor = GPUBlendFactor.DstAlpha;
|
||||
break;
|
||||
|
||||
case OneMinusDstAlphaFactor:
|
||||
blendFactor = GPUBlendFactor.OneMinusDstAlpha;
|
||||
break;
|
||||
|
||||
case SrcAlphaSaturateFactor:
|
||||
blendFactor = GPUBlendFactor.SrcAlphaSaturated;
|
||||
break;
|
||||
|
||||
case BlendColorFactor:
|
||||
blendFactor = GPUBlendFactor.Constant;
|
||||
break;
|
||||
|
||||
case OneMinusBlendColorFactor:
|
||||
blendFactor = GPUBlendFactor.OneMinusConstant;
|
||||
break;
|
||||
|
||||
default:
|
||||
console.error( 'THREE.WebGPURenderer: Blend factor not supported.', blend );
|
||||
|
||||
}
|
||||
|
||||
return blendFactor;
|
||||
|
||||
}
|
||||
|
||||
_getStencilCompare( material ) {
|
||||
|
||||
let stencilCompare;
|
||||
|
||||
const stencilFunc = material.stencilFunc;
|
||||
|
||||
switch ( stencilFunc ) {
|
||||
|
||||
case NeverStencilFunc:
|
||||
stencilCompare = GPUCompareFunction.Never;
|
||||
break;
|
||||
|
||||
case AlwaysStencilFunc:
|
||||
stencilCompare = GPUCompareFunction.Always;
|
||||
break;
|
||||
|
||||
case LessStencilFunc:
|
||||
stencilCompare = GPUCompareFunction.Less;
|
||||
break;
|
||||
|
||||
case LessEqualStencilFunc:
|
||||
stencilCompare = GPUCompareFunction.LessEqual;
|
||||
break;
|
||||
|
||||
case EqualStencilFunc:
|
||||
stencilCompare = GPUCompareFunction.Equal;
|
||||
break;
|
||||
|
||||
case GreaterEqualStencilFunc:
|
||||
stencilCompare = GPUCompareFunction.GreaterEqual;
|
||||
break;
|
||||
|
||||
case GreaterStencilFunc:
|
||||
stencilCompare = GPUCompareFunction.Greater;
|
||||
break;
|
||||
|
||||
case NotEqualStencilFunc:
|
||||
stencilCompare = GPUCompareFunction.NotEqual;
|
||||
break;
|
||||
|
||||
default:
|
||||
console.error( 'THREE.WebGPURenderer: Invalid stencil function.', stencilFunc );
|
||||
|
||||
}
|
||||
|
||||
return stencilCompare;
|
||||
|
||||
}
|
||||
|
||||
_getStencilOperation( op ) {
|
||||
|
||||
let stencilOperation;
|
||||
|
||||
switch ( op ) {
|
||||
|
||||
case KeepStencilOp:
|
||||
stencilOperation = GPUStencilOperation.Keep;
|
||||
break;
|
||||
|
||||
case ZeroStencilOp:
|
||||
stencilOperation = GPUStencilOperation.Zero;
|
||||
break;
|
||||
|
||||
case ReplaceStencilOp:
|
||||
stencilOperation = GPUStencilOperation.Replace;
|
||||
break;
|
||||
|
||||
case InvertStencilOp:
|
||||
stencilOperation = GPUStencilOperation.Invert;
|
||||
break;
|
||||
|
||||
case IncrementStencilOp:
|
||||
stencilOperation = GPUStencilOperation.IncrementClamp;
|
||||
break;
|
||||
|
||||
case DecrementStencilOp:
|
||||
stencilOperation = GPUStencilOperation.DecrementClamp;
|
||||
break;
|
||||
|
||||
case IncrementWrapStencilOp:
|
||||
stencilOperation = GPUStencilOperation.IncrementWrap;
|
||||
break;
|
||||
|
||||
case DecrementWrapStencilOp:
|
||||
stencilOperation = GPUStencilOperation.DecrementWrap;
|
||||
break;
|
||||
|
||||
default:
|
||||
console.error( 'THREE.WebGPURenderer: Invalid stencil operation.', stencilOperation );
|
||||
|
||||
}
|
||||
|
||||
return stencilOperation;
|
||||
|
||||
}
|
||||
|
||||
_getBlendOperation( blendEquation ) {
|
||||
|
||||
let blendOperation;
|
||||
|
||||
switch ( blendEquation ) {
|
||||
|
||||
case AddEquation:
|
||||
blendOperation = GPUBlendOperation.Add;
|
||||
break;
|
||||
|
||||
case SubtractEquation:
|
||||
blendOperation = GPUBlendOperation.Subtract;
|
||||
break;
|
||||
|
||||
case ReverseSubtractEquation:
|
||||
blendOperation = GPUBlendOperation.ReverseSubtract;
|
||||
break;
|
||||
|
||||
case MinEquation:
|
||||
blendOperation = GPUBlendOperation.Min;
|
||||
break;
|
||||
|
||||
case MaxEquation:
|
||||
blendOperation = GPUBlendOperation.Max;
|
||||
break;
|
||||
|
||||
default:
|
||||
console.error( 'THREE.WebGPUPipelineUtils: Blend equation not supported.', blendEquation );
|
||||
|
||||
}
|
||||
|
||||
return blendOperation;
|
||||
|
||||
}
|
||||
|
||||
_getPrimitiveState( object, geometry, material ) {
|
||||
|
||||
const descriptor = {};
|
||||
const utils = this.backend.utils;
|
||||
|
||||
descriptor.topology = utils.getPrimitiveTopology( object, material );
|
||||
|
||||
if ( geometry.index !== null && object.isLine === true && object.isLineSegments !== true ) {
|
||||
|
||||
descriptor.stripIndexFormat = ( geometry.index.array instanceof Uint16Array ) ? GPUIndexFormat.Uint16 : GPUIndexFormat.Uint32;
|
||||
|
||||
}
|
||||
|
||||
switch ( material.side ) {
|
||||
|
||||
case FrontSide:
|
||||
descriptor.frontFace = GPUFrontFace.CCW;
|
||||
descriptor.cullMode = GPUCullMode.Back;
|
||||
break;
|
||||
|
||||
case BackSide:
|
||||
descriptor.frontFace = GPUFrontFace.CCW;
|
||||
descriptor.cullMode = GPUCullMode.Front;
|
||||
break;
|
||||
|
||||
case DoubleSide:
|
||||
descriptor.frontFace = GPUFrontFace.CCW;
|
||||
descriptor.cullMode = GPUCullMode.None;
|
||||
break;
|
||||
|
||||
default:
|
||||
console.error( 'THREE.WebGPUPipelineUtils: Unknown material.side value.', material.side );
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return descriptor;
|
||||
|
||||
}
|
||||
|
||||
_getColorWriteMask( material ) {
|
||||
|
||||
return ( material.colorWrite === true ) ? GPUColorWriteFlags.All : GPUColorWriteFlags.None;
|
||||
|
||||
}
|
||||
|
||||
_getDepthCompare( material ) {
|
||||
|
||||
let depthCompare;
|
||||
|
||||
if ( material.depthTest === false ) {
|
||||
|
||||
depthCompare = GPUCompareFunction.Always;
|
||||
|
||||
} else {
|
||||
|
||||
const depthFunc = material.depthFunc;
|
||||
|
||||
switch ( depthFunc ) {
|
||||
|
||||
case NeverDepth:
|
||||
depthCompare = GPUCompareFunction.Never;
|
||||
break;
|
||||
|
||||
case AlwaysDepth:
|
||||
depthCompare = GPUCompareFunction.Always;
|
||||
break;
|
||||
|
||||
case LessDepth:
|
||||
depthCompare = GPUCompareFunction.Less;
|
||||
break;
|
||||
|
||||
case LessEqualDepth:
|
||||
depthCompare = GPUCompareFunction.LessEqual;
|
||||
break;
|
||||
|
||||
case EqualDepth:
|
||||
depthCompare = GPUCompareFunction.Equal;
|
||||
break;
|
||||
|
||||
case GreaterEqualDepth:
|
||||
depthCompare = GPUCompareFunction.GreaterEqual;
|
||||
break;
|
||||
|
||||
case GreaterDepth:
|
||||
depthCompare = GPUCompareFunction.Greater;
|
||||
break;
|
||||
|
||||
case NotEqualDepth:
|
||||
depthCompare = GPUCompareFunction.NotEqual;
|
||||
break;
|
||||
|
||||
default:
|
||||
console.error( 'THREE.WebGPUPipelineUtils: Invalid depth function.', depthFunc );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return depthCompare;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default WebGPUPipelineUtils;
|
Reference in New Issue
Block a user