UNPKG

@giraphics/grpkggfx

Version:
171 lines (168 loc) 7.68 kB
import SceneGraph from './../base/scenegraph'; import { TYPE_SIZE } from './../renderer/constants'; const geometryShaders = { 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: vec4<f32>; }; [[stage(vertex)]] fn main([[location(0)]] inPos: vec4<f32>, [[location(1)]] inColor: vec4<f32>) -> VSOut { var vsOut: VSOut; vsOut.Position = uniforms.modelViewProjectionMatrix * inPos; vsOut.color = inColor; return vsOut; } `, fragment: ` [[stage(fragment)]] fn main([[location(0)]] inColor: vec4<f32>) -> [[location(0)]] vec4<f32> { return inColor; } `, }; export class MultiGeometry extends SceneGraph { constructor(device, primitiveType, vertexUppperLimit) { // presently type info is 10 elements fixed vertex 4, color 4, uv 2 super(primitiveType, /*typeInfo*/ [TYPE_SIZE.float32x4, TYPE_SIZE.float32x4, TYPE_SIZE.float32x2]); this.vertexUppperLimit = 0xFFFFFFFF; // Possible upper limit: 26843545 this.indexUppperLimit = 0xFFFFFFFF; // Max of index, this.vertexInitLimit = 150000; // Possible upper limit: 26843545 this.indexInitLimit = 0xFFFFF; // Max of index, this.totalVertexCount = 0; this.totalIndexCount = 0; this.isDirty = false; this.isMemoryQuotaExausted = false; // Resources this.deviceVertexBufferSize = 0; this.deviceIndexBufferSize = 0; this.VERTEX_BYTES_PER_ELEMENT = 4; this.INDEX_BYTES_PER_ELEMENT = 4; this.resizeFactor = 0.25; this.scaleFactor = 2; this.device = device; if (vertexUppperLimit) { this.vertexInitLimit = vertexUppperLimit; } this.allocateVertexBuffersIfNeeded(this.vertexInitLimit); this.allocateIndexBuffersIfNeeded(this.indexInitLimit); this.initialize(); } allocateVertexBuffersIfNeeded(verterCount) { let requiredVertexSize = verterCount * this.elementCount * this.VERTEX_BYTES_PER_ELEMENT; if (this.deviceVertexBufferSize * this.resizeFactor <= requiredVertexSize) { console.log("Available Size: " + this.deviceVertexBufferSize + "Required Size: " + requiredVertexSize); if (this.deviceVertexBufferSize == 0) { this.deviceVertexBufferSize = verterCount * this.elementCount * this.VERTEX_BYTES_PER_ELEMENT; } // Scale buffer size by scaleFactor this.deviceVertexBufferSize *= this.scaleFactor; if (this.deviceVertexBuffer) this.deviceVertexBuffer.destroy(); this.deviceVertexBuffer = this.device.createBuffer({ size: this.deviceVertexBufferSize, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST, }); this.hostVertexBuffer = null; this.hostVertexBuffer = new Float32Array(this.deviceVertexBufferSize / this.VERTEX_BYTES_PER_ELEMENT); console.log("Allocating... " + this.deviceVertexBufferSize); } } allocateIndexBuffersIfNeeded(indexCount) { let requiredIndexSize = ((indexCount + 3) & ~3) * this.INDEX_BYTES_PER_ELEMENT; if (this.deviceIndexBufferSize * this.resizeFactor <= requiredIndexSize) { console.log("Available index buffer size: " + this.deviceIndexBufferSize + "Required Size: " + requiredIndexSize); if (this.deviceIndexBufferSize == 0) { this.deviceIndexBufferSize = ((indexCount + 3) & ~3) * this.INDEX_BYTES_PER_ELEMENT; // Aligned to 4 bytes } // Scale buffer size by scaleFactor this.deviceIndexBufferSize *= this.scaleFactor; if (this.indexBuffer) this.indexBuffer.destroy(); this.indexBuffer = this.device.createBuffer({ size: this.deviceIndexBufferSize, usage: GPUBufferUsage.INDEX | GPUBufferUsage.COPY_DST, }); this.hostIndexBuffer = null; this.hostIndexBuffer = new Uint32Array(this.deviceIndexBufferSize / this.INDEX_BYTES_PER_ELEMENT); // this an array of 2 bytes } } updateBuffers() { if (!this.isDirty) return; this.allocateVertexBuffersIfNeeded(this.totalVertexCount); this.allocateIndexBuffersIfNeeded(this.totalIndexCount); this.device.queue.writeBuffer(this.deviceVertexBuffer, 0, this.hostVertexBuffer, 0, this.totalVertexCount * this.hostVertexBuffer.BYTES_PER_ELEMENT * this.elementCount); this.device.queue.writeBuffer(this.indexBuffer, 0, this.hostIndexBuffer, 0, this.totalIndexCount * this.hostIndexBuffer.BYTES_PER_ELEMENT); } drawGeometry(geometryVertexArray, indexArray) { if (this.isMemoryQuotaExausted) { this.isDirty = false; console.log("Warning: Reached maxmium limit of drawing."); return; } this.hostVertexBuffer.set(geometryVertexArray, this.totalVertexCount * this.elementCount); this.hostIndexBuffer.set(indexArray.map(x => x + this.totalVertexCount), this.totalIndexCount); this.totalVertexCount += geometryVertexArray.length / this.elementCount; this.totalIndexCount += indexArray.length; if (this.isPrimtiveTypeStrip) { this.hostIndexBuffer[this.totalIndexCount] = 0xFFFFFFFF; this.totalIndexCount++; } this.isDirty = true; } resetIndex() { this.isMemoryQuotaExausted = (this.totalIndexCount >= this.indexUppperLimit) && (this.totalVertexCount >= this.vertexUppperLimit); if (!this.isMemoryQuotaExausted) { this.totalVertexCount = 0; this.totalIndexCount = 0; } } initialize() { super.initialize(); // super.createDefaultPipeline(vertShaderCode, fragShaderCode); super.createDefaultPipeline(geometryShaders.vertex, geometryShaders.fragment); 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); passEncoder.setPipeline(this.pipeline); this.device.queue.writeBuffer(this.uniformBuffer, 0, this.modelViewProjectionMatrix.buffer, this.modelViewProjectionMatrix.byteOffset, this.modelViewProjectionMatrix.byteLength); passEncoder.setVertexBuffer(0, this.deviceVertexBuffer); passEncoder.setBindGroup(0, this.uniformBindGroup); passEncoder.setIndexBuffer(this.indexBuffer, 'uint32'); passEncoder.drawIndexed(this.totalIndexCount, 1); //console.log(this.totalVertexCount); //console.log(this.totalIndexCount); if (this.isDirty) { this.resetIndex(); } } } export class StaticGeometry extends MultiGeometry { constructor(device, primitiveType, vertexUppperLimit) { super(device, primitiveType, vertexUppperLimit); } } export class DynamicGeometry extends MultiGeometry { constructor(device, primitiveType, vertexUppperLimit) { super(device, primitiveType, vertexUppperLimit); } }