UNPKG

@giraphics/grpkggfx

Version:
227 lines (224 loc) 8.58 kB
// import vertShaderCode from './shaders/pointcloud.vert.wgsl'; // import fragShaderCode from './shaders/pointcloud.frag.wgsl'; import { vec3 } from 'gl-matrix'; import SceneGraph from './../base/scenegraph'; import { TYPE_SIZE } from './../renderer/constants'; const particleShaders = { vertex: ` [[block]] struct Uniforms { modelViewProjectionMatrix : mat4x4<f32>; }; [[binding(0), group(0)]] var<uniform> uniforms : Uniforms; struct VSOut { [[builtin(position)]] Position: vec4<f32>; [[location(0)]] color: vec3<f32>; }; [[stage(vertex)]] fn main([[location(0)]] inPos: vec3<f32>, [[location(1)]] inColor: vec3<f32>) -> VSOut { var vsOut: VSOut; vsOut.Position = uniforms.modelViewProjectionMatrix * vec4<f32>(inPos, 1.0); vsOut.color = inColor; return vsOut; } `, fragment: ` [[stage(fragment)]] fn main([[location(0)]] inColor: vec3<f32>) -> [[location(0)]] vec4<f32> { return vec4<f32>(inColor, 1.0); } `, }; // TODO[Parminder]: Support SPIR-V shaders const vertexShaderGLSL = ` #version 450 layout(location = 0) in vec4 position; layout(location = 1) in vec4 color; layout(location = 0) out vec4 vColor; void main() { gl_Position = position; vColor = color; } `; const fragmentShaderGLSL = ` #version 450 layout(location = 0) in vec4 vColor; layout(location = 0) out vec4 outColor; void main() { outColor = vColor; } `; // Index Buffer Data const VERTEX_COUNT = 1000000; const ELEMENTS = 3; export class Particles extends SceneGraph { constructor(device, primitive, binding, primitiveType) { super(primitiveType, [TYPE_SIZE.float32x4, TYPE_SIZE.float32x4, TYPE_SIZE.float32x2]); this.initializeData = () => { for (let x = 0; x < VERTEX_COUNT; x++) { if (x < VERTEX_COUNT - 100000) { let aa = vec3.fromValues(1.0, 1.0, 1.0); this.position.set(aa, 3 * x); } else { let aa = vec3.fromValues(Math.random() * 2.0 - 1.0, Math.random() * 2.0 - 1.0, Math.random() * 2.0 - 1.0); this.position.set(aa, 3 * x); } let aa = vec3.fromValues(Math.random() * 2.0 - 1.0, Math.random() * 2.0 - 1.0, Math.random() * 2.0 - 1.0); this.position.set(aa, 3 * x); let bb = vec3.fromValues(Math.random(), Math.random(), Math.random()); this.color.set(bb, 3 * x); } }; this.update = () => { for (let x = 0; x < this.binding.vextexCount * ELEMENTS; x += ELEMENTS) { if ((this.position[x] > 1.0) || (this.position[x] < -1.0)) { this.speed[x] = -this.speed[x]; } if ((this.position[x + 1] > 1.0) || (this.position[x + 1] < -1.0)) { this.speed[x + 1] = -this.speed[x + 1]; } if ((this.position[x + 2] > 1.0) || (this.position[x + 2] < -1.0)) { this.speed[x + 2] = -this.speed[x + 2]; } this.position[x] += this.speed[x]; this.position[x + 1] += this.speed[x + 1]; this.position[x + 2] += this.speed[x + 2]; } }; this.device = device; this.primitive = primitive; this.binding = binding; this.allocate(); } async allocate() { this.position = new Float32Array(VERTEX_COUNT * ELEMENTS); this.positionBuffer = /*await*/ this.device.createBuffer({ size: VERTEX_COUNT * ELEMENTS * 4 /**/, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST, }); this.color = new Float32Array(VERTEX_COUNT * ELEMENTS); this.colorBuffer = /*await*/ this.device.createBuffer({ size: VERTEX_COUNT * ELEMENTS * 4 /**/, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST, }); this.speed = new Float32Array(VERTEX_COUNT * ELEMENTS); for (let x = 0; x < VERTEX_COUNT; x++) { let aa = vec3.fromValues(Math.random() / 100.0, Math.random() / 100.0, Math.random() / 100.0); this.speed.set(aa, 3 * x); } //let idxSize = (VERTEX_COUNT * 4 + 3) & ~3; let idxSize = VERTEX_COUNT * 4; this.indexBuffer = /*await*/ this.device.createBuffer({ size: idxSize, usage: GPUBufferUsage.INDEX | GPUBufferUsage.COPY_DST, }); // const indices = new Uint16Array(idxSize / 2); /* Divide because 2 Uint16Array */ const indices = new Uint32Array(VERTEX_COUNT); for (let x = 0; x < VERTEX_COUNT; x++) { indices[x] = x; } this.device.queue.writeBuffer(this.indexBuffer, 0, indices); this.initializeData(); this.device.queue.writeBuffer(this.colorBuffer, 0, this.color); // Shaders const vsmDesc = { // code: vertShaderCode code: particleShaders.vertex }; this.vertModule = this.device.createShaderModule(vsmDesc); const fsmDesc = { // code: fragShaderCode code: particleShaders.fragment }; this.fragModule = this.device.createShaderModule(fsmDesc); // Input Assembly const positionAttribDesc = { shaderLocation: 0, offset: 0, format: 'float32x3' }; const colorAttribDesc = { shaderLocation: 1, offset: 0, format: 'float32x3' }; const positionBufferDesc = { attributes: [positionAttribDesc], arrayStride: 4 * 3, stepMode: 'vertex' }; const colorBufferDesc = { attributes: [colorAttribDesc], arrayStride: 4 * 3, stepMode: 'vertex' }; // Depth const depthStencil = { depthWriteEnabled: true, depthCompare: 'less', format: 'depth24plus-stencil8' }; // Uniform Data const pipelineLayoutDesc = { bindGroupLayouts: [] }; const layout = this.device.createPipelineLayout(pipelineLayoutDesc); // Shader Stages const vertex = { module: this.vertModule, entryPoint: 'main', buffers: [positionBufferDesc, colorBufferDesc] }; // Color/Blend State const colorState = { format: 'bgra8unorm' }; const fragment = { module: this.fragModule, entryPoint: 'main', targets: [colorState] }; // Rasterization const primitive = { frontFace: 'cw', cullMode: 'none', topology: this.primitive ? 'line-list' : 'point-list' }; const pipelineDesc = { vertex, fragment, primitive, depthStencil }; this.pipeline = this.device.createRenderPipeline(pipelineDesc); // Uniform this.uniformBuffer = this.device.createBuffer({ size: this.uniformBufferSize, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST, }); this.uniformBindGroup = this.device.createBindGroup({ layout: this.pipeline.getBindGroupLayout(0), entries: [ { binding: 0, resource: { buffer: this.uniformBuffer, offset: 0, size: this.matrixSize, }, }, ], }); } draw(passEncoder, camera) { super.draw(passEncoder, camera); this.update(); // Updathis.camerathis.camerathis.camerathis.camerate the position first passEncoder.setPipeline(this.pipeline); this.device.queue.writeBuffer(this.uniformBuffer, 0, this.modelViewProjectionMatrix.buffer, this.modelViewProjectionMatrix.byteOffset, this.modelViewProjectionMatrix.byteLength); this.device.queue.writeBuffer(this.positionBuffer, 0, this.position, 0, this.binding.vextexCount * ELEMENTS); passEncoder.setVertexBuffer(0, this.positionBuffer); passEncoder.setVertexBuffer(1, this.colorBuffer); passEncoder.setIndexBuffer(this.indexBuffer, 'uint32'); passEncoder.setBindGroup(0, this.uniformBindGroup); passEncoder.drawIndexed(this.binding.vextexCount, 1); } }