diff --git a/assets/data/block/air.toml b/assets/data/block/air.toml index 0a15eea..2b16aa3 100644 --- a/assets/data/block/air.toml +++ b/assets/data/block/air.toml @@ -1,5 +1,7 @@ id = 0 +is_blend = false is_cross_plane = false +is_discard = true is_gas = true is_liquid = false is_passable = true diff --git a/assets/data/block/dirt.toml b/assets/data/block/dirt.toml index 8c1af59..f62f7e3 100644 --- a/assets/data/block/dirt.toml +++ b/assets/data/block/dirt.toml @@ -1,5 +1,7 @@ id = 2 +is_blend = false is_cross_plane = false +is_discard = false is_gas = false is_liquid = false is_passable = false diff --git a/assets/data/block/grass.toml b/assets/data/block/grass.toml index 05a911b..4eccd44 100644 --- a/assets/data/block/grass.toml +++ b/assets/data/block/grass.toml @@ -1,5 +1,7 @@ id = 9 +is_blend = false is_cross_plane = true +is_discard = true is_gas = false is_liquid = false is_passable = true diff --git a/assets/data/block/grass_block.toml b/assets/data/block/grass_block.toml index 266c892..84bdf57 100644 --- a/assets/data/block/grass_block.toml +++ b/assets/data/block/grass_block.toml @@ -1,5 +1,7 @@ id = 1 +is_blend = false is_cross_plane = false +is_discard = false is_gas = false is_liquid = false is_passable = false diff --git a/assets/data/block/leaf.toml b/assets/data/block/leaf.toml index 3fc5943..ef8ba3f 100644 --- a/assets/data/block/leaf.toml +++ b/assets/data/block/leaf.toml @@ -1,5 +1,7 @@ id = 6 +is_blend = false is_cross_plane = false +is_discard = true is_gas = false is_liquid = false is_passable = false diff --git a/assets/data/block/log.toml b/assets/data/block/log.toml index 40eb1a5..1dea710 100644 --- a/assets/data/block/log.toml +++ b/assets/data/block/log.toml @@ -1,5 +1,7 @@ id = 5 +is_blend = false is_cross_plane = false +is_discard = false is_gas = false is_liquid = false is_passable = false diff --git a/assets/data/block/sand.toml b/assets/data/block/sand.toml index 0ec5867..bb23bbc 100644 --- a/assets/data/block/sand.toml +++ b/assets/data/block/sand.toml @@ -1,5 +1,7 @@ id = 4 +is_blend = false is_cross_plane = false +is_discard = false is_gas = false is_liquid = false is_passable = false diff --git a/assets/data/block/snowy_grass_block.toml b/assets/data/block/snowy_grass_block.toml index 94f6e36..f6b501a 100644 --- a/assets/data/block/snowy_grass_block.toml +++ b/assets/data/block/snowy_grass_block.toml @@ -1,5 +1,7 @@ id = 8 +is_blend = false is_cross_plane = false +is_discard = false is_gas = false is_liquid = false is_passable = false diff --git a/assets/data/block/stone.toml b/assets/data/block/stone.toml index df5b889..b5dddd3 100644 --- a/assets/data/block/stone.toml +++ b/assets/data/block/stone.toml @@ -1,5 +1,7 @@ id = 3 +is_blend = false is_cross_plane = false +is_discard = false is_gas = false is_liquid = false is_passable = false diff --git a/assets/data/block/template.toml b/assets/data/block/template.toml index 8f4e951..4832ece 100644 --- a/assets/data/block/template.toml +++ b/assets/data/block/template.toml @@ -5,3 +5,5 @@ is_gas = false is_passable = false is_cross_plane = false is_transparent = false +is_discard = false +is_blend = false diff --git a/assets/data/block/water.toml b/assets/data/block/water.toml index 710ec0a..ed808b6 100644 --- a/assets/data/block/water.toml +++ b/assets/data/block/water.toml @@ -1,5 +1,7 @@ id = 7 +is_blend = true is_cross_plane = false +is_discard = false is_gas = false is_liquid = true is_passable = true diff --git a/assets/shaders/block_f_shader.glsl b/assets/shaders/block_f_shader.glsl index e9ad2be..0be6e6f 100644 --- a/assets/shaders/block_f_shader.glsl +++ b/assets/shaders/block_f_shader.glsl @@ -8,7 +8,7 @@ layout (binding = 0) uniform sampler2DArray samp; void main(void) { color = texture(samp, vec3(tc, tex_layer)); - if (color.a < 0.1) { + if (color.a < 0.45) { discard; } //color = varyingColor; diff --git a/include/Cubed/gameplay/block.hpp b/include/Cubed/gameplay/block.hpp index b81b90e..c6c6770 100644 --- a/include/Cubed/gameplay/block.hpp +++ b/include/Cubed/gameplay/block.hpp @@ -47,11 +47,16 @@ struct BlockData { bool is_passable = false; bool is_cross_plane = false; bool is_transparent = false; + + bool is_discard = false; + bool is_blend = false; + BlockData(BlockType b_id, std::string_view b_name, bool liquid, - bool passable, bool cross_plane, bool transparent, bool gas) + bool passable, bool cross_plane, bool transparent, bool gas, + bool discard, bool blend) : name(b_name), id(b_id), is_liquid(liquid), is_gas(gas), is_passable(passable), is_cross_plane(cross_plane), - is_transparent(transparent) {} + is_transparent(transparent), is_discard(discard), is_blend(blend) {} }; class BlockManager { @@ -69,6 +74,10 @@ public: static bool is_cross_plane(BlockType id); static bool is_transparent(BlockType id); static bool is_passable(BlockType id); + + static bool is_discard(BlockType id); + static bool is_blend(BlockType id); + static BlockType cross_plane_index(BlockType id); private: diff --git a/include/Cubed/gameplay/chunk.hpp b/include/Cubed/gameplay/chunk.hpp index 0f51b10..7fc4d00 100644 --- a/include/Cubed/gameplay/chunk.hpp +++ b/include/Cubed/gameplay/chunk.hpp @@ -17,7 +17,7 @@ private: static constexpr int SIZE_X = CHUNK_SIZE; static constexpr int SIZE_Y = WORLD_SIZE_Y; static constexpr int SIZE_Z = CHUNK_SIZE; - + static constexpr int VERTEX_DATA_SUM = 4; std::atomic m_dirty{false}; std::atomic m_need_upload{true}; std::atomic m_is_on_gen_vertex_data{false}; @@ -35,7 +35,8 @@ private: /* 0 - normal 1 - cross_plane - 2 - transparent + 2 - normal_discard + 3 - transparent and blend */ std::vector m_vertex_data; float frequency = 0.01f; @@ -45,9 +46,10 @@ private: BiomeConditions m_conditions; void clear_dirty(); - void gen_normal_vertices( + void gen_vertices( const std::array*, 4>& neighbor_block); - void gen_cross_plane_vertices(); + void gen_cross_plane_vertices(int world_x, int world_y, int world_z, + BlockType id); public: Chunk(World& world, ChunkPos chunk_pos); @@ -105,8 +107,11 @@ public: GLuint get_cross_vbo() const; size_t get_cross_vertices_sum() const; - GLuint get_transparent_vbo() const; - size_t get_transparent_vertices_sum() const; + GLuint get_normal_discard_vbo() const; + size_t get_normal_discard_vertices_sum() const; + + GLuint get_normal_blend_vbo() const; + size_t get_normal_blend_vertices_sum() const; bool is_dirty() const; void mark_dirty(); diff --git a/include/Cubed/gameplay/world.hpp b/include/Cubed/gameplay/world.hpp index b676856..0cf158e 100644 --- a/include/Cubed/gameplay/world.hpp +++ b/include/Cubed/gameplay/world.hpp @@ -19,8 +19,10 @@ struct ChunkRenderSnapshot { size_t normal_vertices_count; GLuint cross_vbo; size_t cross_vertices_count; - GLuint transparent_vbo; - size_t transparent_vertices_count; + GLuint normal_discard_vbo; + size_t normal_discard_vertices_count; + GLuint normal_blend_vbo; + size_t normal_blend_vertices_count; glm::vec3 center; glm::vec3 half_extents; }; diff --git a/src/block.cpp b/src/block.cpp index 6074a12..ddb3b4a 100644 --- a/src/block.cpp +++ b/src/block.cpp @@ -90,6 +90,21 @@ bool BlockManager::is_passable(BlockType id) { return m_datas[id].is_passable; } +bool BlockManager::is_discard(BlockType id) { + if (id >= sums()) { + Logger::error("Id {}, is Over The Max Id", id, sums() - 1); + return m_datas[0].is_discard; + } + return m_datas[id].is_discard; +} +bool BlockManager::is_blend(BlockType id) { + if (id >= sums()) { + Logger::error("Id {}, is Over The Max Id", id, sums() - 1); + return m_datas[0].is_blend; + } + return m_datas[id].is_blend; +} + void BlockManager::init() { fs::path data_path{block_data_dir}; @@ -125,8 +140,11 @@ void BlockManager::init() { auto is_cross_plane = safe_get_value(block, "is_cross_plane", false); auto is_transparent = safe_get_value(block, "is_transparent", false); auto is_gas = safe_get_value(block, "is_gas", false); + auto is_discard = safe_get_value(block, "is_discard", false); + auto is_blend = safe_get_value(block, "is_blend", false); m_datas.emplace_back(*id, *name, *is_liquid, *is_passable, - *is_cross_plane, *is_transparent, *is_gas); + *is_cross_plane, *is_transparent, *is_gas, + *is_discard, *is_blend); } std::sort( m_datas.begin(), m_datas.end(), diff --git a/src/gameplay/chunk.cpp b/src/gameplay/chunk.cpp index ed3b77a..38c5e59 100644 --- a/src/gameplay/chunk.cpp +++ b/src/gameplay/chunk.cpp @@ -10,7 +10,7 @@ namespace Cubed { Chunk::Chunk(World& world, ChunkPos chunk_pos) : m_chunk_pos(chunk_pos), m_world(world) { - for (int i = 0; i < 3; i++) { + for (int i = 0; i < VERTEX_DATA_SUM; i++) { m_vertex_data.emplace_back(m_world); } } @@ -115,8 +115,7 @@ void Chunk::gen_vertex_data( data.m_vertices.clear(); } - gen_normal_vertices(neighbor_block); - gen_cross_plane_vertices(); + gen_vertices(neighbor_block); for (auto& data : m_vertex_data) { data.update_sum(); } @@ -138,11 +137,16 @@ size_t Chunk::get_cross_vertices_sum() const { return m_vertex_data[1].m_sum.load(); } -GLuint Chunk::get_transparent_vbo() const { return m_vertex_data[2].m_vbo; } -size_t Chunk::get_transparent_vertices_sum() const { +GLuint Chunk::get_normal_discard_vbo() const { return m_vertex_data[2].m_vbo; } +size_t Chunk::get_normal_discard_vertices_sum() const { return m_vertex_data[2].m_sum.load(); } +GLuint Chunk::get_normal_blend_vbo() const { return m_vertex_data[3].m_vbo; } +size_t Chunk::get_normal_blend_vertices_sum() const { + return m_vertex_data[3].m_sum.load(); +} + void Chunk::gen_phase_one() { m_generator = std::make_unique(*this); if (!m_generator) { @@ -258,7 +262,7 @@ unsigned Chunk::seed() const { BiomeConditions& Chunk::conditions() { return m_conditions; } -void Chunk::gen_normal_vertices( +void Chunk::gen_vertices( const std::array*, 4>& neighbor_block) { static const glm::ivec3 DIR[6] = {{0, 0, 1}, {1, 0, 0}, {0, 0, -1}, {-1, 0, 0}, {0, 1, 0}, {0, -1, 0}}; @@ -355,6 +359,10 @@ void Chunk::gen_normal_vertices( if (neighbor_culled) { continue; } + if (BlockManager::is_cross_plane(cur_id)) { + gen_cross_plane_vertices(world_x, world_y, world_z, + cur_id); + } for (int i = 0; i < 6; i++) { Vertex vex = { VERTICES_POS[face][i][0] + (float)world_x * 1.0f, @@ -366,7 +374,17 @@ void Chunk::gen_normal_vertices( }; if (BlockManager::is_transparent(cur_id)) { - m_vertex_data[2].m_vertices.emplace_back(vex); + if (BlockManager::is_discard(cur_id)) { + m_vertex_data[2].m_vertices.emplace_back(vex); + } else if (BlockManager::is_blend(cur_id)) { + m_vertex_data[3].m_vertices.emplace_back(vex); + } else { + Logger::warn("Id {} is transparent but not " + "discard or blend", + cur_id); + m_vertex_data[3].m_vertices.emplace_back(vex); + } + } else { m_vertex_data[0].m_vertices.emplace_back(vex); } @@ -376,40 +394,30 @@ void Chunk::gen_normal_vertices( } } } -void Chunk::gen_cross_plane_vertices() { +void Chunk::gen_cross_plane_vertices(int world_x, int world_y, int world_z, + BlockType id) { - for (int x = 0; x < SIZE_X; x++) { - for (int y = 0; y < SIZE_Y; y++) { - for (int z = 0; z < SIZE_Z; z++) { - int world_x = x + m_chunk_pos.x * CHUNK_SIZE; - int world_z = z + m_chunk_pos.z * CHUNK_SIZE; - int world_y = y; - int id = m_blocks[index(x, y, z)]; + if (!BlockManager::is_cross_plane(id)) { + Logger::warn("Block {} {} {} id {} is not cross plane", world_x, + world_y, world_z, id); + return; + } + for (int face = 0; face < 2; face++) { + for (int i = 0; i < 6; i++) { + Vertex 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)) - if (!BlockManager::is_cross_plane(id)) { - continue; - } - for (int face = 0; face < 2; face++) { - for (int i = 0; i < 6; i++) { - Vertex 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)) - - }; - m_vertex_data[1].m_vertices.emplace_back(vex); - } - } - } + }; + m_vertex_data[1].m_vertices.emplace_back(vex); } } - // Logger::info("Cross Sum {}", m_cross_vertices_sum.load()); } +// Logger::info("Cross Sum {}", m_cross_vertices_sum.load()); + } // namespace Cubed diff --git a/src/gameplay/world.cpp b/src/gameplay/world.cpp index 6c7e8e6..81a3b89 100644 --- a/src/gameplay/world.cpp +++ b/src/gameplay/world.cpp @@ -319,6 +319,58 @@ void World::render(const glm::mat4& mvp_matrix, rendered_sum++; } } + // cross_plane and normal discard + + for (const auto& snapshot : m_render_snapshots) { + if (!is_aabb_in_frustum(snapshot.center, snapshot.half_extents)) { + continue; + } + glm::vec2 camera_pos_xz{camera_pos.x, camera_pos.z}; + if (snapshot.cross_vertices_count != 0) { + glm::vec2 center_xz{snapshot.center.x, snapshot.center.z}; + float dist2d = glm::distance(camera_pos_xz, center_xz); + if (dist2d <= CROSS_PLANE_DISTANCE * 16) { + glBindTexture(GL_TEXTURE_2D_ARRAY, + texture_manager.get_cross_plane_array()); + glBindBuffer(GL_ARRAY_BUFFER, snapshot.cross_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, snapshot.cross_vertices_count); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + } + if (snapshot.normal_discard_vertices_count != 0) { + glBindTexture(GL_TEXTURE_2D_ARRAY, + texture_manager.get_texture_array()); + glBindBuffer(GL_ARRAY_BUFFER, snapshot.normal_discard_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, + snapshot.normal_discard_vertices_count); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + } + + // blend block + glDepthMask(GL_FALSE); struct SortableSnapshot { @@ -326,8 +378,7 @@ void World::render(const glm::mat4& mvp_matrix, float distance; }; - std::vector cross_list; - std::vector transparent_list; + std::vector blend_list; for (const auto& snapshot : m_render_snapshots) { @@ -336,51 +387,19 @@ void World::render(const glm::mat4& mvp_matrix, } float dist = glm::distance(camera_pos, snapshot.center); - glm::vec2 camera_pos_xz{camera_pos.x, camera_pos.z}; - if (snapshot.cross_vertices_count != 0) { - glm::vec2 center_xz{snapshot.center.x, snapshot.center.z}; - float dist2d = glm::distance(camera_pos_xz, center_xz); - if (dist2d <= CROSS_PLANE_DISTANCE * 16) { - cross_list.push_back({&snapshot, dist}); - } - } - if (snapshot.transparent_vertices_count != 0) { - transparent_list.push_back({&snapshot, dist}); + if (snapshot.normal_blend_vertices_count != 0) { + blend_list.push_back({&snapshot, dist}); } } - std::sort(transparent_list.begin(), transparent_list.end(), - [](const SortableSnapshot& a, const SortableSnapshot& b) { - return a.distance > b.distance; - }); - std::sort(cross_list.begin(), cross_list.end(), + std::sort(blend_list.begin(), blend_list.end(), [](const SortableSnapshot& a, const SortableSnapshot& b) { return a.distance > b.distance; }); - for (const auto& item : cross_list) { - const auto& snapshot = *item.snapshot; - glBindTexture(GL_TEXTURE_2D_ARRAY, - texture_manager.get_cross_plane_array()); - glBindBuffer(GL_ARRAY_BUFFER, snapshot.cross_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, snapshot.cross_vertices_count); - glBindBuffer(GL_ARRAY_BUFFER, 0); - } - - for (const auto& item : transparent_list) { + for (const auto& item : blend_list) { const auto& snapshot = *item.snapshot; glBindTexture(GL_TEXTURE_2D_ARRAY, texture_manager.get_texture_array()); - glBindBuffer(GL_ARRAY_BUFFER, snapshot.transparent_vbo); + glBindBuffer(GL_ARRAY_BUFFER, snapshot.normal_blend_vbo); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), @@ -392,7 +411,7 @@ void World::render(const glm::mat4& mvp_matrix, glEnableVertexAttribArray(1); glEnableVertexAttribArray(2); - glDrawArrays(GL_TRIANGLES, 0, snapshot.transparent_vertices_count); + glDrawArrays(GL_TRIANGLES, 0, snapshot.normal_blend_vertices_count); glBindBuffer(GL_ARRAY_BUFFER, 0); } @@ -966,8 +985,10 @@ void World::update(float delta_time) { m_render_snapshots.push_back( {chunk.get_normal_vbo(), chunk.get_normal_vertices_sum(), chunk.get_cross_vbo(), chunk.get_cross_vertices_sum(), - chunk.get_transparent_vbo(), - chunk.get_transparent_vertices_sum(), + chunk.get_normal_discard_vbo(), + chunk.get_normal_discard_vertices_sum(), + chunk.get_normal_blend_vbo(), + chunk.get_normal_blend_vertices_sum(), glm::vec3(static_cast(pos.x * CHUNK_SIZE) + static_cast(CHUNK_SIZE / 2), static_cast(WORLD_SIZE_Y / 2),