refactor(renderer): rename mesh module to vertex
This commit is contained in:
parent
d2f4beb5af
commit
d8d6635f37
|
|
@ -11,13 +11,13 @@ mod device;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
mod frustum;
|
mod frustum;
|
||||||
mod instance;
|
mod instance;
|
||||||
pub mod mesh;
|
|
||||||
pub mod meshing;
|
pub mod meshing;
|
||||||
mod pipeline;
|
mod pipeline;
|
||||||
mod renderer;
|
mod renderer;
|
||||||
mod surface;
|
mod surface;
|
||||||
mod swapchain;
|
mod swapchain;
|
||||||
mod sync;
|
mod sync;
|
||||||
|
pub mod vertex;
|
||||||
|
|
||||||
/// The maximum number of frames that can be processed by the GPU and CPU simultaneously.
|
/// The maximum number of frames that can be processed by the GPU and CPU simultaneously.
|
||||||
pub const MAX_FRAMES_IN_FLIGHT: usize = 3;
|
pub const MAX_FRAMES_IN_FLIGHT: usize = 3;
|
||||||
|
|
|
||||||
|
|
@ -1,28 +1,13 @@
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
//! Cubic greedy mesher: converts a dense voxel [`Chunk`] into renderer geometry.
|
//! Cubic greedy mesher: converts a dense voxel [`Chunk`] into renderer geometry.
|
||||||
//!
|
|
||||||
//! Exposed voxel faces are merged into the largest possible axis-aligned
|
|
||||||
//! rectangles before emission. The output is visually identical to a naive
|
|
||||||
//! per-face emitter (same faces, colours, and world positions) but carries far
|
|
||||||
//! fewer vertices and indices: a flat `CHUNK_SIZE`×`CHUNK_SIZE` surface becomes a
|
|
||||||
//! single quad rather than one quad per voxel.
|
|
||||||
//!
|
|
||||||
//! This is the **cubic** meshing path only. It is a pure `chunk → (vertices,
|
|
||||||
//! indices)` function and makes no assumption of being the sole mesher, so a
|
|
||||||
//! merged-granular mesher can coexist for softer materials.
|
|
||||||
//!
|
|
||||||
//! Out-of-chunk neighbours are treated as air, so every face on a chunk boundary
|
|
||||||
//! is emitted. Cross-chunk face culling is a separate concern layered on top.
|
|
||||||
|
|
||||||
use crate::mesh::Vertex;
|
use crate::vertex::Vertex;
|
||||||
use shared::world::{BlockId, CHUNK_SIZE, Chunk};
|
use shared::world::{BlockId, CHUNK_SIZE, Chunk};
|
||||||
|
|
||||||
/// The signed direction a face points along one of the three axes.
|
/// The signed direction a face points along one of the three axes.
|
||||||
///
|
///
|
||||||
/// The sign is part of the merge key: two faces on the same plane but pointing
|
/// The sign is part of the merge key: two faces on the same plane but pointing in opposite directions (for example a top face and the bottom face directly above it) must never merge, so `PosY` and `NegY` are distinct variants.
|
||||||
/// in opposite directions (for example a top face and the bottom face directly
|
|
||||||
/// above it) must never merge, so `PosY` and `NegY` are distinct variants.
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
enum FaceDir {
|
enum FaceDir {
|
||||||
/// Points toward increasing X.
|
/// Points toward increasing X.
|
||||||
|
|
@ -40,11 +25,6 @@ enum FaceDir {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Identifies whether two faces are mergeable.
|
/// Identifies whether two faces are mergeable.
|
||||||
///
|
|
||||||
/// Two faces merge only if every attribute a vertex carries is identical. Colour
|
|
||||||
/// currently depends only on [`FaceDir`], but keying additionally on [`BlockId`]
|
|
||||||
/// keeps the merge correct once per-material colours are introduced: two distinct
|
|
||||||
/// block types will not silently coalesce into one quad.
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
struct FaceKey {
|
struct FaceKey {
|
||||||
/// The material of the voxel owning the face.
|
/// The material of the voxel owning the face.
|
||||||
|
|
@ -55,8 +35,7 @@ struct FaceKey {
|
||||||
|
|
||||||
/// Returns the flat RGB colour for a face pointing in `dir`.
|
/// Returns the flat RGB colour for a face pointing in `dir`.
|
||||||
///
|
///
|
||||||
/// The values reproduce the previous per-face emitter exactly so the rendered
|
/// The values reproduce the previous per-face emitter exactly so the rendered output is unchanged.
|
||||||
/// output is unchanged.
|
|
||||||
const fn color_of(dir: FaceDir) -> [f32; 3] {
|
const fn color_of(dir: FaceDir) -> [f32; 3] {
|
||||||
match dir {
|
match dir {
|
||||||
FaceDir::PosY => [0.2, 0.8, 0.2],
|
FaceDir::PosY => [0.2, 0.8, 0.2],
|
||||||
|
|
@ -77,9 +56,7 @@ const fn coord(i: usize) -> f32 {
|
||||||
|
|
||||||
/// Meshes `chunk` into GPU vertices and triangle indices via greedy merging.
|
/// Meshes `chunk` into GPU vertices and triangle indices via greedy merging.
|
||||||
///
|
///
|
||||||
/// Each axis is swept slice by slice; on every slice a 2D mask of exposed faces
|
/// Each axis is swept slice by slice; on every slice a 2D mask of exposed faces over the two perpendicular axes is built and merged into rectangles. Boundary voxels treat out-of-chunk neighbours as air, so chunk-edge faces are emitted.
|
||||||
/// over the two perpendicular axes is built and merged into rectangles. Boundary
|
|
||||||
/// voxels treat out-of-chunk neighbours as air, so chunk-edge faces are emitted.
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[expect(
|
#[expect(
|
||||||
clippy::too_many_lines,
|
clippy::too_many_lines,
|
||||||
|
|
@ -88,8 +65,7 @@ const fn coord(i: usize) -> f32 {
|
||||||
pub fn generate_mesh(chunk: &Chunk) -> (Vec<Vertex>, Vec<u32>) {
|
pub fn generate_mesh(chunk: &Chunk) -> (Vec<Vertex>, Vec<u32>) {
|
||||||
let mut vertices = Vec::new();
|
let mut vertices = Vec::new();
|
||||||
let mut indices = Vec::new();
|
let mut indices = Vec::new();
|
||||||
// A single u×v mask, reused across every slice of every axis; each pass fully
|
// A single u×v mask, reused across every slice of every axis; each pass fully overwrites it per slice, so no explicit clearing is required.
|
||||||
// overwrites it per slice, so no explicit clearing is required.
|
|
||||||
let mut mask = vec![None; CHUNK_SIZE * CHUNK_SIZE];
|
let mut mask = vec![None; CHUNK_SIZE * CHUNK_SIZE];
|
||||||
|
|
||||||
// +Y (top): slice = y, mask u = x, mask v = z.
|
// +Y (top): slice = y, mask u = x, mask v = z.
|
||||||
|
|
@ -259,11 +235,7 @@ pub fn generate_mesh(chunk: &Chunk) -> (Vec<Vertex>, Vec<u32>) {
|
||||||
|
|
||||||
/// Runs one directional meshing pass over all `CHUNK_SIZE` slices.
|
/// Runs one directional meshing pass over all `CHUNK_SIZE` slices.
|
||||||
///
|
///
|
||||||
/// `sample(slice, u, v)` returns the [`FaceKey`] for the face at mask cell
|
/// `sample(slice, u, v)` returns the [`FaceKey`] for the face at mask cell `(u, v)` of `slice`, or `None` when no face is exposed there. `corners(slice, u0, v0, w, h)` yields the four world-space corners, ordered counter-clockwise as seen from outside the face, of a merged rectangle rooted at `(u0, v0)` with width `w` along `u` and height `h` along `v`.
|
||||||
/// `(u, v)` of `slice`, or `None` when no face is exposed there. `corners(slice,
|
|
||||||
/// u0, v0, w, h)` yields the four world-space corners, ordered counter-clockwise
|
|
||||||
/// as seen from outside the face, of a merged rectangle rooted at `(u0, v0)` with
|
|
||||||
/// width `w` along `u` and height `h` along `v`.
|
|
||||||
fn run_pass(
|
fn run_pass(
|
||||||
mask: &mut [Option<FaceKey>],
|
mask: &mut [Option<FaceKey>],
|
||||||
vertices: &mut Vec<Vertex>,
|
vertices: &mut Vec<Vertex>,
|
||||||
|
|
@ -291,11 +263,7 @@ fn run_pass(
|
||||||
|
|
||||||
/// Greedily covers the exposed cells of `mask` with maximal rectangles.
|
/// Greedily covers the exposed cells of `mask` with maximal rectangles.
|
||||||
///
|
///
|
||||||
/// Cells are scanned row-major. At the first exposed, unconsumed cell the run is
|
/// Cells are scanned row-major. At the first exposed, unconsumed cell the run is extended along `u` while the key matches, then along `v` while every cell of the next row over the current width matches. The covered cells are marked consumed (set to `None`) so they are not re-emitted, and `emit(key, u0, v0, w, h)` is called once for the rectangle.
|
||||||
/// extended along `u` while the key matches, then along `v` while every cell of
|
|
||||||
/// the next row over the current width matches. The covered cells are marked
|
|
||||||
/// consumed (set to `None`) so they are not re-emitted, and `emit(key, u0, v0, w,
|
|
||||||
/// h)` is called once for the rectangle.
|
|
||||||
fn merge_mask(
|
fn merge_mask(
|
||||||
mask: &mut [Option<FaceKey>],
|
mask: &mut [Option<FaceKey>],
|
||||||
mut emit: impl FnMut(FaceKey, usize, usize, usize, usize),
|
mut emit: impl FnMut(FaceKey, usize, usize, usize, usize),
|
||||||
|
|
@ -337,8 +305,7 @@ fn merge_mask(
|
||||||
|
|
||||||
/// Appends one quad (four vertices, six indices) with the given corners and colour.
|
/// Appends one quad (four vertices, six indices) with the given corners and colour.
|
||||||
///
|
///
|
||||||
/// Indices wind the two triangles as `[base, base+1, base+2, base+2, base+3,
|
/// Indices wind the two triangles as `[base, base+1, base+2, base+2, base+3, base]`, matching the corner ordering supplied by the caller.
|
||||||
/// base]`, matching the corner ordering supplied by the caller.
|
|
||||||
fn push_quad(
|
fn push_quad(
|
||||||
vertices: &mut Vec<Vertex>,
|
vertices: &mut Vec<Vertex>,
|
||||||
indices: &mut Vec<u32>,
|
indices: &mut Vec<u32>,
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
//! Graphics pipeline creation and shader management.
|
//! Graphics pipeline creation and shader management.
|
||||||
|
|
||||||
use crate::error::RendererError;
|
use crate::error::RendererError;
|
||||||
use crate::mesh::Vertex;
|
use crate::vertex::Vertex;
|
||||||
use ash::{Device, vk};
|
use ash::{Device, vk};
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
use crate::sync::SyncPrimitives;
|
use crate::sync::SyncPrimitives;
|
||||||
use crate::{create_depth_resources, create_gpu_buffer, swapchain};
|
use crate::{create_depth_resources, create_gpu_buffer, swapchain};
|
||||||
use crate::{error::RendererError, frustum::Frustum, mesh::Vertex};
|
use crate::{error::RendererError, frustum::Frustum, vertex::Vertex};
|
||||||
use ash::{Device, Instance, khr, vk};
|
use ash::{Device, Instance, khr, vk};
|
||||||
use gpu_allocator::vulkan::{Allocation, Allocator};
|
use gpu_allocator::vulkan::{Allocation, Allocator};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue