import { gl , IModel , IModelDrawOptions , IModelInitializationOptions , IUniform , } from '@antv/g-webgpu-core' ; import regl from 'regl' ; import { extractUniforms } from '../utils/uniform' ; import { blendEquationMap , blendFuncMap , cullFaceMap , depthFuncMap , primitiveMap , stencilFuncMap , stencilOpMap , } from './constants' ; import ReglAttribute from './ReglAttribute' ; import ReglElements from './ReglElements' ; import ReglFramebuffer from './ReglFramebuffer' ; import ReglTexture2D from './ReglTexture2D' ; /**
 * adaptor for regl.DrawCommand
 */ export default class ReglModel implements IModel { private reGl : regl . Regl ; private drawCommand : regl . DrawCommand ; private uniforms : { [ key ] : IUniform ; } = { } ; constructor ( reGl , options ) { this . reGl = reGl ; const { vs , fs , defines , attributes , uniforms , primitive , count , elements , depth , blend , stencil , cull , instances , scissor , viewport , } = options ; const reglUniforms = { } ; if ( uniforms ) { this . uniforms = extractUniforms ( uniforms ) ; Object . keys ( uniforms ) . forEach ( ( uniformName ) => { reglUniforms [ uniformName ] = reGl . prop ( uniformName ) ; } ) ; } const reglAttributes = { } ; Object . keys ( attributes ) . forEach ( ( name ) => { reglAttributes [ name ] = ( attributes [ name ] as ReglAttribute ) . get ( ) ; } ) ; const defineStmts = ( defines && this . generateDefines ( defines ) ) || '' ; const drawParams = { attributes : reglAttributes , frag : `#ifdef GL_FRAGMENT_PRECISION_HIGH
  precision highp float;
#else
  precision mediump float;
#endif
${ defineStmts }
${ fs }` , uniforms : reglUniforms , vert : `
${ defineStmts }
${ vs }` , primitive : primitiveMap [ primitive === undefined ? gl . TRIANGLES : primitive ] , } ; if ( instances ) { drawParams . instances = instances ; } if ( count ) { drawParams . count = count ; } if ( elements ) { drawParams . elements = ( elements as ReglElements ) . get ( ) ; } if ( scissor ) { drawParams . scissor = scissor ; } if ( viewport ) { drawParams . viewport = viewport ; } this . initDepthDrawParams ( { depth } , drawParams ) ; this . initBlendDrawParams ( { blend } , drawParams ) ; this . initStencilDrawParams ( { stencil } , drawParams ) ; this . initCullDrawParams ( { cull } , drawParams ) ; this . drawCommand = reGl ( drawParams ) ; } public addUniforms ( uniforms ) { this . uniforms = { ... this . uniforms , ... extractUniforms ( uniforms ) , } ; } public draw ( options ) { const uniforms = { ... this . uniforms , ... extractUniforms ( options . uniforms || { } ) , } ; const reglDrawProps = { } ; Object . keys ( uniforms ) . forEach ( ( uniformName ) => { const type = typeof uniforms [ uniformName ] ; if ( type === 'boolean' || type === 'number' || Array . isArray ( uniforms [ uniformName ] ) || uniforms [ uniformName ] . BYTES_PER_ELEMENT ) { reglDrawProps [ uniformName ] = uniforms [ uniformName ] as number | number [ ] | boolean ; } else if ( type === 'string' ) { } else { reglDrawProps [ uniformName ] = ( uniforms [ uniformName ] as ReglFramebuffer | ReglTexture2D ) . get ( ) ; } } ) ; this . drawCommand ( reglDrawProps ) ; } public destroy ( ) { } see https private initDepthDrawParams ( { depth } , drawParams ) { if ( depth ) { drawParams . depth = { enable : depth . enable === undefined ? true : ! ! depth . enable , mask : depth . mask === undefined ? true : ! ! depth . mask , func : depthFuncMap [ depth . func || gl . LESS ] , range : depth . range || [ 0 , 1 ] , } ; } } see https private initBlendDrawParams ( { blend } , drawParams ) { if ( blend ) { const { enable , func , equation , color = [ 0 , 0 , 0 , 0 ] } = blend ; drawParams . blend = { enable : ! ! enable , func : { srcRGB : blendFuncMap [ ( func && func . srcRGB ) || gl . SRC_ALPHA ] , srcAlpha : blendFuncMap [ ( func && func . srcAlpha ) || gl . SRC_ALPHA ] , dstRGB : blendFuncMap [ ( func && func . dstRGB ) || gl . ONE_MINUS_SRC_ALPHA ] , dstAlpha : blendFuncMap [ ( func && func . dstAlpha ) || gl . ONE_MINUS_SRC_ALPHA ] , } , equation : { rgb : blendEquationMap [ ( equation && equation . rgb ) || gl . FUNC_ADD ] , alpha : blendEquationMap [ ( equation && equation . alpha ) || gl . FUNC_ADD ] , } , color , } ; } } see https private initStencilDrawParams ( { stencil } , drawParams ) { if ( stencil ) { const { enable , mask = - 1 , func = { cmp : gl . ALWAYS , ref : 0 , mask : - 1 , } , opFront = { fail : gl . KEEP , zfail : gl . KEEP , zpass : gl . KEEP , } , opBack = { fail : gl . KEEP , zfail : gl . KEEP , zpass : gl . KEEP , } , } = stencil ; drawParams . stencil = { enable : ! ! enable , mask , func : { ... func , cmp : stencilFuncMap [ func . cmp ] , } , opFront : { fail : stencilOpMap [ opFront . fail ] , zfail : stencilOpMap [ opFront . zfail ] , zpass : stencilOpMap [ opFront . zpass ] , } , opBack : { fail : stencilOpMap [ opBack . fail ] , zfail : stencilOpMap [ opBack . zfail ] , zpass : stencilOpMap [ opBack . zpass ] , } , } ; } } see https private initCullDrawParams ( { cull } , drawParams ) { if ( cull ) { const { enable , face = gl . BACK } = cull ; drawParams . cull = { enable : ! ! enable , face : cullFaceMap [ face ] , } ; } } private generateDefines ( defines ) { return Object . keys ( defines ) . map ( ( name ) => `#define ${ name } ${ Number ( defines [ name ] ) }` ) . join ( '\n' ) ; } }