diff --git a/src/render/ChunkBuilder.ts b/src/render/ChunkBuilder.ts index 6d9236e..c8df422 100644 --- a/src/render/ChunkBuilder.ts +++ b/src/render/ChunkBuilder.ts @@ -5,7 +5,7 @@ import { Mesh } from './Mesh.js' import { SpecialRenderer, SpecialRenderers } from './SpecialRenderer.js' export class ChunkBuilder { - private chunks: Mesh[][][] = [] + private chunks: {mesh: Mesh, transparentMesh: Mesh}[][][] = [] private readonly chunkSize: vec3 constructor( @@ -24,13 +24,19 @@ export class ChunkBuilder { } public updateStructureBuffers(chunkPositions?: vec3[]): void { + if (!this.structure) + return + if (!chunkPositions) { this.chunks.forEach(x => x.forEach(y => y.forEach(chunk => { - chunk.clear() + chunk.mesh.clear() + chunk.transparentMesh.clear() }))) } else { chunkPositions.forEach(chunkPos => { - this.getChunk(chunkPos).clear() + const chunk = this.getChunk(chunkPos) + chunk.mesh.clear() + chunk.transparentMesh.clear() }) } @@ -68,7 +74,11 @@ export class ChunkBuilder { } if (!mesh.isEmpty()) { this.finishChunkMesh(mesh, b.pos) - chunk.merge(mesh) + if (this.resources.getBlockFlags(b.state.getName())?.semi_transparent){ + chunk.transparentMesh.merge(mesh) + } else { + chunk.mesh.merge(mesh) + } } } catch (e) { console.error(`Error rendering block ${blockName}`, e) @@ -77,23 +87,33 @@ export class ChunkBuilder { if (!chunkPositions) { this.chunks.forEach(x => x.forEach(y => y.forEach(chunk => { - chunk.rebuild(this.gl, { pos: true, color: true, texture: true, normal: true, blockPos: true }) + chunk.mesh.rebuild(this.gl, { pos: true, color: true, texture: true, normal: true, blockPos: true }) + chunk.transparentMesh.rebuild(this.gl, { pos: true, color: true, texture: true, normal: true, blockPos: true }) }))) } else { chunkPositions.forEach(chunkPos => { - this.getChunk(chunkPos).rebuild(this.gl, { pos: true, color: true, texture: true, normal: true, blockPos: true }) + const chunk = this.getChunk(chunkPos) + chunk.mesh.rebuild(this.gl, { pos: true, color: true, texture: true, normal: true, blockPos: true }) + chunk.transparentMesh.rebuild(this.gl, { pos: true, color: true, texture: true, normal: true, blockPos: true }) }) } } public getMeshes(): Mesh[] { - return this.chunks.flatMap(x => x.flatMap(y => y.flatMap(chunk => chunk ?? []))) + const chunks = this.chunks.flatMap(x => x.flatMap(y => y.flatMap(chunk => chunk ?? []))) + return chunks.flatMap(chunk => chunk.mesh.isEmpty() ? [] : chunk.mesh).concat(chunks.flatMap(chunk => chunk.transparentMesh.isEmpty() ? [] : chunk.transparentMesh)) } private needsCull(block: PlacedBlock, dir: Direction) { const neighbor = this.structure.getBlock(BlockPos.towards(block.pos, dir))?.state if (!neighbor) return false - if (this.resources.getBlockFlags(neighbor.getName())?.opaque) { + const neighborFlags = this.resources.getBlockFlags(neighbor.getName()) + + if (block.state.getName().equals(neighbor.getName()) && neighborFlags?.self_culling){ + return true + } + + if (neighborFlags?.opaque) { return !(dir === Direction.UP && block.state.isFluid()) } else { return block.state.isFluid() && neighbor.isFluid() @@ -112,14 +132,14 @@ export class ChunkBuilder { } } - private getChunk(chunkPos: vec3): Mesh { + private getChunk(chunkPos: vec3): {mesh: Mesh, transparentMesh: Mesh} { const x = Math.abs(chunkPos[0]) * 2 + (chunkPos[0] < 0 ? 1 : 0) const y = Math.abs(chunkPos[1]) * 2 + (chunkPos[1] < 0 ? 1 : 0) const z = Math.abs(chunkPos[2]) * 2 + (chunkPos[2] < 0 ? 1 : 0) if (!this.chunks[x]) this.chunks[x] = [] if (!this.chunks[x][y]) this.chunks[x][y] = [] - if (!this.chunks[x][y][z]) this.chunks[x][y][z] = new Mesh() + if (!this.chunks[x][y][z]) this.chunks[x][y][z] = {mesh: new Mesh(), transparentMesh: new Mesh()} return this.chunks[x][y][z] } diff --git a/src/render/SpecialRenderer.ts b/src/render/SpecialRenderer.ts index 09380b1..1b35ff1 100644 --- a/src/render/SpecialRenderer.ts +++ b/src/render/SpecialRenderer.ts @@ -80,6 +80,49 @@ function chestRenderer(facing: string, type: string, uvProvider: TextureAtlasPro ])).transform(rotation) } +function decoratedPotRenderer(uvProvider: TextureAtlasProvider){ + const id = Identifier.create('decorated_pot') + return dummy(id, uvProvider, {}, new BlockModel(id, undefined, { + 0: 'entity/decorated_pot/decorated_pot_side', + 1: 'entity/decorated_pot/decorated_pot_base', + }, [ + { + from: [1, 0, 1], + to: [15, 16, 15], + faces: { + north: {uv: [1, 0, 15, 16], texture: '#0'}, + east: {uv: [1, 0, 15, 16], texture: '#0'}, + south: {uv: [1, 0, 15, 16], texture: '#0'}, + west: {uv: [1, 0, 15, 16], texture: '#0'}, + up: {uv: [0, 6.5, 7, 13.5], texture: '#1'}, + down: {uv: [7, 6.5, 14, 13.5], texture: '#1'}, + }, + }, + { + from: [5, 16, 5], + to: [11, 17, 11], + faces: { + north: {uv: [0, 5.5, 3, 6], texture: '#1'}, + east: {uv: [3, 5.5, 6, 6], texture: '#1'}, + south: {uv: [6, 5.5, 9, 6], texture: '#1'}, + west: {uv: [9, 5.5, 12, 6], texture: '#1'}, + }, + }, + { + from: [4, 17, 4], + to: [12, 20, 12], + faces: { + north: {uv: [0, 4, 4, 5.5], texture: '#1'}, + east: {uv: [4, 4, 8, 5.5], texture: '#1'}, + south: {uv: [8, 4, 12, 5.5], texture: '#1'}, + west: {uv: [12, 4, 16, 5.5], texture: '#1'}, + up: {uv: [4, 0, 8, 4], texture: '#1'}, + down: {uv: [8, 0, 12, 4], texture: '#1'}, + }, + }, + ])) +} + export const SpecialRenderer: { [key: string]: (props: { [key: string]: string }, uvProvider: TextureAtlasProvider, cull: Cull) => any, } = { @@ -89,6 +132,8 @@ export const SpecialRenderer: { liquidRenderer('lava', parseInt(props.level), uvProvider, cull), 'minecraft:chest': (props, uvProvider) => chestRenderer(props.facing || 'south', props.type || 'single', uvProvider), + 'minecraft:decorated_pot': (_, uvProvider) => + decoratedPotRenderer(uvProvider), } export const SpecialRenderers = new Set(Object.keys(SpecialRenderer)) diff --git a/src/render/StructureRenderer.ts b/src/render/StructureRenderer.ts index e18684e..b543508 100644 --- a/src/render/StructureRenderer.ts +++ b/src/render/StructureRenderer.ts @@ -59,17 +59,10 @@ const fsGrid = ` } ` - - - -type GridBuffers = { - position: WebGLBuffer, - color: WebGLBuffer, - length: number, -} - -type BlockFlags = { +export type BlockFlags = { opaque?: boolean, + semi_transparent?: boolean, + self_culling?: boolean, } export interface BlockFlagsProvider {