From 5386b8bee9deadbe0ed476c2213ade7ca9f972d7 Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Thu, 30 Jul 2026 12:12:24 -0500 Subject: [PATCH] flat renderer --- flat.js | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ flat.wgsl | 42 +++++++++++++++++++++ index.js | 11 ++++-- 3 files changed, 158 insertions(+), 4 deletions(-) create mode 100644 flat.js create mode 100644 flat.wgsl diff --git a/flat.js b/flat.js new file mode 100644 index 0000000..11f6926 --- /dev/null +++ b/flat.js @@ -0,0 +1,109 @@ +import { getPath } from "./common.js"; + +class FlatRenderer { + constructor(device, canvasFormat, viewUniformBuffer, shaderModule) + { + const label = "flat"; + + ////////////////////////////////////////////////////////////////////// + // buffer + ////////////////////////////////////////////////////////////////////// + + const array = new Uint16Array(6); + array[0] = 0; + array[1] = 1; + array[2] = 2; + array[3] = 0; + array[4] = 3; + array[5] = 1; + + this.buffer = device.createBuffer({ + label: `${label} renderer buffer`, + size: array.byteLength, + usage: GPUBufferUsage.INDEX | GPUBufferUsage.COPY_DST, + }); + + device.queue.writeBuffer(this.buffer, 0, array, 0, array.length); + + ////////////////////////////////////////////////////////////////////// + // pipeline + ////////////////////////////////////////////////////////////////////// + + const bindGroupLayouts = [ + device.createBindGroupLayout({ + label: `${label} view matrix bind group layout`, + entries: [{ + binding: 0, + visibility: GPUShaderStage.VERTEX, + buffer: { type: "uniform" } + }] + }), + ]; + + const pipelineLayout = device.createPipelineLayout({ + label: `${label} pipeline layout`, + bindGroupLayouts: bindGroupLayouts, + }); + + this.renderPipeline = device.createRenderPipeline({ + label: `${label} pipeline`, + layout: pipelineLayout, + vertex: { + module: shaderModule, + entryPoint: "vertexMain", + }, + fragment: { + module: shaderModule, + entryPoint: "fragmentMain", + targets: [{ + format: canvasFormat, + }] + }, + primitive: { + topology: "triangle-list", + }, + depthStencil: { + depthWriteEnabled: true, + depthCompare: "less", + format: "depth24plus", + }, + }); + + ////////////////////////////////////////////////////////////////////// + // bind group + ////////////////////////////////////////////////////////////////////// + + this.bindGroups = [ + device.createBindGroup({ + label: `${label} bind group`, + layout: bindGroupLayouts[0], + entries: [{ + binding: 0, + resource: { buffer: viewUniformBuffer }, + }], + }), + ]; + } + + render(renderPass) + { + renderPass.setPipeline(this.renderPipeline); + renderPass.setIndexBuffer(this.buffer, "uint16"); + renderPass.setBindGroup(0, this.bindGroups[0]); + renderPass.drawIndexed(6); + } +} + +async function loadFlat(device, canvasFormat, viewUniformBuffer) +{ + const flatWgsl = await getPath("flat.wgsl"); + const shaderModule = device.createShaderModule({ + label: "flag shader", + code: flatWgsl, + }); + + const renderer = new FlatRenderer(device, canvasFormat, viewUniformBuffer, shaderModule); + return renderer; +} + +export { loadFlat }; diff --git a/flat.wgsl b/flat.wgsl new file mode 100644 index 0000000..a9bc02e --- /dev/null +++ b/flat.wgsl @@ -0,0 +1,42 @@ +struct Configuration { + viewProj: mat4x4f, + lightViewProj: mat4x4f, + lightPosition: vec4f, + eyePosition: vec4f, +}; + +@group(0) @binding(0) var config: Configuration; + +struct VertexInput { + @builtin(vertex_index) vertex_index: u32, +}; + +struct VertexOutput { + @builtin(position) position: vec4f, + @location(0) texture: vec2f, +}; + +const vertices = array( + vec2f(1.0, 0.0), + vec2f(0.0, 1.0), + vec2f(0.0, 0.0), + vec2f(1.0, 1.0), +); + +@vertex +fn vertexMain(input: VertexInput) -> VertexOutput +{ + let texture = vertices[input.vertex_index]; + let position = vec4f(texture * 2.0 - 1.0, 0.0, 1.0); + + var output: VertexOutput; + output.position = position; + output.texture = texture; + return output; +} + +@fragment +fn fragmentMain(input: VertexOutput) -> @location(0) vec4f +{ + return vec4(input.texture, 0.0, 1.0); +} diff --git a/index.js b/index.js index 2c2a6b7..f89c2a1 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,7 @@ import { getPath } from "./common.js"; import { loadGltf } from "./index2.js"; import { loadLight } from "./light.js"; +import { loadFlat } from "./flat.js"; if (!navigator.gpu) { throw new Error("WebGPU not supported on this browser."); @@ -95,8 +96,9 @@ const cameraStateAddress = module.instance.exports.mem_alloc(cameraStateSize); module.instance.exports.camera_init(cameraStateAddress); -const gltfRenderer = await loadGltf(device, canvasFormat, viewUniformBuffer, memory, module); -const lightRenderer = await loadLight(device, canvasFormat, viewUniformBuffer); +//const gltfRenderer = await loadGltf(device, canvasFormat, viewUniformBuffer, memory, module); +//const lightRenderer = await loadLight(device, canvasFormat, viewUniformBuffer); +const flatRenderer = await loadFlat(device, canvasFormat, viewUniformBuffer); const KEY = { @@ -219,8 +221,9 @@ function render2() }, }); - gltfRenderer.render(renderPass); - lightRenderer.render(renderPass); + //gltfRenderer.render(renderPass); + //lightRenderer.render(renderPass); + flatRenderer.render(renderPass); renderPass.end();