From f43ef646914d4ec0c2171814450edc6e0a590990 Mon Sep 17 00:00:00 2001 From: zhenyan121 <3367366583@qq.com> Date: Tue, 16 Jun 2026 13:53:47 +0800 Subject: [PATCH] feat(rendering): add basic diffuse and ambient lighting to block rendering --- assets/shaders/block_f_shader.glsl | 24 +++++++++- assets/shaders/block_v_shader.glsl | 15 +++++- include/Cubed/constants.hpp | 8 ++-- include/Cubed/gameplay/vertex_data.hpp | 2 +- include/Cubed/gameplay/world.hpp | 3 ++ include/Cubed/primitive_data.hpp | 66 +++++++++++++++++++++++++- include/Cubed/renderer.hpp | 3 +- src/gameplay/chunk.cpp | 16 +++++-- src/gameplay/vertex_data.cpp | 16 ++++--- src/gameplay/world.cpp | 2 + src/renderer.cpp | 12 +++++ 11 files changed, 146 insertions(+), 21 deletions(-) diff --git a/assets/shaders/block_f_shader.glsl b/assets/shaders/block_f_shader.glsl index 2523ed7..89921be 100644 --- a/assets/shaders/block_f_shader.glsl +++ b/assets/shaders/block_f_shader.glsl @@ -1,15 +1,35 @@ #version 460 in vec2 tc; +in vec3 normal; +in vec3 vert_pos; flat in int tex_layer; out vec4 color; layout (binding = 0) uniform sampler2DArray samp; +uniform float ambientStrength; +uniform vec3 sunlightColor; +uniform vec3 sunlightDir; + void main(void) { - color = texture(samp, vec3(tc, tex_layer)); - if (color.a < 0.8) { + vec4 objectColor = texture(samp, vec3(tc, tex_layer)); + + if (objectColor.a < 0.8) { discard; } + + vec3 lightDir = normalize(sunlightDir); + + vec3 ambient = ambientStrength * sunlightColor; + + vec3 norm = normalize(normal); + + float diff = max(dot(norm, lightDir), 0.0); + + vec3 diffuse = diff * sunlightColor; + + color = vec4((ambient + diffuse) * objectColor.rgb, objectColor.a); + //color = varyingColor; } diff --git a/assets/shaders/block_v_shader.glsl b/assets/shaders/block_v_shader.glsl index 317b55e..971fd4f 100644 --- a/assets/shaders/block_v_shader.glsl +++ b/assets/shaders/block_v_shader.glsl @@ -3,7 +3,10 @@ layout (location = 0) in vec3 pos; layout (location = 1) in vec2 texCoord; layout (location = 2) in float layer; +layout (location = 3) in vec3 aNormal; out vec2 tc; +out vec3 normal; +out vec3 vert_pos; flat out int tex_layer; mat4 buildRotateX(float rad); @@ -13,13 +16,21 @@ mat4 buildTranslate(float x, float y, float z); uniform mat4 mv_matrix; uniform mat4 proj_matrix; - +uniform mat4 norm_matrix; void main(void) { - gl_Position = proj_matrix * mv_matrix * vec4(pos, 1.0); + vec4 viewPos = mv_matrix * vec4(pos, 1.0); + + vert_pos = viewPos.xyz; + tc = texCoord; + tex_layer = int(layer); + + normal = mat3(norm_matrix) * aNormal; + + gl_Position = proj_matrix * viewPos; } mat4 buildTranslate(float x, float y, float z) { diff --git a/include/Cubed/constants.hpp b/include/Cubed/constants.hpp index ccfd053..5f806c0 100644 --- a/include/Cubed/constants.hpp +++ b/include/Cubed/constants.hpp @@ -23,9 +23,11 @@ constexpr float DEFAULT_MAX_RUN_SPEED = 7.0f; constexpr float DEFAULT_ACCELERATION = 10.0f; constexpr float DEFAULT_DECELERATION = 15.0f; constexpr float DEFAULT_G = 22.5f; -static constexpr int SIZE_X = CHUNK_SIZE; -static constexpr int SIZE_Y = WORLD_SIZE_Y; -static constexpr int SIZE_Z = CHUNK_SIZE; +constexpr int SIZE_X = CHUNK_SIZE; +constexpr int SIZE_Y = WORLD_SIZE_Y; +constexpr int SIZE_Z = CHUNK_SIZE; + +constexpr float AMBIENT_STRENGTH = 0.3f; constexpr ChunkPos CHUNK_DIR[]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}, {1, 1}, {-1, 1}, {1, -1}, {-1, -1}}; diff --git a/include/Cubed/gameplay/vertex_data.hpp b/include/Cubed/gameplay/vertex_data.hpp index aafed9d..b3ae5bb 100644 --- a/include/Cubed/gameplay/vertex_data.hpp +++ b/include/Cubed/gameplay/vertex_data.hpp @@ -7,7 +7,7 @@ namespace Cubed { class World; struct VertexData { - std::vector m_vertices; + std::vector m_vertices; GLuint m_vbo = 0; GLuint m_vao = 0; std::atomic m_sum{0}; diff --git a/include/Cubed/gameplay/world.hpp b/include/Cubed/gameplay/world.hpp index fec1ad5..dbad426 100644 --- a/include/Cubed/gameplay/world.hpp +++ b/include/Cubed/gameplay/world.hpp @@ -40,6 +40,7 @@ private: using ChunkPosSet = std::unordered_set; using ChunkHashMap = std::unordered_map; glm::vec3 m_gen_player_pos{0.0f, 0.0f, 0.0f}; + glm::vec3 m_sunlight_dir{1.0f, 2.0f, 1.0f}; ChunkHashMap m_chunks; std::unordered_map m_players; std::vector m_planes; @@ -125,6 +126,8 @@ public: RiverWorm& river_worm(); std::vector& planes(); std::vector& render_snapshots(); + + glm::vec3 sunlight_dir() const; }; } // namespace Cubed diff --git a/include/Cubed/primitive_data.hpp b/include/Cubed/primitive_data.hpp index 2d3336f..f289f89 100644 --- a/include/Cubed/primitive_data.hpp +++ b/include/Cubed/primitive_data.hpp @@ -91,6 +91,51 @@ constexpr float TEX_COORDS[6][6][2] = { {0.0f, 1.0f}, // back left {0.0f, 0.0f}} // front left }; + +constexpr float NORMALS[6][6][3] = { + // ===== front (z = +1) ===== + {{0.0f, 0.0f, 1.0f}, + {0.0f, 0.0f, 1.0f}, + {0.0f, 0.0f, 1.0f}, + {0.0f, 0.0f, 1.0f}, + {0.0f, 0.0f, 1.0f}, + {0.0f, 0.0f, 1.0f}}, + // ===== right (x = +1) ===== + {{1.0f, 0.0f, 0.0f}, + {1.0f, 0.0f, 0.0f}, + {1.0f, 0.0f, 0.0f}, + {1.0f, 0.0f, 0.0f}, + {1.0f, 0.0f, 0.0f}, + {1.0f, 0.0f, 0.0f}}, + // ===== back (z = -1) ===== + {{0.0f, 0.0f, -1.0f}, + {0.0f, 0.0f, -1.0f}, + {0.0f, 0.0f, -1.0f}, + {0.0f, 0.0f, -1.0f}, + {0.0f, 0.0f, -1.0f}, + {0.0f, 0.0f, -1.0f}}, + // ===== left (x = -1) ===== + {{-1.0f, 0.0f, 0.0f}, + {-1.0f, 0.0f, 0.0f}, + {-1.0f, 0.0f, 0.0f}, + {-1.0f, 0.0f, 0.0f}, + {-1.0f, 0.0f, 0.0f}, + {-1.0f, 0.0f, 0.0f}}, + // ===== top (y = +1) ===== + {{0.0f, 1.0f, 0.0f}, + {0.0f, 1.0f, 0.0f}, + {0.0f, 1.0f, 0.0f}, + {0.0f, 1.0f, 0.0f}, + {0.0f, 1.0f, 0.0f}, + {0.0f, 1.0f, 0.0f}}, + // ===== bottom (y = -1) ===== + {{0.0f, -1.0f, 0.0f}, + {0.0f, -1.0f, 0.0f}, + {0.0f, -1.0f, 0.0f}, + {0.0f, -1.0f, 0.0f}, + {0.0f, -1.0f, 0.0f}, + {0.0f, -1.0f, 0.0f}}}; + #pragma endregion constexpr float CUBE_VER[24] = {0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, @@ -148,6 +193,24 @@ constexpr float CROSS_TEX_COORDS[2][6][2] = { {1.0f, 1.0f}, // bottom right {0.0f, 1.0f}}, // bottom left }; + +constexpr float CROSS_NORMALS[2][6][3] = { + // ===== Plane 1: upward ===== + {{0.0f, 1.0f, 0.0f}, + {0.0f, 1.0f, 0.0f}, + {0.0f, 1.0f, 0.0f}, + {0.0f, 1.0f, 0.0f}, + {0.0f, 1.0f, 0.0f}, + {0.0f, 1.0f, 0.0f}}, + + // ===== Plane 2: upward ===== + {{0.0f, 1.0f, 0.0f}, + {0.0f, 1.0f, 0.0f}, + {0.0f, 1.0f, 0.0f}, + {0.0f, 1.0f, 0.0f}, + {0.0f, 1.0f, 0.0f}, + {0.0f, 1.0f, 0.0f}}}; + #pragma endregion constexpr float QUAD_VERTICES[] = { @@ -156,10 +219,11 @@ constexpr float QUAD_VERTICES[] = { -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f}; -struct Vertex { +struct Vertex3D { float x = 0.0f, y = 0.0f, z = 0.0f; float s = 0.0f, t = 0.0f; float layer = 0.0f; + float nx = 0.0f, ny = 0.0f, nz = 0.0f; }; struct Vertex2D { diff --git a/include/Cubed/renderer.hpp b/include/Cubed/renderer.hpp index d8d1265..5bee9a6 100644 --- a/include/Cubed/renderer.hpp +++ b/include/Cubed/renderer.hpp @@ -30,6 +30,7 @@ public: void updata_framebuffer(int width, int height); private: + static constexpr glm::vec3 SUNLIGHT_COLOR{1.0f, 1.0f, 1.0f}; const Camera& m_camera; DevPanel& m_dev_panel; const TextureManager& m_texture_manager; @@ -43,7 +44,7 @@ private: float m_width = 0.0f; float m_height = 0.0f; - glm::mat4 m_p_mat, m_v_mat, m_m_mat, m_mv_mat, m_mvp_mat; + glm::mat4 m_p_mat, m_v_mat, m_m_mat, m_mv_mat, m_mvp_mat, m_norm_mat; GLuint m_mv_loc = 0; GLuint m_proj_loc = 0; diff --git a/src/gameplay/chunk.cpp b/src/gameplay/chunk.cpp index 2fc9ae9..a8b1a70 100644 --- a/src/gameplay/chunk.cpp +++ b/src/gameplay/chunk.cpp @@ -366,13 +366,18 @@ void Chunk::gen_vertices(const OptionalBlockVectorArray& neighbor_block) { cur_id); } for (int i = 0; i < 6; i++) { - Vertex vex = { + Vertex3D vex = { VERTICES_POS[face][i][0] + (float)world_x * 1.0f, VERTICES_POS[face][i][1] + (float)world_y * 1.0f, VERTICES_POS[face][i][2] + (float)world_z * 1.0f, TEX_COORDS[face][i][0], TEX_COORDS[face][i][1], - static_cast(cur_id * 6 + face) + + static_cast(cur_id * 6 + face), + + NORMALS[face][i][0], + NORMALS[face][i][1], + NORMALS[face][i][2] }; if (BlockManager::is_transparent(cur_id)) { @@ -413,13 +418,16 @@ void Chunk::gen_cross_plane_vertices(int world_x, int world_y, int world_z, } for (int face = 0; face < 2; face++) { for (int i = 0; i < 6; i++) { - Vertex vex = { + Vertex3D vex = { CROSS_VERTICES_POS[face][i][0] + (float)world_x * 1.0f, CROSS_VERTICES_POS[face][i][1] + (float)world_y * 1.0f, CROSS_VERTICES_POS[face][i][2] + (float)world_z * 1.0f, CROSS_TEX_COORDS[face][i][0], CROSS_TEX_COORDS[face][i][1], - static_cast(BlockManager::cross_plane_index(id)) + static_cast(BlockManager::cross_plane_index(id)), + CROSS_NORMALS[face][i][0], + CROSS_NORMALS[face][i][1], + CROSS_NORMALS[face][i][2] }; m_vertex_data[1].m_vertices.emplace_back(vex); diff --git a/src/gameplay/vertex_data.cpp b/src/gameplay/vertex_data.cpp index ea1805a..de1db0c 100644 --- a/src/gameplay/vertex_data.cpp +++ b/src/gameplay/vertex_data.cpp @@ -41,18 +41,20 @@ void VertexData::upload() { } glBindVertexArray(m_vao); glBindBuffer(GL_ARRAY_BUFFER, m_vbo); - glBufferData(GL_ARRAY_BUFFER, m_vertices.size() * sizeof(Vertex), + glBufferData(GL_ARRAY_BUFFER, m_vertices.size() * sizeof(Vertex3D), m_vertices.data(), GL_DYNAMIC_DRAW); - 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)); - + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex3D), (void*)0); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex3D), + (void*)offsetof(Vertex3D, s)); + glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, sizeof(Vertex3D), + (void*)offsetof(Vertex3D, layer)); + glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex3D), + (void*)offsetof(Vertex3D, nx)); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); glEnableVertexAttribArray(2); + glEnableVertexAttribArray(3); glBindVertexArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0); diff --git a/src/gameplay/world.cpp b/src/gameplay/world.cpp index 21b337e..d074e65 100644 --- a/src/gameplay/world.cpp +++ b/src/gameplay/world.cpp @@ -1006,4 +1006,6 @@ std::vector& World::planes() { return m_planes; } std::vector& World::render_snapshots() { return m_render_snapshots; }; +glm::vec3 World::sunlight_dir() const { return m_sunlight_dir; } + } // namespace Cubed \ No newline at end of file diff --git a/src/renderer.cpp b/src/renderer.cpp index a1c06e8..ea75290 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -439,8 +439,20 @@ void Renderer::render_world() { m_m_mat = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, 0.0f)); m_v_mat = m_camera.get_camera_lookat(); m_mv_mat = m_v_mat * m_m_mat; + m_norm_mat = glm::transpose(glm::inverse(m_mv_mat)); + glm::vec3 light_dir_view = + glm::normalize(glm::mat3(m_v_mat) * m_world.sunlight_dir()); + glUniformMatrix4fv(m_mv_loc, 1, GL_FALSE, glm::value_ptr(m_mv_mat)); glUniformMatrix4fv(m_proj_loc, 1, GL_FALSE, glm::value_ptr(m_p_mat)); + glUniformMatrix4fv(normal_block_shader.loc("norm_matrix"), 1, GL_FALSE, + glm::value_ptr(m_norm_mat)); + glUniform1f(normal_block_shader.loc("ambientStrength"), AMBIENT_STRENGTH); + glUniform3fv(normal_block_shader.loc("sunlightColor"), 1, + glm::value_ptr(SUNLIGHT_COLOR)); + glUniform3fv(normal_block_shader.loc("sunlightDir"), 1, + glm::value_ptr(light_dir_view)); + m_mvp_mat = m_p_mat * m_mv_mat; auto& camera_pos = m_camera.get_camera_pos();