From f40d09cb8f712e87691af4912f3630d92d692779 Mon Sep 17 00:00:00 2001 From: untodesu Date: Thu, 11 Dec 2025 15:14:26 +0500 Subject: Shuffle stuff around - Use the new and improved hierarchy I figured out when making Prospero chat - Re-add NSIS scripts, again from Prospero - Update most build and utility scripts with their most recent versions --- game/client/world/CMakeLists.txt | 21 -- game/client/world/chunk_mesher.cc | 450 ---------------------------------- game/client/world/chunk_mesher.hh | 18 -- game/client/world/chunk_quad.hh | 41 ---- game/client/world/chunk_renderer.cc | 204 --------------- game/client/world/chunk_renderer.hh | 8 - game/client/world/chunk_vbo.hh | 22 -- game/client/world/chunk_visibility.cc | 90 ------- game/client/world/chunk_visibility.hh | 6 - game/client/world/outline.cc | 150 ------------ game/client/world/outline.hh | 16 -- game/client/world/player_target.cc | 64 ----- game/client/world/player_target.hh | 17 -- game/client/world/skybox.cc | 11 - game/client/world/skybox.hh | 11 - game/client/world/voxel_anims.cc | 33 --- game/client/world/voxel_anims.hh | 13 - game/client/world/voxel_atlas.cc | 185 -------------- game/client/world/voxel_atlas.hh | 28 --- game/client/world/voxel_sounds.cc | 83 ------- game/client/world/voxel_sounds.hh | 19 -- 21 files changed, 1490 deletions(-) delete mode 100644 game/client/world/CMakeLists.txt delete mode 100644 game/client/world/chunk_mesher.cc delete mode 100644 game/client/world/chunk_mesher.hh delete mode 100644 game/client/world/chunk_quad.hh delete mode 100644 game/client/world/chunk_renderer.cc delete mode 100644 game/client/world/chunk_renderer.hh delete mode 100644 game/client/world/chunk_vbo.hh delete mode 100644 game/client/world/chunk_visibility.cc delete mode 100644 game/client/world/chunk_visibility.hh delete mode 100644 game/client/world/outline.cc delete mode 100644 game/client/world/outline.hh delete mode 100644 game/client/world/player_target.cc delete mode 100644 game/client/world/player_target.hh delete mode 100644 game/client/world/skybox.cc delete mode 100644 game/client/world/skybox.hh delete mode 100644 game/client/world/voxel_anims.cc delete mode 100644 game/client/world/voxel_anims.hh delete mode 100644 game/client/world/voxel_atlas.cc delete mode 100644 game/client/world/voxel_atlas.hh delete mode 100644 game/client/world/voxel_sounds.cc delete mode 100644 game/client/world/voxel_sounds.hh (limited to 'game/client/world') diff --git a/game/client/world/CMakeLists.txt b/game/client/world/CMakeLists.txt deleted file mode 100644 index fdf96bf..0000000 --- a/game/client/world/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ -target_sources(vclient PRIVATE - "${CMAKE_CURRENT_LIST_DIR}/chunk_mesher.cc" - "${CMAKE_CURRENT_LIST_DIR}/chunk_mesher.hh" - "${CMAKE_CURRENT_LIST_DIR}/chunk_quad.hh" - "${CMAKE_CURRENT_LIST_DIR}/chunk_renderer.cc" - "${CMAKE_CURRENT_LIST_DIR}/chunk_renderer.hh" - "${CMAKE_CURRENT_LIST_DIR}/chunk_vbo.hh" - "${CMAKE_CURRENT_LIST_DIR}/chunk_visibility.cc" - "${CMAKE_CURRENT_LIST_DIR}/chunk_visibility.hh" - "${CMAKE_CURRENT_LIST_DIR}/outline.cc" - "${CMAKE_CURRENT_LIST_DIR}/outline.hh" - "${CMAKE_CURRENT_LIST_DIR}/player_target.cc" - "${CMAKE_CURRENT_LIST_DIR}/player_target.hh" - "${CMAKE_CURRENT_LIST_DIR}/skybox.cc" - "${CMAKE_CURRENT_LIST_DIR}/skybox.hh" - "${CMAKE_CURRENT_LIST_DIR}/voxel_anims.cc" - "${CMAKE_CURRENT_LIST_DIR}/voxel_anims.hh" - "${CMAKE_CURRENT_LIST_DIR}/voxel_atlas.cc" - "${CMAKE_CURRENT_LIST_DIR}/voxel_atlas.hh" - "${CMAKE_CURRENT_LIST_DIR}/voxel_sounds.cc" - "${CMAKE_CURRENT_LIST_DIR}/voxel_sounds.hh") diff --git a/game/client/world/chunk_mesher.cc b/game/client/world/chunk_mesher.cc deleted file mode 100644 index da90d2e..0000000 --- a/game/client/world/chunk_mesher.cc +++ /dev/null @@ -1,450 +0,0 @@ -#include "client/pch.hh" - -#include "client/world/chunk_mesher.hh" - -#include "core/math/crc64.hh" - -#include "core/threading.hh" - -#include "shared/world/chunk.hh" -#include "shared/world/dimension.hh" -#include "shared/world/voxel.hh" -#include "shared/world/voxel_registry.hh" - -#include "shared/coord.hh" - -#include "client/world/chunk_quad.hh" -#include "client/world/voxel_atlas.hh" - -#include "client/globals.hh" -#include "client/session.hh" - -using QuadBuilder = std::vector; - -using CachedChunkCoord = unsigned short; -constexpr static CachedChunkCoord CPOS_ITSELF = 0x0000; -constexpr static CachedChunkCoord CPOS_NORTH = 0x0001; -constexpr static CachedChunkCoord CPOS_SOUTH = 0x0002; -constexpr static CachedChunkCoord CPOS_EAST = 0x0003; -constexpr static CachedChunkCoord CPOS_WEST = 0x0004; -constexpr static CachedChunkCoord CPOS_TOP = 0x0005; -constexpr static CachedChunkCoord CPOS_BOTTOM = 0x0006; -constexpr static const size_t NUM_CACHED_CPOS = 7; - -static const CachedChunkCoord get_cached_cpos(const chunk_pos& pivot, const chunk_pos& cpos) -{ - static const CachedChunkCoord nx[3] = { CPOS_WEST, 0, CPOS_EAST }; - static const CachedChunkCoord ny[3] = { CPOS_BOTTOM, 0, CPOS_TOP }; - static const CachedChunkCoord nz[3] = { CPOS_NORTH, 0, CPOS_SOUTH }; - - if(pivot != cpos) { - chunk_pos delta = pivot - cpos; - delta[0] = glm::clamp(delta[0], -1, 1); - delta[1] = glm::clamp(delta[1], -1, 1); - delta[2] = glm::clamp(delta[2], -1, 1); - - if(delta[0]) { - return nx[delta[0] + 1]; - } - else if(delta[1]) { - return ny[delta[1] + 1]; - } - else { - return nz[delta[2] + 1]; - } - } - - return CPOS_ITSELF; -} - -class GL_MeshingTask final : public Task { -public: - explicit GL_MeshingTask(entt::entity entity, const chunk_pos& cpos); - virtual ~GL_MeshingTask(void) = default; - virtual void process(void) override; - virtual void finalize(void) override; - -private: - bool vis_test(const world::Voxel* voxel, const local_pos& lpos) const; - void push_quad_a(const world::Voxel* voxel, const glm::fvec3& pos, const glm::fvec2& size, world::VoxelFace face); - void push_quad_v(const world::Voxel* voxel, const glm::fvec3& pos, const glm::fvec2& size, world::VoxelFace face, std::size_t entropy); - void make_cube(const world::Voxel* voxel, const local_pos& lpos, world::VoxelVisBits vis, std::size_t entropy); - void cache_chunk(const chunk_pos& cpos); - -private: - std::array m_cache; - std::vector m_quads_b; // blending - std::vector m_quads_s; // solid - entt::entity m_entity; - chunk_pos m_cpos; -}; - -GL_MeshingTask::GL_MeshingTask(entt::entity entity, const chunk_pos& cpos) -{ - m_entity = entity; - m_cpos = cpos; - - cache_chunk(m_cpos); - cache_chunk(m_cpos + DIR_NORTH); - cache_chunk(m_cpos + DIR_SOUTH); - cache_chunk(m_cpos + DIR_EAST); - cache_chunk(m_cpos + DIR_WEST); - cache_chunk(m_cpos + DIR_DOWN); - cache_chunk(m_cpos + DIR_UP); -} - -void GL_MeshingTask::process(void) -{ - m_quads_b.resize(world::voxel_atlas::plane_count()); - m_quads_s.resize(world::voxel_atlas::plane_count()); - - const auto& voxels = m_cache.at(CPOS_ITSELF); - - for(std::size_t i = 0; i < CHUNK_VOLUME; ++i) { - if(m_status == task_status::CANCELLED) { - m_quads_b.clear(); - m_quads_s.clear(); - return; - } - - const auto lpos = coord::to_local(i); - const auto voxel = world::voxel_registry::find(voxels[i]); - - if(voxel == nullptr) { - // Either a NULL_VOXEL_ID or something went - // horribly wrong and we don't what this is - continue; - } - - unsigned int vis = 0U; - - if(vis_test(voxel, lpos + DIR_NORTH)) { - vis |= world::VVIS_NORTH; - } - - if(vis_test(voxel, lpos + DIR_SOUTH)) { - vis |= world::VVIS_SOUTH; - } - - if(vis_test(voxel, lpos + DIR_EAST)) { - vis |= world::VVIS_EAST; - } - - if(vis_test(voxel, lpos + DIR_WEST)) { - vis |= world::VVIS_WEST; - } - - if(vis_test(voxel, lpos + DIR_UP)) { - vis |= world::VVIS_UP; - } - - if(vis_test(voxel, lpos + DIR_DOWN)) { - vis |= world::VVIS_DOWN; - } - - const auto vpos = coord::to_voxel(m_cpos, lpos); - const auto entropy_src = vpos[0] * vpos[1] * vpos[2]; - const auto entropy = math::crc64(&entropy_src, sizeof(entropy_src)); - - // FIXME: handle different voxel types - make_cube(voxel, lpos, world::VoxelVisBits(vis), entropy); - } -} - -void GL_MeshingTask::finalize(void) -{ - if(!globals::dimension || !globals::dimension->chunks.valid(m_entity)) { - // We either disconnected or something - // else happened that invalidated the entity - return; - } - - auto& component = globals::dimension->chunks.emplace_or_replace(m_entity); - - const std::size_t plane_count_nb = m_quads_s.size(); - const std::size_t plane_count_b = m_quads_b.size(); - - bool has_no_submeshes_b = true; - bool has_no_submeshes_nb = true; - - component.quad_nb.resize(plane_count_nb); - component.quad_b.resize(plane_count_b); - - for(std::size_t plane = 0; plane < plane_count_nb; ++plane) { - auto& builder = m_quads_s[plane]; - auto& buffer = component.quad_nb[plane]; - - if(builder.empty()) { - if(buffer.handle) { - glDeleteBuffers(1, &buffer.handle); - buffer.handle = 0; - buffer.size = 0; - } - } - else { - if(!buffer.handle) { - glGenBuffers(1, &buffer.handle); - } - - glBindBuffer(GL_ARRAY_BUFFER, buffer.handle); - glBufferData(GL_ARRAY_BUFFER, sizeof(world::ChunkQuad) * builder.size(), builder.data(), GL_STATIC_DRAW); - buffer.size = builder.size(); - has_no_submeshes_nb = false; - } - } - - for(std::size_t plane = 0; plane < plane_count_b; ++plane) { - auto& builder = m_quads_b[plane]; - auto& buffer = component.quad_b[plane]; - - if(builder.empty()) { - if(buffer.handle) { - glDeleteBuffers(1, &buffer.handle); - buffer.handle = 0; - buffer.size = 0; - } - } - else { - if(!buffer.handle) { - glGenBuffers(1, &buffer.handle); - } - - glBindBuffer(GL_ARRAY_BUFFER, buffer.handle); - glBufferData(GL_ARRAY_BUFFER, sizeof(world::ChunkQuad) * builder.size(), builder.data(), GL_STATIC_DRAW); - buffer.size = builder.size(); - has_no_submeshes_b = false; - } - } - - if(has_no_submeshes_b && has_no_submeshes_nb) { - globals::dimension->chunks.remove(m_entity); - } -} - -bool GL_MeshingTask::vis_test(const world::Voxel* voxel, const local_pos& lpos) const -{ - const auto pvpos = coord::to_voxel(m_cpos, lpos); - const auto pcpos = coord::to_chunk(pvpos); - const auto plpos = coord::to_local(pvpos); - const auto index = coord::to_index(plpos); - - const auto cached_cpos = get_cached_cpos(m_cpos, pcpos); - const auto& voxels = m_cache.at(cached_cpos); - const auto neighbour = world::voxel_registry::find(voxels[index]); - - bool result; - - if(neighbour == nullptr) { - result = true; - } - else if(neighbour == voxel) { - result = false; - } - else if(neighbour->get_render_mode() != voxel->get_render_mode()) { - result = true; - } - else { - result = false; - } - - return result; -} - -void GL_MeshingTask::push_quad_a(const world::Voxel* voxel, const glm::fvec3& pos, const glm::fvec2& size, world::VoxelFace face) -{ - auto cached_offset = voxel->get_cached_face_offset(face); - auto cached_plane = voxel->get_cached_face_plane(face); - auto& textures = voxel->get_face_textures(face); - - switch(voxel->get_render_mode()) { - case world::VRENDER_OPAQUE: - m_quads_s[cached_plane].push_back(make_chunk_quad(pos, size, face, cached_offset, textures.size())); - break; - - case world::VRENDER_BLEND: - m_quads_b[cached_plane].push_back(make_chunk_quad(pos, size, face, cached_offset, textures.size())); - break; - } -} - -void GL_MeshingTask::push_quad_v(const world::Voxel* voxel, const glm::fvec3& pos, const glm::fvec2& size, world::VoxelFace face, - std::size_t entropy) -{ - auto cached_offset = voxel->get_cached_face_offset(face); - auto cached_plane = voxel->get_cached_face_plane(face); - auto& textures = voxel->get_face_textures(face); - auto index = entropy % textures.size(); - - switch(voxel->get_render_mode()) { - case world::VRENDER_OPAQUE: - m_quads_s[cached_plane].push_back(make_chunk_quad(pos, size, face, cached_offset + index, 0)); - break; - - case world::VRENDER_BLEND: - m_quads_b[cached_plane].push_back(make_chunk_quad(pos, size, face, cached_offset + index, 0)); - break; - } -} - -void GL_MeshingTask::make_cube(const world::Voxel* voxel, const local_pos& lpos, world::VoxelVisBits vis, std::size_t entropy) -{ - const glm::fvec3 fpos = glm::fvec3(lpos); - const glm::fvec2 fsize = glm::fvec2(1.0f, 1.0f); - - if(voxel->is_animated()) { - if(vis & world::VVIS_NORTH) { - push_quad_a(voxel, fpos, fsize, world::VFACE_NORTH); - } - - if(vis & world::VVIS_SOUTH) { - push_quad_a(voxel, fpos, fsize, world::VFACE_SOUTH); - } - - if(vis & world::VVIS_EAST) { - push_quad_a(voxel, fpos, fsize, world::VFACE_EAST); - } - - if(vis & world::VVIS_WEST) { - push_quad_a(voxel, fpos, fsize, world::VFACE_WEST); - } - - if(vis & world::VVIS_UP) { - push_quad_a(voxel, fpos, fsize, world::VFACE_TOP); - } - - if(vis & world::VVIS_DOWN) { - push_quad_a(voxel, fpos, fsize, world::VFACE_BOTTOM); - } - } - else { - if(vis & world::VVIS_NORTH) { - push_quad_v(voxel, fpos, fsize, world::VFACE_NORTH, entropy); - } - - if(vis & world::VVIS_SOUTH) { - push_quad_v(voxel, fpos, fsize, world::VFACE_SOUTH, entropy); - } - - if(vis & world::VVIS_EAST) { - push_quad_v(voxel, fpos, fsize, world::VFACE_EAST, entropy); - } - - if(vis & world::VVIS_WEST) { - push_quad_v(voxel, fpos, fsize, world::VFACE_WEST, entropy); - } - - if(vis & world::VVIS_UP) { - push_quad_v(voxel, fpos, fsize, world::VFACE_TOP, entropy); - } - - if(vis & world::VVIS_DOWN) { - push_quad_v(voxel, fpos, fsize, world::VFACE_BOTTOM, entropy); - } - } -} - -void GL_MeshingTask::cache_chunk(const chunk_pos& cpos) -{ - const auto index = get_cached_cpos(m_cpos, cpos); - - if(const auto chunk = globals::dimension->find_chunk(cpos)) { - m_cache[index] = chunk->get_voxels(); - return; - } -} - -// Bogus internal flag component -struct NeedsMeshingComponent final {}; - -static void on_chunk_create(const world::ChunkCreateEvent& event) -{ - const std::array neighbours = { - event.cpos + DIR_NORTH, - event.cpos + DIR_SOUTH, - event.cpos + DIR_EAST, - event.cpos + DIR_WEST, - event.cpos + DIR_UP, - event.cpos + DIR_DOWN, - }; - - globals::dimension->chunks.emplace_or_replace(event.chunk->get_entity()); - - for(const chunk_pos& cpos : neighbours) { - if(const world::Chunk* chunk = globals::dimension->find_chunk(cpos)) { - globals::dimension->chunks.emplace_or_replace(chunk->get_entity()); - continue; - } - } -} - -static void on_chunk_update(const world::ChunkUpdateEvent& event) -{ - const std::array neighbours = { - event.cpos + DIR_NORTH, - event.cpos + DIR_SOUTH, - event.cpos + DIR_EAST, - event.cpos + DIR_WEST, - event.cpos + DIR_UP, - event.cpos + DIR_DOWN, - }; - - globals::dimension->chunks.emplace_or_replace(event.chunk->get_entity()); - - for(const chunk_pos& cpos : neighbours) { - if(const world::Chunk* chunk = globals::dimension->find_chunk(cpos)) { - globals::dimension->chunks.emplace_or_replace(chunk->get_entity()); - continue; - } - } -} - -static void on_voxel_set(const world::VoxelSetEvent& event) -{ - globals::dimension->chunks.emplace_or_replace(event.chunk->get_entity()); - - std::vector neighbours; - - for(int dim = 0; dim < 3; dim += 1) { - chunk_pos offset = chunk_pos(0, 0, 0); - offset[dim] = 1; - - if(event.lpos[dim] == 0) { - neighbours.push_back(event.cpos - offset); - continue; - } - - if(event.lpos[dim] == (CHUNK_SIZE - 1)) { - neighbours.push_back(event.cpos + offset); - continue; - } - } - - for(const chunk_pos& cpos : neighbours) { - if(const world::Chunk* chunk = globals::dimension->find_chunk(cpos)) { - globals::dimension->chunks.emplace_or_replace(chunk->get_entity()); - continue; - } - } -} - -void world::chunk_mesher::init(void) -{ - globals::dispatcher.sink().connect<&on_chunk_create>(); - globals::dispatcher.sink().connect<&on_chunk_update>(); - globals::dispatcher.sink().connect<&on_voxel_set>(); -} - -void world::chunk_mesher::shutdown(void) -{ -} - -void world::chunk_mesher::update(void) -{ - if(session::is_ingame()) { - const auto group = globals::dimension->chunks.group(entt::get); - for(const auto [entity, chunk] : group.each()) { - globals::dimension->chunks.remove(entity); - threading::submit(entity, chunk.cpos); - } - } -} diff --git a/game/client/world/chunk_mesher.hh b/game/client/world/chunk_mesher.hh deleted file mode 100644 index 1ef5035..0000000 --- a/game/client/world/chunk_mesher.hh +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include "client/world/chunk_vbo.hh" - -namespace world -{ -struct ChunkMesh final { - std::vector quad_nb; - std::vector quad_b; -}; -} // namespace world - -namespace world::chunk_mesher -{ -void init(void); -void shutdown(void); -void update(void); -} // namespace world::chunk_mesher diff --git a/game/client/world/chunk_quad.hh b/game/client/world/chunk_quad.hh deleted file mode 100644 index d68977e..0000000 --- a/game/client/world/chunk_quad.hh +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include "core/math/constexpr.hh" - -#include "shared/world/voxel_registry.hh" - -namespace world -{ -// [0] XXXXXXXXYYYYYYYYZZZZZZZZWWWWHHHH -// [1] FFFFTTTTTTTTTTTAAAAA------------ -using ChunkQuad = std::array; -} // namespace world - -namespace world -{ -constexpr inline static ChunkQuad make_chunk_quad(const glm::fvec3& position, const glm::fvec2& size, VoxelFace face, std::size_t texture, - std::size_t frames) -{ - ChunkQuad result = {}; - result[0] = 0x00000000; - result[1] = 0x00000000; - - // [0] XXXXXXXXYYYYYYYYZZZZZZZZ-------- - result[0] |= (0x000000FFU & static_cast(position.x * 16.0f)) << 24U; - result[0] |= (0x000000FFU & static_cast(position.y * 16.0f)) << 16U; - result[0] |= (0x000000FFU & static_cast(position.z * 16.0f)) << 8U; - - // [0] ------------------------WWWWHHHH - result[0] |= (0x0000000FU & static_cast(size.x * 16.0f - 1.0f)) << 4U; - result[0] |= (0x0000000FU & static_cast(size.y * 16.0f - 1.0f)); - - // [1] FFFF---------------------------- - result[1] |= (0x0000000FU & static_cast(face)) << 28U; - - // [1] ----TTTTTTTTTTTAAAAA------------ - result[1] |= (0x000007FFU & static_cast(texture)) << 17U; - result[1] |= (0x0000001FU & static_cast(frames)) << 12U; - - return result; -} -} // namespace world diff --git a/game/client/world/chunk_renderer.cc b/game/client/world/chunk_renderer.cc deleted file mode 100644 index 1b195d7..0000000 --- a/game/client/world/chunk_renderer.cc +++ /dev/null @@ -1,204 +0,0 @@ -#include "client/pch.hh" - -#include "client/world/chunk_renderer.hh" - -#include "core/config/boolean.hh" -#include "core/config/number.hh" - -#include "core/io/config_map.hh" - -#include "shared/world/chunk.hh" -#include "shared/world/dimension.hh" - -#include "shared/coord.hh" - -#include "client/entity/camera.hh" - -#include "client/gui/settings.hh" - -#include "client/world/chunk_mesher.hh" -#include "client/world/chunk_quad.hh" -#include "client/world/outline.hh" -#include "client/world/skybox.hh" -#include "client/world/voxel_anims.hh" -#include "client/world/voxel_atlas.hh" - -#include "client/game.hh" -#include "client/globals.hh" -#include "client/program.hh" -#include "client/toggles.hh" - -// ONLY TOUCH THESE IF THE RESPECTIVE SHADER -// VARIANT MACRO DECLARATIONS LAYOUT CHANGED AS WELL -constexpr static unsigned int WORLD_CURVATURE = 0U; -constexpr static unsigned int WORLD_FOG = 1U; - -static config::Boolean depth_sort_chunks(true); - -static GL_Program quad_program; -static std::size_t u_quad_vproj_matrix; -static std::size_t u_quad_world_position; -static std::size_t u_quad_timings; -static std::size_t u_quad_fog_color; -static std::size_t u_quad_view_distance; -static std::size_t u_quad_textures; -static GLuint quad_vaobj; -static GLuint quad_vbo; - -void world::chunk_renderer::init(void) -{ - globals::client_config.add_value("chunk_renderer.depth_sort_chunks", depth_sort_chunks); - - settings::add_checkbox(5, depth_sort_chunks, settings_location::VIDEO, "chunk_renderer.depth_sort_chunks", false); - - if(!quad_program.setup("shaders/chunk_quad.vert", "shaders/chunk_quad.frag")) { - spdlog::critical("chunk_renderer: quad_program: setup failed"); - std::terminate(); - } - - u_quad_vproj_matrix = quad_program.add_uniform("u_ViewProjMatrix"); - u_quad_world_position = quad_program.add_uniform("u_WorldPosition"); - u_quad_timings = quad_program.add_uniform("u_Timings"); - u_quad_fog_color = quad_program.add_uniform("u_FogColor"); - u_quad_view_distance = quad_program.add_uniform("u_ViewDistance"); - u_quad_textures = quad_program.add_uniform("u_Textures"); - - const glm::fvec3 vertices[4] = { - glm::fvec3(1.0f, 0.0f, 1.0f), - glm::fvec3(1.0f, 0.0f, 0.0f), - glm::fvec3(0.0f, 0.0f, 1.0f), - glm::fvec3(0.0f, 0.0f, 0.0f), - }; - - glGenVertexArrays(1, &quad_vaobj); - glBindVertexArray(quad_vaobj); - - glGenBuffers(1, &quad_vbo); - glBindBuffer(GL_ARRAY_BUFFER, quad_vbo); - glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); - - glEnableVertexAttribArray(0); - glVertexAttribDivisor(0, 0); - glVertexAttribPointer(0, 3, GL_FLOAT, false, sizeof(glm::fvec3), nullptr); -} - -void world::chunk_renderer::shutdown(void) -{ - glDeleteBuffers(1, &quad_vbo); - glDeleteVertexArrays(1, &quad_vaobj); - quad_program.destroy(); -} - -void world::chunk_renderer::render(void) -{ - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LEQUAL); - glLineWidth(1.0f); - - if(toggles::get(TOGGLE_WIREFRAME)) { - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - } - else { - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - } - - quad_program.set_variant_vert(WORLD_CURVATURE, client_game::world_curvature.get_value()); - quad_program.set_variant_vert(WORLD_FOG, client_game::fog_mode.get_value()); - quad_program.set_variant_frag(WORLD_FOG, client_game::fog_mode.get_value()); - - if(!quad_program.update()) { - spdlog::critical("chunk_renderer: quad_program: update failed"); - quad_program.destroy(); - std::terminate(); - } - - GLuint timings[3]; - timings[0] = globals::window_frametime; - timings[1] = globals::window_frametime_avg; - timings[2] = world::voxel_anims::frame; - - const auto group = globals::dimension->chunks.group(entt::get); - - if(depth_sort_chunks.get_value()) { - // FIXME: speed! sorting every frame doesn't look - // like a good idea. Can we store the group elsewhere and - // still have all the up-to-date chunk things inside? - group.sort([](entt::entity ea, entt::entity eb) { - const auto dir_a = globals::dimension->chunks.get(ea).cpos - entity::camera::position_chunk; - const auto dir_b = globals::dimension->chunks.get(eb).cpos - entity::camera::position_chunk; - - const auto da = dir_a[0] * dir_a[0] + dir_a[1] * dir_a[1] + dir_a[2] * dir_a[2]; - const auto db = dir_b[0] * dir_b[0] + dir_b[1] * dir_b[1] + dir_b[2] * dir_b[2]; - - return da > db; - }); - } - - for(std::size_t plane_id = 0; plane_id < world::voxel_atlas::plane_count(); ++plane_id) { - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D_ARRAY, world::voxel_atlas::plane_texture(plane_id)); - - glBindVertexArray(quad_vaobj); - - glUseProgram(quad_program.handle); - glUniformMatrix4fv(quad_program.uniforms[u_quad_vproj_matrix].location, 1, false, glm::value_ptr(entity::camera::matrix)); - glUniform3uiv(quad_program.uniforms[u_quad_timings].location, 1, timings); - glUniform4fv(quad_program.uniforms[u_quad_fog_color].location, 1, glm::value_ptr(world::skybox::fog_color)); - glUniform1f(quad_program.uniforms[u_quad_view_distance].location, entity::camera::view_distance.get_value() * CHUNK_SIZE); - glUniform1i(quad_program.uniforms[u_quad_textures].location, 0); // GL_TEXTURE0 - - glDisable(GL_BLEND); - - glEnable(GL_CULL_FACE); - glCullFace(GL_BACK); - glFrontFace(GL_CCW); - - for(const auto [entity, chunk, mesh] : group.each()) { - if(plane_id < mesh.quad_nb.size() && mesh.quad_nb[plane_id].handle && mesh.quad_nb[plane_id].size) { - const auto wpos = coord::to_fvec3(chunk.cpos - entity::camera::position_chunk); - glUniform3fv(quad_program.uniforms[u_quad_world_position].location, 1, glm::value_ptr(wpos)); - - glBindBuffer(GL_ARRAY_BUFFER, mesh.quad_nb[plane_id].handle); - - glEnableVertexAttribArray(1); - glVertexAttribDivisor(1, 1); - glVertexAttribIPointer(1, 2, GL_UNSIGNED_INT, sizeof(ChunkQuad), nullptr); - - glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, mesh.quad_nb[plane_id].size); - - globals::num_drawcalls += 1; - globals::num_triangles += 2 * mesh.quad_nb[plane_id].size; - } - } - - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - for(const auto [entity, chunk, mesh] : group.each()) { - if(plane_id < mesh.quad_b.size() && mesh.quad_b[plane_id].handle && mesh.quad_b[plane_id].size) { - const auto wpos = coord::to_fvec3(chunk.cpos - entity::camera::position_chunk); - glUniform3fv(quad_program.uniforms[u_quad_world_position].location, 1, glm::value_ptr(wpos)); - - glBindBuffer(GL_ARRAY_BUFFER, mesh.quad_b[plane_id].handle); - - glEnableVertexAttribArray(1); - glVertexAttribDivisor(1, 1); - glVertexAttribIPointer(1, 2, GL_UNSIGNED_INT, sizeof(ChunkQuad), nullptr); - - glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, mesh.quad_b[plane_id].size); - - globals::num_drawcalls += 1; - globals::num_triangles += 2 * mesh.quad_b[plane_id].size; - } - } - } - - if(toggles::get(TOGGLE_CHUNK_AABB)) { - world::outline::prepare(); - - for(const auto [entity, chunk, mesh] : group.each()) { - const auto size = glm::fvec3(CHUNK_SIZE, CHUNK_SIZE, CHUNK_SIZE); - world::outline::cube(chunk.cpos, glm::fvec3(0.0f, 0.0f, 0.0f), size, 1.0f, glm::fvec4(1.0f, 1.0f, 0.0f, 1.0f)); - } - } -} diff --git a/game/client/world/chunk_renderer.hh b/game/client/world/chunk_renderer.hh deleted file mode 100644 index 88b381f..0000000 --- a/game/client/world/chunk_renderer.hh +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -namespace world::chunk_renderer -{ -void init(void); -void shutdown(void); -void render(void); -} // namespace world::chunk_renderer diff --git a/game/client/world/chunk_vbo.hh b/game/client/world/chunk_vbo.hh deleted file mode 100644 index 9fedf0d..0000000 --- a/game/client/world/chunk_vbo.hh +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -namespace world -{ -class ChunkVBO final { -public: - std::size_t size; - GLuint handle; - -public: - inline ~ChunkVBO(void) - { - // The ChunkVBO structure is meant to be a part - // of the ChunkMesh component within the EnTT registry; - // When the registry is cleaned or a chunk is removed, components - // are expected to be safely disposed of so we need a destructor; - if(handle) { - glDeleteBuffers(1, &handle); - } - } -}; -} // namespace world diff --git a/game/client/world/chunk_visibility.cc b/game/client/world/chunk_visibility.cc deleted file mode 100644 index e8828ee..0000000 --- a/game/client/world/chunk_visibility.cc +++ /dev/null @@ -1,90 +0,0 @@ -#include "client/pch.hh" - -#include "client/world/chunk_visibility.hh" - -#include "core/config/number.hh" - -#include "core/math/vectors.hh" - -#include "shared/world/chunk.hh" -#include "shared/world/chunk_aabb.hh" -#include "shared/world/dimension.hh" - -#include "shared/protocol.hh" - -#include "client/entity/camera.hh" - -#include "client/globals.hh" -#include "client/session.hh" - -// Sending a somewhat large amount of network packets -// can easily overwhelm both client, server and the network -// channel created between the two. To prevent this from happening -// we throttle the client's ever increasing itch for new chunks -constexpr static unsigned int MAX_CHUNKS_REQUESTS_PER_FRAME = 16U; - -static world::ChunkAABB current_view_box; -static world::ChunkAABB previous_view_box; -static std::vector requests; - -static void update_requests(void) -{ - requests.clear(); - - for(auto cx = current_view_box.min.x; cx != current_view_box.max.x; cx += 1) - for(auto cy = current_view_box.min.y; cy != current_view_box.max.y; cy += 1) - for(auto cz = current_view_box.min.z; cz != current_view_box.max.z; cz += 1) { - auto cpos = chunk_pos(cx, cy, cz); - - if(!globals::dimension->find_chunk(cpos)) { - requests.push_back(cpos); - } - } - - std::sort(requests.begin(), requests.end(), [](const chunk_pos& cpos_a, const chunk_pos& cpos_b) { - auto da = math::distance2(cpos_a, entity::camera::position_chunk); - auto db = math::distance2(cpos_b, entity::camera::position_chunk); - return da > db; - }); -} - -void world::chunk_visibility::update_late(void) -{ - current_view_box.min = entity::camera::position_chunk - static_cast(entity::camera::view_distance.get_value()); - current_view_box.max = entity::camera::position_chunk + static_cast(entity::camera::view_distance.get_value()); - - if(!session::is_ingame()) { - // This makes sure the previous view box - // is always different from the current one - previous_view_box.min = chunk_pos(INT32_MIN, INT32_MIN, INT32_MIN); - previous_view_box.max = chunk_pos(INT32_MAX, INT32_MAX, INT32_MAX); - return; - } - - if((current_view_box.min != previous_view_box.min) || (current_view_box.max != previous_view_box.max)) { - update_requests(); - } - - for(unsigned int i = 0U; i < MAX_CHUNKS_REQUESTS_PER_FRAME; ++i) { - if(requests.empty()) { - // Done sending requests - break; - } - - protocol::RequestChunk packet; - packet.cpos = requests.back(); - protocol::send(session::peer, protocol::encode(packet)); - - requests.pop_back(); - } - - auto view = globals::dimension->chunks.view(); - - for(const auto [entity, chunk] : view.each()) { - if(!current_view_box.contains(chunk.cpos)) { - globals::dimension->remove_chunk(entity); - } - } - - previous_view_box = current_view_box; -} diff --git a/game/client/world/chunk_visibility.hh b/game/client/world/chunk_visibility.hh deleted file mode 100644 index e9b2d89..0000000 --- a/game/client/world/chunk_visibility.hh +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -namespace world::chunk_visibility -{ -void update_late(void); -} // namespace world::chunk_visibility diff --git a/game/client/world/outline.cc b/game/client/world/outline.cc deleted file mode 100644 index 62f9624..0000000 --- a/game/client/world/outline.cc +++ /dev/null @@ -1,150 +0,0 @@ -#include "client/pch.hh" - -#include "client/world/outline.hh" - -#include "core/config/boolean.hh" -#include "core/config/number.hh" - -#include "shared/coord.hh" - -#include "client/entity/camera.hh" - -#include "client/const.hh" -#include "client/game.hh" -#include "client/program.hh" - -// ONLY TOUCH THESE IF THE RESPECTIVE SHADER -// VARIANT MACRO DECLARATIONS LAYOUT CHANGED AS WELL -constexpr static unsigned int WORLD_CURVATURE = 0U; - -static GL_Program program; -static std::size_t u_vpmatrix; -static std::size_t u_worldpos; -static std::size_t u_viewdist; -static std::size_t u_modulate; -static std::size_t u_scale; - -static GLuint vaobj; -static GLuint cube_vbo; -static GLuint line_vbo; - -void world::outline::init(void) -{ - if(!program.setup("shaders/outline.vert", "shaders/outline.frag")) { - spdlog::critical("outline: program setup failed"); - std::terminate(); - } - - u_vpmatrix = program.add_uniform("u_ViewProjMatrix"); - u_worldpos = program.add_uniform("u_WorldPosition"); - u_viewdist = program.add_uniform("u_ViewDistance"); - u_modulate = program.add_uniform("u_Modulate"); - u_scale = program.add_uniform("u_Scale"); - - const glm::fvec3 cube_vertices[24] = { - glm::fvec3(0.0f, 0.0f, 0.0f), - glm::fvec3(0.0f, 1.0f, 0.0f), - glm::fvec3(0.0f, 1.0f, 0.0f), - glm::fvec3(1.0f, 1.0f, 0.0f), - glm::fvec3(1.0f, 1.0f, 0.0f), - glm::fvec3(1.0f, 0.0f, 0.0f), - glm::fvec3(1.0f, 0.0f, 0.0f), - glm::fvec3(0.0f, 0.0f, 0.0f), - - glm::fvec3(0.0f, 0.0f, 1.0f), - glm::fvec3(0.0f, 1.0f, 1.0f), - glm::fvec3(0.0f, 1.0f, 1.0f), - glm::fvec3(1.0f, 1.0f, 1.0f), - glm::fvec3(1.0f, 1.0f, 1.0f), - glm::fvec3(1.0f, 0.0f, 1.0f), - glm::fvec3(1.0f, 0.0f, 1.0f), - glm::fvec3(0.0f, 0.0f, 1.0f), - - glm::fvec3(0.0f, 0.0f, 0.0f), - glm::fvec3(0.0f, 0.0f, 1.0f), - glm::fvec3(0.0f, 1.0f, 0.0f), - glm::fvec3(0.0f, 1.0f, 1.0f), - glm::fvec3(1.0f, 0.0f, 0.0f), - glm::fvec3(1.0f, 0.0f, 1.0f), - glm::fvec3(1.0f, 1.0f, 0.0f), - glm::fvec3(1.0f, 1.0f, 1.0f), - }; - - glGenBuffers(1, &cube_vbo); - glBindBuffer(GL_ARRAY_BUFFER, cube_vbo); - glBufferData(GL_ARRAY_BUFFER, sizeof(cube_vertices), cube_vertices, GL_STATIC_DRAW); - - const glm::fvec3 line_vertices[2] = { - glm::fvec3(0.0f, 0.0f, 0.0f), - glm::fvec3(1.0f, 1.0f, 1.0f), - }; - - glGenBuffers(1, &line_vbo); - glBindBuffer(GL_ARRAY_BUFFER, line_vbo); - glBufferData(GL_ARRAY_BUFFER, sizeof(line_vertices), line_vertices, GL_STATIC_DRAW); - - glGenVertexArrays(1, &vaobj); - - glBindVertexArray(vaobj); - glEnableVertexAttribArray(0); - glVertexAttribDivisor(0, 0); -} - -void world::outline::shutdown(void) -{ - glDeleteVertexArrays(1, &vaobj); - glDeleteBuffers(1, &line_vbo); - glDeleteBuffers(1, &cube_vbo); - program.destroy(); -} - -void world::outline::prepare(void) -{ - program.set_variant_vert(WORLD_CURVATURE, client_game::world_curvature.get_value()); - - if(!program.update()) { - spdlog::critical("outline_renderer: program update failed"); - std::terminate(); - } - - glDisable(GL_CULL_FACE); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - - glUseProgram(program.handle); - glUniformMatrix4fv(program.uniforms[u_vpmatrix].location, 1, false, glm::value_ptr(entity::camera::matrix)); - glUniform1f(program.uniforms[u_viewdist].location, CHUNK_SIZE * entity::camera::view_distance.get_value()); - - glBindVertexArray(vaobj); - glEnableVertexAttribArray(0); - glVertexAttribDivisor(0, 0); -} - -void world::outline::cube(const chunk_pos& cpos, const glm::fvec3& fpos, const glm::fvec3& size, float thickness, const glm::fvec4& color) -{ - auto patch_cpos = cpos - entity::camera::position_chunk; - - glLineWidth(thickness); - - glUniform3fv(program.uniforms[u_worldpos].location, 1, glm::value_ptr(coord::to_fvec3(patch_cpos, fpos))); - glUniform4fv(program.uniforms[u_modulate].location, 1, glm::value_ptr(color)); - glUniform3fv(program.uniforms[u_scale].location, 1, glm::value_ptr(size)); - - glBindBuffer(GL_ARRAY_BUFFER, cube_vbo); - glVertexAttribPointer(0, 3, GL_FLOAT, false, sizeof(glm::fvec3), nullptr); - glDrawArrays(GL_LINES, 0, 24); -} - -void world::outline::line(const chunk_pos& cpos, const glm::fvec3& fpos, const glm::fvec3& size, float thickness, const glm::fvec4& color) -{ - auto patch_cpos = cpos - entity::camera::position_chunk; - - glLineWidth(thickness); - - glUniform3fv(program.uniforms[u_worldpos].location, 1, glm::value_ptr(coord::to_fvec3(patch_cpos, fpos))); - glUniform4fv(program.uniforms[u_modulate].location, 1, glm::value_ptr(color)); - glUniform3fv(program.uniforms[u_scale].location, 1, glm::value_ptr(size)); - - glBindBuffer(GL_ARRAY_BUFFER, line_vbo); - glVertexAttribPointer(0, 3, GL_FLOAT, false, sizeof(glm::fvec3), nullptr); - glDrawArrays(GL_LINES, 0, 2); -} diff --git a/game/client/world/outline.hh b/game/client/world/outline.hh deleted file mode 100644 index bd69ecc..0000000 --- a/game/client/world/outline.hh +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include "shared/types.hh" - -namespace world::outline -{ -void init(void); -void shutdown(void); -void prepare(void); -} // namespace world::outline - -namespace world::outline -{ -void cube(const chunk_pos& cpos, const glm::fvec3& fpos, const glm::fvec3& size, float thickness, const glm::fvec4& color); -void line(const chunk_pos& cpos, const glm::fvec3& fpos, const glm::fvec3& size, float thickness, const glm::fvec4& color); -} // namespace world::outline diff --git a/game/client/world/player_target.cc b/game/client/world/player_target.cc deleted file mode 100644 index 3ede47e..0000000 --- a/game/client/world/player_target.cc +++ /dev/null @@ -1,64 +0,0 @@ -#include "client/pch.hh" - -#include "client/world/player_target.hh" - -#include "shared/world/dimension.hh" -#include "shared/world/ray_dda.hh" - -#include "shared/coord.hh" - -#include "client/entity/camera.hh" -#include "client/world/outline.hh" - -#include "client/game.hh" -#include "client/globals.hh" -#include "client/session.hh" - -constexpr static float MAX_REACH = 16.0f; - -voxel_pos world::player_target::coord; -voxel_pos world::player_target::normal; -const world::Voxel* world::player_target::voxel; - -void world::player_target::init(void) -{ - world::player_target::coord = voxel_pos(); - world::player_target::normal = voxel_pos(); - world::player_target::voxel = nullptr; -} - -void world::player_target::update(void) -{ - if(session::is_ingame()) { - RayDDA ray(globals::dimension, entity::camera::position_chunk, entity::camera::position_local, entity::camera::direction); - - do { - world::player_target::voxel = ray.step(); - - if(world::player_target::voxel) { - world::player_target::coord = ray.vpos; - world::player_target::normal = ray.vnormal; - break; - } - - world::player_target::coord = voxel_pos(); - world::player_target::normal = voxel_pos(); - } while(ray.distance < MAX_REACH); - } - else { - world::player_target::voxel = nullptr; - world::player_target::coord = voxel_pos(); - world::player_target::normal = voxel_pos(); - } -} - -void world::player_target::render(void) -{ - if(world::player_target::voxel && !client_game::hide_hud) { - auto cpos = coord::to_chunk(world::player_target::coord); - auto fpos = coord::to_local(world::player_target::coord); - - world::outline::prepare(); - world::outline::cube(cpos, glm::fvec3(fpos), glm::fvec3(1.0f), 2.0f, glm::fvec4(0.0f, 0.0f, 0.0f, 1.0f)); - } -} diff --git a/game/client/world/player_target.hh b/game/client/world/player_target.hh deleted file mode 100644 index 34532c3..0000000 --- a/game/client/world/player_target.hh +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include "shared/world/voxel_registry.hh" - -namespace world::player_target -{ -extern voxel_pos coord; -extern voxel_pos normal; -extern const Voxel* voxel; -} // namespace world::player_target - -namespace world::player_target -{ -void init(void); -void update(void); -void render(void); -} // namespace world::player_target diff --git a/game/client/world/skybox.cc b/game/client/world/skybox.cc deleted file mode 100644 index cfff141..0000000 --- a/game/client/world/skybox.cc +++ /dev/null @@ -1,11 +0,0 @@ -#include "client/pch.hh" - -#include "client/world/skybox.hh" - -glm::fvec3 world::skybox::fog_color; - -void world::skybox::init(void) -{ - // https://convertingcolors.com/hex-color-B1F3FF.html - world::skybox::fog_color = glm::fvec3(0.690f, 0.950f, 1.000f); -} diff --git a/game/client/world/skybox.hh b/game/client/world/skybox.hh deleted file mode 100644 index 39a514b..0000000 --- a/game/client/world/skybox.hh +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -namespace world::skybox -{ -extern glm::fvec3 fog_color; -} // namespace world::skybox - -namespace world::skybox -{ -void init(void); -} // namespace world::skybox diff --git a/game/client/world/voxel_anims.cc b/game/client/world/voxel_anims.cc deleted file mode 100644 index 185d463..0000000 --- a/game/client/world/voxel_anims.cc +++ /dev/null @@ -1,33 +0,0 @@ -#include "client/pch.hh" - -#include "client/world/voxel_anims.hh" - -#include "core/config/number.hh" - -#include "core/io/config_map.hh" - -#include "core/math/constexpr.hh" - -#include "client/globals.hh" - -static config::Unsigned base_framerate(16U, 1U, 16U); - -std::uint64_t world::voxel_anims::nextframe = 0U; -std::uint32_t world::voxel_anims::frame = 0U; - -void world::voxel_anims::init(void) -{ - globals::client_config.add_value("voxel_anims.base_framerate", base_framerate); - - world::voxel_anims::nextframe = 0U; - world::voxel_anims::frame = 0U; -} - -void world::voxel_anims::update(void) -{ - if(globals::curtime >= world::voxel_anims::nextframe) { - world::voxel_anims::nextframe = globals::curtime - + static_cast(1000000.0 / static_cast(base_framerate.get_value())); - world::voxel_anims::frame += 1U; - } -} diff --git a/game/client/world/voxel_anims.hh b/game/client/world/voxel_anims.hh deleted file mode 100644 index e4fe73e..0000000 --- a/game/client/world/voxel_anims.hh +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -namespace world::voxel_anims -{ -extern std::uint64_t nextframe; -extern std::uint32_t frame; -} // namespace world::voxel_anims - -namespace world::voxel_anims -{ -void init(void); -void update(void); -} // namespace world::voxel_anims diff --git a/game/client/world/voxel_atlas.cc b/game/client/world/voxel_atlas.cc deleted file mode 100644 index 67832d3..0000000 --- a/game/client/world/voxel_atlas.cc +++ /dev/null @@ -1,185 +0,0 @@ -#include "client/pch.hh" - -#include "client/world/voxel_atlas.hh" - -#include "core/math/constexpr.hh" -#include "core/math/crc64.hh" - -#include "core/resource/image.hh" -#include "core/resource/resource.hh" - -struct AtlasPlane final { - std::unordered_map lookup; - std::vector strips; - std::size_t layer_count_max; - std::size_t layer_count; - std::size_t plane_id; - GLuint gl_texture; -}; - -static int atlas_width; -static int atlas_height; -static std::size_t atlas_count; -static std::vector planes; - -// Certain animated and varied voxels just double their -// textures (see the "default" texture part in VoxelInfoBuilder::build) -// so there could either be six UNIQUE atlas strips or only one -// https://crypto.stackexchange.com/questions/55162/best-way-to-hash-two-values-into-one -static std::size_t vector_hash(const std::vector& strings) -{ - std::size_t source = 0; - for(const std::string& str : strings) - source += math::crc64(str); - return math::crc64(&source, sizeof(source)); -} - -static void plane_setup(AtlasPlane& plane) -{ - glGenTextures(1, &plane.gl_texture); - glBindTexture(GL_TEXTURE_2D_ARRAY, plane.gl_texture); - glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, atlas_width, atlas_height, plane.layer_count_max, 0, GL_RED, GL_UNSIGNED_BYTE, nullptr); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_REPEAT); -} - -static world::AtlasStrip* plane_lookup(AtlasPlane& plane, std::size_t hash_value) -{ - const auto it = plane.lookup.find(hash_value); - - if(it != plane.lookup.cend()) { - return &plane.strips[it->second]; - } - - return nullptr; -} - -static world::AtlasStrip* plane_new_strip(AtlasPlane& plane, const std::vector& paths, std::size_t hash_value) -{ - world::AtlasStrip strip = {}; - strip.offset = plane.layer_count; - strip.plane = plane.plane_id; - - glBindTexture(GL_TEXTURE_2D_ARRAY, plane.gl_texture); - - for(std::size_t i = 0; i < paths.size(); ++i) { - if(auto image = resource::load(paths[i].c_str(), IMAGE_LOAD_FLIP)) { - if((image->size.x != atlas_width) || (image->size.y != atlas_height)) { - spdlog::warn("atlas: {}: size mismatch", paths[i]); - continue; - } - - const std::size_t offset = strip.offset + i; - glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, offset, image->size.x, image->size.y, 1, GL_RGBA, GL_UNSIGNED_BYTE, - image->pixels); - } - } - - plane.layer_count += paths.size(); - - const std::size_t index = plane.strips.size(); - plane.lookup.emplace(hash_value, index); - plane.strips.push_back(std::move(strip)); - return &plane.strips[index]; -} - -void world::voxel_atlas::create(int width, int height, std::size_t count) -{ - GLint max_plane_layers; - - atlas_width = 1 << math::log2(width); - atlas_height = 1 << math::log2(height); - - // Clipping this at OpenGL 4.5 limit of 2048 is important due to - // how voxel quad meshes are packed in memory: each texture index is - // confined in 11 bits so having bigger atlas planes makes no sense; - glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &max_plane_layers); - max_plane_layers = glm::clamp(max_plane_layers, 256, 2048); - - for(long i = count; i > 0L; i -= max_plane_layers) { - AtlasPlane plane = {}; - plane.plane_id = planes.size(); - plane.layer_count_max = glm::min(max_plane_layers, i); - plane.layer_count = 0; - - const std::size_t save_id = plane.plane_id; - planes.push_back(std::move(plane)); - plane_setup(planes[save_id]); - } - - spdlog::debug("voxel_atlas: count={}", count); - spdlog::debug("voxel_atlas: atlas_size=[{}x{}]", atlas_width, atlas_height); - spdlog::debug("voxel_atlas: max_plane_layers={}", max_plane_layers); -} - -void world::voxel_atlas::destroy(void) -{ - for(const AtlasPlane& plane : planes) - glDeleteTextures(1, &plane.gl_texture); - atlas_width = 0; - atlas_height = 0; - planes.clear(); -} - -std::size_t world::voxel_atlas::plane_count(void) -{ - return planes.size(); -} - -GLuint world::voxel_atlas::plane_texture(std::size_t plane_id) -{ - if(plane_id < planes.size()) { - return planes[plane_id].gl_texture; - } - else { - return 0; - } -} - -void world::voxel_atlas::generate_mipmaps(void) -{ - for(const AtlasPlane& plane : planes) { - glBindTexture(GL_TEXTURE_2D_ARRAY, plane.gl_texture); - glGenerateMipmap(GL_TEXTURE_2D_ARRAY); - } -} - -world::AtlasStrip* world::voxel_atlas::find_or_load(const std::vector& paths) -{ - const std::size_t hash_value = vector_hash(paths); - - for(AtlasPlane& plane : planes) { - if(AtlasStrip* strip = plane_lookup(plane, hash_value)) { - return strip; - } - - continue; - } - - for(AtlasPlane& plane : planes) { - if((plane.layer_count + paths.size()) <= plane.layer_count_max) { - return plane_new_strip(plane, paths, hash_value); - } - - continue; - } - - return nullptr; -} - -world::AtlasStrip* world::voxel_atlas::find(const std::vector& paths) -{ - const std::size_t hash_value = vector_hash(paths); - - for(AtlasPlane& plane : planes) { - if(AtlasStrip* strip = plane_lookup(plane, hash_value)) { - return strip; - } - - continue; - } - - return nullptr; -} diff --git a/game/client/world/voxel_atlas.hh b/game/client/world/voxel_atlas.hh deleted file mode 100644 index 4ae6381..0000000 --- a/game/client/world/voxel_atlas.hh +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once - -namespace world -{ -struct AtlasStrip final { - std::size_t offset; - std::size_t plane; -}; -} // namespace world - -namespace world::voxel_atlas -{ -void create(int width, int height, std::size_t count); -void destroy(void); -} // namespace world::voxel_atlas - -namespace world::voxel_atlas -{ -std::size_t plane_count(void); -GLuint plane_texture(std::size_t plane_id); -void generate_mipmaps(void); -} // namespace world::voxel_atlas - -namespace world::voxel_atlas -{ -AtlasStrip* find_or_load(const std::vector& paths); -AtlasStrip* find(const std::vector& paths); -} // namespace world::voxel_atlas diff --git a/game/client/world/voxel_sounds.cc b/game/client/world/voxel_sounds.cc deleted file mode 100644 index fe91f01..0000000 --- a/game/client/world/voxel_sounds.cc +++ /dev/null @@ -1,83 +0,0 @@ -#include "client/pch.hh" - -#include "client/world/voxel_sounds.hh" - -#include "client/resource/sound_effect.hh" - -static std::vector> footsteps_sounds[world::VMAT_COUNT]; -static std::mt19937_64 randomizer; - -static void add_footsteps_effect(world::VoxelMaterial material, std::string_view name) -{ - if(auto effect = resource::load(name)) { - footsteps_sounds[material].push_back(effect); - } -} - -static resource_ptr get_footsteps_effect(world::VoxelMaterial material) -{ - auto surface_index = static_cast(material); - - if(surface_index >= world::VMAT_COUNT) { - // Surface index out of range - return nullptr; - } - - const auto& sounds = footsteps_sounds[surface_index]; - - if(sounds.empty()) { - // No sounds for this surface - return nullptr; - } - - auto dist = std::uniform_int_distribution(0, sounds.size() - 1); - return sounds.at(dist(randomizer)); -} - -void world::voxel_sounds::init(void) -{ - add_footsteps_effect(VMAT_DEFAULT, "sounds/surface/default1.wav"); - add_footsteps_effect(VMAT_DEFAULT, "sounds/surface/default2.wav"); - add_footsteps_effect(VMAT_DEFAULT, "sounds/surface/default3.wav"); - add_footsteps_effect(VMAT_DEFAULT, "sounds/surface/default4.wav"); - - add_footsteps_effect(VMAT_DIRT, "sounds/surface/dirt1.wav"); - - add_footsteps_effect(VMAT_GRASS, "sounds/surface/grass1.wav"); - add_footsteps_effect(VMAT_GRASS, "sounds/surface/grass2.wav"); - add_footsteps_effect(VMAT_GRASS, "sounds/surface/grass3.wav"); - - add_footsteps_effect(VMAT_GRAVEL, "sounds/surface/gravel1.wav"); - - add_footsteps_effect(VMAT_SAND, "sounds/surface/sand1.wav"); - add_footsteps_effect(VMAT_SAND, "sounds/surface/sand2.wav"); - - add_footsteps_effect(VMAT_WOOD, "sounds/surface/wood1.wav"); - add_footsteps_effect(VMAT_WOOD, "sounds/surface/wood2.wav"); - add_footsteps_effect(VMAT_WOOD, "sounds/surface/wood3.wav"); -} - -void world::voxel_sounds::shutdown(void) -{ - for(std::size_t i = 0; i < world::VMAT_COUNT; ++i) { - footsteps_sounds[i].clear(); - } -} - -resource_ptr world::voxel_sounds::get_footsteps(world::VoxelMaterial material) -{ - if(auto effect = get_footsteps_effect(material)) { - return effect; - } - - if(auto effect = get_footsteps_effect(VMAT_DEFAULT)) { - return effect; - } - - return nullptr; -} - -resource_ptr world::voxel_sounds::get_placebreak(world::VoxelMaterial material) -{ - return nullptr; -} diff --git a/game/client/world/voxel_sounds.hh b/game/client/world/voxel_sounds.hh deleted file mode 100644 index d0f3e07..0000000 --- a/game/client/world/voxel_sounds.hh +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include "core/resource/resource.hh" - -#include "shared/world/voxel.hh" - -struct SoundEffect; - -namespace world::voxel_sounds -{ -void init(void); -void shutdown(void); -} // namespace world::voxel_sounds - -namespace world::voxel_sounds -{ -resource_ptr get_footsteps(VoxelMaterial material); -resource_ptr get_placebreak(VoxelMaterial material); -} // namespace world::voxel_sounds -- cgit