



Field Trips


Manning College of Nursing
10/9
Thursday
10/14
Tuesday
by Tuesday 9/30!
Assignment 3


Now Due 10/3!
CS460 Computer Graphics - University of Massachusetts Boston
Assignment 3


Now Due 10/3!
CS460 Computer Graphics - University of Massachusetts Boston

Quiz 5
Due Thursday 10/2 11:59pm


History of 3D Graphics

History of 3D Graphics (continued)

History of 3D Graphics (continued)

WebGPU
- Utilizes the device's graphics processing unit (GPU)
- Carry out high-performance computations
- Draw complex images
- Modern graphic features
- Low-Level API
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
Chrome Flags

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 device1. 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 devicecontext = 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()]);<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>WebGPU!</title>
<style>
html, body {
background:#000;
margin:0; padding:0; height:100%;
overflow:hidden !important;
}
#c { width:100%; height:100%; }
</style>
<!-- Vertex Shader -->
<script id="vertexshader" type="wgsl">
@vertex
fn main(@location(0) position: vec3<f32>) -> @builtin(position) vec4<f32> {
return vec4(position, 1.0);
}
</script>
<!-- Fragment Shader -->
<script id="fragmentshader" type="wgsl">
@fragment
fn main() -> @location(0) vec4<f32> {
return vec4(1.0, 1.0, 1.0, 1.0); // white
}
</script>
</head>
<body>
<canvas id="c"></canvas>
<!-- Step 2–5 will go inside this script -->
<script>
window.onload = async function () {
/* paste Step 2 here */
};
</script>
</body>
</html>
HTML + canvas + shader tags

//************************************************************//
// 1) INITIALIZE WEBGPU
//************************************************************//
const canvas = document.getElementById('c');
const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();
const context = canvas.getContext('webgpu');
const format = navigator.gpu.getPreferredCanvasFormat();
context.configure({
device,
format,
alphaMode: 'opaque'
});
/* paste Step 3 below this */
Step 1:Initialize WebGPU
//************************************************************//
// 2) SHADERS
//************************************************************//
const v_shader = device.createShaderModule({
code: document.getElementById('vertexshader').textContent
});
const f_shader = device.createShaderModule({
code: document.getElementById('fragmentshader').textContent
});
//************************************************************//
// 3) CREATE GEOMETRY (three stacked rectangles)
// each rect = 2 triangles = 6 vertices
//************************************************************//
const vertices = new Float32Array([
// ----- RECT #1 (top) y: 0.45 .. 0.75 -----
-0.3, 0.75, 0.0,
-0.3, 0.45, 0.0,
0.3, 0.75, 0.0,
0.3, 0.75, 0.0,
-0.3, 0.45, 0.0,
0.3, 0.45, 0.0,
// ----- RECT #2 (middle) y: -0.15 .. 0.15 -----
-0.3, 0.15, 0.0,
-0.3, -0.15, 0.0,
0.3, 0.15, 0.0,
0.3, 0.15, 0.0,
-0.3, -0.15, 0.0,
0.3, -0.15, 0.0,
// ----- RECT #3 (bottom) y: -0.75 .. -0.45 -----
-0.3, -0.45, 0.0,
-0.3, -0.75, 0.0,
0.3, -0.45, 0.0,
0.3, -0.45, 0.0,
-0.3, -0.75, 0.0,
0.3, -0.75, 0.0,
]);
const 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();
/* paste Step 4 below this */
Step 2 : Shaders + Geometry + Vertex Buffer
//************************************************************//
// 4) CREATE RENDERING PIPELINE
//************************************************************//
const pipeline = device.createRenderPipeline({
layout: 'auto',
vertex: {
module: v_shader,
buffers: [{
arrayStride: 3 * 4, // 3 floats (x,y,z) * 4 bytes
attributes: [{
shaderLocation: 0, // matches @location(0) in vertex shader
offset: 0,
format: 'float32x3'
}]
}]
},
fragment: {
module: f_shader,
targets: [{ format }]
},
primitive: { topology: 'triangle-list' }
});
/* paste Step 5 below this */
Step3: Create The Rendering Pipeline
Step4: Draw!
//************************************************************//
// 5) DRAW!
//************************************************************//
const commandEncoder = device.createCommandEncoder();
const textureView = context.getCurrentTexture().createView();
const renderPassDescriptor = {
colorAttachments: [{
view: textureView,
clearValue: [0, 0, 0, 1], // black background
loadOp: 'clear',
storeOp: 'store'
}]
};
const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
passEncoder.setPipeline(pipeline);
passEncoder.setVertexBuffer(0, v_buffer);
// draw all 3 rectangles at once: 3 * 6 = 18 vertices
passEncoder.draw(18);
passEncoder.end();
device.queue.submit([commandEncoder.finish()]);
Step5: FunStuff!
//************************************************************//
// 6. ANIMATION LOOP (replaces Step 5 static draw)
//************************************************************//
let xOffset = 0; // current movement offset
let direction = 1; // 1 = right, -1 = left
function drawFrame() {
// Move geometry back and forth in X
xOffset += 0.01 * direction;
if (xOffset > 0.5 || xOffset < -0.5) {
direction *= -1; // bounce when hitting edge
}
// Apply offset to geometry
const movedVertices = new Float32Array(vertices.length);
for (let i = 0; i < vertices.length; i += 3) {
movedVertices[i] = vertices[i] + xOffset; // shift X
movedVertices[i+1] = vertices[i+1]; // keep Y
movedVertices[i+2] = vertices[i+2]; // keep Z
}
device.queue.writeBuffer(v_buffer, 0, movedVertices);
// Normal draw commands
const commandEncoder = device.createCommandEncoder();
const textureView = context.getCurrentTexture().createView();
const renderPassDescriptor = {
colorAttachments: [{
view: textureView,
clearValue: [0, 0, 0, 0],
loadOp: 'clear',
storeOp: 'store'
}]
};
const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
passEncoder.setPipeline(pipeline);
passEncoder.setVertexBuffer(0, v_buffer);
passEncoder.draw(18); // 18 vertices = 3 rectangles
passEncoder.end();
device.queue.submit([commandEncoder.finish()]);
requestAnimationFrame(drawFrame); // 🔁 repeat each frame
}
// 🔹 Start animation
drawFrame();

