feat: add frustum culling

This commit is contained in:
2026-03-19 10:54:13 +08:00
parent a62feb9d56
commit 4d4bbe82ec
6 changed files with 74 additions and 18 deletions

View File

@@ -53,6 +53,7 @@ add_executable(${PROJECT_NAME}
src/input.cpp
src/map_table.cpp
src/texture_manager.cpp
src/tools/math_tools.cpp
src/tools/shader_tools.cpp
src/tools/log.cpp
)

View File

@@ -11,6 +11,7 @@ private:
BlockRenderData m_block_render_data;
std::unordered_map<ChunkPos , Chunk, ChunkPos::Hash> m_chunks;
std::unordered_map<std::size_t, Player> m_players;
std::vector<glm::vec4> m_planes;
public:
World();
@@ -20,8 +21,10 @@ public:
const std::optional<LookBlock>& get_look_block_pos(const std::string& name) const;
Player& get_player(const std::string& name);
void init_world();
bool is_aabb_in_frustum(const glm::vec3& center, const glm::vec3& half_extents);
bool is_block(const glm::ivec3& block_pos) const;
void render();
void render(const glm::mat4& mvp_matrix);
void set_block(const glm::ivec3& pos, unsigned id);
void update(float delta_time);

View File

@@ -0,0 +1,5 @@
#pragma once
#include <glm/glm.hpp>
namespace Math {
void extract_frustum_planes(const glm::mat4& mvp_matrix, std::vector<glm::vec4>& planes);
}

View File

@@ -3,6 +3,7 @@
#include <Cubed/map_table.hpp>
#include <Cubed/tools/cubed_assert.hpp>
#include <Cubed/tools/cubed_hash.hpp>
#include <Cubed/tools/math_tools.hpp>
World::World() {
}
@@ -123,26 +124,43 @@ void World::init_world() {
m_players.emplace(HASH::str("TestPlayer"), Player(*this, "TestPlayer"));
}
void World::render() {
void World::render(const glm::mat4& mvp_matrix) {
Math::extract_frustum_planes(mvp_matrix, m_planes);
for (const auto& chunk_map : m_chunks) {
const auto& [pos, chunk] = chunk_map;
glm::vec3 center = glm::vec3(static_cast<float>(pos.x * CHUCK_SIZE) + static_cast<float>(CHUCK_SIZE / 2), static_cast<float>(CHUCK_SIZE / 2), static_cast<float>(pos.z * CHUCK_SIZE) + static_cast<float>(CHUCK_SIZE / 2));
if (is_aabb_in_frustum(center, glm::vec3(static_cast<float>(CHUCK_SIZE / 2), static_cast<float>(CHUCK_SIZE / 2), static_cast<float>(CHUCK_SIZE / 2)))) {
glBindBuffer(GL_ARRAY_BUFFER, chunk.get_vbo());
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, s));
glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, layer));
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glDrawArrays(GL_TRIANGLES, 0, chunk.get_vertex_data().size() * 3);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
glBindBuffer(GL_ARRAY_BUFFER, chunk.get_vbo());
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, s));
glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, layer));
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glDrawArrays(GL_TRIANGLES, 0, chunk.get_vertex_data().size() * 3);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
}
}
bool World::is_aabb_in_frustum(const glm::vec3& center, const glm::vec3& half_extents) {
for (const auto& plane : m_planes) {
// distance
float d = glm::dot(glm::vec3(plane), center) + plane.w;
float r = half_extents.x * std::abs(plane.x) +
half_extents.y * std::abs(plane.y) +
half_extents.z * std::abs(plane.z);
if (d + r < 0) {
return false;
}
}
return true;
}
bool World::is_block(const glm::ivec3& block_pos) const{
int chunk_x, chunk_z;
int world_x, world_y, world_z;

View File

@@ -24,7 +24,7 @@ GLuint vao[NUM_VAO];
GLuint mv_loc, proj_loc;
int width ,height;
float aspect;
glm::mat4 p_mat, v_mat, m_mat, mv_mat;
glm::mat4 p_mat, v_mat, m_mat, mv_mat, mvp_mat;
float inc = 0.01f;
float tf = 0.0f;
double last_time = glfwGetTime();
@@ -183,8 +183,8 @@ void display(GLFWwindow* window, double current_time) {
mv_mat = v_mat * m_mat;
glUniformMatrix4fv(mv_loc, 1, GL_FALSE, glm::value_ptr(mv_mat));
glUniformMatrix4fv(proj_loc, 1 ,GL_FALSE, glm::value_ptr(p_mat));
world.render();
mvp_mat = p_mat * mv_mat;
world.render(mvp_mat);
render_outline();

29
src/tools/math_tools.cpp Normal file
View File

@@ -0,0 +1,29 @@
#include <Cubed/tools/math_tools.hpp>
#include <glm/gtc/type_ptr.hpp>
namespace Math {
void extract_frustum_planes(const glm::mat4& mvp_matrix, std::vector<glm::vec4>& planes) {
if (planes.size() != 6) {
planes.resize(6);
}
const float* m = glm::value_ptr(mvp_matrix);
// left plane
planes[0] = glm::vec4(m[3] + m[0], m[7] + m[4], m[11] + m[8], m[15] + m[12]);
// right plane
planes[1] = glm::vec4(m[3] - m[0], m[7] - m[4], m[11] - m[8], m[15] - m[12]);
// bottom plane
planes[2] = glm::vec4(m[3] + m[1], m[7] + m[5], m[11] + m[9], m[15] + m[13]);
// top plane
planes[3] = glm::vec4(m[3] - m[1], m[7] - m[5], m[11] - m[9], m[15] - m[13]);
// near plane
planes[4] = glm::vec4(m[3] + m[2], m[7] + m[6], m[11] + m[10], m[15] + m[14]);
// far plane
planes[5] = glm::vec4(m[3] - m[2], m[7] - m[6], m[11] - m[10], m[15] - m[14]);
for (auto& p : planes) {
p = glm::normalize(p);
}
}
}