diff --git a/src/buffer.ts b/src/buffer.ts index 51a4c14..ee5ba01 100644 --- a/src/buffer.ts +++ b/src/buffer.ts @@ -1,19 +1,18 @@ +import { Renderer } from './renderer'; + import * as twgl from 'twgl.js'; +import { ASSERT } from './util'; interface Attribute { name: string, numComponents: number } -interface CompleteBuffer { - buffer: BottomlessBufferData, - numElements: number, -} - interface BottomlessBufferData { indices: BottomlessAttributeData, [name: string]: BottomlessAttributeData } + interface BottomlessAttributeData { numComponents: number, data: Array @@ -27,23 +26,18 @@ export interface VoxelData { } export class RenderBuffer { - public WebGLBuffers: Array<{ + private _WebGLBuffer?: { buffer: twgl.BufferInfo, numElements: number - }>; - - private _completeBuffers: Array; + }; private _buffer!: BottomlessBufferData; private _attributes: {[name: string]: Attribute}; private _maxIndex: number = 0; private _compiled: boolean = false; private _sanityCheck: boolean = false; - constructor(attributes: Array) { - this._completeBuffers = []; - + public constructor(attributes: Array) { this._compiled = false; - this.WebGLBuffers = []; this._attributes = {}; for (const attr of attributes) { @@ -58,63 +52,7 @@ export class RenderBuffer { this._getNewBuffer(); } - _getNewBuffer() { - this._buffer = { - indices: {numComponents: 1, data: []}, - }; - for (const attr in this._attributes) { - this._buffer[attr] = { - numComponents: this._attributes[attr].numComponents, - data: [], - }; - } - } - - _cycle() { - // console.log('Cycle'); - - this._completeBuffers.push({ - buffer: this._buffer, - numElements: this._buffer.indices.data.length, - }); - this._getNewBuffer(); - - this._maxIndex = 0; - } - - _willOverflow(data: VoxelData) { - // Check for indices Uint16 overflow - // const dataMaxIndex = Math.max(...data.indices); - const dataMaxIndex = data.indices.reduce((a, v) => Math.max(a, v)); - return ((this._maxIndex + dataMaxIndex) > 65535); - } - - _checkDataMatchesAttributes(data: VoxelData) { - if (!('indices' in data)) { - throw Error('Given data does not have indices data'); - } - const setsRequired = data.indices.reduce((a, v) => Math.max(a, v)) + 1; - for (const attr in this._attributes) { - if (!(attr in data)) { - throw Error(`Given data does not have ${attr} data`); - } - if (data.custom[attr].length % this._attributes[attr].numComponents != 0) { - throw Error(`Not enough/too much ${attr} data given`); - } - const numSets = data.custom[attr].length / this._attributes[attr].numComponents; - if (numSets != setsRequired) { - // throw `Number of indices does not match number of ${attr} components given`; - throw Error(`Expected ${setsRequired * this._attributes[attr].numComponents} values for ${attr}, got ${data.custom[attr].length}`); - } - } - } - - add(data: VoxelData) { - /* - if (this._willOverflow(data)) { - this._cycle(); - } - */ + public add(data: VoxelData) { if (this._sanityCheck) { this._checkDataMatchesAttributes(data); } @@ -134,33 +72,74 @@ export class RenderBuffer { } } - compile(gl: WebGLRenderingContext) { + public attachNewAttribute(data: VoxelData) { + + } + + public removeAttribute(attribute: string) { + + } + + public getWebGLBuffer() { + this._compile(); + ASSERT(this._WebGLBuffer !== undefined); + return this._WebGLBuffer; + } + + private _compile() { if (this._compiled) { return; } - this._cycle(); - - this.WebGLBuffers = new Array(this._completeBuffers.length); - - this._completeBuffers.forEach((buffer, i) => { - const newBuffer : { indices: { data: Uint32Array, numComponents: number }, [arr: string]: { data: (Float32Array | Uint32Array), numComponents: number }} = { - indices: { data: Uint32Array.from(buffer.buffer.indices.data), numComponents: buffer.buffer.indices.numComponents }, - }; - for (const key in buffer.buffer) { - if (key !== 'indices') { - newBuffer[key] = { - data: Float32Array.from(buffer.buffer[key].data), - numComponents: buffer.buffer[key].numComponents, - }; - } + const newBuffer: { indices: { data: Uint32Array, numComponents: number }, [arr: string]: { data: (Float32Array | Uint32Array), numComponents: number }} = { + indices: { data: Uint32Array.from(this._buffer.indices.data), numComponents: this._buffer.indices.numComponents }, + }; + for (const key in this._buffer) { + if (key !== 'indices') { + newBuffer[key] = { + data: Float32Array.from(this._buffer[key].data), + numComponents: this._buffer[key].numComponents, + }; } - this.WebGLBuffers[i] = { - buffer: twgl.createBufferInfoFromArrays(gl, newBuffer), - numElements: buffer.numElements, - }; - }); + } + + this._WebGLBuffer = { + buffer: twgl.createBufferInfoFromArrays(Renderer.Get._gl, newBuffer), + numElements: this._buffer.indices.data.length, + }; this._compiled = true; } + + private _getNewBuffer() { + this._buffer = { + indices: {numComponents: 1, data: []}, + }; + for (const attr in this._attributes) { + this._buffer[attr] = { + numComponents: this._attributes[attr].numComponents, + data: [], + }; + } + } + + private _checkDataMatchesAttributes(data: VoxelData) { + if (!('indices' in data)) { + throw Error('Given data does not have indices data'); + } + const setsRequired = data.indices.reduce((a, v) => Math.max(a, v)) + 1; + for (const attr in this._attributes) { + if (!(attr in data)) { + throw Error(`Given data does not have ${attr} data`); + } + if (data.custom[attr].length % this._attributes[attr].numComponents != 0) { + throw Error(`Not enough/too much ${attr} data given`); + } + const numSets = data.custom[attr].length / this._attributes[attr].numComponents; + if (numSets != setsRequired) { + // throw `Number of indices does not match number of ${attr} components given`; + throw Error(`Expected ${setsRequired * this._attributes[attr].numComponents} values for ${attr}, got ${data.custom[attr].length}`); + } + } + } } diff --git a/src/renderer.ts b/src/renderer.ts index fa055db..e1e6301 100644 --- a/src/renderer.ts +++ b/src/renderer.ts @@ -124,10 +124,6 @@ export class Renderer { } } - this._materialBuffers.forEach((materialBuffer) => { - materialBuffer.buffer.compile(Renderer.Get._gl); - }); - this._meshToUse = MeshType.TriangleMesh; } @@ -135,7 +131,6 @@ export class Renderer { LOG('Using voxel mesh'); LOG(voxelMesh); this._buffer = voxelMesh.createBuffer(ambientOcclusionEnabled); - this._buffer.compile(this._gl); this._meshToUse = MeshType.VoxelMesh; this._voxelSize = voxelMesh?.getVoxelSize(); } @@ -144,7 +139,6 @@ export class Renderer { LOG('Using block mesh'); LOG(blockMesh); this._buffer = blockMesh.createBuffer(ambientOcclusionEnabled); - this._buffer.compile(this._gl); this._meshToUse = MeshType.BlockMesh; this._voxelSize = blockMesh.getVoxelMesh().getVoxelSize(); } @@ -190,9 +184,7 @@ export class Renderer { // ///////////////////////////////////////////////////////////////////////// private _drawRegister(register: RenderBuffer, shaderProgram: twgl.ProgramInfo, uniforms: any) { - for (const buffer of register.WebGLBuffers) { - this._drawBuffer(this._gl.TRIANGLES, buffer, shaderProgram, uniforms); - } + this._drawBuffer(this._gl.TRIANGLES, register.getWebGLBuffer(), shaderProgram, uniforms); } private _setupOcclusions() {