@@ -17,11 +17,18 @@ import {
1717 TransparentBlack ,
1818 Texture ,
1919 StencilOp ,
20+ TransparentWhite ,
21+ Program ,
22+ RenderPipeline ,
23+ InputLayout ,
24+ RenderTarget ,
2025} from '@antv/g-device-api' ;
2126import { mat3 } from 'gl-matrix' ;
2227import { Entity } from '@lastolivegames/becsy' ;
2328import { Drawcall , ZINDEX_FACTOR } from './Drawcall' ;
2429import { vert , frag , Location } from '../shaders/sdf' ;
30+ import { vert as postProcessingVert } from '../shaders/post-processing/vert' ;
31+ import { frag as brightness } from '../shaders/post-processing/brightness' ;
2532import { paddingMat3 , parseColor , parseGradient } from '../utils' ;
2633import {
2734 Circle ,
@@ -41,6 +48,7 @@ import {
4148 SizeAttenuation ,
4249 StrokeAttenuation ,
4350 Stroke ,
51+ Filter ,
4452} from '../components' ;
4553
4654const strokeAlignmentMap = {
@@ -55,6 +63,15 @@ export class SDF extends Drawcall {
5563 #uniformBuffer: Buffer ;
5664 #texture: Texture ;
5765
66+ #filterProgram: Program ;
67+ #filterPipeline: RenderPipeline ;
68+ #filterInputLayout: InputLayout ;
69+ #filterVertexBuffer: Buffer ;
70+ #filterTexture: Texture ;
71+ #filterRenderTarget: RenderTarget ;
72+ #filterTextureWidth: number ;
73+ #filterTextureHeight: number ;
74+
5875 static useDash ( shape : Entity ) {
5976 const { dasharray } = shape . has ( Stroke )
6077 ? shape . read ( Stroke )
@@ -96,6 +113,10 @@ export class SDF extends Drawcall {
96113 return false ;
97114 }
98115
116+ if ( this . shapes [ 0 ] . has ( Filter ) || shape . has ( Filter ) ) {
117+ return false ;
118+ }
119+
99120 return true ;
100121 }
101122
@@ -300,44 +321,122 @@ export class SDF extends Drawcall {
300321
301322 const instance = this . shapes [ 0 ] ;
302323
303- if ( instance . has ( FillGradient ) || instance . has ( FillPattern ) ) {
304- const { minX, minY, maxX, maxY } =
305- instance . read ( ComputedBounds ) . geometryBounds ;
306- const width = maxX - minX ;
307- const height = maxY - minY ;
308-
309- const canvas = instance . has ( FillPattern )
310- ? this . texturePool . getOrCreatePattern ( {
311- pattern : instance . read ( FillPattern ) ,
312- width,
313- height,
314- } )
315- : this . texturePool . getOrCreateGradient ( {
316- gradients : parseGradient ( instance . read ( FillGradient ) . value ) ,
317- min : [ minX , minY ] ,
318- width,
319- height,
320- } ) ;
321- const texture = this . device . createTexture ( {
324+ if ( instance . has ( Filter ) ) {
325+ let width = 0 ;
326+ let height = 0 ;
327+ if ( this . shapes [ 0 ] . has ( Rect ) ) {
328+ const { minX, minY, maxX, maxY } = Rect . getGeometryBounds (
329+ this . shapes [ 0 ] . read ( Rect ) ,
330+ ) ;
331+ width = maxX - minX ;
332+ height = maxY - minY ;
333+ }
334+ this . #filterTextureWidth = width ;
335+ this . #filterTextureHeight = height ;
336+ this . #filterTexture = this . device . createTexture ( {
322337 format : Format . U8_RGBA_NORM ,
323- width : 128 ,
324- height : 128 ,
325- usage : TextureUsage . SAMPLED ,
338+ width,
339+ height,
340+ usage : TextureUsage . RENDER_TARGET ,
326341 } ) ;
327- texture . setImageData ( [ canvas ] ) ;
328- this . #texture = texture ;
329- } else if ( instance . has ( FillTexture ) ) {
330- this . #texture = instance . read ( FillTexture ) . value ;
331- } else if ( instance . has ( FillImage ) ) {
332- const src = instance . read ( FillImage ) . src as ImageBitmap ;
333- const texture = this . device . createTexture ( {
334- format : Format . U8_RGBA_NORM ,
335- width : src . width ,
336- height : src . height ,
337- usage : TextureUsage . SAMPLED ,
342+
343+ this . #filterRenderTarget = this . device . createRenderTargetFromTexture (
344+ this . #filterTexture,
345+ ) ;
346+
347+ const diagnosticDerivativeUniformityHeader =
348+ this . device . queryVendorInfo ( ) . platformString === 'WebGPU'
349+ ? 'diagnostic(off,derivative_uniformity);\n'
350+ : '' ;
351+
352+ this . #filterProgram = this . renderCache . createProgram ( {
353+ vertex : {
354+ glsl : postProcessingVert ,
355+ } ,
356+ fragment : {
357+ glsl : brightness ,
358+ postprocess : ( fs ) => diagnosticDerivativeUniformityHeader + fs ,
359+ } ,
360+ } ) ;
361+
362+ this . #filterVertexBuffer = this . device . createBuffer ( {
363+ viewOrSize : new Float32Array ( [
364+ 0 , 0.5 , - 1 , - 1 , - 0.5 , - 0.5 , - 1 , 1 , 0.5 , - 0.5 , 1 , 1 ,
365+ ] ) ,
366+ usage : BufferUsage . VERTEX ,
367+ hint : BufferFrequencyHint . DYNAMIC ,
338368 } ) ;
339- texture . setImageData ( [ src ] ) ;
340- this . #texture = texture ;
369+
370+ this . #filterInputLayout = this . device . createInputLayout ( {
371+ vertexBufferDescriptors : [
372+ {
373+ arrayStride : 4 * 4 ,
374+ stepMode : VertexStepMode . VERTEX ,
375+ attributes : [
376+ {
377+ shaderLocation : 0 ,
378+ offset : 0 ,
379+ format : Format . F32_RG ,
380+ } ,
381+ {
382+ shaderLocation : 1 ,
383+ offset : 4 * 2 ,
384+ format : Format . F32_RG ,
385+ } ,
386+ ] ,
387+ } ,
388+ ] ,
389+ indexBufferFormat : null ,
390+ program : this . #filterProgram,
391+ } ) ;
392+
393+ this . #filterPipeline = this . device . createRenderPipeline ( {
394+ inputLayout : this . #filterInputLayout,
395+ program : this . #filterProgram,
396+ colorAttachmentFormats : [ Format . U8_RGBA_NORM ] ,
397+ } ) ;
398+
399+ this . #texture = this . #filterTexture;
400+ } else {
401+ if ( instance . has ( FillGradient ) || instance . has ( FillPattern ) ) {
402+ const { minX, minY, maxX, maxY } =
403+ instance . read ( ComputedBounds ) . geometryBounds ;
404+ const width = maxX - minX ;
405+ const height = maxY - minY ;
406+
407+ const canvas = instance . has ( FillPattern )
408+ ? this . texturePool . getOrCreatePattern ( {
409+ pattern : instance . read ( FillPattern ) ,
410+ width,
411+ height,
412+ } )
413+ : this . texturePool . getOrCreateGradient ( {
414+ gradients : parseGradient ( instance . read ( FillGradient ) . value ) ,
415+ min : [ minX , minY ] ,
416+ width,
417+ height,
418+ } ) ;
419+ const texture = this . device . createTexture ( {
420+ format : Format . U8_RGBA_NORM ,
421+ width : 128 ,
422+ height : 128 ,
423+ usage : TextureUsage . SAMPLED ,
424+ } ) ;
425+ texture . setImageData ( [ canvas ] ) ;
426+ this . #texture = texture ;
427+ } else if ( instance . has ( FillTexture ) ) {
428+ this . #texture = instance . read ( FillTexture ) . value ;
429+ } else if ( instance . has ( FillImage ) ) {
430+ const src = instance . read ( FillImage ) . src as ImageBitmap ;
431+ const texture = this . device . createTexture ( {
432+ format : Format . U8_RGBA_NORM ,
433+ width : src . width ,
434+ height : src . height ,
435+ usage : TextureUsage . SAMPLED ,
436+ } ) ;
437+ texture . setImageData ( [ src ] ) ;
438+ this . #texture = texture ;
439+ }
341440 }
342441
343442 const sampler = this . renderCache . createSampler ( {
@@ -364,6 +463,8 @@ export class SDF extends Drawcall {
364463 renderPass : RenderPass ,
365464 sceneUniformLegacyObject : Record < string , unknown > ,
366465 ) {
466+ const hasFilter = this . shapes [ 0 ] . has ( Filter ) ;
467+
367468 if ( this . instanced ) {
368469 const instancedData : number [ ] = [ ] ;
369470 this . shapes . forEach ( ( shape , i , total ) => {
@@ -410,13 +511,6 @@ export class SDF extends Drawcall {
410511 matrix . m22 ,
411512 ] as mat3 ;
412513
413- // if (this.shapes[0].has(Rect)) {
414- // const { x, width } = this.shapes[0].read(Rect);
415- // const { children } = (this.shapes[0].has(Parent) &&
416- // this.shapes[0].read(Parent)) || { children: [] };
417- // console.log(children.length, x, width, matrix.m20);
418- // }
419-
420514 this . #uniformBuffer. setSubData (
421515 0 ,
422516 new Uint8Array (
@@ -440,6 +534,35 @@ export class SDF extends Drawcall {
440534 this . generateWireframe ( ) ;
441535 }
442536
537+ if ( hasFilter ) {
538+ console . log ( 'filter' ) ;
539+ const filterRenderPass = this . device . createRenderPass ( {
540+ colorAttachment : [ this . #filterRenderTarget] ,
541+ colorResolveTo : [ null ] ,
542+ colorClearColor : [ TransparentWhite ] ,
543+ colorStore : [ true ] ,
544+ depthStencilAttachment : null ,
545+ depthStencilResolveTo : null ,
546+ } ) ;
547+ // this.program.setUniformsLegacy(sceneUniformLegacyObject);
548+ filterRenderPass . setViewport (
549+ 0 ,
550+ 0 ,
551+ this . #filterTextureWidth,
552+ this . #filterTextureHeight,
553+ ) ;
554+ filterRenderPass . setPipeline ( this . #filterPipeline) ;
555+ filterRenderPass . setVertexInput (
556+ this . #filterInputLayout,
557+ [ { buffer : this . #filterVertexBuffer } ] ,
558+ null ,
559+ ) ;
560+ filterRenderPass . draw ( 3 ) ;
561+ this . device . submitPass ( filterRenderPass ) ;
562+ const { width, height } = this . swapChain . getCanvas ( ) ;
563+ renderPass . setViewport ( 0 , 0 , width , height ) ;
564+ }
565+
443566 this . program . setUniformsLegacy ( sceneUniformLegacyObject ) ;
444567 renderPass . setPipeline ( this . pipeline ) ;
445568
0 commit comments