forked from mirror/ObjToSchematic
Add instancing to voxel mesh rendering, #132
This commit is contained in:
parent
b8cc31d75a
commit
58cc638149
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
106
src/buffer.ts
106
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;
|
||||
|
@ -25,6 +25,49 @@ export class OcclusionManager {
|
||||
return new Array<number>(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
|
||||
|
@ -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() {
|
||||
|
@ -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]);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user