Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions Ch02_ObjectCreation/ch02_objectcreation.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,31 @@ if (!adapter) {
msg_array.push("GPUAdapter found");
}

console.log(adapter);

// Access information about the GPU adapter
/*const info = await adapter.requestAdapterInfo();
if(info) {
console.log("Vendor: " + info.vendor);
console.log("Architecture: " + info.architecture);
console.log("Device: " + info.device);
console.log("Description: " + info.description);
}*/

// Display all of the supported features
console.log("Supported feature: ");
adapter.features.forEach((value) => {
console.log("\t", value);
});

console.log("Limits: ");
for (const key in adapter.limits)
{
const value = adapter.limits[key];
console.log(`\t${key}: ${value}`);
}


// Access the GPU
const device = await adapter.requestDevice();
if (!device) {
Expand Down
163 changes: 162 additions & 1 deletion Ch05_RotateSquare/ch05_rotatesquare.js
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1 +1,162 @@
const shaderCode = `@group(0) @binding(0) var<uniform> rotMat: mat4x4f;@vertexfn vertexMain(@location(0) coords: vec2f) -> @builtin(position) vec4f { return rotMat * vec4f(coords, 0.0, 1.0);}@fragmentfn fragmentMain() -> @location(0) vec4f { return vec4f(0.2, 0.2, 1.0, 1.0);}`;// Create top-level asynchronous functionasync function runExample() {// Check if WebGPU is supportedif (!navigator.gpu) { throw new Error("WebGPU not supported");}// Access the GPUAdapterconst adapter = await navigator.gpu.requestAdapter();if (!adapter) { throw new Error("No GPUAdapter found");}// Access the GPUconst device = await adapter.requestDevice();if (!device) { throw new Error("Failed to create a GPUDevice");}// Access the canvasconst canvas = document.getElementById("canvas_example");if (!canvas) { throw new Error("Could not access canvas in page");}// Obtain a WebGPU context for the canvasconst context = canvas.getContext("webgpu");if (!context) { throw new Error("Could not obtain WebGPU context for canvas");}// Configure the context with the device and formatconst canvasFormat = navigator.gpu.getPreferredCanvasFormat();context.configure({ device: device, format: canvasFormat,});// Create the command encoderconst encoder = device.createCommandEncoder();if (!encoder) { throw new Error("Failed to create a GPUCommandEncoder");}// Create the render pass encoderconst renderPass = encoder.beginRenderPass({ colorAttachments: [{ view: context.getCurrentTexture().createView(), loadOp: "clear", clearValue: { r: 0.9, g: 0.9, b: 0.9, a: 1.0 }, storeOp: "store" }]});// Define vertex dataconst vertexData = new Float32Array([ -0.5, -0.5, // First vertex 0.5, -0.5, // Second vertex -0.5, 0.5, // Third vertex 0.5, 0.5, // Fourth vertex]);// Create vertex bufferconst vertexBuffer = device.createBuffer({ label: "Vertex Buffer 0", size: vertexData.byteLength, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST});device.queue.writeBuffer(vertexBuffer, 0, vertexData);renderPass.setVertexBuffer(0, vertexBuffer);// Define layout of vertex bufferconst bufferLayout = { arrayStride: 8, attributes: [ { format: "float32x2", offset: 0, shaderLocation: 0 } ],};// Define uniform dataconst uniformData = new Float32Array([ 0.866, 0.5, 0.0, 0.0, // First column of matrix -0.5, 0.866, 0.0, 0.0, // Second column of matrix 0.0, 0.0, 1.0, 0.0, // Third column of matrix 0.0, 0.0, 0.0, 1.0, // Fourth column of matrix]);// Create uniform bufferconst uniformBuffer = device.createBuffer({ label: "Uniform Buffer 0", size: uniformData.byteLength, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST});device.queue.writeBuffer(uniformBuffer, 0, uniformData); // Create the shader moduleconst shaderModule = device.createShaderModule({ label: "Shader module 0", code: shaderCode});// Define the rendering procedureconst renderPipeline = device.createRenderPipeline({ layout: "auto", vertex: { module: shaderModule, entryPoint: "vertexMain", buffers: [bufferLayout] }, fragment: { module: shaderModule, entryPoint: "fragmentMain", targets: [{ format: canvasFormat }] }, primitive: { topology: "triangle-strip" }});renderPass.setPipeline(renderPipeline);// Access the bind group layoutconst bindGroupLayout = renderPipeline.getBindGroupLayout(0);// Create the bind grouplet bindGroup = device.createBindGroup({ layout: bindGroupLayout, entries: [{ binding: 0, resource: { buffer: uniformBuffer } }]});// Associate bind group with render pass encoderrenderPass.setBindGroup(0, bindGroup);// Draw vertices and complete renderingrenderPass.draw(4);renderPass.end();// Submit the render commands to the GPUdevice.queue.submit([encoder.finish()]);}// Run example functionrunExample();
const shaderCode = `
@group(0) @binding(0) var<uniform> rotMat: mat4x4f;

@vertex
fn vertexMain(@location(0) coords: vec2f) -> @builtin(position) vec4f {
return rotMat * vec4f(coords, 0.0, 1.0);
}

@fragment
fn fragmentMain() -> @location(0) vec4f {
return vec4f(0.2, 0.2, 1.0, 1.0);
}
`;

// Create top-level asynchronous function
async function runExample() {

// Check if WebGPU is supported
if (!navigator.gpu) {
throw new Error("WebGPU not supported");
}

// Access the GPUAdapter
const adapter = await navigator.gpu.requestAdapter();
if (!adapter) {
throw new Error("No GPUAdapter found");
}

// Access the GPU
const device = await adapter.requestDevice();
if (!device) {
throw new Error("Failed to create a GPUDevice");
}

// Access the canvas
const canvas = document.getElementById("canvas_example");
if (!canvas) {
throw new Error("Could not access canvas in page");
}

// Obtain a WebGPU context for the canvas
const context = canvas.getContext("webgpu");
if (!context) {
throw new Error("Could not obtain WebGPU context for canvas");
}

// Configure the context with the device and format
const canvasFormat = navigator.gpu.getPreferredCanvasFormat();
context.configure({
device: device,
format: canvasFormat,
});

// Create the command encoder
const encoder = device.createCommandEncoder();
if (!encoder) {
throw new Error("Failed to create a GPUCommandEncoder");
}

// Create the render pass encoder
const renderPass = encoder.beginRenderPass({
colorAttachments: [{
view: context.getCurrentTexture().createView(),
loadOp: "clear",
clearValue: { r: 0.9, g: 0.9, b: 0.9, a: 1.0 },
storeOp: "store"
}]
});

// Define vertex data
const vertexData = new Float32Array([
-0.5, -0.5, // First vertex
0.5, -0.5, // Second vertex
-0.5, 0.5, // Third vertex
0.5, 0.5, // Fourth vertex
]);

// Create vertex buffer
const vertexBuffer = device.createBuffer({
label: "Vertex Buffer 0",
size: vertexData.byteLength,
usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST
});
device.queue.writeBuffer(vertexBuffer, 0, vertexData);
renderPass.setVertexBuffer(0, vertexBuffer);

// Define layout of vertex buffer
const bufferLayout = {
arrayStride: 8,
attributes: [
{ format: "float32x2", offset: 0, shaderLocation: 0 }
],
};

// Define uniform data
const uniformData = new Float32Array([
0.866, 0.5, 0.0, 0.0, // First column of matrix
-0.5, 0.866, 0.0, 0.0, // Second column of matrix
0.0, 0.0, 1.0, 0.0, // Third column of matrix
0.0, 0.0, 0.0, 1.0, // Fourth column of matrix
]);

// Create uniform buffer
const uniformBuffer = device.createBuffer({
label: "Uniform Buffer 0",
size: uniformData.byteLength,
usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
});
device.queue.writeBuffer(uniformBuffer, 0, uniformData);

// Create the shader module
const shaderModule = device.createShaderModule({
label: "Shader module 0",
code: shaderCode
});

// Define the rendering procedure
const renderPipeline = device.createRenderPipeline({
layout: "auto",
vertex: {
module: shaderModule,
entryPoint: "vertexMain",
buffers: [bufferLayout]
},
fragment: {
module: shaderModule,
entryPoint: "fragmentMain",
targets: [{
format: canvasFormat
}]
},
primitive: {
topology: "triangle-strip"
}
});
renderPass.setPipeline(renderPipeline);

// Access the bind group layout
const bindGroupLayout = renderPipeline.getBindGroupLayout(0);

// Create the bind group
let bindGroup = device.createBindGroup({
layout: bindGroupLayout,
entries: [{
binding: 0,
resource: { buffer: uniformBuffer }
}]
});

// Associate bind group with render pass encoder
renderPass.setBindGroup(0, bindGroup);

// Draw vertices and complete rendering
renderPass.draw(4);
renderPass.end();

// Submit the render commands to the GPU
device.queue.submit([encoder.finish()]);
}

// Run example function
runExample();
26 changes: 13 additions & 13 deletions Ch05_RotateSquare/index.html
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<html>
<body>
<h1>Ch05_RotateSquare</h1>
<!-- Create the canvas -->
<canvas id="canvas_example" width="400" height="400"></canvas>
<!-- Execute the script code -->
<script src="ch05_rotatesquare.js"></script>
</body>
</html>
<html>
<body>

<h1>Ch05_RotateSquare</h1>

<!-- Create the canvas -->
<canvas id="canvas_example" width="400" height="400"></canvas>

<!-- Execute the script code -->
<script src="ch05_rotatesquare.js"></script>

</body>
</html>
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ The projects in the chapters are given as follows:
- **Ch03_BlueCanvas** - Fills a WebGPU canvas with color
- **Ch04_OrangeTriangle** - Uses vertex attributes for rendering
- **Ch04_MultiTriangle** - Passes data from the vertex shader to the fragment shader
- **Ch05_RotateSquare** - Rotates a square using matrices stored in uniform buffers
- **Ch05_Cubes** - Transforms objects using matrices stored in uniform buffers
- **Ch06_ShinySphere** - Implements Blinn-Phong shading in a fragment shader
- **Ch06_SimpleTexture** - Uses a texture to display an image in the scene
Expand Down