Skip to content

ASDAlexander77/webgpu-gravity-simulation

Repository files navigation

WebGPU Gravity Simulation (Compute)

Powered by

Compute Example

Example

WebGPU Example

<html>
<!DOCTYPE html>

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

    <title></title>

    <style>
        html,
        body {
            overflow: hidden;
            width: 100%;
            height: 100%;
            margin: 0;
            padding: 0;
        }

        #renderCanvas {
            width: 800;
            height: 600;
            background-color: cadetblue;
            border: 1px red solid;
        }

        textarea {
            display: none;
        }
    </style>
</head>

<body>
    <textarea id="vert_code">
        @vertex
        fn main(@builtin(vertex_index) VertexIndex : u32)
             -> @builtin(position) vec4<f32> {
          var pos = array<vec2<f32>, 3>(
              vec2<f32>(0.0, 0.5),
              vec2<f32>(-0.5, -0.5),
              vec2<f32>(0.5, -0.5));
        
          return vec4<f32>(pos[VertexIndex], 0.0, 1.0);
        }
    </textarea>
    <textarea id="frag_code">
        @fragment
        fn main() -> @location(0) vec4<f32> {
          return vec4<f32>(1.0, 0.0, 0.0, 1.0);
        }
    </textarea>
    <canvas id="renderCanvas"></canvas>
    <script>
        async function init() {
            const canvasRef = document.getElementById("renderCanvas");
            const triangleVertWGSL = document.getElementById("vert_code").value;
            const redFragWGSL = document.getElementById("frag_code").value;

            const adapter = await navigator.gpu.requestAdapter();
            const device = await adapter.requestDevice();

            if (canvasRef === null) return;
            const context = canvasRef.getContext('webgpu');

            const devicePixelRatio = window.devicePixelRatio || 1;
            canvasRef.width = canvasRef.clientWidth * devicePixelRatio;
            canvasRef.height = canvasRef.clientHeight * devicePixelRatio;
            const presentationFormat = navigator.gpu.getPreferredCanvasFormat(adapter);

            context.configure({
                device,
                format: presentationFormat,
                alphaMode: 'premultiplied'
            });

            const pipeline = device.createRenderPipeline({
                vertex: {
                    module: device.createShaderModule({
                        code: triangleVertWGSL,
                    }),
                    entryPoint: 'main',
                },
                fragment: {
                    module: device.createShaderModule({
                        code: redFragWGSL,
                    }),
                    entryPoint: 'main',
                    targets: [
                        {
                            format: presentationFormat,
                        },
                    ],
                },
                primitive: {
                    topology: 'triangle-list',
                },
                layout: 'auto'
            });

            const renderPassDescriptor = {
                colorAttachments: [
                    {
                        view: null,
                        clearValue: { r: 0.0, g: 0.0, b: 0.0, a: 1.0 },
                        loadOp: 'clear',
                        storeOp: 'store',
                    },
                ],
            };

            function frame() {
                const commandEncoder = device.createCommandEncoder();

                renderPassDescriptor.colorAttachments[0].view = context.getCurrentTexture().createView();

                const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
                passEncoder.setPipeline(pipeline);
                passEncoder.draw(3, 1, 0, 0);
                passEncoder.end();

                const drawQueue = [commandEncoder.finish()];

                device.queue.submit(drawQueue);
                requestAnimationFrame(frame);
            }

            requestAnimationFrame(frame);
        };

        window.addEventListener("DOMContentLoaded", init);
    </script>
</body>

</html>

Run

"%ProgramFiles%\Google\Chrome\Application\chrome.exe" --enable-unsafe-webgpu file:///example.html

Result Example