From 58cc63814980d4b4060f4e2fdf9e8d3279d66e76 Mon Sep 17 00:00:00 2001 From: Lucas Dower Date: Sat, 10 Jun 2023 16:05:41 +0100 Subject: [PATCH] Add instancing to voxel mesh rendering, #132 --- res/shaders/voxel_fragment.fs | 264 ++++++++++++++++++++++------------ res/shaders/voxel_vertex.vs | 22 ++- src/app_context.ts | 11 +- src/buffer.ts | 106 ++++++++------ src/occlusion.ts | 43 ++++++ src/renderer.ts | 67 +++++++-- src/shaders.ts | 8 +- src/voxel_mesh.ts | 9 +- 8 files changed, 378 insertions(+), 152 deletions(-) diff --git a/res/shaders/voxel_fragment.fs b/res/shaders/voxel_fragment.fs index a0e48fc..5a67453 100644 --- a/res/shaders/voxel_fragment.fs +++ b/res/shaders/voxel_fragment.fs @@ -2,107 +2,191 @@ precision mediump float; uniform bool u_ambientOcclusion; uniform float u_globalAlpha; +uniform float u_sampler_width; +uniform sampler2D u_occlusion_texture; varying float v_lighting; -varying vec4 v_occlusion; +//varying vec4 v_occlusion; varying vec2 v_texcoord; varying vec4 v_colour; +varying float v_occlusionOriginPixelIndex; +varying float v_occlusionOffsets; float dither8x8(vec2 position, float alpha) { - int x = int(mod(position.x, 8.0)); - int y = int(mod(position.y, 8.0)); - int index = x + y * 8; - float limit = 0.0; + int x = int(mod(position.x, 8.0)); + int y = int(mod(position.y, 8.0)); + int index = x + y * 8; + float limit = 0.0; - if (x < 8) { - if (index == 0) limit = 0.015625; - if (index == 1) limit = 0.515625; - if (index == 2) limit = 0.140625; - if (index == 3) limit = 0.640625; - if (index == 4) limit = 0.046875; - if (index == 5) limit = 0.546875; - if (index == 6) limit = 0.171875; - if (index == 7) limit = 0.671875; - if (index == 8) limit = 0.765625; - if (index == 9) limit = 0.265625; - if (index == 10) limit = 0.890625; - if (index == 11) limit = 0.390625; - if (index == 12) limit = 0.796875; - if (index == 13) limit = 0.296875; - if (index == 14) limit = 0.921875; - if (index == 15) limit = 0.421875; - if (index == 16) limit = 0.203125; - if (index == 17) limit = 0.703125; - if (index == 18) limit = 0.078125; - if (index == 19) limit = 0.578125; - if (index == 20) limit = 0.234375; - if (index == 21) limit = 0.734375; - if (index == 22) limit = 0.109375; - if (index == 23) limit = 0.609375; - if (index == 24) limit = 0.953125; - if (index == 25) limit = 0.453125; - if (index == 26) limit = 0.828125; - if (index == 27) limit = 0.328125; - if (index == 28) limit = 0.984375; - if (index == 29) limit = 0.484375; - if (index == 30) limit = 0.859375; - if (index == 31) limit = 0.359375; - if (index == 32) limit = 0.0625; - if (index == 33) limit = 0.5625; - if (index == 34) limit = 0.1875; - if (index == 35) limit = 0.6875; - if (index == 36) limit = 0.03125; - if (index == 37) limit = 0.53125; - if (index == 38) limit = 0.15625; - if (index == 39) limit = 0.65625; - if (index == 40) limit = 0.8125; - if (index == 41) limit = 0.3125; - if (index == 42) limit = 0.9375; - if (index == 43) limit = 0.4375; - if (index == 44) limit = 0.78125; - if (index == 45) limit = 0.28125; - if (index == 46) limit = 0.90625; - if (index == 47) limit = 0.40625; - if (index == 48) limit = 0.25; - if (index == 49) limit = 0.75; - if (index == 50) limit = 0.125; - if (index == 51) limit = 0.625; - if (index == 52) limit = 0.21875; - if (index == 53) limit = 0.71875; - if (index == 54) limit = 0.09375; - if (index == 55) limit = 0.59375; - if (index == 56) limit = 0.9999; - if (index == 57) limit = 0.5; - if (index == 58) limit = 0.875; - if (index == 59) limit = 0.375; - if (index == 60) limit = 0.96875; - if (index == 61) limit = 0.46875; - if (index == 62) limit = 0.84375; - if (index == 63) limit = 0.34375; - } + if(x < 8) { + if(index == 0) + limit = 0.015625; + if(index == 1) + limit = 0.515625; + if(index == 2) + limit = 0.140625; + if(index == 3) + limit = 0.640625; + if(index == 4) + limit = 0.046875; + if(index == 5) + limit = 0.546875; + if(index == 6) + limit = 0.171875; + if(index == 7) + limit = 0.671875; + if(index == 8) + limit = 0.765625; + if(index == 9) + limit = 0.265625; + if(index == 10) + limit = 0.890625; + if(index == 11) + limit = 0.390625; + if(index == 12) + limit = 0.796875; + if(index == 13) + limit = 0.296875; + if(index == 14) + limit = 0.921875; + if(index == 15) + limit = 0.421875; + if(index == 16) + limit = 0.203125; + if(index == 17) + limit = 0.703125; + if(index == 18) + limit = 0.078125; + if(index == 19) + limit = 0.578125; + if(index == 20) + limit = 0.234375; + if(index == 21) + limit = 0.734375; + if(index == 22) + limit = 0.109375; + if(index == 23) + limit = 0.609375; + if(index == 24) + limit = 0.953125; + if(index == 25) + limit = 0.453125; + if(index == 26) + limit = 0.828125; + if(index == 27) + limit = 0.328125; + if(index == 28) + limit = 0.984375; + if(index == 29) + limit = 0.484375; + if(index == 30) + limit = 0.859375; + if(index == 31) + limit = 0.359375; + if(index == 32) + limit = 0.0625; + if(index == 33) + limit = 0.5625; + if(index == 34) + limit = 0.1875; + if(index == 35) + limit = 0.6875; + if(index == 36) + limit = 0.03125; + if(index == 37) + limit = 0.53125; + if(index == 38) + limit = 0.15625; + if(index == 39) + limit = 0.65625; + if(index == 40) + limit = 0.8125; + if(index == 41) + limit = 0.3125; + if(index == 42) + limit = 0.9375; + if(index == 43) + limit = 0.4375; + if(index == 44) + limit = 0.78125; + if(index == 45) + limit = 0.28125; + if(index == 46) + limit = 0.90625; + if(index == 47) + limit = 0.40625; + if(index == 48) + limit = 0.25; + if(index == 49) + limit = 0.75; + if(index == 50) + limit = 0.125; + if(index == 51) + limit = 0.625; + if(index == 52) + limit = 0.21875; + if(index == 53) + limit = 0.71875; + if(index == 54) + limit = 0.09375; + if(index == 55) + limit = 0.59375; + if(index == 56) + limit = 0.9999; + if(index == 57) + limit = 0.5; + if(index == 58) + limit = 0.875; + if(index == 59) + limit = 0.375; + if(index == 60) + limit = 0.96875; + if(index == 61) + limit = 0.46875; + if(index == 62) + limit = 0.84375; + if(index == 63) + limit = 0.34375; + } - return alpha < limit ? 0.0 : 1.0; + return alpha < limit ? 0.0 : 1.0; } + void main() { - float u = v_texcoord.x; - float v = v_texcoord.y; - - float g = 1.0; - if (u_ambientOcclusion) - { - float a = v_occlusion.x; - float b = v_occlusion.y; - float c = v_occlusion.z; - float d = v_occlusion.w; - g = v*(u*b + (1.0-u)*d) + (1.0-v)*(u*a + (1.0-u)*c); - } + // v_occlusionOffsets: [0.0, 24.0] + // v_occlusionOriginPixelIndex: [0.0, w^2] (doesn't realy reach w^2) - float alpha = dither8x8(gl_FragCoord.xy, v_colour.a); - if (alpha < 0.5) - { - discard; - } + float ao = 1.0; + if (u_ambientOcclusion) + { + float start_index = (24.0 * v_occlusionOriginPixelIndex) + v_occlusionOffsets; + float sampler_row = floor(start_index / u_sampler_width); + float sampler_col = start_index - (sampler_row * u_sampler_width); - gl_FragColor = vec4(v_colour.rgb * (v_lighting * g), 1.0); + float sample_u = (sampler_col + 0.5) / u_sampler_width; + float sample_v = (sampler_row + 0.5) / u_sampler_width; + + vec4 sampler_value = texture2D(u_occlusion_texture, vec2(sample_u, sample_v)).rgba; + //gl_FragColor = vec4(sampler_value.rgb, 1.0); + + float a = sampler_value.x; + float b = sampler_value.y; + float c = sampler_value.z; + float d = sampler_value.w; + + float u = v_texcoord.x; + float v = v_texcoord.y; + + ao = v*(u*b + (1.0-u)*d) + (1.0-v)*(u*a + (1.0-u)*c); + //gl_FragColor = vec4(vec3(ao), 1.0); + } + + float alpha = dither8x8(gl_FragCoord.xy, v_colour.a); + if (alpha < 0.5) + { + discard; + } + + gl_FragColor = vec4(v_colour.rgb * (v_lighting * ao), 1.0); } diff --git a/res/shaders/voxel_vertex.vs b/res/shaders/voxel_vertex.vs index 3bc78b5..9f0241f 100644 --- a/res/shaders/voxel_vertex.vs +++ b/res/shaders/voxel_vertex.vs @@ -5,24 +5,38 @@ uniform float u_voxelSize; uniform vec3 u_gridOffset; uniform bool u_ambientOcclusion; +attribute vec3 position; +attribute vec3 normal; +attribute vec2 texcoord; +attribute float occlusionOffsets; + +attribute vec3 instancePosition; +attribute vec4 instanceColour; +attribute float instanceOcclusionOriginPixelIndex; +/* attribute vec3 position; attribute vec3 normal; attribute vec4 colour; attribute vec4 occlusion; attribute vec2 texcoord; +*/ varying float v_lighting; -varying vec4 v_occlusion; +//varying vec4 v_occlusion; varying vec2 v_texcoord; varying vec4 v_colour; +varying float v_occlusionOriginPixelIndex; +varying float v_occlusionOffsets; vec3 light = vec3(0.78, 0.98, 0.59); void main() { v_lighting = dot(light, abs(normal)); - v_occlusion = occlusion; + //v_occlusion = occlusion; v_texcoord = texcoord; - v_colour = colour; + v_colour = instanceColour; + v_occlusionOriginPixelIndex = instanceOcclusionOriginPixelIndex; + v_occlusionOffsets = occlusionOffsets; - gl_Position = u_worldViewProjection * vec4((position.xyz + u_gridOffset) * u_voxelSize, 1.0); + gl_Position = u_worldViewProjection * vec4((position.xyz + instancePosition.xyz + u_gridOffset) * u_voxelSize, 1.0); } diff --git a/src/app_context.ts b/src/app_context.ts index 2b7fdb4..1c413df 100644 --- a/src/app_context.ts +++ b/src/app_context.ts @@ -334,7 +334,16 @@ export class AppContext { this._lastAction = action; - const success = await this._executeAction(action); + let success = false; + try { + success = await this._executeAction(action); + } catch (err) { + console.error(err); + AppConsole.error(LOC('something_went_wrong')); + + UI.Get.enableTo(action); + return; + } if (success) { if (action === EAction.Import) { UI.Get.enableTo(EAction.Voxelise); diff --git a/src/buffer.ts b/src/buffer.ts index ef22ce4..61f08d3 100644 --- a/src/buffer.ts +++ b/src/buffer.ts @@ -12,6 +12,8 @@ import { Vector3 } from './vector'; import { VoxelMesh } from './voxel_mesh'; import { RenderNextVoxelMeshChunkParams } from './worker_types'; +import * as twgl from 'twgl.js'; + export type TMeshBuffer = { position: { numComponents: 3, data: Float32Array }, texcoord: { numComponents: 2, data: Float32Array }, @@ -35,9 +37,12 @@ export type TVoxelMeshBuffer = { indices: { numComponents: 3, data: Uint32Array }, }; +export type TTWGLBuffer = { [key: string]: twgl.primitives.TypedArray }; + export type TVoxelMeshBufferDescription = { - buffer: TVoxelMeshBuffer, - numElements: number, + occlusionTextureData?: Float32Array, + numInstances: number, + buffers: { [key: string]: twgl.primitives.TypedArray }, } export type TBlockMeshBuffer = { @@ -67,67 +72,84 @@ export class ChunkedBufferGenerator { ASSERT(voxelsStartIndex < numTotalVoxels, 'Invalid voxel start index'); const numBufferVoxels = voxelsEndIndex - voxelsStartIndex; - const newBuffer: TVoxelMeshBuffer = BufferGenerator.createVoxelMeshBuffer(numBufferVoxels); - - const cube: AttributeData = GeometryTemplates.getBoxBufferData(new Vector3(0, 0, 0)); const voxels = voxelMesh.getVoxels(); - // Build position buffer + const instancePositions = new Float32Array(numBufferVoxels * 3); for (let i = 0; i < numBufferVoxels; ++i) { const voxel = voxels[i + voxelsStartIndex]; - const voxelPositionArray = voxel.position.toArray(); - for (let j = 0; j < AppConstants.VoxelMeshBufferComponentOffsets.POSITION; ++j) { - newBuffer.position.data[i * AppConstants.VoxelMeshBufferComponentOffsets.POSITION + j] = cube.custom.position[j] + voxelPositionArray[j % 3]; - } + instancePositions[i * 3 + 0] = voxel.position.x; + instancePositions[i * 3 + 1] = voxel.position.y; + instancePositions[i * 3 + 2] = voxel.position.z; } - // Build colour buffer + const instanceColours = new Float32Array(numBufferVoxels * 4); for (let i = 0; i < numBufferVoxels; ++i) { const voxel = voxels[i + voxelsStartIndex]; - newBuffer.colour.data[i * 96 + 0] = voxel.colour.r; - newBuffer.colour.data[i * 96 + 1] = voxel.colour.g; - newBuffer.colour.data[i * 96 + 2] = voxel.colour.b; - newBuffer.colour.data[i * 96 + 3] = voxel.colour.a; - AppUtil.Array.repeatedFill(newBuffer.colour.data, i * 96, 4, 24); + instanceColours[i * 4 + 0] = voxel.colour.r; + instanceColours[i * 4 + 1] = voxel.colour.g; + instanceColours[i * 4 + 2] = voxel.colour.b; + instanceColours[i * 4 + 3] = voxel.colour.a; } - // Build normal buffer - { - newBuffer.normal.data.set(cube.custom.normal, 0); - AppUtil.Array.repeatedFill(newBuffer.normal.data, 0, 72, numBufferVoxels); - } + const arrays = twgl.primitives.createCubeVertices(1.0); - // Build texcoord buffer - { - newBuffer.texcoord.data.set(cube.custom.texcoord, 0); - AppUtil.Array.repeatedFill(newBuffer.texcoord.data, 0, 48, numBufferVoxels); - } - - - // Build indices buffer - for (let i = 0; i < numBufferVoxels; ++i) { - for (let j = 0; j < AppConstants.VoxelMeshBufferComponentOffsets.INDICES; ++j) { - newBuffer.indices.data[i * AppConstants.VoxelMeshBufferComponentOffsets.INDICES + j] = cube.indices[j] + (i * AppConstants.INDICES_PER_VOXEL); - } - } + Object.assign(arrays, { + instancePosition: { + numComponents: 3, + data: instancePositions, + divisor: 1, + }, + instanceColour: { + numComponents: 4, + data: instanceColours, + divisor: 1, + }, + }); // Build occlusion buffer + let occlusionTextureData: Float32Array | undefined; // RGBA square texture if (params.enableAmbientOcclusion) { - const voxelOcclusionArray = new Float32Array(96); + const instanceOcclusionOriginPixelIndices = new Float32Array(numBufferVoxels); + const occlusionTextureWidth = Math.ceil(Math.sqrt((numBufferVoxels * 24))); + occlusionTextureData = new Float32Array(occlusionTextureWidth * occlusionTextureWidth * 4); // RGBA square texture - for (let i = 0; i < numBufferVoxels; ++i) { - const voxel = voxels[i + voxelsStartIndex]; - OcclusionManager.Get.getOcclusions(voxelOcclusionArray, voxel.position, voxelMesh); + if (params.enableAmbientOcclusion) { + const voxelOcclusionArray = new Float32Array(24 * 4); - newBuffer.occlusion.data.set(voxelOcclusionArray, i * AppConstants.VoxelMeshBufferComponentOffsets.OCCLUSION); + for (let i = 0; i < numBufferVoxels; ++i) { + const voxel = voxels[i + voxelsStartIndex]; + OcclusionManager.Get.getOcclusions(voxelOcclusionArray, voxel.position, voxelMesh); + occlusionTextureData.set(voxelOcclusionArray, i * 24 * 4); + + instanceOcclusionOriginPixelIndices[i] = i; + } } + + const occlusionOffsets = new Float32Array(72); + for (let i = 0; i < 24; ++i) { + for (let j = 0; j < 3; ++j) { + occlusionOffsets[i * 3 + 0] = i; + occlusionOffsets[i * 3 + 0] = i; + occlusionOffsets[i * 3 + 0] = i; + } + } + + Object.assign(arrays, { + instanceOcclusionOriginPixelIndex: { + numComponents: 1, + data: instanceOcclusionOriginPixelIndices, + divisor: 1, + }, + occlusionOffsets: occlusionOffsets, + }); } return { - buffer: newBuffer, - numElements: newBuffer.indices.data.length, + occlusionTextureData: occlusionTextureData, + numInstances: numBufferVoxels, + buffers: arrays, moreVoxelsToBuffer: voxelsEndIndex !== numTotalVoxels, progress: voxelsStartIndex / numTotalVoxels, }; @@ -162,7 +184,7 @@ export class ChunkedBufferGenerator { const numBufferBlocks = blocksEndIndex - blocksStartIndex; const voxelChunkBuffer = blockMesh.getVoxelMesh().getChunkedBuffer(chunkIndex); - const newBuffer = BufferGenerator.createBlockMeshBuffer(numBufferBlocks, voxelChunkBuffer.buffer); + const newBuffer = BufferGenerator.createBlockMeshBuffer(numBufferBlocks, voxelChunkBuffer.buffers as any); // TODO: Broken ASF const faceOrder = ['north', 'south', 'up', 'down', 'east', 'west']; let insertIndex = 0; diff --git a/src/occlusion.ts b/src/occlusion.ts index f884b4c..71d085a 100644 --- a/src/occlusion.ts +++ b/src/occlusion.ts @@ -25,6 +25,49 @@ export class OcclusionManager { return new Array(96).fill(1.0); } + // Assume's buffer is of length 24 + public getOcclusionsUnpacked(buffer: Float32Array, centre: Vector3, voxelMesh: VoxelMesh) { + // Cache local neighbours + const neighbourData = voxelMesh.getNeighbours(centre); + if (neighbourData === undefined) { + // This voxel has no neighbours within a 1-block radius + buffer.fill(0.0); + return; + } + + for (let i = 0; i < 27; ++i) { + this._localNeighbourhoodCache[i] = (neighbourData & (1 << i)) > 0 ? 1 : 0; + } + + // For each face + for (let f = 0; f < 6; ++f) { + for (let v = 0; v < 4; ++v) { + let numNeighbours = 0; + let occlusionValue = 1.0; + for (let i = 0; i < 2; ++i) { + const neighbourIndex = this._occlusionNeighboursIndices[this._getOcclusionMapIndex(f, v, i)]; + numNeighbours += this._localNeighbourhoodCache[neighbourIndex]; + } + // If both edge blocks along this vertex exist, + // assume corner exists (even if it doesnt) + // (This is a stylistic choice) + if (numNeighbours == 2 && AppConfig.Get.AMBIENT_OCCLUSION_OVERRIDE_CORNER) { + ++numNeighbours; + } else { + const neighbourIndex = this._occlusionNeighboursIndices[this._getOcclusionMapIndex(f, v, 2)]; + numNeighbours += this._localNeighbourhoodCache[neighbourIndex]; + } + + // Convert from occlusion denoting the occlusion factor to the + // attenuation in light value: 0 -> 1.0, 1 -> 0.8, 2 -> 0.6, 3 -> 0.4 + occlusionValue = 1.0 - 0.2 * numNeighbours; + const ind = f * 4 + v; + console.log(ind, occlusionValue); + buffer[f * 4 + v] = occlusionValue; + } + } + } + // Assume's buffer is of length 96 public getOcclusions(buffer: Float32Array, centre: Vector3, voxelMesh: VoxelMesh): void { // Cache local neighbours diff --git a/src/renderer.ts b/src/renderer.ts index e58d33a..218d603 100644 --- a/src/renderer.ts +++ b/src/renderer.ts @@ -74,6 +74,8 @@ export class Renderer { numElements: number, materialName: string, }>; + public _newVertexArrayBuffer: { vertexArrayInfo: twgl.VertexArrayInfo, numInstances: number, program: twgl.ProgramInfo, occlusionTex: WebGLTexture | undefined, textureWidth: number }[] = []; + public _voxelBuffer?: twgl.BufferInfo[]; private _blockBuffer?: twgl.BufferInfo[]; private _blockBounds: Bounds; @@ -349,11 +351,29 @@ export class Renderer { public useVoxelMeshChunk(params: RenderNextVoxelMeshChunkParams.Output) { if (params.isFirstChunk) { this._voxelBuffer = []; + this._newVertexArrayBuffer = []; } this._allVoxelChunks = !params.moreVoxelsToBuffer; - this._voxelBuffer?.push(twgl.createBufferInfoFromArrays(this._gl, params.buffer.buffer)); + let occlusionTexture: WebGLTexture | undefined; + let textureWidth = 1; + if (params.buffer.occlusionTextureData !== undefined) { + textureWidth = Math.sqrt(params.buffer.occlusionTextureData.length / 4); // should be int + occlusionTexture = twgl.createTexture(this._gl, { + mag: this._gl.NEAREST, + min: this._gl.NEAREST, + src: params.buffer.occlusionTextureData, + width: textureWidth, + height: textureWidth, + }); + } + + const program = ShaderManager.Get.createNewVoxelProgram(); + const bufferInfo = twgl.createBufferInfoFromArrays(this._gl, params.buffer.buffers) + const vertexArrayInfo = twgl.createVertexArrayInfo(this._gl, program, bufferInfo); + this._newVertexArrayBuffer.push({ vertexArrayInfo: vertexArrayInfo, numInstances: params.buffer.numInstances, program: program, occlusionTex: occlusionTexture, textureWidth: textureWidth }); + this._voxelSize = params.voxelSize; if (params.isFirstChunk) { @@ -478,7 +498,7 @@ export class Renderer { if (gridBuffer !== undefined) { this._drawBuffer(this._gl.LINES, gridBuffer.getWebGLBuffer(), ShaderManager.Get.debugProgram, { u_worldViewProjection: ArcballCamera.Get.getWorldViewProjection(), - u_worldOffset: [0, this._sliceViewEnabled ? this._sliceHeight * this._voxelSize: 0, 0], + u_worldOffset: [0, this._sliceViewEnabled ? this._sliceHeight * this._voxelSize : 0, 0], }); } } @@ -498,7 +518,7 @@ export class Renderer { this._materialBuffers.forEach((materialBuffer, materialName) => { if (materialBuffer.material.type === MaterialType.textured) { this._drawMeshBuffer(materialBuffer.buffer, materialBuffer.numElements, ShaderManager.Get.textureTriProgram, { - u_lightWorldPos: ArcballCamera.Get.getCameraPosition(-Math.PI/4, 0.0).toArray(), + u_lightWorldPos: ArcballCamera.Get.getCameraPosition(-Math.PI / 4, 0.0).toArray(), u_worldViewProjection: ArcballCamera.Get.getWorldViewProjection(), u_worldInverseTranspose: ArcballCamera.Get.getWorldInverseTranspose(), u_texture: materialBuffer.material.diffuseTexture, @@ -511,7 +531,7 @@ export class Renderer { }); } else { this._drawMeshBuffer(materialBuffer.buffer, materialBuffer.numElements, ShaderManager.Get.solidTriProgram, { - u_lightWorldPos: ArcballCamera.Get.getCameraPosition(-Math.PI/4, 0.0).toArray(), + u_lightWorldPos: ArcballCamera.Get.getCameraPosition(-Math.PI / 4, 0.0).toArray(), u_worldViewProjection: ArcballCamera.Get.getWorldViewProjection(), u_worldInverseTranspose: ArcballCamera.Get.getWorldInverseTranspose(), u_fillColour: materialBuffer.material.colourArray, @@ -524,19 +544,41 @@ export class Renderer { } private _drawVoxelMesh() { - const shader = ShaderManager.Get.voxelProgram; - const uniforms = { - u_worldViewProjection: ArcballCamera.Get.getWorldViewProjection(), - u_voxelSize: this._voxelSize, - u_gridOffset: this._gridOffset.toArray(), - u_ambientOcclusion: this._allVoxelChunks, - }; + //const shader = ShaderManager.Get.voxelProgram; + + /* this._voxelBuffer?.forEach((buffer) => { this._gl.useProgram(shader.program); twgl.setBuffersAndAttributes(this._gl, shader, buffer); twgl.setUniforms(shader, uniforms); this._gl.drawElements(this._gl.TRIANGLES, buffer.numElements, this._gl.UNSIGNED_INT, 0); }); + */ + + this._newVertexArrayBuffer.forEach(({ vertexArrayInfo, numInstances, program, occlusionTex, textureWidth }) => { + const uniforms = { + u_worldViewProjection: ArcballCamera.Get.getWorldViewProjection(), + u_voxelSize: this._voxelSize, + u_gridOffset: this._gridOffset.toArray(), + u_ambientOcclusion: occlusionTex !== undefined, + u_occlusion_texture: occlusionTex, + u_sampler_width: textureWidth, + }; + + this._gl.useProgram(program.program); + twgl.setBuffersAndAttributes(this._gl, program, vertexArrayInfo); + twgl.setUniforms(program, uniforms); + + //twgl.drawBufferInfo(this._gl, vertexArrayInfo, this._gl.TRIANGLES, vertexArrayInfo.numElements, 0, numInstances); + twgl.drawObjectList(this._gl, [ + { + programInfo: program, + vertexArrayInfo: vertexArrayInfo, + uniforms: uniforms, + instanceCount: numInstances, + }, + ]); + }); } private _drawBlockMesh() { @@ -589,7 +631,8 @@ export class Renderer { this._gl.useProgram(shader.program); twgl.setBuffersAndAttributes(this._gl, shader, buffer.buffer); twgl.setUniforms(shader, uniforms); - this._gl.drawElements(drawMode, buffer.numElements, this._gl.UNSIGNED_INT, 0); + twgl.drawBufferInfo(this._gl, buffer.buffer, drawMode); + //this._gl.drawElements(drawMode, buffer.numElements, this._gl.UNSIGNED_INT, 0); } public getModelsAvailable() { diff --git a/src/shaders.ts b/src/shaders.ts index c43efc9..d8a08a7 100644 --- a/src/shaders.ts +++ b/src/shaders.ts @@ -15,7 +15,7 @@ import { Renderer } from './renderer'; export class ShaderManager { public readonly textureTriProgram: twgl.ProgramInfo; public readonly solidTriProgram: twgl.ProgramInfo; - public readonly voxelProgram: twgl.ProgramInfo; + //public readonly voxelProgram: twgl.ProgramInfo; public readonly blockProgram: twgl.ProgramInfo; public readonly debugProgram: twgl.ProgramInfo; @@ -31,10 +31,14 @@ export class ShaderManager { this.solidTriProgram = twgl.createProgramInfo(gl, [VERT_TRI_SOLID, FRAG_TRI_SOLID]); - this.voxelProgram = twgl.createProgramInfo(gl, [VERT_VOXEL, FRAG_VOXEL]); + //this.voxelProgram = twgl.createProgramInfo(gl, [VERT_VOXEL, FRAG_VOXEL]); this.blockProgram = twgl.createProgramInfo(gl, [VERT_BLOCK, FRAG_BLOCK]); this.debugProgram = twgl.createProgramInfo(gl, [VERT_DEBUG, FRAG_DEBUG]); } + + public createNewVoxelProgram() { + return twgl.createProgramInfo(Renderer.Get._gl, [VERT_VOXEL, FRAG_VOXEL]); + } } diff --git a/src/voxel_mesh.ts b/src/voxel_mesh.ts index 2c1308d..3e85560 100644 --- a/src/voxel_mesh.ts +++ b/src/voxel_mesh.ts @@ -1,7 +1,7 @@ import { EFaceVisibility } from './block_assigner'; import { Bounds } from './bounds'; import { ChunkedBufferGenerator, TVoxelMeshBufferDescription } from './buffer'; -import { RGBA } from './colour'; +import { RGBA, RGBAColours } from './colour'; import { OcclusionManager } from './occlusion'; import { TOptional } from './util'; import { ASSERT } from './util/error_util'; @@ -80,6 +80,13 @@ export class VoxelMesh { } public addVoxel(inPos: Vector3, colour: RGBA) { + /* + if (this._voxels.size === 0) { + this._voxels.set(new Vector3(0, 0, 0).hash(), { position: new Vector3(0, 0, 0), colour: RGBAColours.WHITE, collisions: 1, neighbours: 0 }); + this._voxels.set(new Vector3(1, 1, 0).hash(), { position: new Vector3(1, 1, 0), colour: RGBAColours.WHITE, collisions: 1, neighbours: 0 }); + } + */ + if (colour.a === 0) { return; }