mgecumshooter/esotera
resolved master merge
Commit fd3c18c648e1 · mgecumshooter · 2026-10-21 12:06 +0300
Comments
No comments yet.
Diff
diff --git a/src/chunk/mod.rs b/src/chunk/mod.rs
--- a/src/chunk/mod.rs
+++ b/src/chunk/mod.rs
@@ -30,12 +30,12 @@
let mut s = Self {
chunk_pos: pos,
voxels: [Voxel::Air; CHUNK_SIZE*CHUNK_SIZE*CHUNK_SIZE],
- dirty: false,
+ dirty: true,
mesh: None
};
- for x in 0..31 {
- for z in 0..31 {
- let y = x + z;
+ for x in 0..CHUNK_SIZE {
+ for z in 0..CHUNK_SIZE {
+ let y = (x + z).min(CHUNK_SIZE - 1);
let i = x + (y * CHUNK_SIZE) + (z * CHUNK_SIZE * CHUNK_SIZE);
s.voxels[i] = Voxel::Stone;
}
@@ -43,6 +43,238 @@
s
}
+ pub fn generate_mesh(&mut self, rl: &RaylibThread) {
+ let mut vertices: Vec<Vector3> = Vec::new();
+ let mut normals: Vec<Vector3> = Vec::new();
+ let mut indices: Vec<u16> = Vec::new();
+
+ let mut vertex_offset: i32 = 0;
+ for x in 0..CHUNK_SIZE {
+ for y in 0..CHUNK_SIZE {
+ for z in 0..CHUNK_SIZE {
+ if let Some(Voxel::Air) = self.get_voxel(x, y, z) {
+ continue;
+ }
+ if !self.is_exposed(x, y, z) {
+ continue;
+ }
+
+
+ // first side
+ vertices.push(
+ Vector3::
+ new(x as f32, y as f32, z as f32)
+ );
+ vertices.push(
+ Vector3::
+ new(x as f32, y as f32 + VOXEL_SIZE as f32, z as f32)
+ );
+ vertices.push(
+ Vector3::
+ new(x as f32 + VOXEL_SIZE as f32, y as f32, z as f32)
+ );
+ vertices.push(
+ Vector3::
+ new(x as f32 + VOXEL_SIZE as f32, y as f32 + VOXEL_SIZE as f32, z as f32)
+ );
+ push_quad_normal(&mut normals, Vector3::new(0f32, 0f32, -1f32));
+
+ // second side
+ vertices.push(
+ Vector3::
+ new(x as f32, y as f32, z as f32)
+ );
+ vertices.push(
+ Vector3::
+ new(x as f32, y as f32 + VOXEL_SIZE as f32, z as f32)
+ );
+ vertices.push(
+ Vector3::
+ new(x as f32, y as f32, z as f32 + VOXEL_SIZE as f32)
+ );
+ vertices.push(
+ Vector3::
+ new(x as f32, y as f32 + VOXEL_SIZE as f32, z as f32 + VOXEL_SIZE as f32)
+ );
+ push_quad_normal(&mut normals, Vector3::new(-1f32, 0f32, 0f32));
+
+ // third side
+ vertices.push(
+ Vector3::
+ new(x as f32, y as f32, z as f32)
+ );
+ vertices.push(
+ Vector3::
+ new(x as f32 + VOXEL_SIZE as f32, y as f32, z as f32)
+ );
+ vertices.push(
+ Vector3::
+ new(x as f32, y as f32, z as f32 + VOXEL_SIZE as f32)
+ );
+ vertices.push(
+ Vector3::
+ new(x as f32 + VOXEL_SIZE as f32, y as f32, z as f32 + VOXEL_SIZE as f32)
+ );
+ push_quad_normal(&mut normals, Vector3::new(0f32, -1f32, 0f32));
+
+ // fourth side
+ vertices.push(
+ Vector3::
+ new(x as f32+VOXEL_SIZE as f32, y as f32+VOXEL_SIZE as f32, z as f32+VOXEL_SIZE as f32)
+ );
+ vertices.push(
+ Vector3::
+ new(x as f32, y as f32 + VOXEL_SIZE as f32, z as f32 + VOXEL_SIZE as f32)
+ );
+ vertices.push(
+ Vector3::
+ new(x as f32 + VOXEL_SIZE as f32, y as f32 + VOXEL_SIZE as f32, z as f32)
+ );
+ vertices.push(
+ Vector3::
+ new(x as f32, y as f32 + VOXEL_SIZE as f32, z as f32)
+ );
+ push_quad_normal(&mut normals, Vector3::new(0f32, 1f32, 0f32));
+
+ // fifth side
+ vertices.push(
+ Vector3::
+ new(x as f32+VOXEL_SIZE as f32, y as f32+VOXEL_SIZE as f32, z as f32+VOXEL_SIZE as f32)
+ );
+ vertices.push(
+ Vector3::
+ new(x as f32 + VOXEL_SIZE as f32, y as f32, z as f32 + VOXEL_SIZE as f32)
+ );
+ vertices.push(
+ Vector3::
+ new(x as f32 + VOXEL_SIZE as f32, y as f32 + VOXEL_SIZE as f32, z as f32)
+ );
+ vertices.push(
+ Vector3::
+ new(x as f32 + VOXEL_SIZE as f32, y as f32, z as f32)
+ );
+ push_quad_normal(&mut normals, Vector3::new(1f32, 0f32, 0f32));
+
+ // sixth side
+ vertices.push(
+ Vector3::
+ new(x as f32+VOXEL_SIZE as f32, y as f32+VOXEL_SIZE as f32, z as f32+VOXEL_SIZE as f32)
+ );
+ vertices.push(
+ Vector3::
+ new(x as f32 + VOXEL_SIZE as f32, y as f32, z as f32 + VOXEL_SIZE as f32)
+ );
+ vertices.push(
+ Vector3::
+ new(x as f32, y as f32 + VOXEL_SIZE as f32, z as f32 + VOXEL_SIZE as f32)
+ );
+ vertices.push(
+ Vector3::
+ new(x as f32, y as f32, z as f32 + VOXEL_SIZE as f32)
+ );
+ push_quad_normal(&mut normals, Vector3::new(0f32, 0f32, 1f32));
+
+
+ indices.push(0 as u16 + vertex_offset as u16);
+ indices.push(1 as u16 + vertex_offset as u16);
+ indices.push(2 as u16 + vertex_offset as u16);
+ indices.push(2 as u16 + vertex_offset as u16);
+ indices.push(1 as u16 + vertex_offset as u16);
+ indices.push(3 as u16 + vertex_offset as u16);
+
+ indices.push(4 as u16 + vertex_offset as u16);
+ indices.push(6 as u16 + vertex_offset as u16);
+ indices.push(5 as u16 + vertex_offset as u16);
+ indices.push(5 as u16 + vertex_offset as u16);
+ indices.push(6 as u16 + vertex_offset as u16);
+ indices.push(7 as u16 + vertex_offset as u16);
+
+ indices.push(8 as u16 + vertex_offset as u16);
+ indices.push(9 as u16 + vertex_offset as u16);
+ indices.push(10 as u16 + vertex_offset as u16);
+ indices.push(10 as u16 + vertex_offset as u16);
+ indices.push(9 as u16 + vertex_offset as u16);
+ indices.push(11 as u16 + vertex_offset as u16);
+
+ indices.push(12 as u16 + vertex_offset as u16);
+ indices.push(14 as u16 + vertex_offset as u16);
+ indices.push(13 as u16 + vertex_offset as u16);
+ indices.push(13 as u16 + vertex_offset as u16);
+ indices.push(14 as u16 + vertex_offset as u16);
+ indices.push(15 as u16 + vertex_offset as u16);
+
+ indices.push(16 as u16 + vertex_offset as u16);
+ indices.push(17 as u16 + vertex_offset as u16);
+ indices.push(18 as u16 + vertex_offset as u16);
+ indices.push(18 as u16 + vertex_offset as u16);
+ indices.push(17 as u16 + vertex_offset as u16);
+ indices.push(19 as u16 + vertex_offset as u16);
+
+ indices.push(20 as u16 + vertex_offset as u16);
+ indices.push(22 as u16 + vertex_offset as u16);
+ indices.push(21 as u16 + vertex_offset as u16);
+ indices.push(21 as u16 + vertex_offset as u16);
+ indices.push(22 as u16 + vertex_offset as u16);
+ indices.push(23 as u16 + vertex_offset as u16);
+
+
+
+ vertex_offset += 24;
+
+ }
+ }
+ }
+
+ let vertex_count = vertices.len();
+ let index_count = indices.len();
+ let normals_count = normals.len();
+
+ if vertex_count == 0 {
+ self.mesh = None;
+ return;
+ }
+
+ unsafe {
+ let v_size = vertex_count * std::mem::size_of::<Vector3>();
+ let i_size = index_count * std::mem::size_of::<u16>();
+ let n_size = normals_count * std::mem::size_of::<Vector3>();
+
+ let v_ptr = rlb::ffi::MemAlloc(v_size as u32) as *mut Vector3;
+ let i_ptr = rlb::ffi::MemAlloc(i_size as u32) as *mut u16;
+ let n_ptr = rlb::ffi::MemAlloc(n_size as u32) as *mut Vector3;
+
+ std::ptr::copy_nonoverlapping(vertices.as_ptr(), v_ptr, vertex_count);
+ std::ptr::copy_nonoverlapping(indices.as_ptr(), i_ptr, index_count);
+ std::ptr::copy_nonoverlapping(normals.as_ptr(), n_ptr, normals_count);
+
+ let raw_mesh = rlb::ffi::Mesh {
+ vertexCount: vertex_count as i32,
+ triangleCount: (index_count / 3) as i32,
+ vertices: v_ptr as *mut std::ffi::c_float,
+ indices: i_ptr,
+ normals: n_ptr as *mut std::ffi::c_float,
+ texcoords: std::ptr::null_mut(),
+ texcoords2: std::ptr::null_mut(),
+ colors: std::ptr::null_mut(),
+ tangents: std::ptr::null_mut(),
+ animVertices: std::ptr::null_mut(),
+ animNormals: std::ptr::null_mut(),
+ boneCount: 0,
+ boneIndices: std::ptr::null_mut(),
+ boneWeights: std::ptr::null_mut(),
+ vaoId: 0,
+ vboId: std::ptr::null_mut(),
+ };
+
+ let mut mesh = Mesh::from_raw(raw_mesh);
+
+ mesh.upload(false);
+
+ self.mesh = Some(mesh);
+ }
+
+ }
+
// returns voxel by chunk coordinates
pub fn get_voxel(&self, x: usize, y: usize, z: usize) -> Option<&Voxel> {
if x >= CHUNK_SIZE || y >= CHUNK_SIZE || z >= CHUNK_SIZE {
@@ -187,7 +419,7 @@
return Some(Self{
chunk_pos: pos,
voxels,
- dirty: false,
+ dirty: true,
mesh: None,
});
}
@@ -195,3 +427,11 @@
None
}
}
+
+
+fn push_quad_normal(normals: &mut Vec<Vector3>, n: Vector3) {
+ for _ in 0..4 {
+ normals.push(n);
+ }
+}
+
diff --git a/src/main.rs b/src/main.rs
--- a/src/main.rs
+++ b/src/main.rs
@@ -12,7 +12,7 @@
// internal modules
use chunk::*;
use player::Player;
-use util::Cube;
+use util::*;
use world::*;
fn main() {
@@ -28,31 +28,32 @@
rl.hide_cursor();
rl.disable_cursor();
+ rl.set_trace_log(TraceLogLevel::LOG_WARNING);
+
// shader stuff
- let mut shader = rl
- .load_shader(
- &rl_thd,
- Some("shaders/vert.glsl"),
- Some("shaders/frag.glsl"),
- )
- .unwrap();
- let mut post_shader = rl
- .load_shader(&rl_thd, None, Some("shaders/post.glsl"))
- .unwrap();
- let mut rend_tex = rl
- .load_render_texture(
- &rl_thd,
- rl.get_render_width() as u32,
- rl.get_render_height() as u32,
- )
- .unwrap();
+ let mut shader = rl.load_shader(&rl_thd, Some("shaders/vert.glsl"), Some("shaders/frag.glsl")).unwrap();
+ let mut post_shader = rl.load_shader(&rl_thd, None, Some("shaders/post.glsl")).unwrap();
+
+ let depth_loc = post_shader.get_shader_location("depth_tex");
+
+ assert!(depth_loc >= 0, "Uniform depth_tex not found");
+
+ // let mut rend_tex = rl.load_render_texture
+ // (&rl_thd, rl.get_render_width() as u32, rl.get_render_height() as u32).unwrap();
+
+ let mut chunk_material = rl.load_material_default(&rl_thd);
+ let mut rend_tex = unsafe { load_depth_tex(rl.get_render_width(), rl.get_render_height()) };
+ unsafe {
+ *chunk_material.shader_mut() = shader.make_weak();
+ }
+ // chunk_material.set_shader(&shader);
// chunks
// let test_chunk = Chunk::new(Vector3::zero());
// let test2 = [&test_chunk];
- let mut world = World::new(2);
+ let mut world = World::new(4);
let mut plr = Player::new(
Vector3::new(0f32, 10f32, 0f32),
@@ -61,21 +62,18 @@
// main game loop
while !rl.window_should_close() {
- world.update_around_player(plr.get_eye_pos());
-
- let active_chunks: Vec<&Chunk> = world.chunks.values().collect();
- plr.update(&rl, &active_chunks);
- plr.apply_to_camera(&mut cam);
+ world.load_around_player(plr.get_eye_pos());
+ world.update_chunks(&rl_thd);
- if rend_tex.width() != rl.get_render_width() || rend_tex.height() != rl.get_render_height()
- {
- rend_tex = rl
- .load_render_texture(
- &rl_thd,
- rl.get_render_width() as u32,
- rl.get_render_height() as u32,
- )
- .unwrap();
+ let active_chunks: Vec<&Chunk> = world.chunks.values().collect();
+ plr.update(&rl, &active_chunks);
+ plr.apply_to_camera(&mut cam);
+
+
+ if rend_tex.width() != rl.get_render_width() || rend_tex.height() != rl.get_render_height() {
+ rend_tex = unsafe { load_depth_tex(rl.get_render_width(), rl.get_render_height()) };
+ // rend_tex = rl.load_render_texture
+ // (&rl_thd, rl.get_render_width() as u32, rl.get_render_height() as u32).unwrap();
}
rl.draw(&rl_thd, |mut d| {
@@ -83,26 +81,38 @@
tx.clear_background(Color::new(30, 30, 30, 255));
tx.draw_mode3D(cam, |mut d3, _| {
d3.draw_grid(100, 1f32);
- d3.draw_shader_mode(&mut shader, |mut shd| {
- // test_chunk.draw(&mut shd);
- for chunk in world.chunks.values() {
- chunk.draw(&mut shd);
- }
- });
+ for chunk in world.chunks.values() {
+ if let Some(ref mesh) = chunk.mesh {
+ d3.draw_mesh(mesh,
+ chunk_material.clone(),
+ Matrix::translate(
+ chunk.chunk_pos.x * CHUNK_SIZE as f32,
+ chunk.chunk_pos.y * CHUNK_SIZE as f32,
+ chunk.chunk_pos.z * CHUNK_SIZE as f32,
+ )
+ );
+ }
+ // chunk.draw(&mut shd);
+ }
});
});
+ post_shader.set_shader_value_texture(
+ post_shader.get_shader_location("depth_tex"),
+ unsafe { Texture2D::from_raw(rend_tex.depth).make_weak() }
+ );
d.draw_shader_mode(&mut post_shader, |mut shd| {
- shd.draw_texture_rec(
- &rend_tex,
- Rectangle {
- x: 0f32,
- y: 0f32,
- width: rend_tex.texture().width as f32,
- height: -rend_tex.texture().height as f32,
- },
- Vector2::zero(),
- Color::WHITE,
- );
+ unsafe {
+ rlb::ffi::rlSetUniformSampler(
+ depth_loc,
+ rend_tex.depth.id
+ );
+ }
+ shd.draw_texture_rec(&rend_tex, Rectangle{
+ x: 0f32,
+ y: 0f32,
+ width: rend_tex.texture().width as f32,
+ height: -rend_tex.texture().height as f32
+ }, Vector2::zero(), Color::WHITE);
});
d.draw_text(
&format!(
diff --git a/src/util/mod.rs b/src/util/mod.rs
--- a/src/util/mod.rs
+++ b/src/util/mod.rs
@@ -1,5 +1,6 @@
use super::rlb;
use rlb::prelude::*;
+// use rlb::core::*;
pub struct Cube {
pub width: f32,
@@ -30,3 +31,62 @@
self.min.z < other.max.z && self.max.z > other.min.z
}
}
+
+// had to do this ;(
+pub fn load_depth_tex(width: i32, height: i32) -> RenderTexture2D {
+ unsafe {
+ let fbo_id = rlb::ffi::rlLoadFramebuffer();
+ rlb::ffi::rlEnableFramebuffer(fbo_id);
+
+ let col_tex_id = rlb::ffi::rlLoadTexture(
+ std::ptr::null(),
+ width,
+ height,
+ rlb::ffi::PixelFormat::PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 as i32,
+ 1
+ );
+
+ rlb::ffi::rlFramebufferAttach(
+ fbo_id,
+ col_tex_id,
+ rlb::ffi::rlFramebufferAttachType::RL_ATTACHMENT_COLOR_CHANNEL0 as i32,
+ rlb::ffi::rlFramebufferAttachTextureType::RL_ATTACHMENT_TEXTURE2D as i32,
+ 0
+ );
+
+ let depth_tex_id = rlb::ffi::rlLoadTextureDepth(width, height, false);
+
+ rlb::ffi::rlFramebufferAttach(
+ fbo_id,
+ depth_tex_id,
+ rlb::ffi::rlFramebufferAttachType::RL_ATTACHMENT_DEPTH as i32,
+ rlb::ffi::rlFramebufferAttachTextureType::RL_ATTACHMENT_TEXTURE2D as i32,
+ 0
+ );
+
+ let fbo_complete = rlb::ffi::rlFramebufferComplete(fbo_id);
+ rlb::ffi::rlDisableFramebuffer();
+ assert!(
+ fbo_complete,
+ "Framebuffer incomplete!"
+ );
+
+ RenderTexture2D::from_raw(rlb::ffi::RenderTexture2D {
+ id: fbo_id,
+ texture: rlb::ffi::Texture2D {
+ id: col_tex_id,
+ width,
+ height,
+ mipmaps: 1,
+ format: rlb::ffi::PixelFormat::PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 as i32,
+ },
+ depth: rlb::ffi::Texture2D {
+ id: depth_tex_id,
+ width,
+ height,
+ mipmaps: 1,
+ format: 19,
+ },
+ })
+ }
+}
diff --git a/src/world/mod.rs b/src/world/mod.rs
--- a/src/world/mod.rs
+++ b/src/world/mod.rs
@@ -15,7 +15,23 @@
}
}
- pub fn update_around_player(&mut self, player_pos: Vector3) {
+ pub fn update_chunks(&mut self, rl: &RaylibThread) {
+ const CHUNK_PER_FRAME: usize = 2;
+ let mut processed = 0;
+
+ for (_, mut chunk) in &mut self.chunks {
+ if processed >= CHUNK_PER_FRAME {
+ break;
+ }
+ if chunk.dirty {
+ chunk.generate_mesh(rl);
+ chunk.dirty = false;
+ processed += 1;
+ }
+ }
+ }
+
+ pub fn load_around_player(&mut self, player_pos: Vector3) {
let p_chunk_x = (player_pos.x / CHUNK_SIZE as f32).floor() as i32;
let p_chunk_y = (player_pos.y / CHUNK_SIZE as f32).floor() as i32;
let p_chunk_z = (player_pos.z / CHUNK_SIZE as f32).floor() as i32;
@@ -56,7 +72,7 @@
}
}
for coords in to_unload {
- if let Some(chunk) = self.chunks.remove(&coords) {
+ if let Some(mut chunk) = self.chunks.remove(&coords) {
chunk.save();
}
}