@bloopjs/toodle 0.0.100
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 +44 -0
- package/dist/Toodle.d.ts +304 -0
- package/dist/Toodle.d.ts.map +1 -0
- package/dist/colors/mod.d.ts +872 -0
- package/dist/colors/mod.d.ts.map +1 -0
- package/dist/coreTypes/Color.d.ts +7 -0
- package/dist/coreTypes/Color.d.ts.map +1 -0
- package/dist/coreTypes/Point.d.ts +8 -0
- package/dist/coreTypes/Point.d.ts.map +1 -0
- package/dist/coreTypes/Size.d.ts +5 -0
- package/dist/coreTypes/Size.d.ts.map +1 -0
- package/dist/coreTypes/Transform.d.ts +16 -0
- package/dist/coreTypes/Transform.d.ts.map +1 -0
- package/dist/coreTypes/Vec2.d.ts +8 -0
- package/dist/coreTypes/Vec2.d.ts.map +1 -0
- package/dist/coreTypes/mod.d.ts +6 -0
- package/dist/coreTypes/mod.d.ts.map +1 -0
- package/dist/docs/snippets/add-remove-children.d.ts +1 -0
- package/dist/docs/snippets/basic-quad.d.ts +1 -0
- package/dist/docs/snippets/filter-linear.d.ts +1 -0
- package/dist/docs/snippets/filter-nearest.d.ts +1 -0
- package/dist/docs/snippets/flipxy.d.ts +1 -0
- package/dist/docs/snippets/hello-text.d.ts +1 -0
- package/dist/docs/snippets/jumbo-textures.d.ts +1 -0
- package/dist/docs/snippets/layer.d.ts +1 -0
- package/dist/docs/snippets/layout-edges.d.ts +1 -0
- package/dist/docs/snippets/layout-screen-and-world-space.d.ts +1 -0
- package/dist/docs/snippets/postprocess.d.ts +1 -0
- package/dist/docs/snippets/quad-size-scale.d.ts +1 -0
- package/dist/docs/snippets/quickstart.d.ts +1 -0
- package/dist/docs/snippets/repeat-texture-loading.d.ts +1 -0
- package/dist/docs/snippets/screen-shaders.d.ts +1 -0
- package/dist/docs/snippets/shader-color-flash.d.ts +1 -0
- package/dist/docs/snippets/shader-default.d.ts +1 -0
- package/dist/docs/snippets/shader-fill.d.ts +1 -0
- package/dist/docs/snippets/shapes-line.d.ts +1 -0
- package/dist/docs/snippets/sprite-region.d.ts +1 -0
- package/dist/docs/snippets/text-alignment.d.ts +1 -0
- package/dist/docs/snippets/text-shrink-to-fit.d.ts +1 -0
- package/dist/docs/snippets/text-word-wrap.d.ts +1 -0
- package/dist/docs/snippets/texture-bundles-prebaked.d.ts +1 -0
- package/dist/docs/snippets/texture-bundles.d.ts +1 -0
- package/dist/docs/snippets/transforms.d.ts +1 -0
- package/dist/docs/snippets/transparent-cropping.d.ts +1 -0
- package/dist/examples/0-hello.d.ts +1 -0
- package/dist/examples/1-hello.d.ts +1 -0
- package/dist/examples/1-hello.d.ts.map +1 -0
- package/dist/examples/1-quad.d.ts +1 -0
- package/dist/examples/10-resize.d.ts +1 -0
- package/dist/examples/10-resize.d.ts.map +1 -0
- package/dist/examples/11-bundle-test.d.ts +1 -0
- package/dist/examples/11-bundle-test.d.ts.map +1 -0
- package/dist/examples/12-transparent-pixel-cropping.d.ts +1 -0
- package/dist/examples/12-transparent-pixel-cropping.d.ts.map +1 -0
- package/dist/examples/13-crop.d.ts +1 -0
- package/dist/examples/13-crop.d.ts.map +1 -0
- package/dist/examples/14-bundle-bench.d.ts +1 -0
- package/dist/examples/14-bundle-bench.d.ts.map +1 -0
- package/dist/examples/15-text-layer.d.ts +1 -0
- package/dist/examples/15-text-layer.d.ts.map +1 -0
- package/dist/examples/16-jumbo-texture.d.ts +1 -0
- package/dist/examples/16-jumbo-textures.d.ts +1 -0
- package/dist/examples/16-screen-shader.d.ts +1 -0
- package/dist/examples/16-screen-shader.d.ts.map +1 -0
- package/dist/examples/17-lighting.d.ts +1 -0
- package/dist/examples/17-lighting.d.ts.map +1 -0
- package/dist/examples/17-translations.d.ts +1 -0
- package/dist/examples/18-blur.d.ts +1 -0
- package/dist/examples/19-postprocess.d.ts +1 -0
- package/dist/examples/19-screenshader.d.ts +1 -0
- package/dist/examples/2-shapes.d.ts +1 -0
- package/dist/examples/2-shapes.d.ts.map +1 -0
- package/dist/examples/3-shader.d.ts +1 -0
- package/dist/examples/3-shader.d.ts.map +1 -0
- package/dist/examples/4-shader-bench.d.ts +1 -0
- package/dist/examples/4-shader-bench.d.ts.map +1 -0
- package/dist/examples/5-z.d.ts +1 -0
- package/dist/examples/5-z.d.ts.map +1 -0
- package/dist/examples/6-atlas.d.ts +1 -0
- package/dist/examples/6-atlas.d.ts.map +1 -0
- package/dist/examples/7-text.d.ts +1 -0
- package/dist/examples/7-text.d.ts.map +1 -0
- package/dist/examples/8-text-bench.d.ts +1 -0
- package/dist/examples/8-text-bench.d.ts.map +1 -0
- package/dist/examples/9-alignment.d.ts +1 -0
- package/dist/examples/9-alignment.d.ts.map +1 -0
- package/dist/examples/main.d.ts +1 -0
- package/dist/examples/main.d.ts.map +1 -0
- package/dist/examples/util.d.ts +82 -0
- package/dist/examples/util.d.ts.map +1 -0
- package/dist/limits.d.ts +23 -0
- package/dist/limits.d.ts.map +1 -0
- package/dist/math/angle.d.ts +13 -0
- package/dist/math/angle.d.ts.map +1 -0
- package/dist/math/matrix.d.ts +26 -0
- package/dist/math/matrix.d.ts.map +1 -0
- package/dist/math/mod.d.ts +3 -0
- package/dist/math/mod.d.ts.map +1 -0
- package/dist/mod.d.ts +17 -0
- package/dist/mod.d.ts.map +1 -0
- package/dist/mod.js +19665 -0
- package/dist/mod.js.map +41 -0
- package/dist/postprocess.d.ts +10 -0
- package/dist/postprocess.d.ts.map +1 -0
- package/dist/scene/Batcher.d.ts +20 -0
- package/dist/scene/Batcher.d.ts.map +1 -0
- package/dist/scene/Camera.d.ts +16 -0
- package/dist/scene/Camera.d.ts.map +1 -0
- package/dist/scene/JumboQuadNode.d.ts +29 -0
- package/dist/scene/JumboQuadNode.d.ts.map +1 -0
- package/dist/scene/QuadNode.d.ts +159 -0
- package/dist/scene/QuadNode.d.ts.map +1 -0
- package/dist/scene/RenderComponent.d.ts +11 -0
- package/dist/scene/RenderComponent.d.ts.map +1 -0
- package/dist/scene/SceneNode.d.ts +300 -0
- package/dist/scene/SceneNode.d.ts.map +1 -0
- package/dist/scene/mod.d.ts +5 -0
- package/dist/scene/mod.d.ts.map +1 -0
- package/dist/screen/mod.d.ts +2 -0
- package/dist/screen/mod.d.ts.map +1 -0
- package/dist/screen/resolution.d.ts +5 -0
- package/dist/screen/resolution.d.ts.map +1 -0
- package/dist/shaders/EngineUniform.d.ts +9 -0
- package/dist/shaders/EngineUniform.d.ts.map +1 -0
- package/dist/shaders/IShader.d.ts +15 -0
- package/dist/shaders/IShader.d.ts.map +1 -0
- package/dist/shaders/QuadShader.d.ts +18 -0
- package/dist/shaders/QuadShader.d.ts.map +1 -0
- package/dist/shaders/ShaderDescriptor.d.ts +7 -0
- package/dist/shaders/ShaderDescriptor.d.ts.map +1 -0
- package/dist/shaders/mod.d.ts +6 -0
- package/dist/shaders/mod.d.ts.map +1 -0
- package/dist/shaders/parser.d.ts +8 -0
- package/dist/shaders/parser.d.ts.map +1 -0
- package/dist/shaders/postprocess/blur.d.ts +3 -0
- package/dist/shaders/postprocess/blur.d.ts.map +1 -0
- package/dist/shaders/postprocess/mod.d.ts +17 -0
- package/dist/shaders/postprocess/mod.d.ts.map +1 -0
- package/dist/shaders/samplers.d.ts +3 -0
- package/dist/shaders/samplers.d.ts.map +1 -0
- package/dist/shaders/wgsl/example.wgsl.d.ts +3 -0
- package/dist/shaders/wgsl/example.wgsl.d.ts.map +1 -0
- package/dist/shaders/wgsl/hello.wgsl.d.ts +3 -0
- package/dist/shaders/wgsl/hello.wgsl.d.ts.map +1 -0
- package/dist/shaders/wgsl/helloInstanced.wgsl.d.ts +3 -0
- package/dist/shaders/wgsl/helloInstanced.wgsl.d.ts.map +1 -0
- package/dist/shaders/wgsl/quad.wgsl.d.ts +3 -0
- package/dist/shaders/wgsl/quad.wgsl.d.ts.map +1 -0
- package/dist/src/Toodle.d.ts +303 -0
- package/dist/src/Toodle.d.ts.map +1 -0
- package/dist/src/colors/mod.d.ts +871 -0
- package/dist/src/coreTypes/Color.d.ts +6 -0
- package/dist/src/coreTypes/Color.d.ts.map +1 -0
- package/dist/src/coreTypes/Point.d.ts +7 -0
- package/dist/src/coreTypes/Point.d.ts.map +1 -0
- package/dist/src/coreTypes/Size.d.ts +4 -0
- package/dist/src/coreTypes/Size.d.ts.map +1 -0
- package/dist/src/coreTypes/Transform.d.ts +15 -0
- package/dist/src/coreTypes/Transform.d.ts.map +1 -0
- package/dist/src/coreTypes/Vec2.d.ts +7 -0
- package/dist/src/coreTypes/Vec2.d.ts.map +1 -0
- package/dist/src/coreTypes/mod.d.ts +5 -0
- package/dist/src/coreTypes/mod.d.ts.map +1 -0
- package/dist/src/limits.d.ts +22 -0
- package/dist/src/limits.d.ts.map +1 -0
- package/dist/src/math/angle.d.ts +12 -0
- package/dist/src/math/angle.d.ts.map +1 -0
- package/dist/src/math/matrix.d.ts +25 -0
- package/dist/src/math/matrix.d.ts.map +1 -0
- package/dist/src/math/mod.d.ts +2 -0
- package/dist/src/math/mod.d.ts.map +1 -0
- package/dist/src/mod.d.ts +16 -0
- package/dist/src/mod.d.ts.map +1 -0
- package/dist/src/postprocess.d.ts +10 -0
- package/dist/src/postprocess.d.ts.map +1 -0
- package/dist/src/scene/Batcher.d.ts +19 -0
- package/dist/src/scene/Batcher.d.ts.map +1 -0
- package/dist/src/scene/Camera.d.ts +15 -0
- package/dist/src/scene/Camera.d.ts.map +1 -0
- package/dist/src/scene/JumboQuadNode.d.ts +28 -0
- package/dist/src/scene/QuadNode.d.ts +158 -0
- package/dist/src/scene/QuadNode.d.ts.map +1 -0
- package/dist/src/scene/RenderComponent.d.ts +10 -0
- package/dist/src/scene/RenderComponent.d.ts.map +1 -0
- package/dist/src/scene/SceneNode.d.ts +299 -0
- package/dist/src/scene/SceneNode.d.ts.map +1 -0
- package/dist/src/scene/mod.d.ts +4 -0
- package/dist/src/scene/mod.d.ts.map +1 -0
- package/dist/src/screen/mod.d.ts +1 -0
- package/dist/src/screen/mod.d.ts.map +1 -0
- package/dist/src/screen/resolution.d.ts +4 -0
- package/dist/src/screen/resolution.d.ts.map +1 -0
- package/dist/src/shaders/EngineUniform.d.ts +8 -0
- package/dist/src/shaders/EngineUniform.d.ts.map +1 -0
- package/dist/src/shaders/IShader.d.ts +14 -0
- package/dist/src/shaders/IShader.d.ts.map +1 -0
- package/dist/src/shaders/QuadShader.d.ts +17 -0
- package/dist/src/shaders/QuadShader.d.ts.map +1 -0
- package/dist/src/shaders/ShaderDescriptor.d.ts +6 -0
- package/dist/src/shaders/ShaderDescriptor.d.ts.map +1 -0
- package/dist/src/shaders/mod.d.ts +5 -0
- package/dist/src/shaders/mod.d.ts.map +1 -0
- package/dist/src/shaders/parser.d.ts +7 -0
- package/dist/src/shaders/parser.d.ts.map +1 -0
- package/dist/src/shaders/postprocess/blur.d.ts +2 -0
- package/dist/src/shaders/postprocess/mod.d.ts +16 -0
- package/dist/src/shaders/postprocess/postprocess.d.ts +8 -0
- package/dist/src/shaders/postprocess/util.d.ts +2 -0
- package/dist/src/shaders/samplers.d.ts +2 -0
- package/dist/src/shaders/samplers.d.ts.map +1 -0
- package/dist/src/shaders/wgsl/example.wgsl.d.ts +2 -0
- package/dist/src/shaders/wgsl/example.wgsl.d.ts.map +1 -0
- package/dist/src/shaders/wgsl/hello.wgsl.d.ts +2 -0
- package/dist/src/shaders/wgsl/hello.wgsl.d.ts.map +1 -0
- package/dist/src/shaders/wgsl/helloInstanced.wgsl.d.ts +2 -0
- package/dist/src/shaders/wgsl/helloInstanced.wgsl.d.ts.map +1 -0
- package/dist/src/shaders/wgsl/quad.wgsl.d.ts +2 -0
- package/dist/src/shaders/wgsl/quad.wgsl.d.ts.map +1 -0
- package/dist/src/text/FontPipeline.d.ts +13 -0
- package/dist/src/text/FontPipeline.d.ts.map +1 -0
- package/dist/src/text/MsdfFont.d.ts +81 -0
- package/dist/src/text/MsdfFont.d.ts.map +1 -0
- package/dist/src/text/TextFormatting.d.ts +18 -0
- package/dist/src/text/TextFormatting.d.ts.map +1 -0
- package/dist/src/text/TextNode.d.ts +18 -0
- package/dist/src/text/TextNode.d.ts.map +1 -0
- package/dist/src/text/TextShader.d.ts +14 -0
- package/dist/src/text/TextShader.d.ts.map +1 -0
- package/dist/src/text/mod.d.ts +3 -0
- package/dist/src/text/mod.d.ts.map +1 -0
- package/dist/src/text/shaping.d.ts +38 -0
- package/dist/src/text/shaping.d.ts.map +1 -0
- package/dist/src/text/text.wgsl.d.ts +2 -0
- package/dist/src/text/text.wgsl.d.ts.map +1 -0
- package/dist/src/textures/AssetManager.d.ts +181 -0
- package/dist/src/textures/AssetManager.d.ts.map +1 -0
- package/dist/src/textures/NewTextureComputeShader.d.ts +28 -0
- package/dist/src/textures/TextureComputeShader.d.ts +20 -0
- package/dist/src/textures/TextureComputeShader.d.ts.map +1 -0
- package/dist/src/textures/crop.wgsl.d.ts +2 -0
- package/dist/src/textures/mod.d.ts +1 -0
- package/dist/src/textures/mod.d.ts.map +1 -0
- package/dist/src/textures/pixel-scraping.wgsl.d.ts +2 -0
- package/dist/src/textures/pixel-scraping.wgsl.d.ts.map +1 -0
- package/dist/src/textures/texture-processing.wgsl.d.ts +2 -0
- package/dist/src/textures/types.d.ts +176 -0
- package/dist/src/textures/types.d.ts.map +1 -0
- package/dist/src/textures/util.d.ts +7 -0
- package/dist/src/textures/util.d.ts.map +1 -0
- package/dist/src/utils/assert.d.ts +1 -0
- package/dist/src/utils/assert.d.ts.map +1 -0
- package/dist/src/utils/boilerplate.d.ts +10 -0
- package/dist/src/utils/boilerplate.d.ts.map +1 -0
- package/dist/src/utils/error.d.ts +7 -0
- package/dist/src/utils/error.d.ts.map +1 -0
- package/dist/src/utils/mod.d.ts +2 -0
- package/dist/src/utils/mod.d.ts.map +1 -0
- package/dist/src/utils/pool.d.ts +22 -0
- package/dist/src/utils/pool.d.ts.map +1 -0
- package/dist/test/math/matrix.test.d.ts +1 -0
- package/dist/test/scene/Batcher.test.d.ts +1 -0
- package/dist/test/scene/SceneNode.test.d.ts +1 -0
- package/dist/test/shader/parser.test.d.ts +1 -0
- package/dist/text/FontPipeline.d.ts +14 -0
- package/dist/text/FontPipeline.d.ts.map +1 -0
- package/dist/text/MsdfFont.d.ts +82 -0
- package/dist/text/MsdfFont.d.ts.map +1 -0
- package/dist/text/TextFormatting.d.ts +19 -0
- package/dist/text/TextFormatting.d.ts.map +1 -0
- package/dist/text/TextNode.d.ts +19 -0
- package/dist/text/TextNode.d.ts.map +1 -0
- package/dist/text/TextShader.d.ts +15 -0
- package/dist/text/TextShader.d.ts.map +1 -0
- package/dist/text/mod.d.ts +4 -0
- package/dist/text/mod.d.ts.map +1 -0
- package/dist/text/shaping.d.ts +39 -0
- package/dist/text/shaping.d.ts.map +1 -0
- package/dist/text/text.wgsl.d.ts +3 -0
- package/dist/text/text.wgsl.d.ts.map +1 -0
- package/dist/textures/AssetManager.d.ts +182 -0
- package/dist/textures/AssetManager.d.ts.map +1 -0
- package/dist/textures/TextureComputeShader.d.ts +21 -0
- package/dist/textures/TextureComputeShader.d.ts.map +1 -0
- package/dist/textures/mod.d.ts +2 -0
- package/dist/textures/mod.d.ts.map +1 -0
- package/dist/textures/pixel-scraping.wgsl.d.ts +3 -0
- package/dist/textures/pixel-scraping.wgsl.d.ts.map +1 -0
- package/dist/textures/types.d.ts +177 -0
- package/dist/textures/types.d.ts.map +1 -0
- package/dist/textures/util.d.ts +8 -0
- package/dist/textures/util.d.ts.map +1 -0
- package/dist/utils/assert.d.ts +2 -0
- package/dist/utils/assert.d.ts.map +1 -0
- package/dist/utils/boilerplate.d.ts +11 -0
- package/dist/utils/boilerplate.d.ts.map +1 -0
- package/dist/utils/error.d.ts +8 -0
- package/dist/utils/error.d.ts.map +1 -0
- package/dist/utils/mod.d.ts +3 -0
- package/dist/utils/mod.d.ts.map +1 -0
- package/dist/utils/pool.d.ts +23 -0
- package/dist/utils/pool.d.ts.map +1 -0
- package/package.json +47 -0
- package/src/Toodle.ts +853 -0
- package/src/colors/mod.ts +151 -0
- package/src/coreTypes/Color.ts +1 -0
- package/src/coreTypes/Point.ts +7 -0
- package/src/coreTypes/Size.ts +4 -0
- package/src/coreTypes/Transform.ts +16 -0
- package/src/coreTypes/Vec2.ts +7 -0
- package/src/coreTypes/mod.ts +5 -0
- package/src/globals.d.ts +4 -0
- package/src/limits.ts +23 -0
- package/src/math/angle.ts +17 -0
- package/src/math/matrix.ts +99 -0
- package/src/math/mod.ts +2 -0
- package/src/mod.ts +22 -0
- package/src/scene/Batcher.ts +61 -0
- package/src/scene/Camera.ts +69 -0
- package/src/scene/JumboQuadNode.ts +219 -0
- package/src/scene/QuadNode.ts +403 -0
- package/src/scene/RenderComponent.ts +12 -0
- package/src/scene/SceneNode.ts +668 -0
- package/src/scene/mod.ts +4 -0
- package/src/screen/mod.ts +1 -0
- package/src/screen/resolution.ts +1 -0
- package/src/shaders/EngineUniform.ts +11 -0
- package/src/shaders/IShader.ts +20 -0
- package/src/shaders/QuadShader.ts +288 -0
- package/src/shaders/ShaderDescriptor.ts +6 -0
- package/src/shaders/mod.ts +5 -0
- package/src/shaders/parser.ts +221 -0
- package/src/shaders/postprocess/blur.ts +245 -0
- package/src/shaders/postprocess/mod.ts +71 -0
- package/src/shaders/samplers.ts +13 -0
- package/src/shaders/wgsl/example.wgsl.ts +24 -0
- package/src/shaders/wgsl/hello.wgsl.ts +62 -0
- package/src/shaders/wgsl/helloInstanced.wgsl.ts +46 -0
- package/src/shaders/wgsl/quad.wgsl.ts +140 -0
- package/src/text/FontPipeline.ts +212 -0
- package/src/text/MsdfFont.ts +190 -0
- package/src/text/TextFormatting.ts +28 -0
- package/src/text/TextNode.ts +82 -0
- package/src/text/TextShader.ts +223 -0
- package/src/text/mod.ts +8 -0
- package/src/text/shaping.ts +280 -0
- package/src/text/text.wgsl.ts +149 -0
- package/src/textures/AssetManager.ts +746 -0
- package/src/textures/TextureComputeShader.ts +434 -0
- package/src/textures/mod.ts +1 -0
- package/src/textures/pixel-scraping.wgsl.ts +131 -0
- package/src/textures/types.ts +182 -0
- package/src/textures/util.ts +352 -0
- package/src/utils/assert.ts +5 -0
- package/src/utils/boilerplate.ts +110 -0
- package/src/utils/error.ts +14 -0
- package/src/utils/mod.ts +2 -0
- package/src/utils/pool.ts +42 -0
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import type { Color } from "../../coreTypes/Color";
|
|
2
|
+
import { PostProcessDefaults } from "./mod";
|
|
3
|
+
|
|
4
|
+
// example of a blur post-process effect using a two-pass Gaussian blur
|
|
5
|
+
export function blur(
|
|
6
|
+
encoder: GPUCommandEncoder,
|
|
7
|
+
context: GPUCanvasContext,
|
|
8
|
+
device: GPUDevice,
|
|
9
|
+
clearColor: Color,
|
|
10
|
+
presentationFormat: GPUTextureFormat,
|
|
11
|
+
pingpong: [GPUTexture, GPUTexture],
|
|
12
|
+
) {
|
|
13
|
+
const blurRadius = 20;
|
|
14
|
+
|
|
15
|
+
const weights = gaussianWeights(blurRadius);
|
|
16
|
+
const lines = weights.map((w) => w.toFixed(7)).join(", ");
|
|
17
|
+
const wgslFragment = `let weights = array<f32, ${weights.length}>(${lines});`;
|
|
18
|
+
|
|
19
|
+
const brightPipeline = device.createRenderPipeline({
|
|
20
|
+
...PostProcessDefaults.pipelineDescriptor(device),
|
|
21
|
+
label: "toodle post process - brightness pass",
|
|
22
|
+
fragment: {
|
|
23
|
+
targets: [{ format: presentationFormat }],
|
|
24
|
+
module: device.createShaderModule({
|
|
25
|
+
label: "toodle post process - brightness pass",
|
|
26
|
+
code: /*wgsl*/ `
|
|
27
|
+
@group(0) @binding(0) var tex: texture_2d<f32>;
|
|
28
|
+
@group(0) @binding(1) var samp: sampler;
|
|
29
|
+
@group(0) @binding(2) var<uniform> engineUniform: EngineUniform;
|
|
30
|
+
|
|
31
|
+
struct EngineUniform {
|
|
32
|
+
// resolution of the canvas in physical pixels
|
|
33
|
+
resolution: vec2f,
|
|
34
|
+
random: f32,
|
|
35
|
+
time: f32,
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
@fragment
|
|
39
|
+
fn fs_main(@location(0) uv: vec2<f32>) -> @location(0) vec4<f32> {
|
|
40
|
+
let color = textureSample(tex, samp, uv);
|
|
41
|
+
let _nope = engineUniform.time;
|
|
42
|
+
return color;
|
|
43
|
+
}
|
|
44
|
+
`,
|
|
45
|
+
}),
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const horizontalBlurPipeline = device.createRenderPipeline({
|
|
50
|
+
...PostProcessDefaults.pipelineDescriptor(device),
|
|
51
|
+
label: "toodle post process - horizontal blur",
|
|
52
|
+
fragment: {
|
|
53
|
+
targets: [{ format: presentationFormat }],
|
|
54
|
+
module: device.createShaderModule({
|
|
55
|
+
label: "toodle post process - horizontal blur",
|
|
56
|
+
code: /*wgsl*/ `
|
|
57
|
+
@group(0) @binding(0) var tex: texture_2d<f32>;
|
|
58
|
+
@group(0) @binding(1) var samp: sampler;
|
|
59
|
+
@group(0) @binding(2) var<uniform> engineUniform: EngineUniform;
|
|
60
|
+
|
|
61
|
+
struct EngineUniform {
|
|
62
|
+
// resolution of the canvas in physical pixels
|
|
63
|
+
resolution: vec2f,
|
|
64
|
+
random: f32,
|
|
65
|
+
time: f32,
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
@fragment
|
|
69
|
+
fn fs_main(@location(0) uv: vec2<f32>) -> @location(0) vec4<f32> {
|
|
70
|
+
let pixelSize = 1.0 / engineUniform.resolution;
|
|
71
|
+
let offset = vec2f(pixelSize.x, 0.0); // horizontal
|
|
72
|
+
|
|
73
|
+
// Gaussian weights for 5-tap kernel
|
|
74
|
+
// let weights = array<f32, 5>(0.204164, 0.304005, 0.093913, 0.010381, 0.000336);
|
|
75
|
+
${wgslFragment}
|
|
76
|
+
|
|
77
|
+
var color = textureSample(tex, samp, uv) * weights[0];
|
|
78
|
+
for (var i = 1; i < ${weights.length}; i++) {
|
|
79
|
+
color += textureSample(tex, samp, uv + offset * f32(i)) * weights[i];
|
|
80
|
+
color += textureSample(tex, samp, uv - offset * f32(i)) * weights[i];
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return color;
|
|
84
|
+
}
|
|
85
|
+
`,
|
|
86
|
+
}),
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
const verticalBlurPipeline = device.createRenderPipeline({
|
|
91
|
+
...PostProcessDefaults.pipelineDescriptor(device),
|
|
92
|
+
label: "toodle post process - vertical blur",
|
|
93
|
+
fragment: {
|
|
94
|
+
targets: [{ format: presentationFormat }],
|
|
95
|
+
module: device.createShaderModule({
|
|
96
|
+
label: "toodle post process - vertical blur",
|
|
97
|
+
code: /*wgsl*/ `
|
|
98
|
+
@group(0) @binding(0) var tex: texture_2d<f32>;
|
|
99
|
+
@group(0) @binding(1) var samp: sampler;
|
|
100
|
+
@group(0) @binding(2) var<uniform> engineUniform: EngineUniform;
|
|
101
|
+
|
|
102
|
+
struct EngineUniform {
|
|
103
|
+
// resolution of the canvas in physical pixels
|
|
104
|
+
resolution: vec2f,
|
|
105
|
+
random: f32,
|
|
106
|
+
time: f32,
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
@fragment
|
|
110
|
+
fn fs_main(@location(0) uv: vec2<f32>) -> @location(0) vec4<f32> {
|
|
111
|
+
let pixelSize = 1.0 / engineUniform.resolution;
|
|
112
|
+
let offset = vec2f(0.0, pixelSize.y); // vertical
|
|
113
|
+
|
|
114
|
+
// Gaussian weights for 5-tap kernel
|
|
115
|
+
// let weights = array<f32, 5>(0.204164, 0.304005, 0.093913, 0.010381, 0.000336);
|
|
116
|
+
${wgslFragment}
|
|
117
|
+
|
|
118
|
+
var color = textureSample(tex, samp, uv) * weights[0];
|
|
119
|
+
for (var i = 1; i < ${weights.length}; i++) {
|
|
120
|
+
color += textureSample(tex, samp, uv + offset * f32(i)) * weights[i];
|
|
121
|
+
color += textureSample(tex, samp, uv - offset * f32(i)) * weights[i];
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return color;
|
|
125
|
+
}
|
|
126
|
+
`,
|
|
127
|
+
}),
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
renderToTarget(
|
|
132
|
+
"blur",
|
|
133
|
+
pingpong[0],
|
|
134
|
+
pingpong[1],
|
|
135
|
+
device,
|
|
136
|
+
encoder,
|
|
137
|
+
horizontalBlurPipeline,
|
|
138
|
+
clearColor,
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
renderToTarget(
|
|
142
|
+
"blur",
|
|
143
|
+
pingpong[1],
|
|
144
|
+
context.getCurrentTexture(),
|
|
145
|
+
device,
|
|
146
|
+
encoder,
|
|
147
|
+
verticalBlurPipeline,
|
|
148
|
+
clearColor,
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Gaussian function is
|
|
153
|
+
// G(x) = exp(-x² / (2σ²))
|
|
154
|
+
// where x is the distance from the center and σ is the standard deviation.
|
|
155
|
+
function gaussianWeights(radius: number, sigma = radius / 2): number[] {
|
|
156
|
+
const weights = [];
|
|
157
|
+
let sum = 0;
|
|
158
|
+
|
|
159
|
+
for (let i = 0; i <= radius; i++) {
|
|
160
|
+
const w = Math.exp(-0.5 * (i / sigma) ** 2);
|
|
161
|
+
weights.push(w);
|
|
162
|
+
sum += i === 0 ? w : w * 2;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return weights.map((w) => w / sum); // normalize to sum = 1
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function renderToTarget(
|
|
169
|
+
label: string,
|
|
170
|
+
from: GPUTexture,
|
|
171
|
+
to: GPUTexture,
|
|
172
|
+
device: GPUDevice,
|
|
173
|
+
encoder: GPUCommandEncoder,
|
|
174
|
+
pipeline: GPURenderPipeline,
|
|
175
|
+
clearColor: Color,
|
|
176
|
+
bindGroups?: GPUBindGroup[],
|
|
177
|
+
) {
|
|
178
|
+
// biome-ignore format:it's a matrix
|
|
179
|
+
const fullscreenQuadVerts = new Float32Array([
|
|
180
|
+
-1, -1, 0, 0,
|
|
181
|
+
1, -1, 1, 0,
|
|
182
|
+
-1, 1, 0, 1,
|
|
183
|
+
1, 1, 1, 1,
|
|
184
|
+
]);
|
|
185
|
+
|
|
186
|
+
// create vertex buffer
|
|
187
|
+
// todo: only create this once
|
|
188
|
+
const fullscreenVB = device.createBuffer({
|
|
189
|
+
size: fullscreenQuadVerts.byteLength,
|
|
190
|
+
usage: GPUBufferUsage.VERTEX,
|
|
191
|
+
mappedAtCreation: true,
|
|
192
|
+
});
|
|
193
|
+
new Float32Array(fullscreenVB.getMappedRange()).set(fullscreenQuadVerts);
|
|
194
|
+
fullscreenVB.unmap();
|
|
195
|
+
|
|
196
|
+
// create engine uniform
|
|
197
|
+
// todo: only create this once
|
|
198
|
+
const engineUniform = device.createBuffer({
|
|
199
|
+
label: `${label} engine uniform buffer`,
|
|
200
|
+
size: 16,
|
|
201
|
+
usage: GPUBufferUsage.UNIFORM,
|
|
202
|
+
mappedAtCreation: true,
|
|
203
|
+
});
|
|
204
|
+
const engineUniformData = new Float32Array(engineUniform.getMappedRange());
|
|
205
|
+
engineUniformData[0] = from.width;
|
|
206
|
+
engineUniformData[1] = from.height;
|
|
207
|
+
engineUniformData[2] = Math.random();
|
|
208
|
+
engineUniformData[3] = performance.now() / 1000;
|
|
209
|
+
engineUniform.unmap();
|
|
210
|
+
|
|
211
|
+
// create bind group
|
|
212
|
+
const bindGroup = device.createBindGroup({
|
|
213
|
+
label: `${label} engine bind group`,
|
|
214
|
+
layout: pipeline.getBindGroupLayout(0),
|
|
215
|
+
entries: [
|
|
216
|
+
{ binding: 0, resource: from.createView() },
|
|
217
|
+
{ binding: 1, resource: PostProcessDefaults.sampler(device) },
|
|
218
|
+
{ binding: 2, resource: engineUniform },
|
|
219
|
+
],
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
const renderPass = encoder.beginRenderPass({
|
|
223
|
+
label: `${label} render pass`,
|
|
224
|
+
colorAttachments: [
|
|
225
|
+
{
|
|
226
|
+
view: to.createView(),
|
|
227
|
+
clearValue: clearColor,
|
|
228
|
+
loadOp: "clear",
|
|
229
|
+
storeOp: "store",
|
|
230
|
+
},
|
|
231
|
+
],
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
renderPass.setPipeline(pipeline);
|
|
235
|
+
renderPass.setVertexBuffer(0, fullscreenVB);
|
|
236
|
+
renderPass.setBindGroup(0, bindGroup);
|
|
237
|
+
if (bindGroups) {
|
|
238
|
+
for (let i = 0; i < bindGroups.length; i++) {
|
|
239
|
+
renderPass.setBindGroup(i + 1, bindGroups[i]);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
renderPass.draw(4, 1, 0, 0);
|
|
243
|
+
|
|
244
|
+
renderPass.end();
|
|
245
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
export type PostProcess = {
|
|
2
|
+
/**
|
|
3
|
+
* A post-processor modifies the current render before it is presented to the screen.
|
|
4
|
+
*
|
|
5
|
+
* @param encoder - a GPUCommandEncoder used to create render passes
|
|
6
|
+
* @param pingpong - a pair of GPUTextures used for ping-pong rendering
|
|
7
|
+
* @param screen - the final screen GPUTexture to render to
|
|
8
|
+
*/
|
|
9
|
+
process(
|
|
10
|
+
queue: GPUQueue,
|
|
11
|
+
encoder: GPUCommandEncoder,
|
|
12
|
+
pingpong: [GPUTexture, GPUTexture],
|
|
13
|
+
screen: GPUTexture,
|
|
14
|
+
): void;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export const PostProcessDefaults = {
|
|
18
|
+
sampler(device: GPUDevice): GPUSampler {
|
|
19
|
+
return device.createSampler({
|
|
20
|
+
label: "toodle post process sampler",
|
|
21
|
+
magFilter: "linear",
|
|
22
|
+
minFilter: "linear",
|
|
23
|
+
mipmapFilter: "linear",
|
|
24
|
+
addressModeU: "clamp-to-edge",
|
|
25
|
+
addressModeV: "clamp-to-edge",
|
|
26
|
+
});
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
vertexBufferLayout(device: GPUDevice): GPUVertexBufferLayout {
|
|
30
|
+
return {
|
|
31
|
+
arrayStride: 4 * 4,
|
|
32
|
+
attributes: [{ shaderLocation: 0, offset: 0, format: "float32x2" }],
|
|
33
|
+
};
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
vertexShader(device: GPUDevice): GPUShaderModule {
|
|
37
|
+
return device.createShaderModule({
|
|
38
|
+
label: "toodle post process vertex shader",
|
|
39
|
+
code: `
|
|
40
|
+
struct VertexOut {
|
|
41
|
+
@builtin(position) position: vec4<f32>,
|
|
42
|
+
@location(0) uv: vec2<f32>,
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const enginePosLookup = array(vec2f(-1, 1), vec2f(-1, -1), vec2f(1, 1), vec2f(1, -1));
|
|
46
|
+
const engineUvLookup = array(vec2f(0, 0), vec2f(0, 1), vec2f(1, 0), vec2f(1, 1));
|
|
47
|
+
|
|
48
|
+
@vertex
|
|
49
|
+
fn vs_main(@builtin(vertex_index) vertexIndex: u32) -> VertexOut {
|
|
50
|
+
var out: VertexOut;
|
|
51
|
+
out.position = vec4(enginePosLookup[vertexIndex], 0.0, 1.0);
|
|
52
|
+
out.uv = engineUvLookup[vertexIndex];
|
|
53
|
+
return out;
|
|
54
|
+
}
|
|
55
|
+
`,
|
|
56
|
+
});
|
|
57
|
+
},
|
|
58
|
+
|
|
59
|
+
pipelineDescriptor(device: GPUDevice): GPURenderPipelineDescriptor {
|
|
60
|
+
return {
|
|
61
|
+
label: "toodle post process pipeline descriptor",
|
|
62
|
+
layout: "auto",
|
|
63
|
+
|
|
64
|
+
primitive: { topology: "triangle-strip" },
|
|
65
|
+
vertex: {
|
|
66
|
+
buffers: [PostProcessDefaults.vertexBufferLayout(device)],
|
|
67
|
+
module: PostProcessDefaults.vertexShader(device),
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
},
|
|
71
|
+
} as const;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export const pixelArtSampler: GPUSamplerDescriptor = {
|
|
2
|
+
magFilter: "nearest",
|
|
3
|
+
minFilter: "nearest",
|
|
4
|
+
addressModeU: "clamp-to-edge",
|
|
5
|
+
addressModeV: "clamp-to-edge",
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export const smoothSampler: GPUSamplerDescriptor = {
|
|
9
|
+
magFilter: "linear",
|
|
10
|
+
minFilter: "linear",
|
|
11
|
+
addressModeU: "clamp-to-edge",
|
|
12
|
+
addressModeV: "clamp-to-edge",
|
|
13
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// this is an example custom quad shader that returns defaults, tinting the red channel
|
|
2
|
+
|
|
3
|
+
export default /*wgsl*/ `
|
|
4
|
+
struct MyStuff {
|
|
5
|
+
red: f32,
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
@vertex
|
|
9
|
+
fn vert(
|
|
10
|
+
@builtin(vertex_index) VertexIndex: u32,
|
|
11
|
+
@builtin(instance_index) InstanceIndex: u32,
|
|
12
|
+
instance: InstanceData
|
|
13
|
+
) -> VertexOutput {
|
|
14
|
+
var output = default_vertex_shader(VertexIndex, InstanceIndex, instance);
|
|
15
|
+
return output;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
@fragment
|
|
19
|
+
fn frag(vertex: VertexOutput) -> @location(0) vec4f {
|
|
20
|
+
let color = default_fragment_shader(vertex);
|
|
21
|
+
color.r = vertex.myStuff_red;
|
|
22
|
+
return color;
|
|
23
|
+
}
|
|
24
|
+
`;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// this is a shader that draws a fullscreen magenta quad
|
|
2
|
+
// it can be used to test a pipeline with no vertex buffers or uniforms
|
|
3
|
+
export default /*wgsl*/ `
|
|
4
|
+
|
|
5
|
+
//
|
|
6
|
+
// SECTION: Struct Definitions
|
|
7
|
+
//
|
|
8
|
+
|
|
9
|
+
struct InstanceData {}
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
struct VertexInput {
|
|
13
|
+
@builtin(vertex_index) vertexIndex: u32,
|
|
14
|
+
@builtin(instance_index) instanceIndex: u32,
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
struct VertexOutput {
|
|
18
|
+
@builtin(position) engine_clip_position : vec4<f32>,
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
struct FragmentInput {
|
|
22
|
+
@builtin(position) engine_clip_position : vec4<f32>,
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
struct FragmentOutput {
|
|
26
|
+
color: vec4<f32>,
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
//
|
|
30
|
+
// SECTION: Base Entrypoints
|
|
31
|
+
//
|
|
32
|
+
|
|
33
|
+
@vertex
|
|
34
|
+
fn base_vertex_entrypoint(input: VertexInput) -> VertexOutput {
|
|
35
|
+
return default_vertex_shader(input);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
@fragment
|
|
39
|
+
fn base_fragment_entrypoint(vertex: VertexOutput) -> @location(0) vec4<f32> {
|
|
40
|
+
let output = base_fragment_shader(vertex);
|
|
41
|
+
return output.color;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
//
|
|
45
|
+
// SECTION: Base Shaders
|
|
46
|
+
//
|
|
47
|
+
|
|
48
|
+
const pos = array(vec2f(-1, -1), vec2f(1, -1), vec2f(-1, 1), vec2f(1, 1));
|
|
49
|
+
|
|
50
|
+
fn base_vertex_shader(input: VertexInput) -> VertexOutput {
|
|
51
|
+
var output : VertexOutput;
|
|
52
|
+
output.engine_clip_position = vec4f(pos[input.vertexIndex], 0.0, 1.0);
|
|
53
|
+
return output;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
fn base_fragment_shader(vertex: VertexOutput) -> FragmentOutput {
|
|
57
|
+
var output : FragmentOutput;
|
|
58
|
+
output.color = vec4f(1.0, 0.0, 1.0, 1.0);
|
|
59
|
+
return output;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
`;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// this is a shader that can be used to test a pipeline with a vertex buffer with a step mode of instance
|
|
2
|
+
|
|
3
|
+
export default /*wgsl*/ `
|
|
4
|
+
// const pos = array(vec2f(-0.5, -0.5), vec2f(0.5, -0.5), vec2f(-0.5, 0.5), vec2f(0.5, 0.5));
|
|
5
|
+
const pos = array(vec2f(-0.5, 0.5), vec2f(-0.5, -0.5), vec2f(0.5, 0.5), vec2f(0.5, -0.5));
|
|
6
|
+
|
|
7
|
+
struct InstanceData {
|
|
8
|
+
@location(0) model0: vec4<f32>,
|
|
9
|
+
@location(1) model1: vec4<f32>,
|
|
10
|
+
@location(2) model2: vec4<f32>,
|
|
11
|
+
@location(3) color: vec4<f32>,
|
|
12
|
+
}
|
|
13
|
+
struct VertexOutput {
|
|
14
|
+
@builtin(position) engine_clip_position : vec4<f32>,
|
|
15
|
+
@location(0) @interpolate(flat) color: vec4<f32>,
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
struct EngineUniform {
|
|
19
|
+
viewProjection: mat3x3<f32>,
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
@group(0) @binding(0) var<uniform> engineUniform: EngineUniform;
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
// this is the vertex shader
|
|
26
|
+
@vertex
|
|
27
|
+
fn vs(
|
|
28
|
+
@builtin(vertex_index) VertexIndex : u32,
|
|
29
|
+
@builtin(instance_index) InstanceIndex: u32, // Instance ID for each instance
|
|
30
|
+
instanceData: InstanceData,
|
|
31
|
+
) -> VertexOutput {
|
|
32
|
+
var output : VertexOutput;
|
|
33
|
+
let modelMatrix = mat3x3(instanceData.model0.xyz, instanceData.model1.xyz, instanceData.model2.xyz);
|
|
34
|
+
let worldPosition = engineUniform.viewProjection * modelMatrix * vec3f(pos[VertexIndex], 1.0);
|
|
35
|
+
|
|
36
|
+
output.engine_clip_position = vec4f(worldPosition, 1.0);
|
|
37
|
+
output.color = instanceData.color;
|
|
38
|
+
return output;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// this is the fragment shader
|
|
42
|
+
@fragment
|
|
43
|
+
fn fs(vertex: VertexOutput) -> @location(0) vec4<f32> {
|
|
44
|
+
return vertex.color;
|
|
45
|
+
}
|
|
46
|
+
`;
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
export default /*wgsl*/ `
|
|
2
|
+
struct InstanceData {
|
|
3
|
+
// location 0-2 are the model matrix for this instanced quad
|
|
4
|
+
@location(0) model0: vec4<f32>,
|
|
5
|
+
@location(1) model1: vec4<f32>,
|
|
6
|
+
@location(2) model2: vec4<f32>,
|
|
7
|
+
// location 3 is the tint - the color will be multiplied by the texture color to determine the pixel color
|
|
8
|
+
@location(3) engine_tint: vec4<f32>,
|
|
9
|
+
// location 4 are the uv offset and scale used to sample the texture atlas. these are in normalized texel coordinates.
|
|
10
|
+
@location(4) uvOffsetAndScale: vec4<f32>,
|
|
11
|
+
// location 5 is the crop offset from center and scale. These are ratios applied to the unit quad.
|
|
12
|
+
@location(5) cropOffsetAndScale: vec4<f32>,
|
|
13
|
+
// location 6 is the atlas index
|
|
14
|
+
@location(6) atlasIndex: u32,
|
|
15
|
+
// @INSTANCE_DATA SNIPPET
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
struct VertexInput {
|
|
19
|
+
@builtin(vertex_index) VertexIndex: u32,
|
|
20
|
+
@builtin(instance_index) InstanceIndex: u32,
|
|
21
|
+
instance: InstanceData
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
struct VertexOutput {
|
|
25
|
+
@builtin(position) engine_clip_position : vec4<f32>,
|
|
26
|
+
// uv coordinates are stored as two vec2s:
|
|
27
|
+
// [0,1] = atlas uv coords
|
|
28
|
+
// [2,3] = uv scale
|
|
29
|
+
@location(0) engine_uv: vec4<f32>,
|
|
30
|
+
@location(1) @interpolate(flat) engine_tint: vec4<f32>,
|
|
31
|
+
@location(2) @interpolate(flat) engine_atlasIndex: u32,
|
|
32
|
+
// @VERTEX_OUTPUT SNIPPET
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
struct EngineUniform {
|
|
36
|
+
viewProjection: mat3x3<f32>,
|
|
37
|
+
resolution: vec2f,
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// we can't divide by 2 in the projection matrix because
|
|
41
|
+
// it will affect the positioning as well as the geometry scale
|
|
42
|
+
// so we need to divide by 2 for the initial position scale.
|
|
43
|
+
// for eg a 10x10 quad in the top left of a 100x100 logical canvas with a 200x200 natural size
|
|
44
|
+
// will be passed in as
|
|
45
|
+
// position=[-45, 45]
|
|
46
|
+
// scale=[10,10]
|
|
47
|
+
// so the top left corner will be: (-0.5 * 10 - 45) * 2 / 100 = -1
|
|
48
|
+
// if the top left vertex was -1, it would be: (-1 * 10 - 45) * 2 / 100 = -1.1
|
|
49
|
+
const enginePosLookup = array(vec2f(-0.5, 0.5), vec2f(-0.5, -0.5), vec2f(0.5, 0.5), vec2f(0.5, -0.5));
|
|
50
|
+
const engineUvLookup = array(vec2f(0, 0), vec2f(0, 1), vec2f(1, 0), vec2f(1, 1));
|
|
51
|
+
|
|
52
|
+
@group(0) @binding(0) var<uniform> engineUniform: EngineUniform;
|
|
53
|
+
@group(0) @binding(1) var linearSampler: sampler;
|
|
54
|
+
@group(0) @binding(2) var nearestSampler: sampler;
|
|
55
|
+
|
|
56
|
+
@group(1) @binding(0) var textureArray: texture_2d_array<f32>;
|
|
57
|
+
|
|
58
|
+
@vertex
|
|
59
|
+
fn engine_vs(
|
|
60
|
+
@builtin(vertex_index) VertexIndex: u32,
|
|
61
|
+
@builtin(instance_index) InstanceIndex: u32,
|
|
62
|
+
instance: InstanceData
|
|
63
|
+
) -> VertexOutput {
|
|
64
|
+
var output = default_vertex_shader(VertexIndex, InstanceIndex,instance);
|
|
65
|
+
return output;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
@fragment
|
|
69
|
+
fn engine_fs(vertex: VertexOutput) -> @location(0) vec4<f32> {
|
|
70
|
+
return default_fragment_shader(vertex, nearestSampler);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
fn default_vertex_shader(
|
|
74
|
+
VertexIndex: u32,
|
|
75
|
+
InstanceIndex: u32,
|
|
76
|
+
instance: InstanceData
|
|
77
|
+
) -> VertexOutput {
|
|
78
|
+
var output : VertexOutput;
|
|
79
|
+
output.engine_tint = instance.engine_tint;
|
|
80
|
+
|
|
81
|
+
// reconstruct the model matrix from the instance data
|
|
82
|
+
// bc we can't pass a mat3x3 as instance data
|
|
83
|
+
let modelMatrix = mat3x3(instance.model0.xyz, instance.model1.xyz, instance.model2.xyz);
|
|
84
|
+
|
|
85
|
+
// transform the vertex position
|
|
86
|
+
let localPosition = enginePosLookup[VertexIndex];
|
|
87
|
+
let cropOffset = instance.cropOffsetAndScale.xy;
|
|
88
|
+
let cropScale = instance.cropOffsetAndScale.zw;
|
|
89
|
+
let croppedPosition = localPosition * cropScale + cropOffset;
|
|
90
|
+
let worldPosition = modelMatrix * vec3f(croppedPosition, 1.0);
|
|
91
|
+
let clipPosition = engineUniform.viewProjection * worldPosition;
|
|
92
|
+
output.engine_clip_position = vec4f(clipPosition, 1.0);
|
|
93
|
+
|
|
94
|
+
// set the uv coordinates in the texture atlas.
|
|
95
|
+
let original_uv = engineUvLookup[VertexIndex];
|
|
96
|
+
// uvOffsetAndScale is a vec4 with the following values:
|
|
97
|
+
// [0,1] = uv offset
|
|
98
|
+
// [2,3] = uv scale
|
|
99
|
+
let atlas_uv = original_uv * instance.uvOffsetAndScale.zw * cropScale + instance.uvOffsetAndScale.xy;
|
|
100
|
+
// we also pack the original uv coordinates in the w and z components
|
|
101
|
+
// since these can be useful in the fragment shader
|
|
102
|
+
output.engine_uv = vec4f(atlas_uv, original_uv);
|
|
103
|
+
output.engine_atlasIndex = u32(instance.atlasIndex);
|
|
104
|
+
// @PASSTHROUGH_SNIPPET
|
|
105
|
+
|
|
106
|
+
return output;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
fn default_fragment_shader(vertex: VertexOutput, samp: sampler) -> vec4<f32> {
|
|
110
|
+
let atlas_uv = vertex.engine_uv.xy;
|
|
111
|
+
let original_uv = vertex.engine_uv.zw;
|
|
112
|
+
|
|
113
|
+
// Force both samplers to be referenced without assignment
|
|
114
|
+
// This prevents WGSLReflect from optimizing them away
|
|
115
|
+
var nope: bool = false;
|
|
116
|
+
if (nope) {
|
|
117
|
+
_ = linearSampler;
|
|
118
|
+
_ = nearestSampler;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
let color = textureSample(textureArray, samp, atlas_uv, vertex.engine_atlasIndex);
|
|
122
|
+
|
|
123
|
+
if (vertex.engine_atlasIndex == 1000u) {
|
|
124
|
+
// rectangle - return a solid color
|
|
125
|
+
return vec4f(1,1,1,1) * vertex.engine_tint;
|
|
126
|
+
} else if (vertex.engine_atlasIndex == 1001u) {
|
|
127
|
+
// circle:
|
|
128
|
+
// edge width is 4 logical pixels
|
|
129
|
+
let edgeWidth = 4. / max(engineUniform.resolution.x, engineUniform.resolution.y);
|
|
130
|
+
// distance from center of the quad ranging from [0,1]
|
|
131
|
+
let centerDistance = 2 * distance(vec2f(0.5, 0.5), original_uv);
|
|
132
|
+
// alpha is 1 before edgeWidth and 0 after edgeWidth
|
|
133
|
+
let alpha = 1. - smoothstep(1. - edgeWidth, 1. + edgeWidth, centerDistance);
|
|
134
|
+
return vec4f(vertex.engine_tint.rgb, alpha * vertex.engine_tint.a);
|
|
135
|
+
} else {
|
|
136
|
+
// texture:
|
|
137
|
+
return color * vertex.engine_tint;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
`;
|