@next2d/webgpu 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +574 -0
- package/package.json +30 -0
- package/src/AtlasManager.d.ts +23 -0
- package/src/AtlasManager.js +123 -0
- package/src/AttachmentManager/service/AttachmentManagerCreateAttachmentObjectService.d.ts +13 -0
- package/src/AttachmentManager/service/AttachmentManagerCreateAttachmentObjectService.js +24 -0
- package/src/AttachmentManager/service/AttachmentManagerCreateColorBufferService.d.ts +15 -0
- package/src/AttachmentManager/service/AttachmentManagerCreateColorBufferService.js +31 -0
- package/src/AttachmentManager/service/AttachmentManagerCreateRenderPassDescriptorService.d.ts +5 -0
- package/src/AttachmentManager/service/AttachmentManagerCreateRenderPassDescriptorService.js +42 -0
- package/src/AttachmentManager/service/AttachmentManagerCreateStencilBufferService.d.ts +16 -0
- package/src/AttachmentManager/service/AttachmentManagerCreateStencilBufferService.js +28 -0
- package/src/AttachmentManager/service/AttachmentManagerCreateTextureObjectService.d.ts +17 -0
- package/src/AttachmentManager/service/AttachmentManagerCreateTextureObjectService.js +33 -0
- package/src/AttachmentManager/service/AttachmentManagerGetColorBufferService.d.ts +16 -0
- package/src/AttachmentManager/service/AttachmentManagerGetColorBufferService.js +28 -0
- package/src/AttachmentManager/service/AttachmentManagerGetStencilBufferService.d.ts +17 -0
- package/src/AttachmentManager/service/AttachmentManagerGetStencilBufferService.js +27 -0
- package/src/AttachmentManager/service/AttachmentManagerGetTextureService.d.ts +18 -0
- package/src/AttachmentManager/service/AttachmentManagerGetTextureService.js +27 -0
- package/src/AttachmentManager/service/AttachmentManagerReleaseTextureService.d.ts +12 -0
- package/src/AttachmentManager/service/AttachmentManagerReleaseTextureService.js +17 -0
- package/src/AttachmentManager/usecase/AttachmentManagerGetAttachmentObjectUseCase.d.ts +26 -0
- package/src/AttachmentManager/usecase/AttachmentManagerGetAttachmentObjectUseCase.js +43 -0
- package/src/AttachmentManager/usecase/AttachmentManagerReleaseAttachmentUseCase.d.ts +18 -0
- package/src/AttachmentManager/usecase/AttachmentManagerReleaseAttachmentUseCase.js +33 -0
- package/src/AttachmentManager.d.ts +19 -0
- package/src/AttachmentManager.js +105 -0
- package/src/BezierConverter/BezierConverter.d.ts +16 -0
- package/src/BezierConverter/BezierConverter.js +15 -0
- package/src/BezierConverter/service/BezierConverterCalculateFlatnessService.d.ts +15 -0
- package/src/BezierConverter/service/BezierConverterCalculateFlatnessService.js +37 -0
- package/src/BezierConverter/service/BezierConverterSplitCubicService.d.ts +15 -0
- package/src/BezierConverter/service/BezierConverterSplitCubicService.js +47 -0
- package/src/BezierConverter/usecase/BezierConverterAdaptiveCubicToQuadUseCase.d.ts +29 -0
- package/src/BezierConverter/usecase/BezierConverterAdaptiveCubicToQuadUseCase.js +80 -0
- package/src/Blend/BlendInstancedManager.d.ts +35 -0
- package/src/Blend/BlendInstancedManager.js +147 -0
- package/src/Blend/service/BlendAddService.d.ts +1 -0
- package/src/Blend/service/BlendAddService.js +8 -0
- package/src/Blend/service/BlendAlphaService.d.ts +1 -0
- package/src/Blend/service/BlendAlphaService.js +8 -0
- package/src/Blend/service/BlendEraseService.d.ts +1 -0
- package/src/Blend/service/BlendEraseService.js +8 -0
- package/src/Blend/service/BlendGetStateService.d.ts +12 -0
- package/src/Blend/service/BlendGetStateService.js +13 -0
- package/src/Blend/service/BlendOneZeroService.d.ts +1 -0
- package/src/Blend/service/BlendOneZeroService.js +8 -0
- package/src/Blend/service/BlendResetService.d.ts +1 -0
- package/src/Blend/service/BlendResetService.js +8 -0
- package/src/Blend/service/BlendScreenService.d.ts +1 -0
- package/src/Blend/service/BlendScreenService.js +8 -0
- package/src/Blend/service/BlendSetModeService.d.ts +2 -0
- package/src/Blend/service/BlendSetModeService.js +4 -0
- package/src/Blend/usecase/BlendApplyComplexBlendUseCase.d.ts +6 -0
- package/src/Blend/usecase/BlendApplyComplexBlendUseCase.js +79 -0
- package/src/Blend/usecase/BlendOperationUseCase.d.ts +11 -0
- package/src/Blend/usecase/BlendOperationUseCase.js +31 -0
- package/src/Blend.d.ts +8 -0
- package/src/Blend.js +91 -0
- package/src/BufferManager/service/BufferManagerCreateIndirectBufferService.d.ts +15 -0
- package/src/BufferManager/service/BufferManagerCreateIndirectBufferService.js +37 -0
- package/src/BufferManager/service/BufferManagerCreateRectVerticesService.d.ts +13 -0
- package/src/BufferManager/service/BufferManagerCreateRectVerticesService.js +23 -0
- package/src/BufferManager/service/BufferManagerCreateStorageBufferService.d.ts +17 -0
- package/src/BufferManager/service/BufferManagerCreateStorageBufferService.js +23 -0
- package/src/BufferManager/service/BufferManagerReleaseUniformBufferService.d.ts +12 -0
- package/src/BufferManager/service/BufferManagerReleaseUniformBufferService.js +32 -0
- package/src/BufferManager/service/BufferManagerReleaseVertexBufferService.d.ts +12 -0
- package/src/BufferManager/service/BufferManagerReleaseVertexBufferService.js +32 -0
- package/src/BufferManager/service/BufferManagerUpdateIndirectBufferService.d.ts +12 -0
- package/src/BufferManager/service/BufferManagerUpdateIndirectBufferService.js +20 -0
- package/src/BufferManager/service/BufferManagerUpperPowerOfTwoService.d.ts +10 -0
- package/src/BufferManager/service/BufferManagerUpperPowerOfTwoService.js +18 -0
- package/src/BufferManager/usecase/BufferManagerAcquireStorageBufferUseCase.d.ts +15 -0
- package/src/BufferManager/usecase/BufferManagerAcquireStorageBufferUseCase.js +51 -0
- package/src/BufferManager/usecase/BufferManagerAcquireUniformBufferUseCase.d.ts +13 -0
- package/src/BufferManager/usecase/BufferManagerAcquireUniformBufferUseCase.js +26 -0
- package/src/BufferManager/usecase/BufferManagerAcquireVertexBufferUseCase.d.ts +14 -0
- package/src/BufferManager/usecase/BufferManagerAcquireVertexBufferUseCase.js +46 -0
- package/src/BufferManager/usecase/BufferManagerCleanupStorageBuffersUseCase.d.ts +12 -0
- package/src/BufferManager/usecase/BufferManagerCleanupStorageBuffersUseCase.js +20 -0
- package/src/BufferManager/usecase/BufferManagerReleaseStorageBufferUseCase.d.ts +9 -0
- package/src/BufferManager/usecase/BufferManagerReleaseStorageBufferUseCase.js +15 -0
- package/src/BufferManager.d.ts +93 -0
- package/src/BufferManager.js +487 -0
- package/src/Compute/ComputePipelineManager.d.ts +61 -0
- package/src/Compute/ComputePipelineManager.js +313 -0
- package/src/Compute/service/ComputeExecuteBlurService.d.ts +21 -0
- package/src/Compute/service/ComputeExecuteBlurService.js +81 -0
- package/src/Context/service/ContextComputeBitmapMatrixService.d.ts +1 -0
- package/src/Context/service/ContextComputeBitmapMatrixService.js +74 -0
- package/src/Context/service/ContextComputeGradientMatrixService.d.ts +4 -0
- package/src/Context/service/ContextComputeGradientMatrixService.js +88 -0
- package/src/Context/service/ContextFillSimpleService.d.ts +2 -0
- package/src/Context/service/ContextFillSimpleService.js +28 -0
- package/src/Context/service/ContextFillWithStencilMainService.d.ts +2 -0
- package/src/Context/service/ContextFillWithStencilMainService.js +19 -0
- package/src/Context/service/ContextFillWithStencilService.d.ts +2 -0
- package/src/Context/service/ContextFillWithStencilService.js +19 -0
- package/src/Context/usecase/ContextApplyFilterUseCase.d.ts +5 -0
- package/src/Context/usecase/ContextApplyFilterUseCase.js +668 -0
- package/src/Context/usecase/ContextBitmapFillUseCase.d.ts +4 -0
- package/src/Context/usecase/ContextBitmapFillUseCase.js +210 -0
- package/src/Context/usecase/ContextBitmapStrokeUseCase.d.ts +4 -0
- package/src/Context/usecase/ContextBitmapStrokeUseCase.js +119 -0
- package/src/Context/usecase/ContextClipUseCase.d.ts +5 -0
- package/src/Context/usecase/ContextClipUseCase.js +101 -0
- package/src/Context/usecase/ContextContainerEndLayerUseCase.d.ts +5 -0
- package/src/Context/usecase/ContextContainerEndLayerUseCase.js +476 -0
- package/src/Context/usecase/ContextDrawArraysInstancedUseCase.d.ts +6 -0
- package/src/Context/usecase/ContextDrawArraysInstancedUseCase.js +135 -0
- package/src/Context/usecase/ContextDrawIndirectUseCase.d.ts +6 -0
- package/src/Context/usecase/ContextDrawIndirectUseCase.js +154 -0
- package/src/Context/usecase/ContextGradientFillUseCase.d.ts +4 -0
- package/src/Context/usecase/ContextGradientFillUseCase.js +230 -0
- package/src/Context/usecase/ContextGradientStrokeUseCase.d.ts +4 -0
- package/src/Context/usecase/ContextGradientStrokeUseCase.js +138 -0
- package/src/Context/usecase/ContextProcessComplexBlendQueueUseCase.d.ts +6 -0
- package/src/Context/usecase/ContextProcessComplexBlendQueueUseCase.js +213 -0
- package/src/Context.d.ts +430 -0
- package/src/Context.js +2453 -0
- package/src/FillTexturePool.d.ts +6 -0
- package/src/FillTexturePool.js +72 -0
- package/src/Filter/BevelFilter/FilterApplyBevelFilterUseCase.d.ts +10 -0
- package/src/Filter/BevelFilter/FilterApplyBevelFilterUseCase.js +214 -0
- package/src/Filter/BevelFilterShader.d.ts +2 -0
- package/src/Filter/BevelFilterShader.js +107 -0
- package/src/Filter/BitmapFilterShader.d.ts +2 -0
- package/src/Filter/BitmapFilterShader.js +207 -0
- package/src/Filter/BlurFilter/FilterApplyBlurFilterUseCase.d.ts +16 -0
- package/src/Filter/BlurFilter/FilterApplyBlurFilterUseCase.js +243 -0
- package/src/Filter/BlurFilter/service/BlurFilterComputeShaderService.d.ts +40 -0
- package/src/Filter/BlurFilter/service/BlurFilterComputeShaderService.js +51 -0
- package/src/Filter/BlurFilter/usecase/FilterApplyBlurComputeUseCase.d.ts +25 -0
- package/src/Filter/BlurFilter/usecase/FilterApplyBlurComputeUseCase.js +180 -0
- package/src/Filter/BlurFilterShader.d.ts +5 -0
- package/src/Filter/BlurFilterShader.js +109 -0
- package/src/Filter/BlurFilterUseCase.d.ts +36 -0
- package/src/Filter/BlurFilterUseCase.js +85 -0
- package/src/Filter/ColorMatrixFilter/FilterApplyColorMatrixFilterUseCase.d.ts +12 -0
- package/src/Filter/ColorMatrixFilter/FilterApplyColorMatrixFilterUseCase.js +90 -0
- package/src/Filter/ColorMatrixFilterShader.d.ts +4 -0
- package/src/Filter/ColorMatrixFilterShader.js +51 -0
- package/src/Filter/ConvolutionFilter/FilterApplyConvolutionFilterUseCase.d.ts +6 -0
- package/src/Filter/ConvolutionFilter/FilterApplyConvolutionFilterUseCase.js +144 -0
- package/src/Filter/ConvolutionFilterShader.d.ts +2 -0
- package/src/Filter/ConvolutionFilterShader.js +115 -0
- package/src/Filter/DisplacementMapFilter/FilterApplyDisplacementMapFilterUseCase.d.ts +6 -0
- package/src/Filter/DisplacementMapFilter/FilterApplyDisplacementMapFilterUseCase.js +172 -0
- package/src/Filter/DisplacementMapFilterShader.d.ts +2 -0
- package/src/Filter/DisplacementMapFilterShader.js +114 -0
- package/src/Filter/DropShadowFilter/FilterApplyDropShadowFilterUseCase.d.ts +24 -0
- package/src/Filter/DropShadowFilter/FilterApplyDropShadowFilterUseCase.js +179 -0
- package/src/Filter/DropShadowFilterShader.d.ts +4 -0
- package/src/Filter/DropShadowFilterShader.js +93 -0
- package/src/Filter/FilterGradientLUTCache.d.ts +29 -0
- package/src/Filter/FilterGradientLUTCache.js +84 -0
- package/src/Filter/FilterOffset.d.ts +8 -0
- package/src/Filter/FilterOffset.js +10 -0
- package/src/Filter/GlowFilter/FilterApplyGlowFilterUseCase.d.ts +24 -0
- package/src/Filter/GlowFilter/FilterApplyGlowFilterUseCase.js +143 -0
- package/src/Filter/GlowFilterShader.d.ts +4 -0
- package/src/Filter/GlowFilterShader.js +66 -0
- package/src/Filter/GradientBevelFilter/FilterApplyGradientBevelFilterUseCase.d.ts +29 -0
- package/src/Filter/GradientBevelFilter/FilterApplyGradientBevelFilterUseCase.js +216 -0
- package/src/Filter/GradientGlowFilter/FilterApplyGradientGlowFilterUseCase.d.ts +29 -0
- package/src/Filter/GradientGlowFilter/FilterApplyGradientGlowFilterUseCase.js +164 -0
- package/src/FrameBufferManager/service/FrameBufferManagerCreateRenderPassDescriptorService.d.ts +4 -0
- package/src/FrameBufferManager/service/FrameBufferManagerCreateRenderPassDescriptorService.js +23 -0
- package/src/FrameBufferManager/service/FrameBufferManagerCreateStencilRenderPassDescriptorService.d.ts +4 -0
- package/src/FrameBufferManager/service/FrameBufferManagerCreateStencilRenderPassDescriptorService.js +28 -0
- package/src/FrameBufferManager/service/FrameBufferManagerFlushPendingReleasesService.d.ts +11 -0
- package/src/FrameBufferManager/service/FrameBufferManagerFlushPendingReleasesService.js +19 -0
- package/src/FrameBufferManager/usecase/FrameBufferManagerCreateAttachmentUseCase.d.ts +23 -0
- package/src/FrameBufferManager/usecase/FrameBufferManagerCreateAttachmentUseCase.js +125 -0
- package/src/FrameBufferManager/usecase/FrameBufferManagerReleaseTemporaryAttachmentUseCase.d.ts +14 -0
- package/src/FrameBufferManager/usecase/FrameBufferManagerReleaseTemporaryAttachmentUseCase.js +23 -0
- package/src/FrameBufferManager.d.ts +24 -0
- package/src/FrameBufferManager.js +161 -0
- package/src/Gradient/GradientLUTCache.d.ts +61 -0
- package/src/Gradient/GradientLUTCache.js +153 -0
- package/src/Gradient/GradientLUTGenerator.d.ts +30 -0
- package/src/Gradient/GradientLUTGenerator.js +202 -0
- package/src/Grid.d.ts +18 -0
- package/src/Grid.js +21 -0
- package/src/Mask/service/MaskBeginMaskService.d.ts +9 -0
- package/src/Mask/service/MaskBeginMaskService.js +22 -0
- package/src/Mask/service/MaskEndMaskService.d.ts +15 -0
- package/src/Mask/service/MaskEndMaskService.js +36 -0
- package/src/Mask/service/MaskSetMaskBoundsService.d.ts +13 -0
- package/src/Mask/service/MaskSetMaskBoundsService.js +36 -0
- package/src/Mask/service/MaskUnionMaskService.d.ts +4 -0
- package/src/Mask/service/MaskUnionMaskService.js +74 -0
- package/src/Mask/usecase/MaskBindUseCase.d.ts +10 -0
- package/src/Mask/usecase/MaskBindUseCase.js +20 -0
- package/src/Mask/usecase/MaskLeaveMaskUseCase.d.ts +13 -0
- package/src/Mask/usecase/MaskLeaveMaskUseCase.js +51 -0
- package/src/Mask.d.ts +12 -0
- package/src/Mask.js +41 -0
- package/src/Mesh/service/MeshFillGenerateService.d.ts +19 -0
- package/src/Mesh/service/MeshFillGenerateService.js +76 -0
- package/src/Mesh/service/MeshLerpService.d.ts +13 -0
- package/src/Mesh/service/MeshLerpService.js +17 -0
- package/src/Mesh/service/MeshStrokeFillGenerateService.d.ts +19 -0
- package/src/Mesh/service/MeshStrokeFillGenerateService.js +76 -0
- package/src/Mesh/usecase/MeshBitmapStrokeGenerateUseCase.d.ts +13 -0
- package/src/Mesh/usecase/MeshBitmapStrokeGenerateUseCase.js +65 -0
- package/src/Mesh/usecase/MeshFillGenerateUseCase.d.ts +12 -0
- package/src/Mesh/usecase/MeshFillGenerateUseCase.js +48 -0
- package/src/Mesh/usecase/MeshGradientStrokeGenerateUseCase.d.ts +13 -0
- package/src/Mesh/usecase/MeshGradientStrokeGenerateUseCase.js +65 -0
- package/src/Mesh/usecase/MeshSplitQuadraticBezierUseCase.d.ts +14 -0
- package/src/Mesh/usecase/MeshSplitQuadraticBezierUseCase.js +28 -0
- package/src/Mesh/usecase/MeshStrokeFillGenerateUseCase.d.ts +18 -0
- package/src/Mesh/usecase/MeshStrokeFillGenerateUseCase.js +54 -0
- package/src/Mesh/usecase/MeshStrokeGenerateUseCase.d.ts +25 -0
- package/src/Mesh/usecase/MeshStrokeGenerateUseCase.js +608 -0
- package/src/PathCommand.d.ts +123 -0
- package/src/PathCommand.js +317 -0
- package/src/SamplerCache/service/SamplerCacheCreateCommonSamplersService.d.ts +11 -0
- package/src/SamplerCache/service/SamplerCacheCreateCommonSamplersService.js +35 -0
- package/src/SamplerCache/service/SamplerCacheGenerateKeyService.d.ts +13 -0
- package/src/SamplerCache/service/SamplerCacheGenerateKeyService.js +15 -0
- package/src/SamplerCache/service/SamplerCacheGetOrCreateService.d.ts +15 -0
- package/src/SamplerCache/service/SamplerCacheGetOrCreateService.js +30 -0
- package/src/SamplerCache.d.ts +18 -0
- package/src/SamplerCache.js +61 -0
- package/src/Shader/BlendModeShader.d.ts +51 -0
- package/src/Shader/BlendModeShader.js +71 -0
- package/src/Shader/GradientLUTGenerator/service/GradientLUTCalculateResolutionService.d.ts +12 -0
- package/src/Shader/GradientLUTGenerator/service/GradientLUTCalculateResolutionService.js +28 -0
- package/src/Shader/GradientLUTGenerator/service/GradientLUTGeneratePixelsService.d.ts +13 -0
- package/src/Shader/GradientLUTGenerator/service/GradientLUTGeneratePixelsService.js +61 -0
- package/src/Shader/GradientLUTGenerator/service/GradientLUTInterpolateColorService.d.ts +19 -0
- package/src/Shader/GradientLUTGenerator/service/GradientLUTInterpolateColorService.js +37 -0
- package/src/Shader/GradientLUTGenerator/service/GradientLUTParseStopsService.d.ts +11 -0
- package/src/Shader/GradientLUTGenerator/service/GradientLUTParseStopsService.js +24 -0
- package/src/Shader/GradientLUTGenerator/usecase/GradientLUTGenerateDataUseCase.d.ts +14 -0
- package/src/Shader/GradientLUTGenerator/usecase/GradientLUTGenerateDataUseCase.js +24 -0
- package/src/Shader/PipelineManager.d.ts +57 -0
- package/src/Shader/PipelineManager.js +2868 -0
- package/src/Shader/ShaderInstancedManager.d.ts +8 -0
- package/src/Shader/ShaderInstancedManager.js +18 -0
- package/src/Shader/ShaderSource.d.ts +60 -0
- package/src/Shader/ShaderSource.js +518 -0
- package/src/Shader/wgsl/common/SharedWgsl.d.ts +5 -0
- package/src/Shader/wgsl/common/SharedWgsl.js +37 -0
- package/src/Shader/wgsl/fragment/BasicFragment.d.ts +2 -0
- package/src/Shader/wgsl/fragment/BasicFragment.js +28 -0
- package/src/Shader/wgsl/fragment/BitmapFragment.d.ts +1 -0
- package/src/Shader/wgsl/fragment/BitmapFragment.js +43 -0
- package/src/Shader/wgsl/fragment/BlendFragment.d.ts +8 -0
- package/src/Shader/wgsl/fragment/BlendFragment.js +63 -0
- package/src/Shader/wgsl/fragment/EffectFragment.d.ts +6 -0
- package/src/Shader/wgsl/fragment/EffectFragment.js +324 -0
- package/src/Shader/wgsl/fragment/FillFragment.d.ts +1 -0
- package/src/Shader/wgsl/fragment/FillFragment.js +28 -0
- package/src/Shader/wgsl/fragment/FilterFragment.d.ts +10 -0
- package/src/Shader/wgsl/fragment/FilterFragment.js +212 -0
- package/src/Shader/wgsl/fragment/GradientFragment.d.ts +3 -0
- package/src/Shader/wgsl/fragment/GradientFragment.js +118 -0
- package/src/Shader/wgsl/fragment/InstancedFragment.d.ts +1 -0
- package/src/Shader/wgsl/fragment/InstancedFragment.js +20 -0
- package/src/Shader/wgsl/fragment/MaskFragment.d.ts +1 -0
- package/src/Shader/wgsl/fragment/MaskFragment.js +17 -0
- package/src/Shader/wgsl/fragment/StencilFragment.d.ts +2 -0
- package/src/Shader/wgsl/fragment/StencilFragment.js +33 -0
- package/src/Shader/wgsl/vertex/BasicVertex.d.ts +1 -0
- package/src/Shader/wgsl/vertex/BasicVertex.js +37 -0
- package/src/Shader/wgsl/vertex/BitmapVertex.d.ts +1 -0
- package/src/Shader/wgsl/vertex/BitmapVertex.js +43 -0
- package/src/Shader/wgsl/vertex/FillVertex.d.ts +1 -0
- package/src/Shader/wgsl/vertex/FillVertex.js +35 -0
- package/src/Shader/wgsl/vertex/FilterVertex.d.ts +12 -0
- package/src/Shader/wgsl/vertex/FilterVertex.js +193 -0
- package/src/Shader/wgsl/vertex/GradientVertex.d.ts +1 -0
- package/src/Shader/wgsl/vertex/GradientVertex.js +44 -0
- package/src/Shader/wgsl/vertex/InstancedVertex.d.ts +1 -0
- package/src/Shader/wgsl/vertex/InstancedVertex.js +48 -0
- package/src/Shader/wgsl/vertex/MaskVertex.d.ts +1 -0
- package/src/Shader/wgsl/vertex/MaskVertex.js +36 -0
- package/src/Shader/wgsl/vertex/StencilVertex.d.ts +2 -0
- package/src/Shader/wgsl/vertex/StencilVertex.js +66 -0
- package/src/TextureManager/service/TextureManagerInitializeSamplersService.d.ts +11 -0
- package/src/TextureManager/service/TextureManagerInitializeSamplersService.js +48 -0
- package/src/TextureManager/usecase/TextureManagerCreateTextureFromImageBitmapUseCase.d.ts +13 -0
- package/src/TextureManager/usecase/TextureManagerCreateTextureFromImageBitmapUseCase.js +30 -0
- package/src/TextureManager/usecase/TextureManagerCreateTextureFromPixelsUseCase.d.ts +15 -0
- package/src/TextureManager/usecase/TextureManagerCreateTextureFromPixelsUseCase.js +26 -0
- package/src/TextureManager.d.ts +15 -0
- package/src/TextureManager.js +87 -0
- package/src/TexturePool/service/TexturePoolCleanupService.d.ts +14 -0
- package/src/TexturePool/service/TexturePoolCleanupService.js +28 -0
- package/src/TexturePool/service/TexturePoolEvictOldestService.d.ts +11 -0
- package/src/TexturePool/service/TexturePoolEvictOldestService.js +24 -0
- package/src/TexturePool/service/TexturePoolReleaseService.d.ts +13 -0
- package/src/TexturePool/service/TexturePoolReleaseService.js +22 -0
- package/src/TexturePool/usecase/TexturePoolAcquireUseCase.d.ts +19 -0
- package/src/TexturePool/usecase/TexturePoolAcquireUseCase.js +90 -0
- package/src/TexturePool.d.ts +69 -0
- package/src/TexturePool.js +151 -0
- package/src/WebGPUUtil.d.ts +102 -0
- package/src/WebGPUUtil.js +157 -0
- package/src/index.d.ts +1 -0
- package/src/index.js +1 -0
- package/src/interface/IAttachmentObject.d.ts +41 -0
- package/src/interface/IAttachmentObject.js +1 -0
- package/src/interface/IBlendMode.d.ts +1 -0
- package/src/interface/IBlendMode.js +1 -0
- package/src/interface/IBlendState.d.ts +8 -0
- package/src/interface/IBlendState.js +1 -0
- package/src/interface/IBounds.d.ts +6 -0
- package/src/interface/IBounds.js +1 -0
- package/src/interface/ICachedBindGroup.d.ts +8 -0
- package/src/interface/ICachedBindGroup.js +1 -0
- package/src/interface/IColorBufferObject.d.ts +17 -0
- package/src/interface/IColorBufferObject.js +1 -0
- package/src/interface/IComplexBlendItem.d.ts +19 -0
- package/src/interface/IComplexBlendItem.js +1 -0
- package/src/interface/IFilterConfig.d.ts +29 -0
- package/src/interface/IFilterConfig.js +1 -0
- package/src/interface/IGradientLUTData.d.ts +8 -0
- package/src/interface/IGradientLUTData.js +1 -0
- package/src/interface/IGradientStop.d.ts +11 -0
- package/src/interface/IGradientStop.js +1 -0
- package/src/interface/ILocalFilterConfig.d.ts +21 -0
- package/src/interface/ILocalFilterConfig.js +1 -0
- package/src/interface/IMeshResult.d.ts +8 -0
- package/src/interface/IMeshResult.js +1 -0
- package/src/interface/IPath.d.ts +8 -0
- package/src/interface/IPath.js +1 -0
- package/src/interface/IPoint.d.ts +4 -0
- package/src/interface/IPoint.js +1 -0
- package/src/interface/IPooledBuffer.d.ts +8 -0
- package/src/interface/IPooledBuffer.js +1 -0
- package/src/interface/IPooledTexture.d.ts +17 -0
- package/src/interface/IPooledTexture.js +1 -0
- package/src/interface/IQuadraticSegment.d.ts +9 -0
- package/src/interface/IQuadraticSegment.js +1 -0
- package/src/interface/IRectangleInfo.d.ts +13 -0
- package/src/interface/IRectangleInfo.js +1 -0
- package/src/interface/IStencilBufferObject.d.ts +16 -0
- package/src/interface/IStencilBufferObject.js +1 -0
- package/src/interface/IStorageBufferConfig.d.ts +40 -0
- package/src/interface/IStorageBufferConfig.js +1 -0
- package/src/interface/ITextureObject.d.ts +16 -0
- package/src/interface/ITextureObject.js +1 -0
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import { $offset } from "../FilterOffset";
|
|
2
|
+
import { calculateBlurParams, calculateDirectionalBlurParams } from "../BlurFilterUseCase";
|
|
3
|
+
import { shouldUseComputeShader } from "./service/BlurFilterComputeShaderService";
|
|
4
|
+
import { execute as executeBlurCompute } from "../../Compute/service/ComputeExecuteBlurService";
|
|
5
|
+
/**
|
|
6
|
+
* @description プリアロケートされたFloat32Array (サイズ4)
|
|
7
|
+
*/
|
|
8
|
+
const $uniform4 = new Float32Array(4);
|
|
9
|
+
/**
|
|
10
|
+
* @description プリアロケートされたBindGroupEntry配列 (バインディング3つ)
|
|
11
|
+
*/
|
|
12
|
+
const $entries3 = [
|
|
13
|
+
{ "binding": 0, "resource": { "buffer": null } },
|
|
14
|
+
{ "binding": 1, "resource": null },
|
|
15
|
+
{ "binding": 2, "resource": null }
|
|
16
|
+
];
|
|
17
|
+
/**
|
|
18
|
+
* @description ブラーフィルターを適用
|
|
19
|
+
* Apply blur filter
|
|
20
|
+
*
|
|
21
|
+
* @param {IAttachmentObject} sourceAttachment - 入力テクスチャ(アタッチメント)
|
|
22
|
+
* @param {Float32Array} matrix - 変換行列
|
|
23
|
+
* @param {number} blurX - X方向のブラー量
|
|
24
|
+
* @param {number} blurY - Y方向のブラー量
|
|
25
|
+
* @param {number} quality - クオリティ (1-15)
|
|
26
|
+
* @param {number} devicePixelRatio - デバイスピクセル比
|
|
27
|
+
* @param {IFilterConfig} config - WebGPUリソース設定
|
|
28
|
+
* @return {IAttachmentObject} - フィルター適用後のアタッチメント
|
|
29
|
+
*/
|
|
30
|
+
export const execute = (sourceAttachment, matrix, blurX, blurY, quality, devicePixelRatio, config) => {
|
|
31
|
+
const { device, commandEncoder, frameBufferManager, pipelineManager, textureManager } = config;
|
|
32
|
+
// ブラーパラメータを計算
|
|
33
|
+
const blurParams = calculateBlurParams(matrix, blurX, blurY, quality, devicePixelRatio);
|
|
34
|
+
const { baseBlurX, baseBlurY, offsetX, offsetY, bufferScaleX, bufferScaleY } = blurParams;
|
|
35
|
+
// オフセットを更新
|
|
36
|
+
$offset.x += offsetX;
|
|
37
|
+
$offset.y += offsetY;
|
|
38
|
+
// ブラー用バッファサイズを計算
|
|
39
|
+
const width = sourceAttachment.width + offsetX * 2;
|
|
40
|
+
const height = sourceAttachment.height + offsetY * 2;
|
|
41
|
+
const bufferWidth = Math.ceil(width * bufferScaleX);
|
|
42
|
+
const bufferHeight = Math.ceil(height * bufferScaleY);
|
|
43
|
+
// ピンポンバッファ用の一時アタッチメントを作成
|
|
44
|
+
const attachment0 = frameBufferManager.createTemporaryAttachment(bufferWidth, bufferHeight);
|
|
45
|
+
const attachment1 = frameBufferManager.createTemporaryAttachment(bufferWidth, bufferHeight);
|
|
46
|
+
// サンプラーを作成(線形補間)
|
|
47
|
+
const sampler = textureManager.createSampler("blur_sampler", true);
|
|
48
|
+
// ソーステクスチャをattachment0にコピー(スケーリング付き)
|
|
49
|
+
copyTextureToAttachment(device, commandEncoder, frameBufferManager, pipelineManager, sourceAttachment, attachment0, sampler, bufferScaleX, bufferScaleY, offsetX * bufferScaleX, offsetY * bufferScaleY, config.bufferManager);
|
|
50
|
+
// バッファスケールを考慮したブラー値
|
|
51
|
+
const bufferBlurX = baseBlurX * bufferScaleX;
|
|
52
|
+
const bufferBlurY = baseBlurY * bufferScaleY;
|
|
53
|
+
// Compute Shaderを使用すべきか判定
|
|
54
|
+
const useCompute = config.computePipelineManager
|
|
55
|
+
&& shouldUseComputeShader(baseBlurX, baseBlurY, bufferWidth, bufferHeight);
|
|
56
|
+
// ブラーパスを実行
|
|
57
|
+
const attachments = [attachment0, attachment1];
|
|
58
|
+
let attachmentIndex = 0;
|
|
59
|
+
for (let q = 0; q < quality; ++q) {
|
|
60
|
+
// 水平ブラー
|
|
61
|
+
if (blurX > 0) {
|
|
62
|
+
const srcIndex = attachmentIndex;
|
|
63
|
+
attachmentIndex = (attachmentIndex + 1) % 2;
|
|
64
|
+
if (useCompute) {
|
|
65
|
+
executeBlurCompute(device, commandEncoder, config.computePipelineManager, attachments[srcIndex], attachments[attachmentIndex], true, bufferBlurX, config.bufferManager);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
applyDirectionalBlur(device, commandEncoder, frameBufferManager, pipelineManager, attachments[srcIndex], attachments[attachmentIndex], sampler, true, bufferBlurX, config.bufferManager);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// 垂直ブラー
|
|
72
|
+
if (blurY > 0) {
|
|
73
|
+
const srcIndex = attachmentIndex;
|
|
74
|
+
attachmentIndex = (attachmentIndex + 1) % 2;
|
|
75
|
+
if (useCompute) {
|
|
76
|
+
executeBlurCompute(device, commandEncoder, config.computePipelineManager, attachments[srcIndex], attachments[attachmentIndex], false, bufferBlurY, config.bufferManager);
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
applyDirectionalBlur(device, commandEncoder, frameBufferManager, pipelineManager, attachments[srcIndex], attachments[attachmentIndex], sampler, false, bufferBlurY, config.bufferManager);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
// 結果のアタッチメント
|
|
84
|
+
let resultAttachment = attachments[attachmentIndex];
|
|
85
|
+
// バッファスケールが1でない場合は元のサイズにアップスケール
|
|
86
|
+
if (bufferScaleX !== 1 || bufferScaleY !== 1) {
|
|
87
|
+
const finalAttachment = frameBufferManager.createTemporaryAttachment(width, height);
|
|
88
|
+
upscaleTexture(device, commandEncoder, frameBufferManager, pipelineManager, resultAttachment, finalAttachment, sampler, 1 / bufferScaleX, 1 / bufferScaleY, config.bufferManager);
|
|
89
|
+
// ピンポンバッファを解放
|
|
90
|
+
frameBufferManager.releaseTemporaryAttachment(attachment0);
|
|
91
|
+
frameBufferManager.releaseTemporaryAttachment(attachment1);
|
|
92
|
+
resultAttachment = finalAttachment;
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
// 使わなかったバッファを解放
|
|
96
|
+
const unusedIndex = (attachmentIndex + 1) % 2;
|
|
97
|
+
frameBufferManager.releaseTemporaryAttachment(attachments[unusedIndex]);
|
|
98
|
+
}
|
|
99
|
+
return resultAttachment;
|
|
100
|
+
};
|
|
101
|
+
/**
|
|
102
|
+
* @description テクスチャをアタッチメントにコピー(オフセット位置に配置、スケーリング対応)
|
|
103
|
+
*
|
|
104
|
+
* @param source - ソーステクスチャ
|
|
105
|
+
* @param dest - デストテクスチャ(ソースより大きい)
|
|
106
|
+
* @param bufferScaleX - X方向のバッファスケール
|
|
107
|
+
* @param bufferScaleY - Y方向のバッファスケール
|
|
108
|
+
* @param pixelOffsetX - デスト内でのX方向オフセット(ピクセル単位、スケーリング済み)
|
|
109
|
+
* @param pixelOffsetY - デスト内でのY方向オフセット(ピクセル単位、スケーリング済み)
|
|
110
|
+
*/
|
|
111
|
+
const copyTextureToAttachment = (device, commandEncoder, frameBufferManager, pipelineManager, source, dest, sampler, bufferScaleX, bufferScaleY, pixelOffsetX, pixelOffsetY, bufferManager) => {
|
|
112
|
+
// texture_copy_rgba8を使用し、ビューポートでオフセットを制御
|
|
113
|
+
const pipeline = pipelineManager.getPipeline("texture_copy_rgba8");
|
|
114
|
+
const bindGroupLayout = pipelineManager.getBindGroupLayout("texture_copy");
|
|
115
|
+
if (!pipeline || !bindGroupLayout) {
|
|
116
|
+
console.error("[WebGPU BlurFilter] texture_copy_rgba8 pipeline not found");
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
// デスト内でのソース描画サイズ(スケーリング後)
|
|
120
|
+
const scaledSourceWidth = source.width * bufferScaleX;
|
|
121
|
+
const scaledSourceHeight = source.height * bufferScaleY;
|
|
122
|
+
// シェーダー: uv = texCoord * scale + offset
|
|
123
|
+
// ソース全体をサンプリングするので scale = 1, offset = 0
|
|
124
|
+
const scaleX = 1;
|
|
125
|
+
const scaleY = 1;
|
|
126
|
+
const offsetX = 0;
|
|
127
|
+
const offsetY = 0;
|
|
128
|
+
// ユニフォームバッファ: scale(2) + offset(2)
|
|
129
|
+
$uniform4[0] = scaleX;
|
|
130
|
+
$uniform4[1] = scaleY;
|
|
131
|
+
$uniform4[2] = offsetX;
|
|
132
|
+
$uniform4[3] = offsetY;
|
|
133
|
+
const uniformBuffer = bufferManager
|
|
134
|
+
? bufferManager.acquireAndWriteUniformBuffer($uniform4)
|
|
135
|
+
: device.createBuffer({
|
|
136
|
+
"size": $uniform4.byteLength,
|
|
137
|
+
"usage": GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
|
|
138
|
+
});
|
|
139
|
+
if (!bufferManager) {
|
|
140
|
+
device.queue.writeBuffer(uniformBuffer, 0, $uniform4);
|
|
141
|
+
}
|
|
142
|
+
$entries3[0].resource.buffer = uniformBuffer;
|
|
143
|
+
$entries3[1].resource = sampler;
|
|
144
|
+
$entries3[2].resource = source.texture.view;
|
|
145
|
+
const bindGroup = device.createBindGroup({
|
|
146
|
+
"layout": bindGroupLayout,
|
|
147
|
+
"entries": $entries3
|
|
148
|
+
});
|
|
149
|
+
const renderPassDescriptor = frameBufferManager.createRenderPassDescriptor(dest.texture.view, 0, 0, 0, 0, "clear");
|
|
150
|
+
const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
|
|
151
|
+
passEncoder.setPipeline(pipeline);
|
|
152
|
+
passEncoder.setBindGroup(0, bindGroup);
|
|
153
|
+
// ビューポートを設定してオフセット位置に描画
|
|
154
|
+
passEncoder.setViewport(pixelOffsetX, pixelOffsetY, scaledSourceWidth, scaledSourceHeight, 0, 1);
|
|
155
|
+
passEncoder.setScissorRect(Math.floor(pixelOffsetX), Math.floor(pixelOffsetY), Math.ceil(scaledSourceWidth), Math.ceil(scaledSourceHeight));
|
|
156
|
+
passEncoder.draw(6, 1, 0, 0);
|
|
157
|
+
passEncoder.end();
|
|
158
|
+
// Note: uniformBuffer is not destroyed here - it will be garbage collected after GPU submission
|
|
159
|
+
};
|
|
160
|
+
/**
|
|
161
|
+
* @description 方向ブラーを適用
|
|
162
|
+
*/
|
|
163
|
+
const applyDirectionalBlur = (device, commandEncoder, frameBufferManager, pipelineManager, source, dest, sampler, isHorizontal, blur, bufferManager) => {
|
|
164
|
+
const params = calculateDirectionalBlurParams(isHorizontal, blur, source.width, source.height);
|
|
165
|
+
const { offsetX, offsetY, fraction, samples, halfBlur } = params;
|
|
166
|
+
// halfBlurに対応するパイプラインを取得(1〜16の範囲でクランプ)
|
|
167
|
+
const clampedHalfBlur = Math.max(1, Math.min(16, halfBlur));
|
|
168
|
+
const pipeline = pipelineManager.getPipeline(`blur_filter_${clampedHalfBlur}`);
|
|
169
|
+
const bindGroupLayout = pipelineManager.getBindGroupLayout("blur_filter");
|
|
170
|
+
if (!pipeline || !bindGroupLayout) {
|
|
171
|
+
console.error(`[WebGPU BlurFilter] blur_filter_${clampedHalfBlur} pipeline not found`);
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
// ユニフォームバッファ: offset(2) + fraction + samples
|
|
175
|
+
$uniform4[0] = offsetX;
|
|
176
|
+
$uniform4[1] = offsetY;
|
|
177
|
+
$uniform4[2] = fraction;
|
|
178
|
+
$uniform4[3] = samples;
|
|
179
|
+
const uniformBuffer = bufferManager
|
|
180
|
+
? bufferManager.acquireAndWriteUniformBuffer($uniform4)
|
|
181
|
+
: device.createBuffer({
|
|
182
|
+
"size": $uniform4.byteLength,
|
|
183
|
+
"usage": GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
|
|
184
|
+
});
|
|
185
|
+
if (!bufferManager) {
|
|
186
|
+
device.queue.writeBuffer(uniformBuffer, 0, $uniform4);
|
|
187
|
+
}
|
|
188
|
+
$entries3[0].resource.buffer = uniformBuffer;
|
|
189
|
+
$entries3[1].resource = sampler;
|
|
190
|
+
$entries3[2].resource = source.texture.view;
|
|
191
|
+
const bindGroup = device.createBindGroup({
|
|
192
|
+
"layout": bindGroupLayout,
|
|
193
|
+
"entries": $entries3
|
|
194
|
+
});
|
|
195
|
+
const renderPassDescriptor = frameBufferManager.createRenderPassDescriptor(dest.texture.view, 0, 0, 0, 0, "clear");
|
|
196
|
+
const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
|
|
197
|
+
passEncoder.setPipeline(pipeline);
|
|
198
|
+
passEncoder.setBindGroup(0, bindGroup);
|
|
199
|
+
passEncoder.draw(6, 1, 0, 0);
|
|
200
|
+
passEncoder.end();
|
|
201
|
+
// Note: uniformBuffer is not destroyed here - it will be garbage collected after GPU submission
|
|
202
|
+
};
|
|
203
|
+
/**
|
|
204
|
+
* @description テクスチャをアップスケール(ソース全体をデスト全体にマッピング)
|
|
205
|
+
*/
|
|
206
|
+
const upscaleTexture = (device, commandEncoder, frameBufferManager, pipelineManager, source, dest, sampler, _scaleX, _scaleY, bufferManager) => {
|
|
207
|
+
// temp_アタッチメントはrgba8unormフォーマットなので、texture_copy_rgba8パイプラインを使用
|
|
208
|
+
const pipeline = pipelineManager.getPipeline("texture_copy_rgba8");
|
|
209
|
+
const bindGroupLayout = pipelineManager.getBindGroupLayout("texture_copy");
|
|
210
|
+
if (!pipeline || !bindGroupLayout) {
|
|
211
|
+
console.error("[WebGPU BlurFilter] texture_copy_rgba8 pipeline not found");
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
// アップスケールではソース全体をデスト全体にマッピング
|
|
215
|
+
// シェーダー: uv = (texCoord - offset) * scale
|
|
216
|
+
// scale = 1, offset = 0 で uv = texCoord となり、ソース全体がデスト全体にマッピングされる
|
|
217
|
+
$uniform4[0] = 1;
|
|
218
|
+
$uniform4[1] = 1;
|
|
219
|
+
$uniform4[2] = 0;
|
|
220
|
+
$uniform4[3] = 0;
|
|
221
|
+
const uniformBuffer = bufferManager
|
|
222
|
+
? bufferManager.acquireAndWriteUniformBuffer($uniform4)
|
|
223
|
+
: device.createBuffer({
|
|
224
|
+
"size": $uniform4.byteLength,
|
|
225
|
+
"usage": GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
|
|
226
|
+
});
|
|
227
|
+
if (!bufferManager) {
|
|
228
|
+
device.queue.writeBuffer(uniformBuffer, 0, $uniform4);
|
|
229
|
+
}
|
|
230
|
+
$entries3[0].resource.buffer = uniformBuffer;
|
|
231
|
+
$entries3[1].resource = sampler;
|
|
232
|
+
$entries3[2].resource = source.texture.view;
|
|
233
|
+
const bindGroup = device.createBindGroup({
|
|
234
|
+
"layout": bindGroupLayout,
|
|
235
|
+
"entries": $entries3
|
|
236
|
+
});
|
|
237
|
+
const renderPassDescriptor = frameBufferManager.createRenderPassDescriptor(dest.texture.view, 0, 0, 0, 0, "clear");
|
|
238
|
+
const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
|
|
239
|
+
passEncoder.setPipeline(pipeline);
|
|
240
|
+
passEncoder.setBindGroup(0, bindGroup);
|
|
241
|
+
passEncoder.draw(6, 1, 0, 0);
|
|
242
|
+
passEncoder.end();
|
|
243
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { IAttachmentObject } from "../../../interface/IAttachmentObject";
|
|
2
|
+
import type { IFilterConfig } from "../../../interface/IFilterConfig";
|
|
3
|
+
import type { ComputePipelineManager } from "../../../Compute/ComputePipelineManager";
|
|
4
|
+
/**
|
|
5
|
+
* @description Compute Shaderでブラーパスを実行
|
|
6
|
+
* Apply blur pass using Compute Shader
|
|
7
|
+
*
|
|
8
|
+
* Fragment Shaderベースの従来実装と比較して:
|
|
9
|
+
* - 並列処理による高速化(大きな半径で20-35%)
|
|
10
|
+
* - 共有メモリを活用したメモリアクセス最適化
|
|
11
|
+
* - ワークグループ内でのデータ共有
|
|
12
|
+
*
|
|
13
|
+
* @param {GPUDevice} device - WebGPU device
|
|
14
|
+
* @param {GPUCommandEncoder} commandEncoder - コマンドエンコーダー
|
|
15
|
+
* @param {ComputePipelineManager} computePipelineManager - Compute Pipeline Manager
|
|
16
|
+
* @param {IFilterConfig} config - フィルター設定
|
|
17
|
+
* @param {IAttachmentObject} source - 入力アタッチメント
|
|
18
|
+
* @param {IAttachmentObject} dest - 出力アタッチメント
|
|
19
|
+
* @param {boolean} isHorizontal - 水平ブラーかどうか
|
|
20
|
+
* @param {number} blur - ブラー量
|
|
21
|
+
* @return {void}
|
|
22
|
+
*/
|
|
23
|
+
export declare const execute: (device: GPUDevice, commandEncoder: GPUCommandEncoder, computePipelineManager: ComputePipelineManager, _config: IFilterConfig, source: IAttachmentObject, dest: IAttachmentObject, isHorizontal: boolean, blur: number) => void;
|
|
24
|
+
/**
|
|
25
|
+
* @description Compute Shaderを使用すべきかどうか判定
|
|
26
|
+
* Determine whether to use Compute Shader
|
|
27
|
+
*
|
|
28
|
+
* 以下の条件でCompute Shaderを使用:
|
|
29
|
+
* - ブラー半径が大きい(8以上)
|
|
30
|
+
* - テクスチャサイズが十分大きい(256x256以上)
|
|
31
|
+
*
|
|
32
|
+
* 小さなブラー半径では Fragment Shader の方が効率的な場合がある。
|
|
33
|
+
*
|
|
34
|
+
* @param {number} blurX - X方向のブラー量
|
|
35
|
+
* @param {number} blurY - Y方向のブラー量
|
|
36
|
+
* @param {number} width - テクスチャ幅
|
|
37
|
+
* @param {number} height - テクスチャ高さ
|
|
38
|
+
* @return {boolean} Compute Shaderを使用すべきかどうか
|
|
39
|
+
*/
|
|
40
|
+
export declare const shouldUseComputeShader: (blurX: number, blurY: number, width: number, height: number) => boolean;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { execute as executeBlurCompute } from "../../../Compute/service/ComputeExecuteBlurService";
|
|
2
|
+
/**
|
|
3
|
+
* @description Compute Shaderでブラーパスを実行
|
|
4
|
+
* Apply blur pass using Compute Shader
|
|
5
|
+
*
|
|
6
|
+
* Fragment Shaderベースの従来実装と比較して:
|
|
7
|
+
* - 並列処理による高速化(大きな半径で20-35%)
|
|
8
|
+
* - 共有メモリを活用したメモリアクセス最適化
|
|
9
|
+
* - ワークグループ内でのデータ共有
|
|
10
|
+
*
|
|
11
|
+
* @param {GPUDevice} device - WebGPU device
|
|
12
|
+
* @param {GPUCommandEncoder} commandEncoder - コマンドエンコーダー
|
|
13
|
+
* @param {ComputePipelineManager} computePipelineManager - Compute Pipeline Manager
|
|
14
|
+
* @param {IFilterConfig} config - フィルター設定
|
|
15
|
+
* @param {IAttachmentObject} source - 入力アタッチメント
|
|
16
|
+
* @param {IAttachmentObject} dest - 出力アタッチメント
|
|
17
|
+
* @param {boolean} isHorizontal - 水平ブラーかどうか
|
|
18
|
+
* @param {number} blur - ブラー量
|
|
19
|
+
* @return {void}
|
|
20
|
+
*/
|
|
21
|
+
export const execute = (device, commandEncoder, computePipelineManager, _config, source, dest, isHorizontal, blur) => {
|
|
22
|
+
// ブラー半径を計算(ブラー量の半分)
|
|
23
|
+
const radius = Math.ceil(blur / 2);
|
|
24
|
+
// Compute Shaderでブラーを実行
|
|
25
|
+
executeBlurCompute(device, commandEncoder, computePipelineManager, source, dest, isHorizontal, radius);
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* @description Compute Shaderを使用すべきかどうか判定
|
|
29
|
+
* Determine whether to use Compute Shader
|
|
30
|
+
*
|
|
31
|
+
* 以下の条件でCompute Shaderを使用:
|
|
32
|
+
* - ブラー半径が大きい(8以上)
|
|
33
|
+
* - テクスチャサイズが十分大きい(256x256以上)
|
|
34
|
+
*
|
|
35
|
+
* 小さなブラー半径では Fragment Shader の方が効率的な場合がある。
|
|
36
|
+
*
|
|
37
|
+
* @param {number} blurX - X方向のブラー量
|
|
38
|
+
* @param {number} blurY - Y方向のブラー量
|
|
39
|
+
* @param {number} width - テクスチャ幅
|
|
40
|
+
* @param {number} height - テクスチャ高さ
|
|
41
|
+
* @return {boolean} Compute Shaderを使用すべきかどうか
|
|
42
|
+
*/
|
|
43
|
+
export const shouldUseComputeShader = (blurX, blurY, width, height) => {
|
|
44
|
+
// ブラー半径のしきい値
|
|
45
|
+
const BLUR_THRESHOLD = 4;
|
|
46
|
+
// テクスチャサイズのしきい値
|
|
47
|
+
const SIZE_THRESHOLD = 128;
|
|
48
|
+
const maxBlur = Math.max(blurX, blurY);
|
|
49
|
+
const minSize = Math.min(width, height);
|
|
50
|
+
return maxBlur >= BLUR_THRESHOLD && minSize >= SIZE_THRESHOLD;
|
|
51
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { IAttachmentObject } from "../../../interface/IAttachmentObject";
|
|
2
|
+
import type { IFilterConfig } from "../../../interface/IFilterConfig";
|
|
3
|
+
import type { ComputePipelineManager } from "../../../Compute/ComputePipelineManager";
|
|
4
|
+
/**
|
|
5
|
+
* @description Compute Shaderを使用したブラーフィルター
|
|
6
|
+
* Apply blur filter using Compute Shader
|
|
7
|
+
*
|
|
8
|
+
* Fragment Shaderベースの従来実装と比較して:
|
|
9
|
+
* - 大きなブラー半径で20-35%高速化
|
|
10
|
+
* - 並列処理による効率的なテクスチャサンプリング
|
|
11
|
+
* - 共有メモリを活用したメモリアクセス最適化
|
|
12
|
+
*
|
|
13
|
+
* 小さなブラー半径(8未満)では従来のFragment Shaderを使用。
|
|
14
|
+
*
|
|
15
|
+
* @param {IAttachmentObject} sourceAttachment - 入力テクスチャ
|
|
16
|
+
* @param {Float32Array} matrix - 変換行列
|
|
17
|
+
* @param {number} blurX - X方向のブラー量
|
|
18
|
+
* @param {number} blurY - Y方向のブラー量
|
|
19
|
+
* @param {number} quality - クオリティ (1-15)
|
|
20
|
+
* @param {number} devicePixelRatio - デバイスピクセル比
|
|
21
|
+
* @param {IFilterConfig} config - WebGPUリソース設定
|
|
22
|
+
* @param {ComputePipelineManager} computePipelineManager - Compute Pipeline Manager
|
|
23
|
+
* @return {IAttachmentObject} - フィルター適用後のアタッチメント
|
|
24
|
+
*/
|
|
25
|
+
export declare const execute: (sourceAttachment: IAttachmentObject, matrix: Float32Array, blurX: number, blurY: number, quality: number, devicePixelRatio: number, config: IFilterConfig, computePipelineManager: ComputePipelineManager) => IAttachmentObject;
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { $offset } from "../../FilterOffset";
|
|
2
|
+
import { calculateBlurParams } from "../../BlurFilterUseCase";
|
|
3
|
+
import { execute as blurComputeService, shouldUseComputeShader } from "../service/BlurFilterComputeShaderService";
|
|
4
|
+
import { execute as executeFragmentBlur } from "../FilterApplyBlurFilterUseCase";
|
|
5
|
+
/**
|
|
6
|
+
* @description プリアロケートされたFloat32Array (サイズ4)
|
|
7
|
+
*/
|
|
8
|
+
const $uniform4 = new Float32Array(4);
|
|
9
|
+
/**
|
|
10
|
+
* @description プリアロケートされたBindGroupEntry配列 (バインディング3つ)
|
|
11
|
+
*/
|
|
12
|
+
const $entries3 = [
|
|
13
|
+
{ "binding": 0, "resource": { "buffer": null } },
|
|
14
|
+
{ "binding": 1, "resource": null },
|
|
15
|
+
{ "binding": 2, "resource": null }
|
|
16
|
+
];
|
|
17
|
+
/**
|
|
18
|
+
* @description Compute Shaderを使用したブラーフィルター
|
|
19
|
+
* Apply blur filter using Compute Shader
|
|
20
|
+
*
|
|
21
|
+
* Fragment Shaderベースの従来実装と比較して:
|
|
22
|
+
* - 大きなブラー半径で20-35%高速化
|
|
23
|
+
* - 並列処理による効率的なテクスチャサンプリング
|
|
24
|
+
* - 共有メモリを活用したメモリアクセス最適化
|
|
25
|
+
*
|
|
26
|
+
* 小さなブラー半径(8未満)では従来のFragment Shaderを使用。
|
|
27
|
+
*
|
|
28
|
+
* @param {IAttachmentObject} sourceAttachment - 入力テクスチャ
|
|
29
|
+
* @param {Float32Array} matrix - 変換行列
|
|
30
|
+
* @param {number} blurX - X方向のブラー量
|
|
31
|
+
* @param {number} blurY - Y方向のブラー量
|
|
32
|
+
* @param {number} quality - クオリティ (1-15)
|
|
33
|
+
* @param {number} devicePixelRatio - デバイスピクセル比
|
|
34
|
+
* @param {IFilterConfig} config - WebGPUリソース設定
|
|
35
|
+
* @param {ComputePipelineManager} computePipelineManager - Compute Pipeline Manager
|
|
36
|
+
* @return {IAttachmentObject} - フィルター適用後のアタッチメント
|
|
37
|
+
*/
|
|
38
|
+
export const execute = (sourceAttachment, matrix, blurX, blurY, quality, devicePixelRatio, config, computePipelineManager) => {
|
|
39
|
+
const { device, commandEncoder, frameBufferManager, pipelineManager, textureManager } = config;
|
|
40
|
+
// ブラーパラメータを計算
|
|
41
|
+
const blurParams = calculateBlurParams(matrix, blurX, blurY, quality, devicePixelRatio);
|
|
42
|
+
const { baseBlurX, baseBlurY, offsetX, offsetY, bufferScaleX, bufferScaleY } = blurParams;
|
|
43
|
+
// オフセットを更新
|
|
44
|
+
$offset.x += offsetX;
|
|
45
|
+
$offset.y += offsetY;
|
|
46
|
+
// ブラー用バッファサイズを計算
|
|
47
|
+
const width = sourceAttachment.width + offsetX * 2;
|
|
48
|
+
const height = sourceAttachment.height + offsetY * 2;
|
|
49
|
+
const bufferWidth = Math.ceil(width * bufferScaleX);
|
|
50
|
+
const bufferHeight = Math.ceil(height * bufferScaleY);
|
|
51
|
+
// Compute Shaderを使用すべきか判定
|
|
52
|
+
const useCompute = shouldUseComputeShader(baseBlurX, baseBlurY, bufferWidth, bufferHeight);
|
|
53
|
+
if (!useCompute) {
|
|
54
|
+
// 小さなブラーは従来のFragment Shaderを使用
|
|
55
|
+
// FilterApplyBlurFilterUseCaseにフォールバック
|
|
56
|
+
return executeFragmentBlur(sourceAttachment, matrix, blurX, blurY, quality, devicePixelRatio, config);
|
|
57
|
+
}
|
|
58
|
+
// ピンポンバッファ用の一時アタッチメントを作成
|
|
59
|
+
const attachment0 = frameBufferManager.createTemporaryAttachment(bufferWidth, bufferHeight);
|
|
60
|
+
const attachment1 = frameBufferManager.createTemporaryAttachment(bufferWidth, bufferHeight);
|
|
61
|
+
// サンプラーを作成(線形補間)
|
|
62
|
+
const sampler = textureManager.createSampler("blur_compute_sampler", true);
|
|
63
|
+
// ソーステクスチャをattachment0にコピー
|
|
64
|
+
copyTextureToAttachment(device, commandEncoder, frameBufferManager, pipelineManager, sourceAttachment, attachment0, sampler, bufferScaleX, bufferScaleY, offsetX * bufferScaleX, offsetY * bufferScaleY, config.bufferManager);
|
|
65
|
+
// バッファスケールを考慮したブラー値
|
|
66
|
+
const bufferBlurX = baseBlurX * bufferScaleX;
|
|
67
|
+
const bufferBlurY = baseBlurY * bufferScaleY;
|
|
68
|
+
// Compute Shaderでブラーパスを実行
|
|
69
|
+
const attachments = [attachment0, attachment1];
|
|
70
|
+
let attachmentIndex = 0;
|
|
71
|
+
for (let q = 0; q < quality; ++q) {
|
|
72
|
+
// 水平ブラー
|
|
73
|
+
if (blurX > 0) {
|
|
74
|
+
const srcIndex = attachmentIndex;
|
|
75
|
+
attachmentIndex = (attachmentIndex + 1) % 2;
|
|
76
|
+
blurComputeService(device, commandEncoder, computePipelineManager, config, attachments[srcIndex], attachments[attachmentIndex], true, bufferBlurX);
|
|
77
|
+
}
|
|
78
|
+
// 垂直ブラー
|
|
79
|
+
if (blurY > 0) {
|
|
80
|
+
const srcIndex = attachmentIndex;
|
|
81
|
+
attachmentIndex = (attachmentIndex + 1) % 2;
|
|
82
|
+
blurComputeService(device, commandEncoder, computePipelineManager, config, attachments[srcIndex], attachments[attachmentIndex], false, bufferBlurY);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// 結果のアタッチメント
|
|
86
|
+
let resultAttachment = attachments[attachmentIndex];
|
|
87
|
+
// バッファスケールが1でない場合は元のサイズにアップスケール
|
|
88
|
+
if (bufferScaleX !== 1 || bufferScaleY !== 1) {
|
|
89
|
+
const finalAttachment = frameBufferManager.createTemporaryAttachment(width, height);
|
|
90
|
+
upscaleTexture(device, commandEncoder, frameBufferManager, pipelineManager, resultAttachment, finalAttachment, sampler, config.bufferManager);
|
|
91
|
+
// ピンポンバッファを解放
|
|
92
|
+
frameBufferManager.releaseTemporaryAttachment(attachment0);
|
|
93
|
+
frameBufferManager.releaseTemporaryAttachment(attachment1);
|
|
94
|
+
resultAttachment = finalAttachment;
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
// 使わなかったバッファを解放
|
|
98
|
+
const unusedIndex = (attachmentIndex + 1) % 2;
|
|
99
|
+
frameBufferManager.releaseTemporaryAttachment(attachments[unusedIndex]);
|
|
100
|
+
}
|
|
101
|
+
return resultAttachment;
|
|
102
|
+
};
|
|
103
|
+
/**
|
|
104
|
+
* @description テクスチャをアタッチメントにコピー
|
|
105
|
+
*/
|
|
106
|
+
const copyTextureToAttachment = (device, commandEncoder, frameBufferManager, pipelineManager, source, dest, sampler, bufferScaleX, bufferScaleY, pixelOffsetX, pixelOffsetY, bufferManager) => {
|
|
107
|
+
const pipeline = pipelineManager.getPipeline("texture_copy_rgba8");
|
|
108
|
+
const bindGroupLayout = pipelineManager.getBindGroupLayout("texture_copy");
|
|
109
|
+
if (!pipeline || !bindGroupLayout) {
|
|
110
|
+
console.error("[WebGPU BlurCompute] texture_copy_rgba8 pipeline not found");
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const scaledSourceWidth = source.width * bufferScaleX;
|
|
114
|
+
const scaledSourceHeight = source.height * bufferScaleY;
|
|
115
|
+
$uniform4[0] = 1;
|
|
116
|
+
$uniform4[1] = 1;
|
|
117
|
+
$uniform4[2] = 0;
|
|
118
|
+
$uniform4[3] = 0;
|
|
119
|
+
const uniformBuffer = bufferManager
|
|
120
|
+
? bufferManager.acquireAndWriteUniformBuffer($uniform4)
|
|
121
|
+
: device.createBuffer({
|
|
122
|
+
"size": $uniform4.byteLength,
|
|
123
|
+
"usage": GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
|
|
124
|
+
});
|
|
125
|
+
if (!bufferManager) {
|
|
126
|
+
device.queue.writeBuffer(uniformBuffer, 0, $uniform4);
|
|
127
|
+
}
|
|
128
|
+
$entries3[0].resource.buffer = uniformBuffer;
|
|
129
|
+
$entries3[1].resource = sampler;
|
|
130
|
+
$entries3[2].resource = source.texture.view;
|
|
131
|
+
const bindGroup = device.createBindGroup({
|
|
132
|
+
"layout": bindGroupLayout,
|
|
133
|
+
"entries": $entries3
|
|
134
|
+
});
|
|
135
|
+
const renderPassDescriptor = frameBufferManager.createRenderPassDescriptor(dest.texture.view, 0, 0, 0, 0, "clear");
|
|
136
|
+
const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
|
|
137
|
+
passEncoder.setPipeline(pipeline);
|
|
138
|
+
passEncoder.setBindGroup(0, bindGroup);
|
|
139
|
+
passEncoder.setViewport(pixelOffsetX, pixelOffsetY, scaledSourceWidth, scaledSourceHeight, 0, 1);
|
|
140
|
+
passEncoder.setScissorRect(Math.floor(pixelOffsetX), Math.floor(pixelOffsetY), Math.ceil(scaledSourceWidth), Math.ceil(scaledSourceHeight));
|
|
141
|
+
passEncoder.draw(6, 1, 0, 0);
|
|
142
|
+
passEncoder.end();
|
|
143
|
+
};
|
|
144
|
+
/**
|
|
145
|
+
* @description テクスチャをアップスケール
|
|
146
|
+
*/
|
|
147
|
+
const upscaleTexture = (device, commandEncoder, frameBufferManager, pipelineManager, source, dest, sampler, bufferManager) => {
|
|
148
|
+
const pipeline = pipelineManager.getPipeline("texture_copy_rgba8");
|
|
149
|
+
const bindGroupLayout = pipelineManager.getBindGroupLayout("texture_copy");
|
|
150
|
+
if (!pipeline || !bindGroupLayout) {
|
|
151
|
+
console.error("[WebGPU BlurCompute] texture_copy_rgba8 pipeline not found");
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
$uniform4[0] = 1;
|
|
155
|
+
$uniform4[1] = 1;
|
|
156
|
+
$uniform4[2] = 0;
|
|
157
|
+
$uniform4[3] = 0;
|
|
158
|
+
const uniformBuffer = bufferManager
|
|
159
|
+
? bufferManager.acquireAndWriteUniformBuffer($uniform4)
|
|
160
|
+
: device.createBuffer({
|
|
161
|
+
"size": $uniform4.byteLength,
|
|
162
|
+
"usage": GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
|
|
163
|
+
});
|
|
164
|
+
if (!bufferManager) {
|
|
165
|
+
device.queue.writeBuffer(uniformBuffer, 0, $uniform4);
|
|
166
|
+
}
|
|
167
|
+
$entries3[0].resource.buffer = uniformBuffer;
|
|
168
|
+
$entries3[1].resource = sampler;
|
|
169
|
+
$entries3[2].resource = source.texture.view;
|
|
170
|
+
const bindGroup = device.createBindGroup({
|
|
171
|
+
"layout": bindGroupLayout,
|
|
172
|
+
"entries": $entries3
|
|
173
|
+
});
|
|
174
|
+
const renderPassDescriptor = frameBufferManager.createRenderPassDescriptor(dest.texture.view, 0, 0, 0, 0, "clear");
|
|
175
|
+
const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
|
|
176
|
+
passEncoder.setPipeline(pipeline);
|
|
177
|
+
passEncoder.setBindGroup(0, bindGroup);
|
|
178
|
+
passEncoder.draw(6, 1, 0, 0);
|
|
179
|
+
passEncoder.end();
|
|
180
|
+
};
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
export class BlurFilterShader {
|
|
2
|
+
static getVertexShader() {
|
|
3
|
+
return /* wgsl */ `
|
|
4
|
+
struct VertexInput {
|
|
5
|
+
@location(0) position: vec2<f32>,
|
|
6
|
+
@location(1) texCoord: vec2<f32>,
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
struct VertexOutput {
|
|
10
|
+
@builtin(position) position: vec4<f32>,
|
|
11
|
+
@location(0) texCoord: vec2<f32>,
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
@vertex
|
|
15
|
+
fn main(input: VertexInput) -> VertexOutput {
|
|
16
|
+
var output: VertexOutput;
|
|
17
|
+
output.position = vec4<f32>(input.position, 0.0, 1.0);
|
|
18
|
+
output.texCoord = input.texCoord;
|
|
19
|
+
return output;
|
|
20
|
+
}
|
|
21
|
+
`;
|
|
22
|
+
}
|
|
23
|
+
static getHorizontalBlurShader() {
|
|
24
|
+
return /* wgsl */ `
|
|
25
|
+
struct VertexOutput {
|
|
26
|
+
@builtin(position) position: vec4<f32>,
|
|
27
|
+
@location(0) texCoord: vec2<f32>,
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
struct BlurUniforms {
|
|
31
|
+
blurSize: f32,
|
|
32
|
+
textureWidth: f32,
|
|
33
|
+
textureHeight: f32,
|
|
34
|
+
_padding: f32,
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
@group(0) @binding(0) var<uniform> uniforms: BlurUniforms;
|
|
38
|
+
@group(0) @binding(1) var textureSampler: sampler;
|
|
39
|
+
@group(0) @binding(2) var textureData: texture_2d<f32>;
|
|
40
|
+
|
|
41
|
+
@fragment
|
|
42
|
+
fn main(input: VertexOutput) -> @location(0) vec4<f32> {
|
|
43
|
+
let texelSize = 1.0 / uniforms.textureWidth;
|
|
44
|
+
var color = vec4<f32>(0.0);
|
|
45
|
+
let blurRadius = i32(uniforms.blurSize);
|
|
46
|
+
|
|
47
|
+
var totalWeight = 0.0;
|
|
48
|
+
|
|
49
|
+
for (var i = -blurRadius; i <= blurRadius; i++) {
|
|
50
|
+
let offset = f32(i) * texelSize;
|
|
51
|
+
let weight = 1.0 - abs(f32(i)) / f32(blurRadius + 1);
|
|
52
|
+
|
|
53
|
+
let sampleCoord = vec2<f32>(
|
|
54
|
+
input.texCoord.x + offset,
|
|
55
|
+
input.texCoord.y
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
color += textureSample(textureData, textureSampler, sampleCoord) * weight;
|
|
59
|
+
totalWeight += weight;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return color / totalWeight;
|
|
63
|
+
}
|
|
64
|
+
`;
|
|
65
|
+
}
|
|
66
|
+
static getVerticalBlurShader() {
|
|
67
|
+
return /* wgsl */ `
|
|
68
|
+
struct VertexOutput {
|
|
69
|
+
@builtin(position) position: vec4<f32>,
|
|
70
|
+
@location(0) texCoord: vec2<f32>,
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
struct BlurUniforms {
|
|
74
|
+
blurSize: f32,
|
|
75
|
+
textureWidth: f32,
|
|
76
|
+
textureHeight: f32,
|
|
77
|
+
_padding: f32,
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
@group(0) @binding(0) var<uniform> uniforms: BlurUniforms;
|
|
81
|
+
@group(0) @binding(1) var textureSampler: sampler;
|
|
82
|
+
@group(0) @binding(2) var textureData: texture_2d<f32>;
|
|
83
|
+
|
|
84
|
+
@fragment
|
|
85
|
+
fn main(input: VertexOutput) -> @location(0) vec4<f32> {
|
|
86
|
+
let texelSize = 1.0 / uniforms.textureHeight;
|
|
87
|
+
var color = vec4<f32>(0.0);
|
|
88
|
+
let blurRadius = i32(uniforms.blurSize);
|
|
89
|
+
|
|
90
|
+
var totalWeight = 0.0;
|
|
91
|
+
|
|
92
|
+
for (var i = -blurRadius; i <= blurRadius; i++) {
|
|
93
|
+
let offset = f32(i) * texelSize;
|
|
94
|
+
let weight = 1.0 - abs(f32(i)) / f32(blurRadius + 1);
|
|
95
|
+
|
|
96
|
+
let sampleCoord = vec2<f32>(
|
|
97
|
+
input.texCoord.x,
|
|
98
|
+
input.texCoord.y + offset
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
color += textureSample(textureData, textureSampler, sampleCoord) * weight;
|
|
102
|
+
totalWeight += weight;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return color / totalWeight;
|
|
106
|
+
}
|
|
107
|
+
`;
|
|
108
|
+
}
|
|
109
|
+
}
|