<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>WebGPU!</title>
<style>
html,
body {
background: #000;
margin: 0;
padding: 0;
height: 100%;
overflow: hidden !important;
}
#c {
width: 100%;
height: 100%;
}
</style>
<!-- Vertex Shader -->
<script id="vertexshader" type="wgsl">
@vertex
fn main(@location(0) position: vec3<f32>) -> @builtin(position) vec4<f32> {
return vec4(position, 1.0);
}
</script>
<!-- Fragment Shader -->
<script id="fragmentshader" type="wgsl">
@fragment
fn main() -> @location(0) vec4<f32> {
return vec4(1.0, 1.0, 1.0, 1.0); // white
}
</script>
</head>
<body>
<canvas id="c"></canvas>
<!-- Step 2–5 will go inside this script -->
<script>
window.onload = async function () {
/* paste Step 2 here */
//************************************************************//
// 1) INITIALIZE WEBGPU
//************************************************************//
const canvas = document.getElementById('c');
const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();
const context = canvas.getContext('webgpu');
const format = navigator.gpu.getPreferredCanvasFormat();
context.configure({
device,
format,
alphaMode: 'opaque'
});
//************************************************************//
// 2) SHADERS
//************************************************************//
const v_shader = device.createShaderModule({
code: document.getElementById('vertexshader').textContent
});
const f_shader = device.createShaderModule({
code: document.getElementById('fragmentshader').textContent
});
//************************************************************//
// 3) CREATE GEOMETRY (three stacked rectangles)
// each rect = 2 triangles = 6 vertices
//************************************************************//
const vertices = new Float32Array([
// ----- RECT #1 (top) y: 0.45 .. 0.75 -----
-0.3, 0.75, 0.0,
-0.3, 0.45, 0.0,
0.3, 0.75, 0.0,
0.3, 0.75, 0.0,
-0.3, 0.45, 0.0,
0.3, 0.45, 0.0,
// ----- RECT #2 (middle) y: -0.15 .. 0.15 -----
-0.3, 0.15, 0.0,
-0.3, -0.15, 0.0,
0.3, 0.15, 0.0,
0.3, 0.15, 0.0,
-0.3, -0.15, 0.0,
0.3, -0.15, 0.0,
// ----- RECT #3 (bottom) y: -0.75 .. -0.45 -----
-0.3, -0.45, 0.0,
-0.3, -0.75, 0.0,
0.3, -0.45, 0.0,
0.3, -0.45, 0.0,
-0.3, -0.75, 0.0,
0.3, -0.75, 0.0,
]);
const 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
//************************************************************//
const pipeline = device.createRenderPipeline({
layout: 'auto',
vertex: {
module: v_shader,
buffers: [{
arrayStride: 3 * 4, // 3 floats (x,y,z) * 4 bytes
attributes: [{
shaderLocation: 0, // matches @location(0) in vertex shader
offset: 0,
format: 'float32x3'
}]
}]
},
fragment: {
module: f_shader,
targets: [{ format }]
},
primitive: { topology: 'triangle-list' }
});
//************************************************************//
// 5) DRAW!
//************************************************************//
//************************************************************//
// 6. ANIMATION LOOP (replaces Step 5 static draw)
//************************************************************//
let xOffset = 0; // current movement offset
let direction = 1; // 1 = right, -1 = left
function drawFrame() {
// Move geometry back and forth in X
xOffset += 0.01 * direction;
if (xOffset > 0.5 || xOffset < -0.5) {
direction *= -1; // bounce when hitting edge
}
// Apply offset to geometry
const movedVertices = new Float32Array(vertices.length);
for (let i = 0; i < vertices.length; i += 3) {
movedVertices[i] = vertices[i] + xOffset; // shift X
movedVertices[i + 1] = vertices[i + 1]; // keep Y
movedVertices[i + 2] = vertices[i + 2]; // keep Z
}
device.queue.writeBuffer(v_buffer, 0, movedVertices);
// Normal draw commands
const commandEncoder = device.createCommandEncoder();
const textureView = context.getCurrentTexture().createView();
const renderPassDescriptor = {
colorAttachments: [{
view: textureView,
clearValue: [0, 0, 0, 0],
loadOp: 'clear',
storeOp: 'store'
}]
};
const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
passEncoder.setPipeline(pipeline);
passEncoder.setVertexBuffer(0, v_buffer);
passEncoder.draw(18); // 18 vertices = 3 rectangles
passEncoder.end();
device.queue.submit([commandEncoder.finish()]);
requestAnimationFrame(drawFrame); // 🔁 repeat each frame
}
// 🔹 Start animation
drawFrame();
/* paste Step 5 below this */
/* paste Step 4 below this */
/* paste Step 3 below this */
};
</script>
</body>
</html>

