diff options
Diffstat (limited to 'public/js/webgpu.js')
| -rw-r--r-- | public/js/webgpu.js | 253 |
1 files changed, 253 insertions, 0 deletions
diff --git a/public/js/webgpu.js b/public/js/webgpu.js new file mode 100644 index 0000000..b66f9ab --- /dev/null +++ b/public/js/webgpu.js @@ -0,0 +1,253 @@ +//import { mat4, vec3 } from './gl-matrix/dist/gl-matrix.js'; + +//import { formToJSON } from "axios"; + + +var ctx = null; +var cnv = null; +var wgc = null; +var W = 800; +var H = 600; + +const vertexShaderWGSL = ` +struct Uniforms { + modelViewProjectionMatrix : mat4x4<f32>, +} +@binding(0) @group(0) var<uniform> uniforms : Uniforms; + +struct VertexOutput { + @builtin(position) Position : vec4<f32>, + @location(0) color : vec4<f32>, +} + +@vertex +fn main( + @location(0) position : vec4<f32>, + @location(1) color : vec4<f32> +) -> VertexOutput { + var output : VertexOutput; + output.Position = uniforms.modelViewProjectionMatrix * position; + output.color = color; + return output; +} +`; + +const fragmentShaderWGSL = ` +@fragment +fn main(@location(0) color : vec4<f32>) -> @location(0) vec4<f32> { + return color; +} +`; + +$(document).ready(function() { + cnv = $('#c')[0]; + if (cnv != null) { + //initDOM(); + //ctx = cnv.getContext("2d"); + W = window.outerWidth; + H = window.outerHeight; + cnv.width = W; + cnv.height = H; + //ctx.fillRect(0,0,W,H); + + window.addEventListener('resize', resizeCanvas); + doWebGPUStuff(); + } else { + console.error('Canvas element not found'); + } +}); + +function resizeCanvas() { + W = window.outerWidth; + H = window.outerHeight; + cnv.width = W; + cnv.height = H; +} + +async function doWebGPUStuff(){ + console.log(navigator); + if (!navigator.gpu) { + console.error("WebGPU not supported on this browser."); + return; + } + const adapter = await navigator.gpu.requestAdapter(); + if (!adapter) { + console.error("No appropriate GPUAdapter found."); + return; + } + console.log(adapter); + + const device = await adapter.requestDevice(); + console.log(device); + + wgc = cnv.getContext("webgpu"); + console.log(wgc); + const cnvFormat = navigator.gpu.getPreferredCanvasFormat(); + wgc.configure({ + device: device, + format: cnvFormat + }); + + const vertices = new Float32Array([ + // Front face + -0.5, -0.5, 0.5, 1.0, 0.0, 0.0, 1.0, + 0.5, -0.5, 0.5, 1.0, 0.0, 0.0, 1.0, + 0.5, 0.5, 0.5, 1.0, 0.0, 0.0, 1.0, + -0.5, 0.5, 0.5, 1.0, 0.0, 0.0, 1.0, + // Back face + -0.5, -0.5, -0.5, 0.0, 1.0, 0.0, 1.0, + 0.5, -0.5, -0.5, 0.0, 1.0, 0.0, 1.0, + 0.5, 0.5, -0.5, 0.0, 1.0, 0.0, 1.0, + -0.5, 0.5, -0.5, 0.0, 1.0, 0.0, 1.0, + ]); + + const indices = new Uint16Array([ + 0, 1, 2, 0, 2, 3, + 1, 5, 6, 1, 6, 2, + 5, 4, 7, 5, 7, 6, + 4, 0, 3, 4, 3, 7, + 3, 2, 6, 3, 6, 7, + 4, 5, 1, 4, 1, 0 + ]); + + const vertexBuffer = device.createBuffer({ + size: vertices.byteLength, + usage: GPUBufferUsage.VERTEX, + mappedAtCreation: true, + }); + new Float32Array(vertexBuffer.getMappedRange()).set(vertices); + vertexBuffer.unmap(); + + const indexBuffer = device.createBuffer({ + size: indices.byteLength, + usage: GPUBufferUsage.INDEX, + mappedAtCreation: true, + }); + new Uint16Array(indexBuffer.getMappedRange()).set(indices); + indexBuffer.unmap(); + + const uniformBuffer = device.createBuffer({ + size: 16 * 4, + usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST, + }); + + const pipeline = device.createRenderPipeline({ + layout: 'auto', + vertex: { + module: device.createShaderModule({ + code: vertexShaderWGSL, + }), + entryPoint: 'main', + buffers: [ + { + arrayStride: 7 * 4, + attributes: [ + { shaderLocation: 0, offset: 0, format: 'float32x3' }, + { shaderLocation: 1, offset: 3 * 4, format: 'float32x4' }, + ], + }, + ], + }, + fragment: { + module: device.createShaderModule({ + code: fragmentShaderWGSL, + }), + entryPoint: 'main', + targets: [ + { + format: cnvFormat, + }, + ], + }, + primitive: { + topology: 'triangle-list', + }, + depthStencil: { + depthWriteEnabled: true, + depthCompare: 'less', + format: 'depth24plus', + }, + }); + + const depthTexture = device.createTexture({ + size: [cnv.width, cnv.height], + format: 'depth24plus', + usage: GPUTextureUsage.RENDER_ATTACHMENT, + }); + + const uniformBindGroup = device.createBindGroup({ + layout: pipeline.getBindGroupLayout(0), + entries: [ + { + binding: 0, + resource: { + buffer: uniformBuffer, + }, + }, + ], + }); + + render(device); +} + +function render (device) { + const aspect = cnv.width / cnv.height; + const projectionMatrix = mat4.create(); + mat4.perspective(projectionMatrix, (2 * Math.PI) / 5, aspect, 1, 100.0); + + const viewMatrix = mat4.create(); + const eye = vec3.fromValues(0, 0, 4); + const center = vec3.fromValues(0, 0, 0); + const up = vec3.fromValues(0, 1, 0); + mat4.lookAt(viewMatrix, eye, center, up); + + const modelViewProjectionMatrix = mat4.create(); + const modelMatrix = mat4.create(); + mat4.translate(modelMatrix, modelMatrix, [ + (200 /*cursorPosition.x*/ / cnv.width) * 2 - 1, + -(( 200 /*cursorPosition.y*/ / cnv.height) * 2 - 1), + 0 + ]); + mat4.rotate(modelMatrix, modelMatrix, Date.now() * 0.001, vec3.fromValues(0, 1, 0)); + + mat4.multiply(modelViewProjectionMatrix, viewMatrix, modelMatrix); + mat4.multiply(modelViewProjectionMatrix, projectionMatrix, modelViewProjectionMatrix); + + device.queue.writeBuffer( + uniformBuffer, + 0, + modelViewProjectionMatrix.buffer, + modelViewProjectionMatrix.byteOffset, + modelViewProjectionMatrix.byteLength + ); + + const commandEncoder = device.createCommandEncoder(); + const textureView = wgc.getCurrentTexture().createView(); + + const renderPassDescriptor = { + colorAttachments: [ + { + view: textureView, + clearValue: { r: 0.1, g: 0.2, b: 0.3, a: 1.0 }, + loadOp: 'clear', + storeOp: 'store', + }, + ], + depthStencilAttachment: { + view: depthTexture.createView(), + depthClearValue: 1.0, + depthLoadOp: 'clear', + depthStoreOp: 'store', + }, + }; + const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); + passEncoder.setPipeline(pipeline); + passEncoder.setBindGroup(0, uniformBindGroup); + passEncoder.setVertexBuffer(0, vertexBuffer); + passEncoder.setIndexBuffer(indexBuffer, 'uint16'); + passEncoder.drawIndexed(36); + passEncoder.end(); + + device.queue.submit([commandEncoder.finish()]); + requestAnimationFrame(render); +} |
