mirror of
https://github.com/LucasDower/ObjToSchematic.git
synced 2024-12-15 02:59:55 +08:00
Initial lighting commit, very unoptimised
This commit is contained in:
parent
1a0615260c
commit
f5932e61b1
@ -1,7 +1,7 @@
|
||||
{
|
||||
"AMBIENT_OCCLUSION_OVERRIDE_CORNER": true,
|
||||
"LOG_TO_FILE": true,
|
||||
"USE_WORKER_THREAD": true,
|
||||
"USE_WORKER_THREAD": false,
|
||||
"MULTISAMPLE_COUNT": 16,
|
||||
"OLD_SPACE_SIZE_MB": 8192,
|
||||
"ALPHA_BIAS": 1.0,
|
||||
|
@ -2,11 +2,13 @@ precision mediump float;
|
||||
|
||||
uniform sampler2D u_texture;
|
||||
uniform float u_atlasSize;
|
||||
uniform bool u_nightVision;
|
||||
|
||||
varying float v_lighting;
|
||||
varying vec4 v_occlusion;
|
||||
varying vec2 v_texcoord;
|
||||
varying vec2 v_blockTexcoord;
|
||||
varying float v_blockLighting;
|
||||
|
||||
float dither8x8(vec2 position, float alpha) {
|
||||
int x = int(mod(position.x, 8.0));
|
||||
@ -103,5 +105,5 @@ void main() {
|
||||
discard;
|
||||
}
|
||||
|
||||
gl_FragColor = vec4(diffuse.rgb * v_lighting * g, 1.0);
|
||||
gl_FragColor = vec4(diffuse.rgb * v_lighting * g * (u_nightVision ? 1.0 : v_blockLighting), 1.0);
|
||||
}
|
||||
|
@ -4,17 +4,20 @@ uniform mat4 u_worldViewProjection;
|
||||
uniform sampler2D u_texture;
|
||||
uniform float u_voxelSize;
|
||||
uniform vec3 u_gridOffset;
|
||||
uniform bool u_nightVision;
|
||||
|
||||
attribute vec3 position;
|
||||
attribute vec3 normal;
|
||||
attribute vec4 occlusion;
|
||||
attribute vec2 texcoord;
|
||||
attribute vec2 blockTexcoord;
|
||||
attribute float lighting;
|
||||
|
||||
varying float v_lighting;
|
||||
varying vec4 v_occlusion;
|
||||
varying vec2 v_texcoord;
|
||||
varying vec2 v_blockTexcoord;
|
||||
varying float v_blockLighting;
|
||||
|
||||
vec3 light = vec3(0.78, 0.98, 0.59);
|
||||
|
||||
@ -23,6 +26,7 @@ void main() {
|
||||
v_occlusion = occlusion;
|
||||
v_blockTexcoord = blockTexcoord;
|
||||
v_lighting = dot(light, abs(normal));
|
||||
v_blockLighting = lighting;
|
||||
|
||||
gl_Position = u_worldViewProjection * vec4((position.xyz + u_gridOffset) * u_voxelSize, 1.0);
|
||||
}
|
||||
|
5
res/static/bulb.svg
Normal file
5
res/static/bulb.svg
Normal file
@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-sun" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#00abfb" fill="none" stroke-linecap="round" stroke-linejoin="round" id="bulb-svg">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
|
||||
<circle cx="12" cy="12" r="4" />
|
||||
<path d="M3 12h1m8 -9v1m8 8h1m-9 8v1m-6.4 -15.4l.7 .7m12.1 -.7l-.7 .7m0 11.4l.7 .7m-12.1 -.7l-.7 .7" />
|
||||
</svg>
|
After Width: | Height: | Size: 435 B |
@ -37,10 +37,12 @@ export class BlockMesh {
|
||||
private _voxelMesh: VoxelMesh;
|
||||
private _fallableBlocks: string[];
|
||||
private _atlas: Atlas;
|
||||
private _lighting: Map<string, number>;
|
||||
|
||||
public static createFromVoxelMesh(voxelMesh: VoxelMesh, blockMeshParams: AssignParams.Input) {
|
||||
const blockMesh = new BlockMesh(voxelMesh);
|
||||
blockMesh._assignBlocks(blockMeshParams);
|
||||
blockMesh._calculateLighting();
|
||||
return blockMesh;
|
||||
}
|
||||
|
||||
@ -49,6 +51,7 @@ export class BlockMesh {
|
||||
this._blocks = [];
|
||||
this._voxelMesh = voxelMesh;
|
||||
this._atlas = Atlas.getVanillaAtlas()!;
|
||||
this._lighting = new Map<string, number>();
|
||||
//this._recreateBuffer = true;
|
||||
|
||||
const fallableBlocksString = fs.readFileSync(PathUtil.join(AppPaths.Get.resources, 'fallable_blocks.json'), 'utf-8');
|
||||
@ -76,7 +79,7 @@ export class BlockMesh {
|
||||
ProgressManager.Get.progress(taskHandle, voxelIndex / voxels.length);
|
||||
|
||||
const voxel = voxels[voxelIndex];
|
||||
|
||||
|
||||
let block = blockAssigner.assignBlock(
|
||||
atlasPalette,
|
||||
voxel.colour,
|
||||
@ -123,6 +126,83 @@ export class BlockMesh {
|
||||
}
|
||||
}
|
||||
|
||||
// Face order: ['north', 'south', 'up', 'down', 'east', 'west']
|
||||
public getBlockLighting(position: Vector3) {
|
||||
/*
|
||||
return {
|
||||
up: this._lighting.get(new Vector3(0, 1, 0).add(position).stringify()) ?? 15,
|
||||
north: this._lighting.get(new Vector3(1, 0, 0).add(position).stringify()) ?? 15,
|
||||
east: this._lighting.get(new Vector3(0, 0, 1).add(position).stringify()) ?? 15,
|
||||
south: this._lighting.get(new Vector3(-1, 0, 0).add(position).stringify()) ?? 15,
|
||||
west: this._lighting.get(new Vector3(0, 0, -1).add(position).stringify()) ?? 15,
|
||||
down: this._lighting.get(new Vector3(0, -1, 0).add(position).stringify()) ?? 15,
|
||||
};
|
||||
*/
|
||||
return [
|
||||
this._lighting.get(new Vector3(1, 0, 0).add(position).stringify()) ?? 15,
|
||||
this._lighting.get(new Vector3(-1, 0, 0).add(position).stringify()) ?? 15,
|
||||
this._lighting.get(new Vector3(0, 1, 0).add(position).stringify()) ?? 15,
|
||||
this._lighting.get(new Vector3(0, -1, 0).add(position).stringify()) ?? 15,
|
||||
this._lighting.get(new Vector3(0, 0, 1).add(position).stringify()) ?? 15,
|
||||
this._lighting.get(new Vector3(0, 0, -1).add(position).stringify()) ?? 15,
|
||||
];
|
||||
}
|
||||
|
||||
private _calculateLighting() {
|
||||
this._lighting.clear();
|
||||
const blocksBounds = this._voxelMesh.getBounds();
|
||||
|
||||
// Todo replace with Buffer as each value should only 4-bits instead of 64-bits.
|
||||
const tmp = new Vector3(0, 0, 0);
|
||||
for (let x = blocksBounds.min.x - 1; x <= blocksBounds.max.x + 1; ++x) {
|
||||
tmp.x = x;
|
||||
for (let y = blocksBounds.min.y - 1; y <= blocksBounds.max.y + 1; ++y) {
|
||||
tmp.y = y;
|
||||
for (let z = blocksBounds.min.z - 1; z <= blocksBounds.max.z + 1; ++z) {
|
||||
tmp.z = z;
|
||||
this._lighting.set(tmp.stringify(), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Cache stringify
|
||||
const actions: { pos: Vector3, value: number }[] = []; // = [{ pos: blocksBounds.min, value: 15 }];
|
||||
|
||||
// Add initial light emitters to top of mesh to simulate sunlight
|
||||
for (let x = blocksBounds.min.x - 1; x <= blocksBounds.max.x + 1; ++x) {
|
||||
for (let z = blocksBounds.min.z - 1; z <= blocksBounds.max.z + 1; ++z) {
|
||||
actions.push({
|
||||
pos: new Vector3(x, blocksBounds.max.y + 1, z),
|
||||
value: 15,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
while (actions.length > 0) {
|
||||
const action = actions.pop();
|
||||
ASSERT(action !== undefined);
|
||||
const newLightValue = action.value;
|
||||
|
||||
const currentLightValue = this._lighting.get(action.pos.stringify());
|
||||
// We're trying to update the lighting value of an out-of-bounds block, skip.
|
||||
if (currentLightValue === undefined) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Update lighting values only if the new value is lighter than the current brightness.
|
||||
if (newLightValue > currentLightValue && !this._voxelMesh.isVoxelAt(action.pos)) {
|
||||
this._lighting.set(action.pos.stringify(), newLightValue);
|
||||
|
||||
actions.push({ pos: new Vector3(0, 1, 0).add(action.pos), value: newLightValue - 1 }); // up
|
||||
actions.push({ pos: new Vector3(1, 0, 0).add(action.pos), value: newLightValue - 1 });
|
||||
actions.push({ pos: new Vector3(0, 0, 1).add(action.pos), value: newLightValue - 1 });
|
||||
actions.push({ pos: new Vector3(-1, 0, 0).add(action.pos), value: newLightValue - 1 });
|
||||
actions.push({ pos: new Vector3(0, 0, -1).add(action.pos), value: newLightValue - 1 });
|
||||
actions.push({ pos: new Vector3(0, -1, 0).add(action.pos), value: newLightValue === 15 ? 15 : newLightValue - 1 }); // down
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public getBlocks(): Block[] {
|
||||
return this._blocks;
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ export type TBlockMeshBuffer = {
|
||||
texcoord: { numComponents: 2, data: Float32Array },
|
||||
normal: { numComponents: 3, data: Float32Array },
|
||||
blockTexcoord: { numComponents: 2, data: Float32Array },
|
||||
lighting: { numComponents: 1, data: Float32Array },
|
||||
indices: { numComponents: 3, data: Uint32Array },
|
||||
};
|
||||
|
||||
@ -70,7 +71,7 @@ export class ChunkedBufferGenerator {
|
||||
|
||||
for (let i = 0; i < numBufferVoxels; ++i) {
|
||||
const voxelIndex = i + voxelsStartIndex;
|
||||
|
||||
|
||||
const voxel = voxels[voxelIndex];
|
||||
const voxelColourArray = [voxel.colour.r, voxel.colour.g, voxel.colour.b, voxel.colour.a];
|
||||
const voxelPositionArray = voxel.position.toArray();
|
||||
@ -114,6 +115,24 @@ export class ChunkedBufferGenerator {
|
||||
public static fromBlockMesh(blockMesh: BlockMesh, chunkIndex: number): TBlockMeshBufferDescription & { moreBlocksToBuffer: boolean, progress: number } {
|
||||
const blocks = blockMesh.getBlocks();
|
||||
|
||||
const lightingRamp = new Map<number, number>();
|
||||
lightingRamp.set(15, 40 / 40);
|
||||
lightingRamp.set(14, 40 / 40);
|
||||
lightingRamp.set(13, 39 / 40);
|
||||
lightingRamp.set(12, 37 / 40);
|
||||
lightingRamp.set(11, 35 / 40);
|
||||
lightingRamp.set(10, 32 / 40);
|
||||
lightingRamp.set(9, 29 / 40);
|
||||
lightingRamp.set(8, 26 / 40);
|
||||
lightingRamp.set(7, 23 / 40);
|
||||
lightingRamp.set(6, 20 / 40);
|
||||
lightingRamp.set(5, 17 / 40);
|
||||
lightingRamp.set(4, 14 / 40);
|
||||
lightingRamp.set(3, 12 / 40);
|
||||
lightingRamp.set(2, 9 / 40);
|
||||
lightingRamp.set(1, 7 / 40);
|
||||
lightingRamp.set(0, 5 / 40);
|
||||
|
||||
const numTotalBlocks = blocks.length;
|
||||
const blocksStartIndex = chunkIndex * AppConfig.Get.VOXEL_BUFFER_CHUNK_SIZE;
|
||||
const blocksEndIndex = Math.min((chunkIndex + 1) * AppConfig.Get.VOXEL_BUFFER_CHUNK_SIZE, numTotalBlocks);
|
||||
@ -126,16 +145,22 @@ export class ChunkedBufferGenerator {
|
||||
|
||||
const faceOrder = ['north', 'south', 'up', 'down', 'east', 'west'];
|
||||
let insertIndex = 0;
|
||||
let lightingInsertIndex = 0;
|
||||
|
||||
for (let i = 0; i < numBufferBlocks; ++i) {
|
||||
const blockIndex = i + blocksStartIndex;
|
||||
const blockLighting = blockMesh.getBlockLighting(blocks[blockIndex].voxel.position);
|
||||
|
||||
for (let f = 0; f < AppConstants.FACES_PER_VOXEL; ++f) {
|
||||
const faceName = faceOrder[f];
|
||||
const faceLighting = lightingRamp.get(blockLighting[f]) ?? 1.0;
|
||||
|
||||
const texcoord = blocks[blockIndex].blockInfo.faces[faceName].texcoord;
|
||||
for (let v = 0; v < AppConstants.VERTICES_PER_FACE; ++v) {
|
||||
newBuffer.blockTexcoord.data[insertIndex++] = texcoord.u;
|
||||
newBuffer.blockTexcoord.data[insertIndex++] = texcoord.v;
|
||||
|
||||
newBuffer.lighting.data[lightingInsertIndex++] = faceLighting;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -394,6 +419,10 @@ export class BufferGenerator {
|
||||
numComponents: AppConstants.ComponentSize.TEXCOORD,
|
||||
data: new Float32Array(numBlocks * AppConstants.VoxelMeshBufferComponentOffsets.TEXCOORD),
|
||||
},
|
||||
lighting: {
|
||||
numComponents: AppConstants.ComponentSize.LIGHTING,
|
||||
data: new Float32Array(numBlocks * AppConstants.VoxelMeshBufferComponentOffsets.LIGHTING),
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ export namespace AppConstants {
|
||||
export const COMPONENT_PER_SIZE_OFFSET = FACES_PER_VOXEL * VERTICES_PER_FACE;
|
||||
|
||||
export namespace ComponentSize {
|
||||
export const LIGHTING = 1;
|
||||
export const TEXCOORD = 2;
|
||||
export const POSITION = 3;
|
||||
export const COLOUR = 4;
|
||||
@ -12,8 +13,9 @@ export namespace AppConstants {
|
||||
export const INDICES = 3;
|
||||
export const OCCLUSION = 4;
|
||||
}
|
||||
|
||||
|
||||
export namespace VoxelMeshBufferComponentOffsets {
|
||||
export const LIGHTING = ComponentSize.LIGHTING * COMPONENT_PER_SIZE_OFFSET;
|
||||
export const TEXCOORD = ComponentSize.TEXCOORD * COMPONENT_PER_SIZE_OFFSET;
|
||||
export const POSITION = ComponentSize.POSITION * COMPONENT_PER_SIZE_OFFSET;
|
||||
export const COLOUR = ComponentSize.COLOUR * COMPONENT_PER_SIZE_OFFSET;
|
||||
|
@ -57,6 +57,7 @@ export class Renderer {
|
||||
|
||||
private _isGridComponentEnabled: { [bufferComponent: string]: boolean };
|
||||
private _axesEnabled: boolean;
|
||||
private _nightVisionEnabled: boolean;
|
||||
|
||||
private _gridBuffers: {
|
||||
x: { [meshType: string]: RenderBuffer };
|
||||
@ -90,6 +91,7 @@ export class Renderer {
|
||||
|
||||
this._isGridComponentEnabled = {};
|
||||
this._axesEnabled = false;
|
||||
this._nightVisionEnabled = true;
|
||||
|
||||
this._axisBuffer = new RenderBuffer([
|
||||
{ name: 'position', numComponents: 3 },
|
||||
@ -140,6 +142,14 @@ export class Renderer {
|
||||
this._axesEnabled = !this._axesEnabled;
|
||||
}
|
||||
|
||||
public toggleIsNightVisionEnabled() {
|
||||
this._nightVisionEnabled = !this._nightVisionEnabled;
|
||||
}
|
||||
|
||||
public isNightVisionEnabled() {
|
||||
return this._nightVisionEnabled;
|
||||
}
|
||||
|
||||
public toggleIsWireframeEnabled() {
|
||||
const isEnabled = !this._isGridComponentEnabled[EDebugBufferComponents.Wireframe];
|
||||
this._isGridComponentEnabled[EDebugBufferComponents.Wireframe] = isEnabled;
|
||||
@ -228,7 +238,7 @@ export class Renderer {
|
||||
this._gridBuffers.x[MeshType.VoxelMesh] = DebugGeometryTemplates.gridX(Vector3.mulScalar(dimensions, voxelSize), voxelSize);
|
||||
this._gridBuffers.y[MeshType.VoxelMesh] = DebugGeometryTemplates.gridY(Vector3.mulScalar(dimensions, voxelSize), voxelSize);
|
||||
this._gridBuffers.z[MeshType.VoxelMesh] = DebugGeometryTemplates.gridZ(Vector3.mulScalar(dimensions, voxelSize), voxelSize);
|
||||
|
||||
|
||||
this._modelsAvailable = 2;
|
||||
this.setModelToUse(MeshType.VoxelMesh);
|
||||
}
|
||||
@ -258,7 +268,7 @@ export class Renderer {
|
||||
this.setModelToUse(MeshType.VoxelMesh);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
public useBlockMeshChunk(params: RenderNextBlockMeshChunkParams.Output) {
|
||||
if (params.isFirstChunk) {
|
||||
this._blockBuffer = [];
|
||||
@ -393,6 +403,7 @@ export class Renderer {
|
||||
u_voxelSize: this._voxelSize,
|
||||
u_atlasSize: this._atlasSize,
|
||||
u_gridOffset: this._gridOffset.toArray(),
|
||||
u_nightVision: this.isNightVisionEnabled(),
|
||||
};
|
||||
this._blockBuffer?.forEach((buffer) => {
|
||||
this._gl.useProgram(shader.program);
|
||||
|
@ -233,8 +233,15 @@ export class UI {
|
||||
.isActive(() => {
|
||||
return Renderer.Get.isAxesEnabled();
|
||||
}),
|
||||
'night-vision': new ToolbarItemElement({ icon: 'bulb' })
|
||||
.onClick(() => {
|
||||
Renderer.Get.toggleIsNightVisionEnabled();
|
||||
})
|
||||
.isActive(() => {
|
||||
return Renderer.Get.isNightVisionEnabled();
|
||||
}),
|
||||
},
|
||||
elementsOrder: ['grid', 'axes'],
|
||||
elementsOrder: ['grid', 'axes', 'night-vision'],
|
||||
},
|
||||
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user