diff --git a/src/gltf_group.ts b/src/gltf_group.ts index ff29b3c..612687e 100644 --- a/src/gltf_group.ts +++ b/src/gltf_group.ts @@ -45,7 +45,9 @@ export default class GLTFGroup // Calculate matrix for each node locally // since gltf alone does not give this info directly this.nodeMatrics = new Map(); - const defaultTransform : mat4 = [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1]; + //const defaultTransform : mat4 = [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1]; + + let defaultTransform = mat4.identity(mat4.create()); for(const node of this.gltf.nodes) { this.#calcNodeMatrix(node, defaultTransform); diff --git a/src/gltf_renderer.ts b/src/gltf_renderer.ts index 0bb0998..56805c0 100644 --- a/src/gltf_renderer.ts +++ b/src/gltf_renderer.ts @@ -1,12 +1,14 @@ import vertShaderCode from './shaders/gltf.vert.wgsl'; import fragShaderCode from './shaders/gltf.frag.wgsl'; +import compShaderCode from './shaders/comp.wgsl'; import * as GLTFSpace from 'gltf-loader-ts/lib/gltf'; import {mat4, vec3} from 'gl-matrix'; import GLTFGroup from './gltf_group'; - +var frame = 0; +var tmp; // Make sure the shaders follow this mapping const ShaderLocations = { @@ -77,6 +79,17 @@ export default class GltfRenderer commandEncoder: GPUCommandEncoder; passEncoder: GPURenderPassEncoder; + //ComputePipeline + computepassEncoder: GPUComputePassEncoder; + computePipeline: GPUComputePipeline; + computePipelineLayout: GPUPipelineLayout; + computeBindGroup: GPUBindGroup; + computeBindGroupLayout: GPUBindGroupLayout; + computeBuffer: GPUBuffer; + compShaderModule : GPUShaderModule; + + + // Web stuff canvas : HTMLCanvasElement; @@ -139,6 +152,26 @@ export default class GltfRenderer this.initFrameBindGroup(); this.initNodeBindGroup(); this.initInstanceBindGroup(); + this.initComputeBindGroup(); + + //create compute pipeline here, maybe not + this.computePipelineLayout = this.device.createPipelineLayout + ({ + label: 'glTF Compute Pipeline Layout', + bindGroupLayouts: [ + this.computeBindGroupLayout, + ] + + }); + const computeModule = this.getComputeShaderModule(); + this.computePipeline = this.device.createComputePipeline({ + layout: this.computePipelineLayout, + compute: { + module: computeModule, + entryPoint: 'simulate', + }, + }); + // Pipeline Layout this.gltfPipelineLayout = this.device.createPipelineLayout @@ -217,7 +250,7 @@ export default class GltfRenderer this.instanceBuffer = this.device.createBuffer ({ size: 16 * this.gltf_group.instanceCount * Float32Array.BYTES_PER_ELEMENT, - usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST + usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST, }); this.instanceBindGroupLayout = this.device.createBindGroupLayout ({ @@ -240,6 +273,31 @@ export default class GltfRenderer }); } + initComputeBindGroup() { + //a 4x4 transformation matrix + const computeBufferSize = 4 * 16; + this.computeBuffer = this.instanceBuffer; + this.computeBindGroupLayout = this.device.createBindGroupLayout + ({ + label: `Compute BindGroupLayout`, + entries: + [{ + binding: 0, // transformation matrix + visibility: GPUShaderStage.COMPUTE, + buffer: {type: 'storage'}, + }], + }); + this.computeBindGroup = this.device.createBindGroup + ({ + label: `Compute BindGroup`, + layout: this.computeBindGroupLayout, + entries: + [{ + binding: 0, // transformation matrix + resource: { buffer: this.computeBuffer }, + }], + }); + } async loadGPUBuffers() { // TODO:: Create instanced bind group @@ -312,6 +370,16 @@ export default class GltfRenderer } return this.fragShaderModule; } + getComputeShaderModule() { + if (!this.compShaderModule) + { + this.compShaderModule = this.device.createShaderModule({ + label: 'glTF compute shader module', + code : compShaderCode + }); + } + return this.compShaderModule; + } setupMeshNodeBindGroup(node : GLTFSpace.Node) { @@ -456,13 +524,39 @@ export default class GltfRenderer }; this.commandEncoder = this.device.createCommandEncoder(); + + //let transformationMatrixData = new Float32Array (this.gltf_group.transforms[0]).buffer; + + //let gpuBufferArray = new Uint8Array(this.computeBuffer.getMappedRange()); + //const tablesArray = new Float32Array(this.computeBuffer.getMappedRange()); + // this.device.queue.writeBuffer(this.computeBuffer, 0, transformationMatrixData); + + // console.log("before: "); + // let tmpBufferArray = new Uint8Array(this.computeBuffer.getMappedRange()); + // console.log(tmpBufferArray); + // this.instanceBuffer + + //compute shader first + this.computepassEncoder = this.commandEncoder.beginComputePass(); + this.computepassEncoder.setPipeline(this.computePipeline); + this.computepassEncoder.setBindGroup(0, this.computeBindGroup); + this.computepassEncoder.dispatchWorkgroups(1); + + + this.computepassEncoder.end(); + + if(tmp != this.computeBuffer) { + + } + // Render pass this.passEncoder = this.commandEncoder.beginRenderPass(renderPassDesc); this.passEncoder.setBindGroup(0, this.frameBindGroup); this.passEncoder.setBindGroup(2, this.instanceBindGroup); + //+5 // Bind gltf data to render pass for (const [node, bindGroup] of this.nodeGpuData) { @@ -514,7 +608,9 @@ export default class GltfRenderer // Submit command queue this.queue.submit([this.commandEncoder.finish()]); - requestAnimationFrame(this.renderGLTF); + frame++; + requestAnimationFrame(this.renderGLTF); + } updateFrameBuffer(projMat : mat4, viewMat : mat4, pos : vec3, time : number) @@ -543,7 +639,6 @@ export default class GltfRenderer let arr = new Float32Array(instanceArrayBuffer, st, 16); arr.set(mat); } - this.device.queue.writeBuffer(this.instanceBuffer, 0, instanceArrayBuffer); } } diff --git a/src/main.ts b/src/main.ts index 1425255..0319c26 100644 --- a/src/main.ts +++ b/src/main.ts @@ -53,11 +53,12 @@ export default class Application // Butterfly let s : number = 0.01; this.gltf_butterfly = new GLTFGroup(); - await this.gltf_butterfly.init( - 'https://raw.githubusercontent.com/Li-Jia-Jun/WebGPU-Butterfly/gltf/models/butterfly/butterfly.gltf', - 3, - ["b1", "b2", "b3"], - [[s,0,0,0, 0,s,0,0, 0,0,s,0, 3,0,0,1], [s,0,0,0, 0,s,0,0, 0,0,s,0, -3,0,0,1], [s,0,0,0, 0,s,0,0, 0,0,s,0, 0,4.5,0,1]]); + // await this.gltf_butterfly.init( + // 'https://raw.githubusercontent.com/Li-Jia-Jun/WebGPU-Butterfly/gltf/models/butterfly/butterfly.gltf', + // 3, + // ["b1", "b2", "b3"], + // [[s,0,0,0, 0,s,0,0, 0,0,s,0, 3,0,0,1], [s,0,0,0, 0,s,0,0, 0,0,s,0, -3,0,0,1], [s,0,0,0, 0,s,0,0, 0,0,s,0, 0,4.5,0,1]]); + await this.gltf_butterfly.init('https://raw.githubusercontent.com/Li-Jia-Jun/WebGPU-Butterfly/gltf/models/butterfly/butterfly.gltf',1, ["b1"],[[s,0,0,0, 0,s,0,0, 0,0,s,0, 0,4.5,0,1] ]); this.renderer_butterfly = new GltfRenderer(); await this.renderer_butterfly.init(this.adapter, this.device, this.queue, this.canvas, this.gltf_butterfly); diff --git a/src/shaders/comp.wgsl b/src/shaders/comp.wgsl new file mode 100644 index 0000000..f7257c3 --- /dev/null +++ b/src/shaders/comp.wgsl @@ -0,0 +1,24 @@ + +@binding(0) @group(0) var transform : array>; + + +@compute @workgroup_size(1) +fn simulate( + @builtin(global_invocation_id) GlobalInvocationID : vec3 +) { + var m = transform[0]; + + //column major + + + + + + m[3][0] = m[3][0] + 0.001; + transform[0] = m; + } + + + + // Store the new particle value + //transform.transformationMatrix = ;