diff --git a/Ch02_ObjectCreation/ch02_objectcreation.js b/Ch02_ObjectCreation/ch02_objectcreation.js index 9de976d..194dc83 100755 --- a/Ch02_ObjectCreation/ch02_objectcreation.js +++ b/Ch02_ObjectCreation/ch02_objectcreation.js @@ -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) { diff --git a/Ch05_RotateSquare/ch05_rotatesquare.js b/Ch05_RotateSquare/ch05_rotatesquare.js old mode 100755 new mode 100644 index 25e29a9..f931464 --- a/Ch05_RotateSquare/ch05_rotatesquare.js +++ b/Ch05_RotateSquare/ch05_rotatesquare.js @@ -1 +1,162 @@ -const shaderCode = ` @group(0) @binding(0) var 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(); \ No newline at end of file +const shaderCode = ` +@group(0) @binding(0) var 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(); diff --git a/Ch05_RotateSquare/index.html b/Ch05_RotateSquare/index.html old mode 100755 new mode 100644 index d61802a..380793c --- a/Ch05_RotateSquare/index.html +++ b/Ch05_RotateSquare/index.html @@ -1,13 +1,13 @@ - - - -

Ch05_RotateSquare

- - - - - - - - - + + + +

Ch05_RotateSquare

+ + + + + + + + + diff --git a/README.md b/README.md index a18191c..cb19dd3 100644 --- a/README.md +++ b/README.md @@ -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