New deadline : 10/15
WebGPU
And many more ....
Browser Compatibility
Linux :
Firefox Nightly (recommended)
Does not require any flags
Mac and Windows :
WebGPU works out of the box
Chrome
Edge
Hello Rectangle !!
WebGL
1. Initialize WebGL
2. Shaders
3. Create Geometry
4. Connect Shader with Geometry
5. Draw!
WebGL
1. Initialize WebGL
2. Shaders
3. Create Geometry
4. Connect Shader with Geometry
5. Draw!
WebGPU
WebGL
1. Initialize WebGL
2. Shaders
3. Create Geometry
4. Connect Shader with Geometry
5. Draw!
WebGPU
1. Initialize WebGPU
WebGL
1. Initialize WebGL
2. Shaders
3. Create Geometry
4. Connect Shader with Geometry
5. Draw!
WebGPU
1. Initialize WebGPU
2. Shaders
WebGL
1. Initialize WebGL
2. Shaders
3. Create Geometry
4. Connect Shader with Geometry
5. Draw!
WebGPU
1. Initialize WebGPU
2. Shaders
3. Create Geometry
WebGL
1. Initialize WebGL
2. Shaders
3. Create Geometry
4. Connect Shader with Geometry
5. Draw!
WebGPU
1. Initialize WebGPU
2. Shaders
3. Create Geometry
4. Create Rendering Pipeline
WebGL
1. Initialize WebGL
2. Shaders
3. Create Geometry
4. Connect Shader with Geometry
5. Draw!
WebGPU
1. Initialize WebGPU
2. Shaders
3. Create Geometry
4. Create Rendering Pipeline
5. Draw
1. Initialize WebGPU
1. Initialize WebGPU
setup canvas
request GPU adapter and Device
setup GPU context
1. Initialize WebGPU
setup canvas
request GPU adapter and Device
setup GPU context
canvas = document.getElementById('c'); // setup canvas
1. Initialize WebGPU
setup canvas
request GPU adapter and Device
setup GPU context
canvas = document.getElementById('c'); // setup canvas
adapter = await navigator.gpu.requestAdapter(); // request GPU
device = await adapter.requestDevice(); // request device
1. Initialize WebGPU
setup canvas
request GPU adapter and Device
setup GPU context
canvas = document.getElementById('c'); // setup canvas
adapter = await navigator.gpu.requestAdapter(); // request GPU
device = await adapter.requestDevice(); // request device
context = canvas.getContext('webgpu'); // setup GPU context
format = navigator.gpu.getPreferredCanvasFormat();
context.configure({
device: device,
format: format,
alphaMode: 'opaque'
});
2. Shaders
2. Shaders
define shaders
create shaders module
2. Shaders
define shaders
create shaders module
<script id="vertexshader" type="wgsl"> // vertex shader
@vertex
fn main(@location(0) position: vec3<f32>) -> @builtin(position) vec4<f32> {
return vec4(position, 1.0);
}
</script>
<script id="fragmentshader" type="wgsl"> // fragment shader
@fragment
fn main() -> @location(0) vec4<f32> {
return vec4(1.0, 1.0, 1.0, 1.0); // White color
}
</script>
2. Shaders
define shaders
create shaders module
<script id="vertexshader" type="wgsl"> // vertex shader
@vertex
fn main(@location(0) position: vec3<f32>) -> @builtin(position) vec4<f32> {
return vec4(position, 1.0);
}
</script>
<script id="fragmentshader" type="wgsl"> // fragment shader
@fragment
fn main() -> @location(0) vec4<f32> {
return vec4(1.0, 1.0, 1.0, 1.0); // White color
}
</script>
v_shader = device.createShaderModule({ // vertex module
code: document.getElementById('vertexshader').innerText
});
f_shader = device.createShaderModule({ // fragment module
code: document.getElementById('fragmentshader').innerText
});
3. Create Geometry
3. Create Geometry
create vertices
create buffer
map buffer
unmap buffer
3. Create Geometry
create vertices
create buffer
map buffer
unmap buffer
vertices = new Float32Array( [ // create vertices
-0.5, 0.5, 0.0, // V0
-0.5, -0.5, 0.0, // V1
0.5, 0.5, 0.0, // V2
0.5, 0.5, 0.0, // V3
-0.5, -0.5, 0.0, // V4
0.5, -0.5, 0.0 // V5
] );
3. Create Geometry
create vertices
create buffer
map buffer
unmap buffer
vertices = new Float32Array( [ // create vertices
-0.5, 0.5, 0.0, // V0
-0.5, -0.5, 0.0, // V1
0.5, 0.5, 0.0, // V2
0.5, 0.5, 0.0, // V3
-0.5, -0.5, 0.0, // V4
0.5, -0.5, 0.0 // V5
] );
v_buffer = device.createBuffer({
size: vertices.byteLength,
usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
mappedAtCreation: true
});
3. Create Geometry
create vertices
create buffer
map buffer
unmap buffer
vertices = new Float32Array( [ // create vertices
-0.5, 0.5, 0.0, // V0
-0.5, -0.5, 0.0, // V1
0.5, 0.5, 0.0, // V2
0.5, 0.5, 0.0, // V3
-0.5, -0.5, 0.0, // V4
0.5, -0.5, 0.0 // V5
] );
v_buffer = device.createBuffer({
size: vertices.byteLength,
usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
mappedAtCreation: true
});
new Float32Array(v_buffer.getMappedRange()).set(vertices);
3. Create Geometry
create vertices
create buffer
map buffer
unmap buffer
vertices = new Float32Array( [ // create vertices
-0.5, 0.5, 0.0, // V0
-0.5, -0.5, 0.0, // V1
0.5, 0.5, 0.0, // V2
0.5, 0.5, 0.0, // V3
-0.5, -0.5, 0.0, // V4
0.5, -0.5, 0.0 // V5
] );
v_buffer = device.createBuffer({
size: vertices.byteLength,
usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
mappedAtCreation: true
});
new Float32Array(v_buffer.getMappedRange()).set(vertices);
v_buffer.unmap();
4. Create Rendering Pipeline
4. Create Rendering Pipeline
create pipeline
setup vertex and fragment modules
4. Create Rendering Pipeline
create pipeline
setup vertex and fragment modules
pipeline = device.createRenderPipeline({
layout: 'auto',
vertex: {
module: v_shader,
buffers: [{
arrayStride: 3 * 4, // 3 components * 4 bytes per component (float32)
attributes: [{
shaderLocation: 0,
offset: 0,
format: 'float32x3'
}]
}]
},
fragment: {
module: f_shader,
targets: [{
format: format
}]
},
primitive: {
topology: 'triangle-list'
}
});
5. Draw
5. Draw
create command encoder
begin render pass
end render pass
submit to GPU
5. Draw
create command encoder
begin render pass
end render pass
submit to GPU
commandEncoder = device.createCommandEncoder();
5. Draw
create command encoder
begin render pass
end render pass
submit to GPU
commandEncoder = device.createCommandEncoder();
passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
.....
5. Draw
create command encoder
begin render pass
end render pass
submit to GPU
commandEncoder = device.createCommandEncoder();
passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
.....
renderPassDescriptor = {
colorAttachments: [{
view: textureView,
clearValue: [0, 0, 0, 0],
loadOp: 'clear',
storeOp: 'store'
}]
};
passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
passEncoder.setPipeline(pipeline);
passEncoder.setVertexBuffer(0, v_buffer);
passEncoder.draw(6); // Drawing 6 vertices (2 triangles)
5. Draw
create command encoder
begin render pass
end render pass
submit to GPU
commandEncoder = device.createCommandEncoder();
passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
.....
passEncoder.end();
5. Draw
create command encoder
begin render pass
end render pass
submit to GPU
commandEncoder = device.createCommandEncoder();
passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
.....
passEncoder.end();
device.queue.submit([commandEncoder.finish()]);
<html>
<head>
<title>WebGPU!</title>
<style>
html, body {
background-color:#000;
margin: 0;
padding: 0;
height: 100%;
overflow: hidden !important;
}
#c {
width: 100%;
height: 100%;
}
</style>
<script id="vertexshader" type="wgsl">
@vertex
fn main(@location(0) position: vec3<f32>) -> @builtin(position) vec4<f32> {
return vec4(position, 1.0);
}
</script>
<script id="fragmentshader" type="wgsl">
@fragment
fn main() -> @location(0) vec4<f32> {
return vec4(1.0, 1.0, 1.0, 1.0); // White color
}
</script>
<script>
window.onload = async function() {
//************************************************************//
//
// INITIALIZE WEBGPU
//
canvas = document.getElementById('c');
adapter = await navigator.gpu.requestAdapter();
device = await adapter.requestDevice();
context = canvas.getContext('webgpu');
format = navigator.gpu.getPreferredCanvasFormat();
context.configure({
device: device,
format: format,
alphaMode: 'opaque'
});
//************************************************************//
//
// SHADERS
//
v_shader = device.createShaderModule({
code: document.getElementById('vertexshader').innerText
});
f_shader = device.createShaderModule({
code: document.getElementById('fragmentshader').innerText
});
//************************************************************//
//
// CREATE GEOMETRY
//
vertices = new Float32Array( [
-0.5, 0.5, 0.0, // V0
-0.5, -0.5, 0.0, // V1
0.5, 0.5, 0.0, // V2
0.5, 0.5, 0.0, // V3
-0.5, -0.5, 0.0, // V4
0.5, -0.5, 0.0 // V5
] );
v_buffer = device.createBuffer({
size: vertices.byteLength,
usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
mappedAtCreation: true
});
new Float32Array(v_buffer.getMappedRange()).set(vertices);
v_buffer.unmap();
//************************************************************//
//
// SETUP RENDERING PIPELINE
//
pipeline = device.createRenderPipeline({
layout: 'auto',
vertex: {
module: v_shader,
buffers: [{
arrayStride: 3 * 4, // 3 components * 4 bytes per component (float32)
attributes: [{
shaderLocation: 0,
offset: 0,
format: 'float32x3'
}]
}]
},
fragment: {
module: f_shader,
targets: [{
format: format
}]
},
primitive: {
topology: 'triangle-list'
}
});
//************************************************************//
//
// DRAW!
//
commandEncoder = device.createCommandEncoder();
textureView = context.getCurrentTexture().createView();
renderPassDescriptor = {
colorAttachments: [{
view: textureView,
clearValue: [0, 0, 0, 0],
loadOp: 'clear',
storeOp: 'store'
}]
};
passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
passEncoder.setPipeline(pipeline);
passEncoder.setVertexBuffer(0, v_buffer);
passEncoder.draw(6); // Drawing 6 vertices (2 triangles)
passEncoder.end();
device.queue.submit([commandEncoder.finish()]);
}
</script>
</head>
<body>
<canvas id="c"></canvas>
</body>
</html>