Messing With Geometry
const vertices = new Float32Array([
-0.6, -0.4, 0.0,
0.6, -0.4, 0.0,
0.0, 0.6, 0.0,
]);
Single triangle
const vertices = new Float32Array([
-0.5, 0.5, 0.0,
-0.5, -0.5, 0.0,
0.5, 0.5, 0.0,
0.5, 0.5, 0.0,
-0.5, -0.5, 0.0,
0.5, -0.5, 0.0,
]);
Centered rectangle
const vertices = new Float32Array([
0.0, 0.7, 0.0, // top
-0.7, 0.0, 0.0, // left
0.7, 0.0, 0.0, // right
0.0, -0.7, 0.0, // bottom
-0.7, 0.0, 0.0, // left
0.7, 0.0, 0.0, // right
]);Diamond
House
const vertices = new Float32Array([
// base (quad)
-0.6, -0.4, 0.0,
0.6, -0.4, 0.0,
-0.6, 0.4, 0.0,
-0.6, 0.4, 0.0,
0.6, -0.4, 0.0,
0.6, 0.4, 0.0,
// roof
-0.7, 0.4, 0.0,
0.7, 0.4, 0.0,
0.0, 0.8, 0.0,
]);

Messing With Geometry
const vertices = new Float32Array([
0.0, 0.8, 0.0,
-0.2, 0.2, 0.0,
0.2, 0.2, 0.0,
-0.8, 0.0, 0.0,
-0.2, 0.2, 0.0,
0.0, -0.2, 0.0,
0.8, 0.0, 0.0,
0.2, 0.2, 0.0,
0.0, -0.2, 0.0
]);Star
const vertices = new Float32Array([
-0.5, 0.5, 0.0,
0.0, -0.5, 0.0,
0.5, 0.5, 0.0,
]);
passEncoder.draw(3);
V
const vertices = new Float32Array([
// Vertical bar
-0.1, 0.6, 0.0,
0.1, 0.6, 0.0,
-0.1, -0.6, 0.0,
0.1, 0.6, 0.0,
0.1, -0.6, 0.0,
-0.1, -0.6, 0.0,
// Horizontal bar
-0.6, 0.1, 0.0,
0.6, 0.1, 0.0,
-0.6, -0.1, 0.0,
0.6, 0.1, 0.0,
0.6, -0.1, 0.0,
-0.6, -0.1, 0.0,
]);
passEncoder.draw(12);
Cross
Trapezoid
const vertices = new Float32Array([
-0.6, 0.5, 0.0,
0.6, 0.5, 0.0,
-0.3, -0.5, 0.0,
0.6, 0.5, 0.0,
0.3, -0.5, 0.0,
-0.3, -0.5, 0.0,
]);
passEncoder.draw(6);


