Skip to content

Instantly share code, notes, and snippets.

@ccincotti3
Last active January 19, 2024 22:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ccincotti3/377291ec08fdc7426dce77a4203905bf to your computer and use it in GitHub Desktop.
Save ccincotti3/377291ec08fdc7426dce77a4203905bf to your computer and use it in GitHub Desktop.
WebGPU Triangle 2022
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Carmen Cincotti - WebGPU Triangle</title>
<style>
canvas {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<canvas id="canvas-container"></canvas>
<script>
const init = async () => {
// ~~ INITIALIZE ~~ Make sure we can initialize WebGPU
if (!navigator.gpu) {
console.error(
"WebGPU cannot be initialized - navigator.gpu not found"
);
return null;
}
const adapter = await navigator.gpu.requestAdapter();
if (!adapter) {
console.error("WebGPU cannot be initialized - Adapter not found");
return null;
}
const device = await adapter.requestDevice();
device.lost.then(() => {
console.error("WebGPU cannot be initialized - Device has been lost");
return null;
});
const canvas = document.getElementById("canvas-container");
const context = canvas.getContext("webgpu");
if (!context) {
console.error(
"WebGPU cannot be initialized - Canvas does not support WebGPU"
);
return null;
}
// ~~ CONFIGURE THE SWAP CHAIN ~~
const devicePixelRatio = window.devicePixelRatio || 1;
const presentationSize = [
canvas.clientWidth * devicePixelRatio,
canvas.clientHeight * devicePixelRatio,
];
const presentationFormat = context.getPreferredFormat(adapter);
context.configure({
device,
format: presentationFormat,
size: presentationSize,
});
// ~~ SETUP VERTICES (position (vec3<f32>), color(vec4<i32>)) ~~
// Pack them all into one array
// Each vertex has a position and a color packed in memory in X Y Z W R G B A order
const vertices = new Float32Array([
-1.0, -1.0, 0, 1, 1, 0, 0, 1, -0.0, 1.0, 0, 1, 0, 1, 0, 1, 1.0, -1.0,
0, 1, 0, 0, 1, 1,
]);
const vertexBuffer = device.createBuffer({
size: vertices.byteLength,
usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
mappedAtCreation: true,
});
new Float32Array(vertexBuffer.getMappedRange()).set(vertices);
vertexBuffer.unmap();
const vertexBuffersDescriptors = [
{
attributes: [
{
shaderLocation: 0,
offset: 0,
format: "float32x4",
},
{
shaderLocation: 1,
offset: 16,
format: "float32x4",
},
],
arrayStride: 32,
stepMode: "vertex",
},
];
// ~~ DEFINE BASIC SHADERS ~~
const shaderModule = device.createShaderModule({
code: `
struct VertexOut {
@builtin(position) position : vec4<f32>,
@location(0) color : vec4<f32>,
};
@stage(vertex)
fn vertex_main(@location(0) position: vec4<f32>,
@location(1) color: vec4<f32>) -> VertexOut
{
var output : VertexOut;
output.position = position;
output.color = color;
return output;
}
@stage(fragment)
fn fragment_main(fragData: VertexOut) -> @location(0) vec4<f32>
{
return fragData.color;
}
`,
});
// ~~ CREATE RENDER PIPELINE ~~
const pipeline = device.createRenderPipeline({
vertex: {
module: shaderModule,
entryPoint: "vertex_main",
buffers: vertexBuffersDescriptors,
},
fragment: {
module: shaderModule,
entryPoint: "fragment_main",
targets: [
{
format: presentationFormat,
},
],
},
primitive: {
topology: "triangle-list",
},
});
// ~~ CREATE RENDER PASS DESCRIPTOR ~~
const renderPassDescriptor = {
colorAttachments: [
{
clearValue: { r: 0.0, g: 0.0, b: 0.0, a: 1.0 },
loadOp: "clear",
storeOp: "store",
},
],
};
// ~~ Define render loop ~~
function frame() {
renderPassDescriptor.colorAttachments[0].view = context
.getCurrentTexture()
.createView();
const commandEncoder = device.createCommandEncoder();
const passEncoder =
commandEncoder.beginRenderPass(renderPassDescriptor);
passEncoder.setPipeline(pipeline);
passEncoder.setVertexBuffer(0, vertexBuffer);
passEncoder.draw(3);
passEncoder.end();
device.queue.submit([commandEncoder.finish()]);
requestAnimationFrame(frame);
}
requestAnimationFrame(frame);
};
init();
</script>
</body>
</html>
@Kablys
Copy link

Kablys commented Jan 19, 2024

To anyone who stumbles upon this, this code doesn't work there are multiple errors with it find newer version in creators profile.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment