Fix transparent blocks

This commit is contained in:
2026-09-25 15:01:03 -03:00
parent dfabe40e7a
commit f8d406dcf0
13 changed files with 645 additions and 192 deletions
+9 -2
View File
@@ -5,7 +5,7 @@ import { Dimension } from "../components/dimension.ts";
import { Camera } from "$/client/components/camera.ts";
import { render_animated_sprite, render_sprite } from "./rendering/sprites.ts";
import { render_dimension } from "./rendering/dimension.ts";
import { render_dimension_opaque, render_dimension_translucent } from "./rendering/dimension.ts";
import { render_player_breaking, render_player_crosshair, render_player_hotbar } from "./rendering/player.ts";
import { PlayerComponent } from "../player.ts";
import { begin_mode_3d, end_mode_3d } from "../renderer/core.ts";
@@ -31,7 +31,7 @@ export class RenderSystem extends System {
const dimension = entity.get(Dimension);
if (dimension) {
render_dimension(dimension, camera);
render_dimension_opaque(dimension, camera);
}
const player_component = entity.get(PlayerComponent);
@@ -44,6 +44,13 @@ export class RenderSystem extends System {
render_remote_players(world.connection);
}
for (const entity of world.get_entities()) {
const dimension = entity.get(Dimension);
if (dimension) {
render_dimension_translucent(dimension, camera);
}
}
end_mode_3d();
for (const entity of world.get_entities()) {
+31 -19
View File
@@ -1,33 +1,45 @@
import { Chunk, Dimension } from "$/client/components/dimension.ts";
import { CHUNK_SIZE, Dimension } from "$/client/components/dimension.ts";
import { Camera } from "$/client/components/camera.ts";
import { flush_buffer, set_current_texture } from "$/client/renderer/mod.ts";
import { draw_terrain, set_current_texture } from "$/client/renderer/mod.ts";
export function render_dimension(dimension: Dimension, _camera: Camera) {
dimension.request_meshes();
// solid and cutout terrain, drawn before entities
export function render_dimension_opaque(dimension: Dimension, camera: Camera) {
dimension.request_meshes(camera);
dimension.update_translucent_sorting(camera);
set_current_texture(dimension.image.tex);
for (const chunk of dimension.chunks.values()) {
render_chunk_opaque(chunk);
const mesh = chunk.meshes.solid;
if (mesh) {
draw_terrain("solid", mesh.vertex_buffer, mesh.quad_count);
}
}
for (const chunk of dimension.chunks.values()) {
render_chunk_transparent(chunk);
const mesh = chunk.meshes.cutout;
if (mesh) {
draw_terrain("cutout", mesh.vertex_buffer, mesh.quad_count);
}
}
}
function render_chunk_opaque(chunk: Chunk) {
if (!chunk.opaque_vertex_buffer || !chunk.opaque_vertex_count) {
return;
// translucent terrain, drawn after entities so they show through water and glass.
// chunks go back to front, and each chunk's quads are already sorted back to front
export function render_dimension_translucent(dimension: Dimension, camera: Camera) {
const distance_sq = (x: number, z: number) => {
const dx = (x + 0.5) * CHUNK_SIZE - camera.x;
const dz = (z + 0.5) * CHUNK_SIZE - camera.z;
return dx * dx + dz * dz;
};
const chunks = [...dimension.chunks.values()]
.filter((chunk) => chunk.meshes.translucent)
.map((chunk) => ({ mesh: chunk.meshes.translucent!, distance: distance_sq(chunk.x, chunk.z) }))
.sort((a, b) => b.distance - a.distance);
set_current_texture(dimension.image.tex);
for (const { mesh } of chunks) {
draw_terrain("translucent", mesh.vertex_buffer, mesh.quad_count, mesh.index_buffer);
}
flush_buffer(chunk.opaque_vertex_buffer, chunk.opaque_vertex_count);
}
function render_chunk_transparent(chunk: Chunk) {
if (!chunk.transparent_vertex_buffer || !chunk.transparent_vertex_count) {
return;
}
flush_buffer(chunk.transparent_vertex_buffer, chunk.transparent_vertex_count);
}