<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">
struct VertexInput {
@location(0) position: vec3<f32>,
@location(1) offset: vec3<f32>,
@location(2) color: vec4<f32>, // Color for the instance
};
struct VertexOutput {
@builtin(position) position: vec4<f32>,
@location(0) color: vec4<f32>, // Pass color to fragment shader
};
@vertex
fn main(input: VertexInput) -> VertexOutput {
var output: VertexOutput;
output.position = vec4(input.position + input.offset, 1.0); // Add offset
output.color = input.color; // Pass color to fragment shader
return output;
}
</script>
<script id="fragmentshader" type="wgsl">
@fragment
fn main(@location(0) color: vec4<f32>) -> @location(0) vec4<f32> {
return color; // Use the color passed from the vertex shader
}
</script>
<script>
window.onload = async function() {
//************************************************************//
//
// INITIALIZE WEBGPU
//
const canvas = document.getElementById('c');
const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();
const context = canvas.getContext('webgpu');
const format = navigator.gpu.getPreferredCanvasFormat();
context.configure({
device: device,
format: format,
alphaMode: 'opaque'
});
//************************************************************//
//
// SHADERS
//
const v_shader = device.createShaderModule({
code: document.getElementById('vertexshader').innerText
});
const f_shader = device.createShaderModule({
code: document.getElementById('fragmentshader').innerText
});
//************************************************************//
//
// CREATE GEOMETRY
//
// Define a single rectangle using triangles
const 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
]);
const 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();
//************************************************************//
//
// INSTANCE DATA
//
// Define the initial offsets for 3 rectangles
const instanceOffsets = new Float32Array([
-0.4, -0.4, 0.0, // Rectangle 1
0.0, 0.0, 0.0, // Rectangle 2
0.4, 0.4, 0.0, // Rectangle 3
]);
const i_buffer = device.createBuffer({
size: instanceOffsets.byteLength,
usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
mappedAtCreation: true
});
new Float32Array(i_buffer.getMappedRange()).set(instanceOffsets);
i_buffer.unmap();
// Define colors for 3 rectangles
const instanceColors = new Float32Array([
1.0, 0.0, 0.0, 1.0, // Red for Rectangle 1
0.0, 1.0, 0.0, 1.0, // Green for Rectangle 2
0.0, 0.0, 1.0, 1.0, // Blue for Rectangle 3
]);
const c_buffer = device.createBuffer({
size: instanceColors.byteLength,
usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
mappedAtCreation: true
});
new Float32Array(c_buffer.getMappedRange()).set(instanceColors);
c_buffer.unmap();
//************************************************************//
//
// SETUP RENDERING PIPELINE
//
const pipeline = device.createRenderPipeline({
layout: 'auto',
vertex: {
module: v_shader,
buffers: [
{
arrayStride: 3 * 4, // Vertex size
attributes: [{
shaderLocation: 0,
offset: 0,
format: 'float32x3'
}]
},
{
arrayStride: 3 * 4, // Instance size
attributes: [{
shaderLocation: 1,
offset: 0,
format: 'float32x3'
}],
stepMode: 'instance' // Instance data
},
{
arrayStride: 4 * 4, // Color size
attributes: [{
shaderLocation: 2,
offset: 0,
format: 'float32x4'
}],
stepMode: 'instance' // Color data for each instance
}
]
},
fragment: {
module: f_shader,
targets: [{
format: format
}]
},
primitive: {
topology: 'triangle-list'
}
});
//************************************************************//
//
// ANIMATION VARIABLES
//
let offsetSpeed = 0.005; // Speed of movement
let offsetDirection = 1; // 1 for right, -1 for left
//************************************************************//
//
// ANIMATION LOOP
//
console.log(instanceOffsets.length);
function animate() {
// Update instance offsets
for (let i = 0; i < instanceOffsets.length / 3; i++) {
instanceOffsets[i * 3] += offsetSpeed * offsetDirection;// Move in x direction
// Reverse direction when reaching bounds
if (instanceOffsets[i * 3] > 1.0 || instanceOffsets[i * 3] < -1.0) {
offsetDirection *= -1;
}
}
// Update the instance buffer with new offsets
device.queue.writeBuffer(i_buffer, 0, instanceOffsets);
// Draw!
const commandEncoder = device.createCommandEncoder();
const textureView = context.getCurrentTexture().createView();
const renderPassDescriptor = {
colorAttachments: [{
view: textureView,
clearValue: [0, 0, 0, 0],
loadOp: 'clear',
storeOp: 'store'
}]
};
const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
passEncoder.setPipeline(pipeline);
passEncoder.setVertexBuffer(0, v_buffer); // Set vertex buffer
passEncoder.setVertexBuffer(1, i_buffer); // Set instance buffer for offsets
passEncoder.setVertexBuffer(2, c_buffer); // Set instance buffer for colors
passEncoder.draw(6, 3); // Draw 6 vertices (2 triangles) for 3 instances
passEncoder.end();
device.queue.submit([commandEncoder.finish()]);
requestAnimationFrame(animate); // Continue the animation
}
animate(); // Start the animation loop
}
</script>
</head>
<body>
<canvas id="c"></canvas>
</body>
</html>
CODE !!

WebGPU
By Avanith Kanamarlapudi
WebGPU
- 67