@giraphics/grpkggfx
Version:
227 lines (224 loc) • 8.58 kB
JavaScript
// 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);
}
}