mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-08-09 02:07:04 +08:00
Compare commits
5 Commits
v0.0.3
...
9a510d2319
| Author | SHA1 | Date | |
|---|---|---|---|
| 9a510d2319 | |||
| 176df4ee04 | |||
| f8aac019bd | |||
| 1e30345c98 | |||
|
|
913809a5f0 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -41,6 +41,7 @@ CMakeError.log
|
||||
*~
|
||||
.DS_Store
|
||||
assets/config.toml
|
||||
assets/server-config.toml
|
||||
.venv/
|
||||
pyout/
|
||||
vcpkg_installed/
|
||||
@@ -5,8 +5,9 @@
|
||||
#include "Cubed/gameplay/server_world.hpp"
|
||||
#define GLFW_INCLUDE_NONE
|
||||
#include "Cubed/camera.hpp"
|
||||
#include "Cubed/config.hpp"
|
||||
#include "Cubed/dev_panel.hpp"
|
||||
#include "Cubed/renderer.hpp"
|
||||
#include "Cubed/render/renderer.hpp"
|
||||
#include "Cubed/texture_manager.hpp"
|
||||
#include "Cubed/window.hpp"
|
||||
namespace Cubed {
|
||||
@@ -49,23 +50,23 @@ public:
|
||||
Window& window();
|
||||
ClientWorld& client_world();
|
||||
ServerWorld& server_world();
|
||||
Config& config();
|
||||
const Argument& argument() const;
|
||||
AudioEngine& audio();
|
||||
|
||||
private:
|
||||
Config m_game_config;
|
||||
Camera m_camera;
|
||||
TextureManager m_texture_manager;
|
||||
NetworkServer m_server;
|
||||
std::shared_ptr<NetworkClient> m_client;
|
||||
AudioEngine m_audio;
|
||||
ClientWorld m_client_world;
|
||||
|
||||
DevPanel m_dev_panel{*this};
|
||||
Renderer m_renderer{m_camera, m_client_world, m_texture_manager,
|
||||
m_dev_panel};
|
||||
DevPanel m_dev_panel;
|
||||
Renderer m_renderer;
|
||||
|
||||
Window m_window{m_renderer};
|
||||
|
||||
AudioEngine m_audio;
|
||||
Window m_window;
|
||||
|
||||
inline static double last_time = glfwGetTime();
|
||||
inline static double current_time = glfwGetTime();
|
||||
@@ -74,6 +75,7 @@ private:
|
||||
inline static int frame_count = 0;
|
||||
inline static int fps = 0;
|
||||
Argument m_argument;
|
||||
|
||||
void init(int argc, char** argv);
|
||||
void handle_argument(int argc, char** argv);
|
||||
void handle_toml();
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "Cubed/audio/audio_source.hpp"
|
||||
#include "Cubed/audio/sound_manager.hpp"
|
||||
#include "Cubed/audio/source_pool.hpp"
|
||||
#include "Cubed/config.hpp"
|
||||
|
||||
#include <AL/al.h>
|
||||
#include <AL/alc.h>
|
||||
@@ -17,7 +18,7 @@ class ClientWorld;
|
||||
|
||||
class AudioEngine {
|
||||
public:
|
||||
AudioEngine();
|
||||
AudioEngine(Config& config);
|
||||
AudioEngine(const AudioEngine&) = delete;
|
||||
AudioEngine(AudioEngine&&) = delete;
|
||||
AudioEngine& operator=(const AudioEngine&) = delete;
|
||||
@@ -48,6 +49,7 @@ private:
|
||||
std::unique_ptr<AudioSource> m_bgm;
|
||||
FadeMap m_fade_map;
|
||||
SoundManager m_sounds;
|
||||
Config& m_config;
|
||||
std::shared_ptr<SourcePool> m_pool;
|
||||
bool m_efx_supported = false;
|
||||
bool m_underwater = false;
|
||||
|
||||
@@ -1,99 +1,75 @@
|
||||
#pragma once
|
||||
#include "Cubed/tools/cubed_assert.hpp"
|
||||
#include "Cubed/tools/toml.utils.hpp"
|
||||
|
||||
namespace Cubed {
|
||||
|
||||
class Config {
|
||||
public:
|
||||
Config();
|
||||
explicit Config(std::string_view path);
|
||||
Config(const Config&) = delete;
|
||||
Config(Config&&) = delete;
|
||||
Config& operator=(const Config&) = delete;
|
||||
Config& operator=(Config&&) = delete;
|
||||
~Config();
|
||||
|
||||
static Config& get();
|
||||
|
||||
toml::table& table();
|
||||
|
||||
void load_or_create_config();
|
||||
void load_config();
|
||||
void save_to_file();
|
||||
|
||||
template <TOML::TomlValueType T> T get(std::string_view key) const {
|
||||
size_t cur = 0;
|
||||
auto pos = key.find('.');
|
||||
const toml::table* table = &m_tbl;
|
||||
while (pos != std::string_view::npos) {
|
||||
std::string_view s = key.substr(cur, pos - cur);
|
||||
if (s.empty()) {
|
||||
Logger::error("Empty key/table name in path '{}'", key);
|
||||
ASSERT(false);
|
||||
std::abort();
|
||||
template <TOML::TomlValueType T>
|
||||
T get(std::string_view key, T default_value) {
|
||||
if (auto* node = find_node(m_tbl, key)) {
|
||||
if (auto value = node->value<T>())
|
||||
return *value;
|
||||
}
|
||||
cur = pos + 1;
|
||||
pos = key.find('.', cur);
|
||||
if (auto* next = (*table)[s].as_table()) {
|
||||
table = next;
|
||||
|
||||
set(key, default_value);
|
||||
save_to_file();
|
||||
|
||||
return default_value;
|
||||
}
|
||||
|
||||
template <TOML::TomlValueType T> void set(std::string_view key, T&& value) {
|
||||
auto pos = key.rfind('.');
|
||||
|
||||
toml::table* table;
|
||||
std::string_view name;
|
||||
|
||||
if (pos == std::string_view::npos) {
|
||||
table = &m_tbl;
|
||||
name = key;
|
||||
} else {
|
||||
Logger::error("Can't find table {}", s);
|
||||
ASSERT(false);
|
||||
std::abort();
|
||||
table = find_or_create_table(key.substr(0, pos));
|
||||
name = key.substr(pos + 1);
|
||||
}
|
||||
// Insert node at the last level's table
|
||||
table->insert_or_assign(name, std::forward<T>(value));
|
||||
}
|
||||
std::string_view n_key = key.substr(cur);
|
||||
if (n_key.empty()) {
|
||||
Logger::error("Trailing dot in path '{}'", key);
|
||||
ASSERT(false);
|
||||
std::abort();
|
||||
}
|
||||
auto opt = (*table)[n_key].value<T>();
|
||||
if (opt) {
|
||||
return *opt;
|
||||
} else {
|
||||
Logger::error("Can't find key {}", n_key);
|
||||
ASSERT(false);
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
template <typename T> void set(std::string_view key, T&& val) {
|
||||
if constexpr (!TOML::TomlValueType<std::decay_t<T>>) {
|
||||
static_assert(false, "Type Not Support");
|
||||
}
|
||||
size_t cur = 0;
|
||||
auto pos = key.find('.');
|
||||
toml::table* table = &m_tbl;
|
||||
while (pos != std::string_view::npos) {
|
||||
std::string_view s = key.substr(cur, pos - cur);
|
||||
if (s.empty()) {
|
||||
Logger::error("Empty key/table name in path '{}'", key);
|
||||
ASSERT(false);
|
||||
std::abort();
|
||||
}
|
||||
cur = pos + 1;
|
||||
pos = key.find('.', cur);
|
||||
if (auto* next = (*table)[s].as_table()) {
|
||||
table = next;
|
||||
} else {
|
||||
auto [it, inserted] = table->insert_or_assign(s, toml::table{});
|
||||
table = it->second.as_table();
|
||||
}
|
||||
}
|
||||
std::string_view n_key = key.substr(cur);
|
||||
if (n_key.empty()) {
|
||||
Logger::error("Trailing dot in path '{}'", key);
|
||||
ASSERT(false);
|
||||
std::abort();
|
||||
}
|
||||
table->insert_or_assign(n_key, std::forward<T>(val));
|
||||
}
|
||||
|
||||
template <typename T> void set_and_save(std::string_view key, T&& val) {
|
||||
set(key, std::forward(val));
|
||||
save_to_file();
|
||||
}
|
||||
toml::node_view<toml::node> val_view(std::string_view key);
|
||||
|
||||
private:
|
||||
toml::table m_tbl;
|
||||
constexpr static inline std::string_view CONGIF_PATH =
|
||||
ASSETS_PATH "config.toml";
|
||||
void create_config();
|
||||
const std::string CONGIF_PATH;
|
||||
const toml::node* find_node(const toml::table& root,
|
||||
std::string_view path) const;
|
||||
// Follow the path to find the last-level toml::table, creating it if it
|
||||
// does not exist
|
||||
toml::table* find_or_create_table(std::string_view path);
|
||||
};
|
||||
|
||||
template <>
|
||||
inline float Config::get(std::string_view key, float default_value) {
|
||||
return static_cast<float>(
|
||||
Config::get<double>(key, static_cast<double>(default_value)));
|
||||
}
|
||||
|
||||
template <> inline void Config::set(std::string_view key, float&& value) {
|
||||
Config::set<double>(key, static_cast<double>(value));
|
||||
}
|
||||
|
||||
} // namespace Cubed
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "Cubed/config.hpp"
|
||||
|
||||
#include <toml++/toml.hpp>
|
||||
|
||||
namespace Cubed {
|
||||
@@ -36,7 +38,8 @@ public:
|
||||
|
||||
private:
|
||||
App& m_app;
|
||||
ConfigView m_config;
|
||||
Config& m_config;
|
||||
ConfigView m_config_view;
|
||||
ClientPlayer* m_player;
|
||||
PlayerProfile m_player_profile;
|
||||
bool m_need_save_config = false;
|
||||
|
||||
@@ -25,7 +25,7 @@ public:
|
||||
|
||||
void update_chunk_set(const ChunkPosSet& set);
|
||||
const ChunkPosSet& get_chunk_pos_set() const;
|
||||
ChunkPosSet& get_chunk_pos_set();
|
||||
ChunkPosSet get_chunk_pos_set();
|
||||
|
||||
static AABB get_aabb(const glm::vec3& pos);
|
||||
const glm::vec3& get_front() const;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include "Cubed/audio/audio_engine.hpp"
|
||||
#include "Cubed/config.hpp"
|
||||
#include "Cubed/gameplay/block.hpp"
|
||||
#include "Cubed/gameplay/chunk_pos.hpp"
|
||||
#include "Cubed/gameplay/client_chunk.hpp"
|
||||
@@ -43,7 +44,7 @@ struct PlayerRenderData {
|
||||
|
||||
class ClientWorld {
|
||||
public:
|
||||
ClientWorld(AudioEngine& auido);
|
||||
ClientWorld(AudioEngine& auido, Config& config);
|
||||
~ClientWorld();
|
||||
void init(std::string_view player_name,
|
||||
std::shared_ptr<NetworkClient> client);
|
||||
@@ -58,8 +59,8 @@ public:
|
||||
|
||||
void rebuild_world();
|
||||
|
||||
void push_delete_vbo(GLuint vbo);
|
||||
void push_delete_vao(GLuint vao);
|
||||
void push_delete_vbo(std::unique_ptr<VertexBuffer>& vbo);
|
||||
void push_delete_vao(std::unique_ptr<VertexArray>& vao);
|
||||
// void hot_reload();
|
||||
|
||||
// void rebuild_world();
|
||||
@@ -95,6 +96,7 @@ public:
|
||||
int chunk_size() const;
|
||||
static AABB get_block_aabb(const glm::ivec3& pos);
|
||||
AudioEngine& get_audio();
|
||||
Config& get_config();
|
||||
template <typename Fn>
|
||||
void register_ticktimer(std::string_view id, TickType threshold, Fn&& f) {
|
||||
m_ticktimers.emplace(
|
||||
@@ -103,6 +105,12 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
std::atomic<bool> m_is_pending_delete_queue_free{false};
|
||||
std::mutex m_delete_vbo_mutex;
|
||||
std::mutex m_delete_vao_mutex;
|
||||
std::vector<std::unique_ptr<VertexBuffer>> m_pending_delete_vbo;
|
||||
std::vector<std::unique_ptr<VertexArray>> m_pending_delete_vao;
|
||||
|
||||
enum class ChunkLoadStyle { RANDOM, CENTER };
|
||||
using ChunkHashMap =
|
||||
tbb::concurrent_hash_map<ChunkPos, std::shared_ptr<ClientChunk>,
|
||||
@@ -124,18 +132,15 @@ private:
|
||||
OtherPlayerHashMap m_player_info;
|
||||
ChunkHashMap m_chunks;
|
||||
AudioEngine& m_audio;
|
||||
Config& m_config;
|
||||
std::vector<glm::vec4> m_planes;
|
||||
std::jthread m_client_thread;
|
||||
|
||||
std::mutex m_delete_vbo_mutex;
|
||||
std::mutex m_delete_vao_mutex;
|
||||
mutable std::shared_mutex m_player_info_mutex;
|
||||
|
||||
tbb::concurrent_queue<std::unique_ptr<ClientChunk>> m_pending_upload_queue;
|
||||
tbb::concurrent_queue<ChunkPos> m_dirty_chunk_queue;
|
||||
tbb::concurrent_queue<PendingSound> m_pending_sound;
|
||||
std::vector<GLuint> m_pending_delete_vbo;
|
||||
std::vector<GLuint> m_pending_delete_vao;
|
||||
|
||||
std::deque<ChunkPos> m_dirty_queue;
|
||||
std::vector<const ChunkRenderSnapshot*> m_render_snapshots;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
#include "Cubed/config.hpp"
|
||||
#include "Cubed/gameplay/server_world.hpp"
|
||||
#include "Cubed/gameplay/session.hpp"
|
||||
|
||||
@@ -8,17 +9,19 @@ namespace Cubed {
|
||||
|
||||
class NetworkServer {
|
||||
public:
|
||||
NetworkServer(int port = 25530);
|
||||
explicit NetworkServer();
|
||||
~NetworkServer();
|
||||
void stop();
|
||||
|
||||
// Run in another thread after initialization is complete
|
||||
void start_server(int port = 25530);
|
||||
|
||||
void start_server(int port);
|
||||
void start_server();
|
||||
int port() const;
|
||||
ServerWorld& server_world();
|
||||
|
||||
private:
|
||||
Config m_config;
|
||||
|
||||
asio::io_context m_io;
|
||||
std::thread m_net_thread;
|
||||
int m_port = 25530;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "Cubed/config.hpp"
|
||||
#include "Cubed/gameplay/cave_carver.hpp"
|
||||
#include "Cubed/gameplay/chunk_pos.hpp"
|
||||
#include "Cubed/gameplay/game_time.hpp"
|
||||
@@ -25,7 +26,7 @@ class Session;
|
||||
class ServerWorld {
|
||||
public:
|
||||
enum class ThreadPoolKind { NET, GEN };
|
||||
ServerWorld();
|
||||
ServerWorld(Config& config);
|
||||
~ServerWorld();
|
||||
void stop();
|
||||
void handle_player_exit(const std::string& uuid);
|
||||
@@ -118,6 +119,9 @@ private:
|
||||
|
||||
using uuid_acc = PlayerUUIDMap::accessor;
|
||||
using uuid_cacc = PlayerUUIDMap::const_accessor;
|
||||
|
||||
Config& m_config;
|
||||
|
||||
// key = uuid
|
||||
PlayerHashMap m_players;
|
||||
ChunkHashMap m_chunks;
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
#pragma once
|
||||
#include "Cubed/primitive_data.hpp"
|
||||
#include "Cubed/render/vertex_array.hpp"
|
||||
#include "Cubed/render/vertex_buffer.hpp"
|
||||
|
||||
#include <atomic>
|
||||
#include <glad/glad.h>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
namespace Cubed {
|
||||
class ClientWorld;
|
||||
struct VertexData {
|
||||
std::vector<Vertex3D> m_vertices;
|
||||
GLuint m_vbo = 0;
|
||||
GLuint m_vao = 0;
|
||||
std::unique_ptr<VertexBuffer> m_vbo;
|
||||
std::unique_ptr<VertexArray> m_vao;
|
||||
std::atomic<std::size_t> m_sum{0};
|
||||
ClientWorld& m_world;
|
||||
VertexData(ClientWorld& world);
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
#pragma once
|
||||
// #include <string>
|
||||
// #include <unordered_map>
|
||||
// #include <vector>
|
||||
namespace Cubed {
|
||||
|
||||
class MapTable {
|
||||
private:
|
||||
/*
|
||||
static inline std::unordered_map<unsigned, std::string> id_to_name_map;
|
||||
static inline std::unordered_map<size_t, unsigned> name_to_id_map;
|
||||
static inline std::vector<std::string> item_id_to_name;
|
||||
*/
|
||||
public:
|
||||
// please using reference
|
||||
/*
|
||||
static std::string_view get_name_from_id(unsigned id);
|
||||
static unsigned get_id_from_name(const std::string& name);
|
||||
|
||||
static std::string_view item_name(unsigned id);
|
||||
static const std::vector<std::string>& item_map();
|
||||
*/
|
||||
static void init_map();
|
||||
};
|
||||
|
||||
} // namespace Cubed
|
||||
46
include/Cubed/render/frame_buffer.hpp
Normal file
46
include/Cubed/render/frame_buffer.hpp
Normal file
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
#include "Cubed/render/texture.hpp"
|
||||
|
||||
#include <glad/glad.h>
|
||||
#include <span>
|
||||
|
||||
enum class Attachment : GLenum {
|
||||
COLOR_ATTACHMENT0 = GL_COLOR_ATTACHMENT0,
|
||||
COLOR_ATTACHMENT1 = GL_COLOR_ATTACHMENT1,
|
||||
DEPTH_ATTACHMENT = GL_DEPTH_ATTACHMENT
|
||||
};
|
||||
|
||||
enum class FrameBufferType : GLenum {
|
||||
FRAMEBUFFER = GL_FRAMEBUFFER,
|
||||
READ_FRAMEBUFFER = GL_READ_FRAMEBUFFER,
|
||||
DRAW_FRAMEBUFFER = GL_DRAW_FRAMEBUFFER
|
||||
};
|
||||
|
||||
namespace Cubed {
|
||||
class FrameBuffer {
|
||||
public:
|
||||
FrameBuffer();
|
||||
~FrameBuffer();
|
||||
FrameBuffer(const FrameBuffer&) = delete;
|
||||
FrameBuffer(FrameBuffer&&) noexcept;
|
||||
FrameBuffer& operator=(const FrameBuffer&) = delete;
|
||||
FrameBuffer& operator=(FrameBuffer&&) noexcept;
|
||||
|
||||
void bind(FrameBufferType type = FrameBufferType::FRAMEBUFFER) const;
|
||||
GLuint id() const;
|
||||
|
||||
void attach(Attachment attachment, const Texture& texture,
|
||||
GLint level = 0) const;
|
||||
static void unbind();
|
||||
|
||||
bool check_status() const;
|
||||
|
||||
void draw_buffer(GLenum buf) const;
|
||||
void read_buffer(GLenum src) const;
|
||||
void draw_buffer(GLsizei n, const GLenum* bufs) const;
|
||||
void draw_buffer(std::span<const GLenum> bufs) const;
|
||||
|
||||
private:
|
||||
GLuint m_fbo = 0;
|
||||
};
|
||||
} // namespace Cubed
|
||||
127
include/Cubed/render/renderer.hpp
Normal file
127
include/Cubed/render/renderer.hpp
Normal file
@@ -0,0 +1,127 @@
|
||||
#pragma once
|
||||
|
||||
#include "Cubed/config.hpp"
|
||||
#include "Cubed/constants.hpp"
|
||||
#include "Cubed/primitive_data.hpp"
|
||||
#include "Cubed/render/player_renderer.hpp"
|
||||
#include "Cubed/render/shader_manager.hpp"
|
||||
#include "Cubed/render/vertex_array.hpp"
|
||||
#include "Cubed/render/vertex_buffer.hpp"
|
||||
#include "Cubed/render/world_renderer.hpp"
|
||||
#include "Cubed/shader.hpp"
|
||||
#include "Cubed/ui/text.hpp"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <vector>
|
||||
namespace Cubed {
|
||||
|
||||
class Camera;
|
||||
class TextureManager;
|
||||
class ClientWorld;
|
||||
class DevPanel;
|
||||
class Renderer {
|
||||
public:
|
||||
constexpr static int NUM_VAO = 7;
|
||||
|
||||
Renderer(const Camera& camera, ClientWorld& world,
|
||||
const TextureManager& texture_manager, DevPanel& dev_panel,
|
||||
Config& config);
|
||||
~Renderer();
|
||||
void hot_reload();
|
||||
void init(bool debug_on);
|
||||
const Shader& get_shader(const std::string& name) const;
|
||||
void render();
|
||||
void update(float delta_time);
|
||||
void update_fov(float fov);
|
||||
void update_proj_matrix(float aspect, float width, float height);
|
||||
void updata_framebuffer(int width, int height);
|
||||
float& ambient_strength();
|
||||
|
||||
bool& discard_transparent();
|
||||
bool& shader_on();
|
||||
bool& water_perturb();
|
||||
bool& water_depth_fade();
|
||||
bool& pbr();
|
||||
bool& flip_y();
|
||||
int& shadow_mode();
|
||||
int& light_cull_face();
|
||||
int& light_size_uv();
|
||||
float& min_radius();
|
||||
float& max_radius();
|
||||
int& samples();
|
||||
float& specular_strength();
|
||||
float& cloud_speed();
|
||||
float& cloud_threshold_low();
|
||||
float& cloud_threshold_high();
|
||||
float& refract_strength();
|
||||
|
||||
float& underwater_fog_density();
|
||||
float& water_density();
|
||||
|
||||
const Camera& camera() const;
|
||||
const ClientWorld& world() const;
|
||||
ClientWorld& world();
|
||||
const glm::mat4& world_proj_matrix() const;
|
||||
const TextureManager& texture_mamger() const;
|
||||
float delta_time() const;
|
||||
|
||||
float height() const;
|
||||
float width() const;
|
||||
const glm::mat4& p_mat() const;
|
||||
|
||||
const std::vector<VertexArray>& vao() const;
|
||||
|
||||
private:
|
||||
const Camera& m_camera;
|
||||
DevPanel& m_dev_panel;
|
||||
const TextureManager& m_texture_manager;
|
||||
ClientWorld& m_world;
|
||||
|
||||
bool m_init = false;
|
||||
|
||||
float m_aspect = 0.0f;
|
||||
float m_fov = DEFAULT_FOV;
|
||||
|
||||
float m_delta_time = 0.0f;
|
||||
|
||||
float m_width = 0.0f;
|
||||
float m_height = 0.0f;
|
||||
|
||||
glm::mat4 m_world_proj_matrix;
|
||||
|
||||
std::unique_ptr<VertexBuffer> m_sky_vbo;
|
||||
std::unique_ptr<VertexBuffer> m_outline_indices_vbo;
|
||||
std::unique_ptr<VertexBuffer> m_outline_vbo;
|
||||
std::unique_ptr<VertexBuffer> m_ui_vbo;
|
||||
std::unique_ptr<VertexBuffer> m_player_vbo;
|
||||
std::unique_ptr<VertexBuffer> m_quad_vbo;
|
||||
|
||||
glm::mat4 m_ui_proj_matrix;
|
||||
glm::mat4 m_ui_model_matrix;
|
||||
ShaderManager m_shaders;
|
||||
|
||||
/*
|
||||
0 - quad vao
|
||||
1 - sky vao
|
||||
2 - outline vao
|
||||
3 - ui vao
|
||||
4 - text vao
|
||||
*/
|
||||
std::vector<VertexArray> m_vao;
|
||||
std::vector<Vertex2D> m_ui;
|
||||
|
||||
WorldRenderer m_world_renderer;
|
||||
Config& m_config;
|
||||
void init_quad();
|
||||
void init_text();
|
||||
|
||||
void day_night_calculation();
|
||||
|
||||
void render_sky();
|
||||
void render_text();
|
||||
void render_ui();
|
||||
|
||||
void render_dev_panel();
|
||||
};
|
||||
|
||||
} // namespace Cubed
|
||||
21
include/Cubed/render/renderer_constants.hpp
Normal file
21
include/Cubed/render/renderer_constants.hpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
namespace Cubed {
|
||||
constexpr glm::vec3 SUN_COLOR{1.00f, 0.95f, 0.80f};
|
||||
constexpr glm::vec3 MOON_COLOR{0.75f, 0.80f, 1.00f};
|
||||
|
||||
constexpr glm::vec3 SUNSET_SUNLIGHT_COLOR{1.00f, 0.45f, 0.15f};
|
||||
constexpr glm::vec3 NOON_SUNLIGHT_COLOR{1.00f, 0.90f, 0.65f};
|
||||
constexpr glm::vec3 SUNSET_AMBIENT_COLOR{0.18f, 0.12f, 0.35f};
|
||||
constexpr glm::vec3 NOON_AMBIENT_COLOR{0.35f, 0.50f, 0.85f};
|
||||
constexpr glm::vec3 MOONLIGHT_COLOR{0.55f, 0.70f, 1.00f};
|
||||
constexpr glm::vec3 NIGHT_AMBIENT_COLOR{0.08f, 0.10f, 0.18f};
|
||||
constexpr float FAR_PLANE = 1000.0f;
|
||||
constexpr float NEAR_PLANE = 0.1f;
|
||||
constexpr float SUN_SIZE = 50.0f;
|
||||
constexpr float MOON_SIZE = 50.0f;
|
||||
constexpr float DEPTH_MAP_SIZE = 4096.0f;
|
||||
constexpr float ANGLE_STEP_DEG = 0.5f;
|
||||
} // namespace Cubed
|
||||
28
include/Cubed/render/shader_manager.hpp
Normal file
28
include/Cubed/render/shader_manager.hpp
Normal file
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include "Cubed/shader.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
namespace Cubed {
|
||||
class ShaderManager {
|
||||
public:
|
||||
ShaderManager();
|
||||
~ShaderManager();
|
||||
ShaderManager(const ShaderManager&) = delete;
|
||||
ShaderManager(ShaderManager&&) = delete;
|
||||
ShaderManager& operator=(const ShaderManager&) = delete;
|
||||
ShaderManager& operator=(ShaderManager&&) = delete;
|
||||
|
||||
void init();
|
||||
|
||||
const Shader& get_shader(const std::string& name) const;
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, Shader> m_shaders;
|
||||
|
||||
void register_shader(const std::string& name, const std::string& v_shader,
|
||||
const std::string& f_shader);
|
||||
};
|
||||
|
||||
} // namespace Cubed
|
||||
94
include/Cubed/render/texture.hpp
Normal file
94
include/Cubed/render/texture.hpp
Normal file
@@ -0,0 +1,94 @@
|
||||
#pragma once
|
||||
#include <cstddef>
|
||||
#include <glad/glad.h>
|
||||
namespace Cubed {
|
||||
|
||||
enum TextureType : GLenum {
|
||||
TEXTURE_2D = GL_TEXTURE_2D,
|
||||
TEXTURE_2D_ARRAY = GL_TEXTURE_2D_ARRAY
|
||||
};
|
||||
|
||||
enum TexturePname : GLenum {
|
||||
MIN_FILTER = GL_TEXTURE_MIN_FILTER,
|
||||
MAG_FILTER = GL_TEXTURE_MAG_FILTER,
|
||||
WRAP_S = GL_TEXTURE_WRAP_S,
|
||||
WRAP_T = GL_TEXTURE_WRAP_T,
|
||||
WRAP_R = GL_TEXTURE_WRAP_R,
|
||||
BORDER_COLOR = GL_TEXTURE_BORDER_COLOR,
|
||||
COMPARE_MODE = GL_TEXTURE_COMPARE_MODE
|
||||
};
|
||||
|
||||
enum TextureParam : GLenum {
|
||||
LINEAR = GL_LINEAR,
|
||||
NEAREST = GL_NEAREST,
|
||||
LINEAR_MIPMAP_LINEAR = GL_LINEAR_MIPMAP_LINEAR,
|
||||
CLAMP_TO_BORDER = GL_CLAMP_TO_BORDER,
|
||||
CLAMP_TO_EDGE = GL_CLAMP_TO_EDGE,
|
||||
T_NONE = GL_NONE,
|
||||
REPEAT = GL_REPEAT
|
||||
};
|
||||
|
||||
enum TextureFormat : GLenum {
|
||||
DEPTH_COMPONENT32F = GL_DEPTH_COMPONENT32F,
|
||||
DEPTH_COMPONENT = GL_DEPTH_COMPONENT,
|
||||
R16F = GL_R16F,
|
||||
RGBA16F = GL_RGBA16F,
|
||||
RED = GL_RED,
|
||||
RGBA = GL_RGBA,
|
||||
RGB = GL_RGB,
|
||||
RGBA8 = GL_RGBA8,
|
||||
|
||||
};
|
||||
|
||||
class Texture {
|
||||
public:
|
||||
explicit Texture(TextureType type);
|
||||
~Texture();
|
||||
Texture(const Texture&) = delete;
|
||||
Texture(Texture&&) noexcept;
|
||||
Texture& operator=(const Texture&) = delete;
|
||||
Texture& operator=(Texture&&) noexcept;
|
||||
|
||||
void bind() const;
|
||||
void bind(size_t unit) const;
|
||||
static void unbind();
|
||||
static void active(size_t id);
|
||||
GLuint id() const;
|
||||
|
||||
void parameter(TexturePname pname, TextureParam param) const;
|
||||
void parameterfv(TexturePname pname, const float* param) const;
|
||||
|
||||
void tex_image_2d(TextureFormat internalformat, TextureFormat format,
|
||||
GLenum type, const void* data, GLsizei width,
|
||||
GLsizei height, GLint level = 0, GLint border = 0) const;
|
||||
|
||||
void tex_image_3d(TextureFormat internalformat, TextureFormat format,
|
||||
GLenum type, const void* data, GLsizei width,
|
||||
GLsizei height, GLsizei depth, GLint level = 0,
|
||||
GLint border = 0) const;
|
||||
|
||||
void tex_sub_image_3d(TextureFormat format, GLenum type, const void* data,
|
||||
GLint xoffset, GLint yoffset, GLint zoffset,
|
||||
GLsizei width, GLsizei height, GLsizei depth = 1,
|
||||
GLint level = 0) const;
|
||||
|
||||
void set_aniso(int aniso) const;
|
||||
|
||||
void gen_mipmap() const;
|
||||
|
||||
void set_linear() const;
|
||||
void set_nearest_and_minpmap() const;
|
||||
void set_nearest() const;
|
||||
void set_repeat(bool r = true, bool s = true, bool t = true) const;
|
||||
void set_clamp_to_border(bool r = true, bool s = true, bool t = true) const;
|
||||
void set_clamp_to_edge(bool r = true, bool s = true, bool t = true) const;
|
||||
|
||||
TextureType type() const;
|
||||
|
||||
private:
|
||||
GLuint m_id = 0;
|
||||
const TextureType M_TYPE;
|
||||
|
||||
GLenum get_gl_texture_type() const;
|
||||
};
|
||||
} // namespace Cubed
|
||||
26
include/Cubed/render/vertex_array.hpp
Normal file
26
include/Cubed/render/vertex_array.hpp
Normal file
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
#include <glad/glad.h>
|
||||
|
||||
namespace Cubed {
|
||||
class VertexArray {
|
||||
public:
|
||||
VertexArray();
|
||||
VertexArray(const VertexArray&) = delete;
|
||||
VertexArray(VertexArray&&) noexcept;
|
||||
VertexArray& operator=(const VertexArray&) = delete;
|
||||
VertexArray& operator=(VertexArray&&) noexcept;
|
||||
~VertexArray();
|
||||
|
||||
void bind() const;
|
||||
|
||||
static void unbind();
|
||||
|
||||
GLuint id() const;
|
||||
|
||||
void attribute(GLuint index, GLint size, GLenum type, GLsizei stride,
|
||||
const void* ptr, bool normalized = false) const;
|
||||
|
||||
private:
|
||||
GLuint m_vao = 0;
|
||||
};
|
||||
} // namespace Cubed
|
||||
36
include/Cubed/render/vertex_buffer.hpp
Normal file
36
include/Cubed/render/vertex_buffer.hpp
Normal file
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
#include <glad/glad.h>
|
||||
namespace Cubed {
|
||||
|
||||
enum class BufferType : GLenum {
|
||||
ARRAY_BUFFER = GL_ARRAY_BUFFER,
|
||||
ELEMENT_ARRAY_BUFFER = GL_ELEMENT_ARRAY_BUFFER
|
||||
};
|
||||
|
||||
enum class BufferUsage : GLenum {
|
||||
STATIC_DRAW = GL_STATIC_DRAW,
|
||||
DYNAMIC_DRAW = GL_DYNAMIC_DRAW
|
||||
};
|
||||
|
||||
class VertexBuffer {
|
||||
public:
|
||||
VertexBuffer(BufferType type = BufferType::ARRAY_BUFFER);
|
||||
VertexBuffer(const VertexBuffer&) = delete;
|
||||
VertexBuffer(VertexBuffer&&) noexcept;
|
||||
VertexBuffer& operator=(const VertexBuffer&) = delete;
|
||||
VertexBuffer& operator=(VertexBuffer&&) noexcept;
|
||||
~VertexBuffer();
|
||||
|
||||
void bind() const;
|
||||
static void unbind();
|
||||
GLuint id() const;
|
||||
void buffer_data(const void* data, GLsizeiptr size,
|
||||
BufferUsage usage = BufferUsage::STATIC_DRAW) const;
|
||||
|
||||
private:
|
||||
GLuint m_vbo = 0;
|
||||
BufferType m_type = BufferType::ARRAY_BUFFER;
|
||||
|
||||
GLenum get_buffer_target() const;
|
||||
};
|
||||
} // namespace Cubed
|
||||
@@ -1,65 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include "Cubed/constants.hpp"
|
||||
#include "Cubed/player_renderer.hpp"
|
||||
#include "Cubed/primitive_data.hpp"
|
||||
#include "Cubed/shader.hpp"
|
||||
#include "Cubed/ui/text.hpp"
|
||||
#include "Cubed/render/frame_buffer.hpp"
|
||||
#include "Cubed/render/player_renderer.hpp"
|
||||
#include "Cubed/render/texture.hpp"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
namespace Cubed {
|
||||
|
||||
class Camera;
|
||||
class TextureManager;
|
||||
class Renderer;
|
||||
class ClientWorld;
|
||||
class DevPanel;
|
||||
class Renderer {
|
||||
class TextureManager;
|
||||
class Camera;
|
||||
class WorldRenderer {
|
||||
public:
|
||||
constexpr static int NUM_VAO = 7;
|
||||
|
||||
Renderer(const Camera& camera, ClientWorld& world,
|
||||
const TextureManager& texture_manager, DevPanel& dev_panel);
|
||||
~Renderer();
|
||||
void hot_reload();
|
||||
void init(bool debug_on);
|
||||
const Shader& get_shader(const std::string& name) const;
|
||||
void render();
|
||||
void update(float delta_time);
|
||||
void update_fov(float fov);
|
||||
void update_proj_matrix(float aspect, float width, float height);
|
||||
void updata_framebuffer(int width, int height);
|
||||
float& ambient_strength();
|
||||
|
||||
bool& discard_transparent();
|
||||
bool& shader_on();
|
||||
bool& water_perturb();
|
||||
bool& water_depth_fade();
|
||||
bool& pbr();
|
||||
bool& flip_y();
|
||||
int& shadow_mode();
|
||||
int& light_cull_face();
|
||||
int& light_size_uv();
|
||||
float& min_radius();
|
||||
float& max_radius();
|
||||
int& samples();
|
||||
float& specular_strength();
|
||||
float& cloud_speed();
|
||||
float& cloud_threshold_low();
|
||||
float& cloud_threshold_high();
|
||||
float& refract_strength();
|
||||
float& underwater_fog_density();
|
||||
float& water_density();
|
||||
|
||||
const Camera& camera() const;
|
||||
const ClientWorld& world() const;
|
||||
ClientWorld& world();
|
||||
const glm::mat4& proj_mat() const;
|
||||
const TextureManager& texture_mamger() const;
|
||||
|
||||
float delta_time() const;
|
||||
|
||||
private:
|
||||
struct ParallelLight {
|
||||
glm::vec3 sundir; // direction from sun to vertex
|
||||
glm::vec3 lightdir;
|
||||
@@ -79,132 +31,121 @@ private:
|
||||
float horizon_sharpness;
|
||||
float cloud_white_mix;
|
||||
};
|
||||
WorldRenderer(Renderer& renderer);
|
||||
~WorldRenderer();
|
||||
|
||||
static constexpr glm::vec3 SUN_COLOR{1.00f, 0.95f, 0.80f};
|
||||
static constexpr glm::vec3 MOON_COLOR{0.75f, 0.80f, 1.00f};
|
||||
WorldRenderer(const WorldRenderer&) = delete;
|
||||
WorldRenderer(WorldRenderer&&) = delete;
|
||||
WorldRenderer& operator=(const WorldRenderer&) = delete;
|
||||
WorldRenderer& operator=(WorldRenderer&&) = delete;
|
||||
void init();
|
||||
void render();
|
||||
void updata_framebuffer(int width, int height);
|
||||
|
||||
static constexpr glm::vec3 SUNSET_SUNLIGHT_COLOR{1.00f, 0.45f, 0.15f};
|
||||
static constexpr glm::vec3 NOON_SUNLIGHT_COLOR{1.00f, 0.90f, 0.65f};
|
||||
static constexpr glm::vec3 SUNSET_AMBIENT_COLOR{0.18f, 0.12f, 0.35f};
|
||||
static constexpr glm::vec3 NOON_AMBIENT_COLOR{0.35f, 0.50f, 0.85f};
|
||||
static constexpr glm::vec3 MOONLIGHT_COLOR{0.55f, 0.70f, 1.00f};
|
||||
static constexpr glm::vec3 NIGHT_AMBIENT_COLOR{0.08f, 0.10f, 0.18f};
|
||||
static constexpr float FAR_PLANE = 1000.0f;
|
||||
static constexpr float NEAR_PLANE = 0.1f;
|
||||
static constexpr float SUN_SIZE = 50.0f;
|
||||
static constexpr float MOON_SIZE = 50.0f;
|
||||
static constexpr float DEPTH_MAP_SIZE = 4096.0f;
|
||||
static constexpr float ANGLE_STEP_DEG = 0.5f;
|
||||
float m_ambient_strength = 0.1f;
|
||||
float& ambient_strength();
|
||||
bool& discard_transparent();
|
||||
bool& shader_on();
|
||||
bool& water_perturb();
|
||||
bool& water_depth_fade();
|
||||
bool& pbr();
|
||||
bool& flip_y();
|
||||
int& shadow_mode();
|
||||
int& light_cull_face();
|
||||
int& light_size_uv();
|
||||
float& min_radius();
|
||||
float& max_radius();
|
||||
int& samples();
|
||||
float& specular_strength();
|
||||
float& cloud_speed();
|
||||
float& cloud_threshold_low();
|
||||
float& cloud_threshold_high();
|
||||
float& refract_strength();
|
||||
float& underwater_fog_density();
|
||||
|
||||
const Camera& m_camera;
|
||||
DevPanel& m_dev_panel;
|
||||
const TextureManager& m_texture_manager;
|
||||
ClientWorld& m_world;
|
||||
float& water_density();
|
||||
|
||||
const FrameBuffer* world_fbo() const;
|
||||
|
||||
private:
|
||||
Renderer& m_renderer;
|
||||
PlayerRenderer m_player_renderer;
|
||||
bool m_discard_tranparent = true;
|
||||
bool m_shader_on = true;
|
||||
bool m_water_perturb = true;
|
||||
bool m_water_depth_fade = true;
|
||||
bool m_pbr = true;
|
||||
bool m_flip_y = false;
|
||||
std::unique_ptr<Texture> m_accum_texture;
|
||||
std::unique_ptr<Texture> m_reveal_texture;
|
||||
|
||||
bool m_init = false;
|
||||
std::unique_ptr<FrameBuffer> m_world_fbo;
|
||||
std::unique_ptr<Texture> m_screen_texture;
|
||||
std::unique_ptr<Texture> m_screen_depth_texture;
|
||||
|
||||
int m_shadow_mode = 0;
|
||||
int m_light_cull_face = 0;
|
||||
float m_aspect = 0.0f;
|
||||
float m_fov = DEFAULT_FOV;
|
||||
std::unique_ptr<FrameBuffer> m_oit_fbo;
|
||||
|
||||
float m_delta_time = 0.0f;
|
||||
std::unique_ptr<Texture> m_oit_depth_texture;
|
||||
|
||||
float m_cloud_time = 0.0f;
|
||||
float m_cloud_speed = 5.0f;
|
||||
|
||||
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, m_norm_mat;
|
||||
|
||||
GLuint m_sky_vbo = 0;
|
||||
GLuint m_text_vbo = 0;
|
||||
GLuint m_outline_indices_vbo = 0;
|
||||
GLuint m_outline_vbo = 0;
|
||||
GLuint m_ui_vbo = 0;
|
||||
GLuint m_player_vbo = 0;
|
||||
GLuint m_fbo = 0;
|
||||
GLuint m_screen_texture = 0;
|
||||
GLuint m_screen_depth_texture = 0;
|
||||
|
||||
GLuint m_oit_fbo = 0;
|
||||
GLuint m_accum_texture = 0;
|
||||
GLuint m_reveal_texture = 0;
|
||||
GLuint m_oit_depth_texture = 0;
|
||||
|
||||
GLuint m_depth_map_fbo = 0;
|
||||
GLuint m_depth_map_texture = 0;
|
||||
|
||||
GLuint m_quad_vbo = 0;
|
||||
|
||||
glm::mat4 m_ui_proj;
|
||||
glm::mat4 m_ui_m_matrix;
|
||||
std::unordered_map<std::size_t, Shader> m_shaders;
|
||||
std::unique_ptr<FrameBuffer> m_depth_map_fbo;
|
||||
std::unique_ptr<Texture> m_depth_map_texture;
|
||||
|
||||
glm::vec3 m_blend_from_lightdir;
|
||||
glm::vec3 m_blend_to_lightdir;
|
||||
float m_blend_t = 1.0f;
|
||||
bool m_blend_initialized = false;
|
||||
static constexpr float BLEND_DURATION = 0.15f;
|
||||
int m_light_size_uv = 20;
|
||||
|
||||
float m_min_radius = 2.0f;
|
||||
float m_max_radius = 20.0f;
|
||||
int m_samples = 16;
|
||||
|
||||
float m_specular_strength = 0.5f;
|
||||
|
||||
float moon_intensity = 0.3f;
|
||||
float sun_intensity = 1.00f;
|
||||
|
||||
float m_cloud_threshold_low = 0.5f;
|
||||
float m_cloud_threshold_high = 0.75f;
|
||||
|
||||
float m_refract_strength = 0.03f;
|
||||
|
||||
float m_underwater_fog_density = 0.08f;
|
||||
|
||||
float m_water_density = 0.12f;
|
||||
|
||||
float m_ambient_strength = 0.1f;
|
||||
bool m_discard_tranparent = true;
|
||||
bool m_shader_on = true;
|
||||
bool m_water_perturb = true;
|
||||
bool m_water_depth_fade = true;
|
||||
bool m_pbr = true;
|
||||
bool m_flip_y = false;
|
||||
int m_shadow_mode = 0;
|
||||
int m_light_size_uv = 20;
|
||||
float m_min_radius = 2.0f;
|
||||
float m_max_radius = 20.0f;
|
||||
int m_samples = 16;
|
||||
float m_specular_strength = 0.5f;
|
||||
float m_cloud_threshold_low = 0.5f;
|
||||
float m_cloud_threshold_high = 0.75f;
|
||||
float m_cloud_time = 0.0f;
|
||||
float m_cloud_speed = 5.0f;
|
||||
float m_refract_strength = 0.03f;
|
||||
int m_light_cull_face = 0;
|
||||
|
||||
float moon_intensity = 0.3f;
|
||||
float sun_intensity = 1.00f;
|
||||
|
||||
ParallelLight m_parallel_light;
|
||||
SkyUniform m_sky_uniform;
|
||||
/*
|
||||
0 - quad vao
|
||||
1 - sky vao
|
||||
2 - outline vao
|
||||
3 - ui vao
|
||||
4 - text vao
|
||||
*/
|
||||
std::vector<GLuint> m_vao;
|
||||
std::vector<Vertex2D> m_ui;
|
||||
|
||||
void init_quad();
|
||||
void init_text();
|
||||
glm::mat4 view_matrix;
|
||||
|
||||
ClientWorld& m_world;
|
||||
const Camera& m_camera;
|
||||
const TextureManager& m_texture_manager;
|
||||
void day_night_calculation();
|
||||
|
||||
void render_outline();
|
||||
void render_sky();
|
||||
void render_text();
|
||||
void render_ui();
|
||||
|
||||
void render_world();
|
||||
void render_player();
|
||||
|
||||
void shadow_map_generate();
|
||||
|
||||
void render_underwater();
|
||||
void render_dev_panel();
|
||||
void render_outline();
|
||||
void render_player();
|
||||
|
||||
void render_normal_block(const glm::mat4& model_mat,
|
||||
const glm::mat4& mv_mat,
|
||||
const glm::mat4& norm_mat);
|
||||
|
||||
void render_transparent_block(const glm::mat4& mv_mat,
|
||||
const glm::mat4& norm_mat);
|
||||
|
||||
glm::vec3 quantize_sun_direction(const glm::vec3& sundir,
|
||||
float angle_step_deg) const;
|
||||
glm::vec3 get_smoothed_shadow_lightdir(const glm::vec3& raw_shadow_sundir,
|
||||
float dt);
|
||||
};
|
||||
|
||||
} // namespace Cubed
|
||||
@@ -1,7 +1,10 @@
|
||||
#pragma once
|
||||
#include "Cubed/config.hpp"
|
||||
#include "Cubed/gameplay/block.hpp"
|
||||
#include "Cubed/render/texture.hpp"
|
||||
|
||||
#include <glad/glad.h>
|
||||
#include <memory>
|
||||
|
||||
namespace Cubed {
|
||||
|
||||
@@ -9,19 +12,17 @@ class TextureManager {
|
||||
private:
|
||||
bool m_need_reload = false;
|
||||
bool m_init = false;
|
||||
GLuint m_block_status_array = 0;
|
||||
GLuint m_texture_array = 0;
|
||||
GLuint m_cross_plane_array = 0;
|
||||
GLuint m_ui_array = 0;
|
||||
GLuint m_normal_texture_array = 0;
|
||||
std::unique_ptr<Texture> m_block_status_array;
|
||||
std::unique_ptr<Texture> m_texture_array;
|
||||
std::unique_ptr<Texture> m_cross_plane_array;
|
||||
std::unique_ptr<Texture> m_ui_array;
|
||||
std::unique_ptr<Texture> m_normal_texture_array;
|
||||
std::unique_ptr<Texture> m_skin;
|
||||
std::vector<std::unique_ptr<Texture>> m_item_textures;
|
||||
GLfloat m_max_aniso = 0.0f;
|
||||
|
||||
GLuint m_skin = 0;
|
||||
|
||||
Config& m_config;
|
||||
int m_aniso = 1;
|
||||
|
||||
std::vector<GLuint> m_item_textures;
|
||||
|
||||
void load_block_status(unsigned status_id);
|
||||
void load_block_texture(unsigned block_id);
|
||||
void load_block_item_texture(unsigned id);
|
||||
@@ -36,17 +37,17 @@ private:
|
||||
void hot_reload();
|
||||
|
||||
public:
|
||||
TextureManager();
|
||||
TextureManager(Config& config);
|
||||
~TextureManager();
|
||||
|
||||
void delet_texture();
|
||||
GLuint get_block_status_array() const;
|
||||
GLuint get_texture_array() const;
|
||||
GLuint get_cross_plane_array() const;
|
||||
GLuint get_ui_array() const;
|
||||
GLuint get_pbr_texture() const;
|
||||
const std::vector<GLuint>& item_textures() const;
|
||||
GLuint get_skin() const;
|
||||
void delete_texture();
|
||||
const Texture* get_block_status_array() const;
|
||||
const Texture* get_texture_array() const;
|
||||
const Texture* get_cross_plane_array() const;
|
||||
const Texture* get_ui_array() const;
|
||||
const Texture* get_pbr_texture() const;
|
||||
const std::vector<std::unique_ptr<Texture>>& item_textures() const;
|
||||
const Texture* get_skin() const;
|
||||
// Must call after MapTable::init_map() and glfwMakeContextCurrent(window);
|
||||
void init_texture();
|
||||
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
#pragma once
|
||||
#include "Cubed/render/texture.hpp"
|
||||
|
||||
#include <ft2build.h>
|
||||
#include <memory>
|
||||
#include FT_FREETYPE_H
|
||||
|
||||
#include "Cubed/primitive_data.hpp"
|
||||
@@ -29,7 +32,7 @@ public:
|
||||
static std::vector<Vertex2D> vertices(const std::string& text,
|
||||
float x = 0.0f, float y = 0.0f,
|
||||
float scale = 1.0f);
|
||||
static GLuint text_texture();
|
||||
static const Texture* text_texture();
|
||||
static const std::string& font_path();
|
||||
|
||||
private:
|
||||
@@ -39,7 +42,7 @@ private:
|
||||
float m_texture_width = 64;
|
||||
float m_texture_height = 64;
|
||||
|
||||
static inline GLuint m_text_texture;
|
||||
static inline std::unique_ptr<Texture> m_text_texture;
|
||||
static inline std::string m_font_path{ASSETS_PATH
|
||||
"fonts/IBMPlexSans-Regular.ttf"};
|
||||
std::unordered_map<char8_t, Character> m_characters;
|
||||
|
||||
@@ -14,6 +14,7 @@ concept TomlValueType =
|
||||
std::same_as<std::decay_t<T>, toml::date> ||
|
||||
std::same_as<std::decay_t<T>, toml::time> ||
|
||||
std::same_as<std::decay_t<T>, toml::date_time> ||
|
||||
std::same_as<std::decay_t<T>, float> ||
|
||||
std::same_as<std::decay_t<T>, std::string>;
|
||||
|
||||
template <TomlValueType T>
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "Cubed/primitive_data.hpp"
|
||||
#include "Cubed/render/vertex_array.hpp"
|
||||
#include "Cubed/render/vertex_buffer.hpp"
|
||||
#include "Cubed/ui/color.hpp"
|
||||
|
||||
#include <glad/glad.h>
|
||||
@@ -27,8 +29,7 @@ public:
|
||||
Text& text(std::string_view str);
|
||||
|
||||
std::size_t uuid() const;
|
||||
static void set_loc(const Shader& shader);
|
||||
void render();
|
||||
void render(const Shader& shader);
|
||||
|
||||
bool operator==(const Text& other) const;
|
||||
|
||||
@@ -38,14 +39,14 @@ private:
|
||||
|
||||
const std::string NAME;
|
||||
const std::size_t UUID;
|
||||
|
||||
std::string m_text;
|
||||
glm::vec4 m_color{1.0f, 1.0f, 1.0f, 1.0f};
|
||||
glm::mat4 m_model_matrix;
|
||||
|
||||
std::vector<Vertex2D> m_vertices;
|
||||
GLuint m_vbo = 0;
|
||||
static inline GLuint m_color_loc = 0;
|
||||
static inline GLuint m_mv_loc = 0;
|
||||
std::unique_ptr<VertexBuffer> m_vbo;
|
||||
std::unique_ptr<VertexArray> m_vao;
|
||||
|
||||
void update_vertices();
|
||||
void upload_to_gpu();
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "Cubed/config.hpp"
|
||||
|
||||
#define GLFW_INCLUDE_NONE
|
||||
#include <GLFW/glfw3.h>
|
||||
namespace Cubed {
|
||||
@@ -6,7 +9,7 @@ namespace Cubed {
|
||||
class Renderer;
|
||||
class Window {
|
||||
public:
|
||||
Window(Renderer& renderer);
|
||||
Window(Renderer& renderer, Config& config);
|
||||
~Window();
|
||||
|
||||
bool is_mouse_enable() const;
|
||||
@@ -29,6 +32,7 @@ private:
|
||||
int m_width;
|
||||
int m_height;
|
||||
Renderer& m_renderer;
|
||||
Config& m_config;
|
||||
};
|
||||
|
||||
} // namespace Cubed
|
||||
@@ -10,8 +10,7 @@ target_sources(${PROJECT_NAME}
|
||||
gameplay/chunk_generator.cpp
|
||||
gameplay/tree.cpp
|
||||
input.cpp
|
||||
map_table.cpp
|
||||
renderer.cpp
|
||||
render/renderer.cpp
|
||||
shader.cpp
|
||||
texture_manager.cpp
|
||||
tools/cubed_random.cpp
|
||||
@@ -43,7 +42,7 @@ target_sources(${PROJECT_NAME}
|
||||
gameplay/client_player.cpp
|
||||
gameplay/session.cpp
|
||||
gameplay/network_client.cpp
|
||||
player_renderer.cpp
|
||||
render/player_renderer.cpp
|
||||
audio/audio_engine.cpp
|
||||
audio/audio_loader.cpp
|
||||
audio/audio_source.cpp
|
||||
@@ -54,4 +53,10 @@ target_sources(${PROJECT_NAME}
|
||||
audio/audio_filter.cpp
|
||||
audio/audio_effect.cpp
|
||||
audio/audio_effect_slot.cpp
|
||||
render/vertex_buffer.cpp
|
||||
render/vertex_array.cpp
|
||||
render/texture.cpp
|
||||
render/frame_buffer.cpp
|
||||
render/shader_manager.cpp
|
||||
render/world_renderer.cpp
|
||||
)
|
||||
12
src/app.cpp
12
src/app.cpp
@@ -12,7 +12,14 @@
|
||||
#include <imgui_impl_glfw.h>
|
||||
namespace Cubed {
|
||||
|
||||
App::App() : m_client_world(m_audio) {}
|
||||
App::App()
|
||||
|
||||
: m_game_config(ASSETS_PATH "config.toml"),
|
||||
m_texture_manager(m_game_config), m_audio(m_game_config),
|
||||
m_client_world(m_audio, m_game_config), m_dev_panel(*this),
|
||||
m_renderer(m_camera, m_client_world, m_texture_manager, m_dev_panel,
|
||||
m_game_config),
|
||||
m_window(m_renderer, m_game_config) {}
|
||||
|
||||
App::~App() {
|
||||
if (m_client) {
|
||||
@@ -357,7 +364,7 @@ void App::update() {
|
||||
const auto& player = m_client_world.get_player();
|
||||
if (player_gait != player.get_gait()) {
|
||||
player_gait = player.get_gait();
|
||||
float fov = static_cast<float>(Config::get().get<double>("player.fov"));
|
||||
float fov = m_game_config.get("player.fov", 70.0f);
|
||||
if (player_gait == Gait::WALK) {
|
||||
m_renderer.update_fov(fov);
|
||||
}
|
||||
@@ -401,6 +408,7 @@ TextureManager& App::texture_manager() { return m_texture_manager; }
|
||||
Window& App::window() { return m_window; }
|
||||
ClientWorld& App::client_world() { return m_client_world; }
|
||||
ServerWorld& App::server_world() { return m_server.server_world(); }
|
||||
Config& App::config() { return m_game_config; }
|
||||
const App::Argument& App::argument() const { return m_argument; }
|
||||
AudioEngine& App::audio() { return m_audio; }
|
||||
} // namespace Cubed
|
||||
@@ -1,14 +1,13 @@
|
||||
#include "Cubed/audio/audio_engine.hpp"
|
||||
|
||||
#include "Cubed/audio/audio_error.hpp"
|
||||
#include "Cubed/config.hpp"
|
||||
#include "Cubed/tools/cubed_assert.hpp"
|
||||
#include "Cubed/tools/log.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
namespace Cubed {
|
||||
AudioEngine::AudioEngine() {};
|
||||
AudioEngine::AudioEngine(Config& config) : m_config(config) {};
|
||||
|
||||
AudioEngine::~AudioEngine() {
|
||||
if (!m_init) {
|
||||
@@ -64,10 +63,8 @@ void AudioEngine::init() {
|
||||
alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED);
|
||||
check_al_error();
|
||||
|
||||
auto& config = Config::get();
|
||||
|
||||
m_music_volume = static_cast<float>(config.get<double>("volume.music"));
|
||||
m_sfx_volume = static_cast<float>(config.get<double>("volume.SFX"));
|
||||
m_music_volume = m_config.get("volume.music", 1.0f);
|
||||
m_sfx_volume = m_config.get("volume.SFX", 1.0f);
|
||||
|
||||
m_sounds.init();
|
||||
|
||||
@@ -187,10 +184,8 @@ void AudioEngine::update() {
|
||||
}
|
||||
|
||||
void AudioEngine::reload_config() {
|
||||
auto& config = Config::get();
|
||||
|
||||
m_music_volume = static_cast<float>(config.get<double>("volume.music"));
|
||||
m_sfx_volume = static_cast<float>(config.get<double>("volume.SFX"));
|
||||
m_music_volume = m_config.get("volume.music", 1.0f);
|
||||
m_sfx_volume = m_config.get("volume.SFX", 1.0f);
|
||||
if (m_bgm) {
|
||||
m_bgm->set_target_volume(m_music_volume);
|
||||
}
|
||||
|
||||
126
src/config.cpp
126
src/config.cpp
@@ -1,6 +1,5 @@
|
||||
#include "Cubed/config.hpp"
|
||||
|
||||
#include "Cubed/tools/cubed_assert.hpp"
|
||||
#include "Cubed/tools/log.hpp"
|
||||
|
||||
#include <filesystem>
|
||||
@@ -11,71 +10,24 @@ using namespace std::string_view_literals;
|
||||
|
||||
namespace Cubed {
|
||||
|
||||
Config::Config() { load_or_create_config(); }
|
||||
Config::Config(std::string_view path) : CONGIF_PATH(path) { load_config(); }
|
||||
|
||||
Config::~Config() { save_to_file(); }
|
||||
|
||||
Config& Config::get() {
|
||||
static Config instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
toml::table& Config::table() { return m_tbl; }
|
||||
|
||||
void Config::create_config() {
|
||||
static constexpr auto SOURCE = R"(
|
||||
|
||||
[window]
|
||||
width = 800
|
||||
height = 600
|
||||
fullscreen = false
|
||||
V-Sync = true
|
||||
|
||||
[player]
|
||||
fov = 70.0
|
||||
mouse_sensitivity = 0.15
|
||||
|
||||
[world]
|
||||
rendering_distance = 24
|
||||
|
||||
[devpanel]
|
||||
theme = 0 # 0 is Dark Theme, 1 is Light Theme
|
||||
|
||||
[texture]
|
||||
aniso = 1 # i is the minimun value, indicating off
|
||||
|
||||
[volume]
|
||||
music = 1.0
|
||||
SFX = 1.0
|
||||
|
||||
|
||||
)"sv;
|
||||
|
||||
try {
|
||||
m_tbl = toml::parse(SOURCE);
|
||||
} catch (const toml::parse_error& err) {
|
||||
Logger::error("Load Config Error {}", err.what());
|
||||
ASSERT(false);
|
||||
std::abort();
|
||||
}
|
||||
Logger::info("Create New Config File Success");
|
||||
}
|
||||
|
||||
void Config::load_or_create_config() {
|
||||
void Config::load_config() {
|
||||
fs::path config_path{CONGIF_PATH};
|
||||
if (!fs::is_regular_file(config_path)) {
|
||||
create_config();
|
||||
} else
|
||||
|
||||
if (fs::is_regular_file(config_path)) {
|
||||
try {
|
||||
m_tbl = toml::parse_file(config_path.string());
|
||||
Logger::info("Load Config File Success");
|
||||
} catch (const toml::parse_error& err) {
|
||||
Logger::error("Load Config Error: \"{}\"", err.what());
|
||||
create_config();
|
||||
}
|
||||
|
||||
Logger::info("Load Config File Success");
|
||||
}
|
||||
|
||||
}
|
||||
void Config::save_to_file() {
|
||||
fs::path config_path{CONGIF_PATH};
|
||||
std::ofstream file{config_path};
|
||||
@@ -83,40 +35,54 @@ void Config::save_to_file() {
|
||||
Logger::info("Save File Success");
|
||||
}
|
||||
|
||||
toml::node_view<toml::node> Config::val_view(std::string_view key) {
|
||||
const toml::node* Config::find_node(const toml::table& root,
|
||||
std::string_view path) const {
|
||||
const toml::table* table = &root;
|
||||
|
||||
size_t cur = 0;
|
||||
auto pos = key.find('.');
|
||||
toml::table* table = &m_tbl;
|
||||
auto pos = path.find('.');
|
||||
|
||||
while (pos != std::string_view::npos) {
|
||||
std::string_view s = key.substr(cur, pos - cur);
|
||||
if (s.empty()) {
|
||||
Logger::error("Empty key/table name in path '{}'", key);
|
||||
ASSERT(false);
|
||||
std::abort();
|
||||
}
|
||||
cur = pos + 1;
|
||||
pos = key.find('.', cur);
|
||||
if (auto* next = (*table)[s].as_table()) {
|
||||
auto name = path.substr(cur, pos - cur);
|
||||
|
||||
if (auto* next = (*table)[name].as_table()) {
|
||||
table = next;
|
||||
} else {
|
||||
Logger::error("Can't find table {}", s);
|
||||
ASSERT(false);
|
||||
std::abort();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
cur = pos + 1;
|
||||
pos = path.find('.', cur);
|
||||
}
|
||||
std::string_view n_key = key.substr(cur);
|
||||
if (n_key.empty()) {
|
||||
Logger::error("Trailing dot in path '{}'", key);
|
||||
ASSERT(false);
|
||||
std::abort();
|
||||
|
||||
auto key = path.substr(cur);
|
||||
|
||||
return (*table)[key].node();
|
||||
}
|
||||
auto view = (*table)[n_key];
|
||||
if (!view) {
|
||||
Logger::error("The view is null");
|
||||
ASSERT(false);
|
||||
std::abort();
|
||||
|
||||
toml::table* Config::find_or_create_table(std::string_view path) {
|
||||
toml::table* table = &m_tbl;
|
||||
|
||||
while (true) {
|
||||
auto pos = path.find('.');
|
||||
auto part = pos == std::string_view::npos ? path : path.substr(0, pos);
|
||||
|
||||
if (auto* next = (*table)[part].as_table()) {
|
||||
// If there is a table, proceed to the next
|
||||
table = next;
|
||||
} else {
|
||||
// If there is no table, create a new one
|
||||
auto [it, _] = table->insert(part, toml::table{});
|
||||
table = it->second.as_table();
|
||||
}
|
||||
return view;
|
||||
|
||||
if (pos == std::string_view::npos)
|
||||
break;
|
||||
|
||||
path.remove_prefix(pos + 1);
|
||||
}
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
} // namespace Cubed
|
||||
@@ -46,7 +46,7 @@ constexpr float DELTA_ANGLE_MAX = 30.0f;
|
||||
constexpr int PATH_STEP_MIN = 1;
|
||||
constexpr int PATH_STEP_MAX = 1000;
|
||||
|
||||
DevPanel::DevPanel(App& app) : m_app(app) {}
|
||||
DevPanel::DevPanel(App& app) : m_app(app), m_config(app.config()) {}
|
||||
|
||||
void DevPanel::init() {
|
||||
m_player = &m_app.client_world().get_player();
|
||||
@@ -355,96 +355,95 @@ void DevPanel::show_chunk_table_bar() {
|
||||
|
||||
void DevPanel::show_settings_tab_item() {
|
||||
if (ImGui::BeginTabItem("settings")) {
|
||||
if (ImGui::SliderFloat("FOV", &m_config.fov, 1.0f, 140.0f)) {
|
||||
Config::get().set("player.fov", static_cast<double>(m_config.fov));
|
||||
if (ImGui::SliderFloat("FOV", &m_config_view.fov, 1.0f, 140.0f)) {
|
||||
m_config.set("player.fov", static_cast<double>(m_config_view.fov));
|
||||
m_app.renderer().hot_reload();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("default##1")) {
|
||||
m_config.fov = DEFAULT_FOV;
|
||||
Config::get().set("player.fov", static_cast<double>(m_config.fov));
|
||||
m_config_view.fov = DEFAULT_FOV;
|
||||
m_config.set("player.fov", static_cast<double>(m_config_view.fov));
|
||||
m_app.renderer().hot_reload();
|
||||
}
|
||||
if (ImGui::SliderFloat("Sensitivity", &m_config.mouse_sensitivity,
|
||||
if (ImGui::SliderFloat("Sensitivity", &m_config_view.mouse_sensitivity,
|
||||
0.01f, 1.0f)) {
|
||||
Config::get().set("player.mouse_sensitivity",
|
||||
static_cast<double>(m_config.mouse_sensitivity));
|
||||
m_config.set("player.mouse_sensitivity",
|
||||
static_cast<double>(m_config_view.mouse_sensitivity));
|
||||
m_player->hot_reload();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("default##2")) {
|
||||
m_config.mouse_sensitivity = 0.15f;
|
||||
Config::get().set("player.mouse_sensitivity",
|
||||
static_cast<double>(m_config.mouse_sensitivity));
|
||||
m_config_view.mouse_sensitivity = 0.15f;
|
||||
m_config.set("player.mouse_sensitivity",
|
||||
static_cast<double>(m_config_view.mouse_sensitivity));
|
||||
m_player->hot_reload();
|
||||
}
|
||||
|
||||
if (ImGui::SliderInt("Distance", &m_config.rendering_distance, 2,
|
||||
if (ImGui::SliderInt("Distance", &m_config_view.rendering_distance, 2,
|
||||
128)) {
|
||||
Config::get().set("world.rendering_distance",
|
||||
m_config.rendering_distance);
|
||||
m_config.set("world.rendering_distance",
|
||||
m_config_view.rendering_distance);
|
||||
m_app.client_world().hot_reload();
|
||||
}
|
||||
if (ImGui::Checkbox("Fullscreen", &m_config.fullscreen)) {
|
||||
Config::get().set("window.fullscreen", m_config.fullscreen);
|
||||
if (ImGui::Checkbox("Fullscreen", &m_config_view.fullscreen)) {
|
||||
m_config.set("window.fullscreen", m_config_view.fullscreen);
|
||||
m_app.window().hot_reload();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Checkbox("V-Sync", &m_config.v_sync)) {
|
||||
Config::get().set("window.V-Sync", m_config.v_sync);
|
||||
if (ImGui::Checkbox("V-Sync", &m_config_view.v_sync)) {
|
||||
m_config.set("window.V-Sync", m_config_view.v_sync);
|
||||
m_app.window().hot_reload();
|
||||
}
|
||||
if (ImGui::Checkbox("Aniso", &m_config.is_enable_aniso)) {
|
||||
m_config.is_reload = false;
|
||||
if (m_config.is_enable_aniso) {
|
||||
m_config.max_aniso = m_app.texture_manager().max_aniso();
|
||||
if (m_config.max_aniso < 2) {
|
||||
m_config.is_support_aniso = false;
|
||||
if (ImGui::Checkbox("Aniso", &m_config_view.is_enable_aniso)) {
|
||||
m_config_view.is_reload = false;
|
||||
if (m_config_view.is_enable_aniso) {
|
||||
m_config_view.max_aniso = m_app.texture_manager().max_aniso();
|
||||
if (m_config_view.max_aniso < 2) {
|
||||
m_config_view.is_support_aniso = false;
|
||||
} else {
|
||||
m_config.aniso = 2;
|
||||
m_config_view.aniso = 2;
|
||||
}
|
||||
} else {
|
||||
m_config.aniso = 1;
|
||||
m_config_view.aniso = 1;
|
||||
}
|
||||
}
|
||||
if (m_config.is_enable_aniso) {
|
||||
if (m_config_view.is_enable_aniso) {
|
||||
ImGui::SameLine();
|
||||
if (!m_config.is_support_aniso) {
|
||||
if (!m_config_view.is_support_aniso) {
|
||||
ImGui::Text("Not Support\n");
|
||||
} else {
|
||||
if (ImGui::SliderInt("##aniso", &m_config.aniso, 2,
|
||||
m_config.max_aniso)) {
|
||||
m_config.is_reload = false;
|
||||
if (ImGui::SliderInt("##aniso", &m_config_view.aniso, 2,
|
||||
m_config_view.max_aniso)) {
|
||||
m_config_view.is_reload = false;
|
||||
int log =
|
||||
static_cast<int>(std::log2(m_config.aniso) + 0.5f);
|
||||
m_config.aniso = static_cast<int>(std::pow(2, log));
|
||||
if (m_config.aniso < 2) {
|
||||
m_config.aniso = 2;
|
||||
static_cast<int>(std::log2(m_config_view.aniso) + 0.5f);
|
||||
m_config_view.aniso = static_cast<int>(std::pow(2, log));
|
||||
if (m_config_view.aniso < 2) {
|
||||
m_config_view.aniso = 2;
|
||||
}
|
||||
if (m_config.aniso > m_config.max_aniso) {
|
||||
m_config.aniso = m_config.max_aniso;
|
||||
if (m_config_view.aniso > m_config_view.max_aniso) {
|
||||
m_config_view.aniso = m_config_view.max_aniso;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ImGui::Button("ReloadTexture")) {
|
||||
Config::get().set("texture.aniso", m_config.aniso);
|
||||
m_config.set("texture.aniso", m_config_view.aniso);
|
||||
m_app.texture_manager().need_reload();
|
||||
m_config.is_reload = true;
|
||||
m_config_view.is_reload = true;
|
||||
}
|
||||
if (!m_config.is_reload) {
|
||||
if (!m_config_view.is_reload) {
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("Your need to click this button to apply config\n");
|
||||
}
|
||||
|
||||
if (ImGui::SliderFloat("Music", &m_config.volume_music, 0.0f, 1.0f)) {
|
||||
Config::get().set("volume.music",
|
||||
static_cast<double>(m_config.volume_music));
|
||||
if (ImGui::SliderFloat("Music", &m_config_view.volume_music, 0.0f,
|
||||
1.0f)) {
|
||||
m_config.set("volume.music", m_config_view.volume_music);
|
||||
m_app.audio().reload_config();
|
||||
}
|
||||
if (ImGui::SliderFloat("SFX", &m_config.volume_sfx, 0.0f, 1.0f)) {
|
||||
Config::get().set("volume.SFX",
|
||||
static_cast<double>(m_config.volume_sfx));
|
||||
if (ImGui::SliderFloat("SFX", &m_config_view.volume_sfx, 0.0f, 1.0f)) {
|
||||
m_config.set("volume.SFX", m_config_view.volume_sfx);
|
||||
m_app.audio().reload_config();
|
||||
}
|
||||
if (ImGui::Combo("Theme", &m_theme, THEMES, IM_ARRAYSIZE(THEMES))) {
|
||||
@@ -453,10 +452,10 @@ void DevPanel::show_settings_tab_item() {
|
||||
} else if (m_theme == 1) {
|
||||
ImGui::StyleColorsLight();
|
||||
}
|
||||
Config::get().set("devpanel.theme", m_theme);
|
||||
m_config.set("devpanel.theme", m_theme);
|
||||
}
|
||||
if (ImGui::Button("save")) {
|
||||
Config::get().save_to_file();
|
||||
m_config.save_to_file();
|
||||
}
|
||||
|
||||
ImGui::EndTabItem();
|
||||
@@ -650,13 +649,22 @@ void DevPanel::show_items_tab_item() {
|
||||
if (ImGui::BeginTabItem("item")) {
|
||||
ImGui::Text("Place Block ");
|
||||
ImGui::SameLine();
|
||||
ImGui::Image(static_cast<ImTextureID>(static_cast<intptr_t>(
|
||||
textures[m_player->place_block()])),
|
||||
auto& place_texture = textures[m_player->place_block()];
|
||||
if (place_texture) {
|
||||
ImGui::Image(static_cast<ImTextureID>(
|
||||
static_cast<intptr_t>(place_texture->id())),
|
||||
ImVec2{48, 48});
|
||||
}
|
||||
|
||||
for (size_t i = 1; i < textures.size(); i++) {
|
||||
if (ImGui::ImageButton(("##item" + std::to_string(i)).c_str(),
|
||||
auto& item_texture = textures[i];
|
||||
if (!item_texture) {
|
||||
continue;
|
||||
}
|
||||
if (ImGui::ImageButton(
|
||||
("##item" + std::to_string(i)).c_str(),
|
||||
static_cast<ImTextureID>(
|
||||
static_cast<intptr_t>(textures[i])),
|
||||
static_cast<intptr_t>(item_texture->id())),
|
||||
ImVec2{48, 48})) {
|
||||
m_player->set_place_block(i);
|
||||
}
|
||||
@@ -741,32 +749,28 @@ void DevPanel::show_shader_tab_item() {
|
||||
}
|
||||
|
||||
void DevPanel::update_config_view() {
|
||||
auto config = Config::get();
|
||||
m_config.fov =
|
||||
static_cast<float>(config.val_view("player.fov").value_or(70.0));
|
||||
m_config.fullscreen = config.val_view("window.fullscreen").value_or(false);
|
||||
m_config.v_sync = config.val_view("window.V-Sync").value_or(true);
|
||||
m_config.mouse_sensitivity = static_cast<float>(
|
||||
config.val_view("player.mouse_sensitivity").value_or(0.15));
|
||||
m_config.width = config.val_view("window.width").value_or(800);
|
||||
m_config.height = config.val_view("window.height").value_or(600);
|
||||
m_config.rendering_distance =
|
||||
config.val_view("world.rendering_distance").value_or(24);
|
||||
m_theme = config.val_view("devpanel.theme").value_or(0);
|
||||
m_config_view.fov = m_config.get("player.fov", 70.0f);
|
||||
m_config_view.fullscreen = m_config.get("window.fullscreen", false);
|
||||
m_config_view.v_sync = m_config.get("window.V-Sync", true);
|
||||
m_config_view.mouse_sensitivity =
|
||||
m_config.get("player.mouse_sensitivity", 0.15f);
|
||||
m_config_view.width = m_config.get("window.width", 800);
|
||||
m_config_view.height = m_config.get("window.height", 600);
|
||||
m_config_view.rendering_distance =
|
||||
m_config.get("world.rendering_distance", 24);
|
||||
m_theme = m_config.get("devpanel.theme", 0);
|
||||
if (m_theme != 1 && m_theme != 0) {
|
||||
m_theme = 0;
|
||||
}
|
||||
m_config.aniso = config.val_view("texture.aniso").value_or(1);
|
||||
m_config.max_aniso = m_app.texture_manager().max_aniso();
|
||||
if (m_config.aniso <= 1) {
|
||||
m_config.is_enable_aniso = false;
|
||||
m_config_view.aniso = m_config.get("texture.aniso", 1);
|
||||
m_config_view.max_aniso = m_app.texture_manager().max_aniso();
|
||||
if (m_config_view.aniso <= 1) {
|
||||
m_config_view.is_enable_aniso = false;
|
||||
} else {
|
||||
m_config.is_enable_aniso = true;
|
||||
m_config_view.is_enable_aniso = true;
|
||||
}
|
||||
m_config.volume_music =
|
||||
static_cast<float>(config.val_view("volume.music").value_or(1.0));
|
||||
m_config.volume_sfx =
|
||||
static_cast<float>(config.val_view("volume.SFX").value_or(1.0));
|
||||
m_config_view.volume_music = m_config.get("volume.music", 1.0f);
|
||||
m_config_view.volume_sfx = m_config.get("volume.SFX", 1.0f);
|
||||
}
|
||||
void DevPanel::update_player_profile() {
|
||||
if (!m_player) {
|
||||
|
||||
@@ -198,7 +198,12 @@ void ClientChunk::gen_vertex_data(
|
||||
m_is_on_gen_vertex_data = false;
|
||||
}
|
||||
|
||||
GLuint ClientChunk::get_normal_vao() const { return m_vertex_data[0].m_vao; }
|
||||
GLuint ClientChunk::get_normal_vao() const {
|
||||
if (!m_vertex_data[0].m_vao) {
|
||||
return 0;
|
||||
}
|
||||
return m_vertex_data[0].m_vao->id();
|
||||
}
|
||||
|
||||
size_t ClientChunk::get_normal_vertices_sum() const {
|
||||
if (m_vertex_data[0].m_sum == 0) {
|
||||
@@ -207,26 +212,43 @@ size_t ClientChunk::get_normal_vertices_sum() const {
|
||||
return m_vertex_data[0].m_sum.load();
|
||||
}
|
||||
|
||||
GLuint ClientChunk::get_cross_vao() const { return m_vertex_data[1].m_vao; }
|
||||
GLuint ClientChunk::get_cross_vao() const {
|
||||
if (!m_vertex_data[1].m_vao) {
|
||||
return 0;
|
||||
}
|
||||
return m_vertex_data[1].m_vao->id();
|
||||
}
|
||||
size_t ClientChunk::get_cross_vertices_sum() const {
|
||||
return m_vertex_data[1].m_sum.load();
|
||||
}
|
||||
|
||||
GLuint ClientChunk::get_normal_discard_vao() const {
|
||||
return m_vertex_data[2].m_vao;
|
||||
if (!m_vertex_data[2].m_vao) {
|
||||
return 0;
|
||||
}
|
||||
return m_vertex_data[2].m_vao->id();
|
||||
}
|
||||
size_t ClientChunk::get_normal_discard_vertices_sum() const {
|
||||
|
||||
return m_vertex_data[2].m_sum.load();
|
||||
}
|
||||
|
||||
GLuint ClientChunk::get_normal_blend_vao() const {
|
||||
return m_vertex_data[3].m_vao;
|
||||
if (!m_vertex_data[3].m_vao) {
|
||||
return 0;
|
||||
}
|
||||
return m_vertex_data[3].m_vao->id();
|
||||
}
|
||||
size_t ClientChunk::get_normal_blend_vertices_sum() const {
|
||||
return m_vertex_data[3].m_sum.load();
|
||||
}
|
||||
|
||||
GLuint ClientChunk::get_water_vao() const { return m_vertex_data[4].m_vao; }
|
||||
GLuint ClientChunk::get_water_vao() const {
|
||||
if (!m_vertex_data[4].m_vao) {
|
||||
return 0;
|
||||
}
|
||||
return m_vertex_data[4].m_vao->id();
|
||||
}
|
||||
size_t ClientChunk::get_water_vertices_sum() const {
|
||||
return m_vertex_data[4].m_sum.load();
|
||||
}
|
||||
|
||||
@@ -121,9 +121,8 @@ void ClientPlayer::change_mode(GameMode mode) {
|
||||
}
|
||||
}
|
||||
void ClientPlayer::hot_reload() {
|
||||
auto& config = Config::get();
|
||||
m_sensitivity =
|
||||
static_cast<float>(config.get<double>("player.mouse_sensitivity"));
|
||||
auto& config = m_world.get_config();
|
||||
m_sensitivity = config.get("player.mouse_sensitivity", 0.15f);
|
||||
}
|
||||
void ClientPlayer::set_player_pos(const glm::vec3& pos) { m_player_pos = pos; }
|
||||
|
||||
@@ -562,7 +561,7 @@ const ClientPlayer::ChunkPosSet& ClientPlayer::get_chunk_pos_set() const {
|
||||
return m_player_chunk_pos_set;
|
||||
}
|
||||
|
||||
ClientPlayer::ChunkPosSet& ClientPlayer::get_chunk_pos_set() {
|
||||
ClientPlayer::ChunkPosSet ClientPlayer::get_chunk_pos_set() {
|
||||
std::lock_guard lock(m_chunk_pos_mutex);
|
||||
return m_player_chunk_pos_set;
|
||||
}
|
||||
|
||||
@@ -21,27 +21,32 @@ struct ChunkRenderData {
|
||||
};
|
||||
} // namespace
|
||||
|
||||
ClientWorld::ClientWorld(AudioEngine& auido)
|
||||
: m_player(*this), m_audio(auido) {}
|
||||
ClientWorld::ClientWorld(AudioEngine& auido, Config& config)
|
||||
: m_player(*this), m_audio(auido), m_config(config) {}
|
||||
|
||||
ClientWorld::~ClientWorld() {
|
||||
m_client->close();
|
||||
|
||||
stop_client_thread();
|
||||
stop_thread_pool();
|
||||
// Must first clean up and push the generated chunk data into
|
||||
// m_pending_delete_vbo and m_pending_delete_vao; cannot delete them in the
|
||||
// destructor, otherwise it will cause leaks and use-after-free.
|
||||
m_dirty_chunk_queue.clear();
|
||||
m_pending_upload_queue.clear();
|
||||
|
||||
m_chunks.clear();
|
||||
|
||||
if (m_is_pending_delete_queue_free.exchange(true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
std::lock_guard lk(m_delete_vbo_mutex);
|
||||
for (auto x : m_pending_delete_vbo) {
|
||||
glDeleteBuffers(1, &x);
|
||||
}
|
||||
m_pending_delete_vbo.clear();
|
||||
}
|
||||
{
|
||||
std::lock_guard lk(m_delete_vao_mutex);
|
||||
for (auto x : m_pending_delete_vao) {
|
||||
glDeleteVertexArrays(1, &x);
|
||||
}
|
||||
m_pending_delete_vao.clear();
|
||||
}
|
||||
m_ticktimers.clear();
|
||||
@@ -267,13 +272,21 @@ void ClientWorld::set_block(const glm::ivec3& block_pos, unsigned id) {
|
||||
});
|
||||
}
|
||||
}
|
||||
void ClientWorld::push_delete_vbo(GLuint vbo) {
|
||||
std::lock_guard lk(m_delete_vbo_mutex);
|
||||
m_pending_delete_vbo.push_back(vbo);
|
||||
void ClientWorld::push_delete_vbo(std::unique_ptr<VertexBuffer>& vbo) {
|
||||
if (m_is_pending_delete_queue_free) {
|
||||
Logger::error("Push delete vbo Use After Free");
|
||||
return;
|
||||
}
|
||||
std::lock_guard lk(m_delete_vbo_mutex);
|
||||
m_pending_delete_vbo.push_back(std::move(vbo));
|
||||
}
|
||||
void ClientWorld::push_delete_vao(std::unique_ptr<VertexArray>& vao) {
|
||||
if (m_is_pending_delete_queue_free) {
|
||||
Logger::error("Push delete vao Use After Free");
|
||||
return;
|
||||
}
|
||||
void ClientWorld::push_delete_vao(GLuint vao) {
|
||||
std::lock_guard lk(m_delete_vao_mutex);
|
||||
m_pending_delete_vao.push_back(vao);
|
||||
m_pending_delete_vao.push_back(std::move(vao));
|
||||
}
|
||||
|
||||
void ClientWorld::report_block_change(const glm::ivec3& pos,
|
||||
@@ -510,8 +523,7 @@ void ClientWorld::change_pool_threads(int threads) {
|
||||
}
|
||||
|
||||
void ClientWorld::hot_reload() {
|
||||
auto& config = Config::get();
|
||||
int dist = config.get<int>("world.rendering_distance");
|
||||
int dist = m_config.get<int>("world.rendering_distance", PRE_LOAD_DISTANCE);
|
||||
Logger::info("Get Config Randering dist {}", dist);
|
||||
m_rendering_distance = dist <= MAX_DISTANCE ? dist : MAX_DISTANCE;
|
||||
request_chunk();
|
||||
@@ -597,7 +609,7 @@ void ClientWorld::request_chunk() {
|
||||
}
|
||||
}
|
||||
|
||||
ChunkPosSet old = std::move(m_player.get_chunk_pos_set());
|
||||
ChunkPosSet old = m_player.get_chunk_pos_set();
|
||||
m_player.update_chunk_set(required_chunks);
|
||||
|
||||
ChunkPosVector need_send_pos;
|
||||
@@ -705,6 +717,7 @@ AABB ClientWorld::get_block_aabb(const glm::ivec3& pos) {
|
||||
}
|
||||
|
||||
AudioEngine& ClientWorld::get_audio() { return m_audio; }
|
||||
Config& ClientWorld::get_config() { return m_config; }
|
||||
|
||||
void ClientWorld::request_exit() {
|
||||
if (m_receive_exit) {
|
||||
@@ -729,17 +742,11 @@ void ClientWorld::update(float delta_time) {
|
||||
m_player.update(delta_time);
|
||||
{
|
||||
std::lock_guard lk(m_delete_vbo_mutex);
|
||||
for (auto x : m_pending_delete_vbo) {
|
||||
glDeleteBuffers(1, &x);
|
||||
}
|
||||
m_pending_delete_vbo.clear();
|
||||
}
|
||||
|
||||
{
|
||||
std::lock_guard lk(m_delete_vao_mutex);
|
||||
for (auto x : m_pending_delete_vao) {
|
||||
glDeleteVertexArrays(1, &x);
|
||||
}
|
||||
m_pending_delete_vao.clear();
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
using asio::ip::tcp;
|
||||
namespace Cubed {
|
||||
|
||||
NetworkServer::NetworkServer(int port) : m_port(port) {}
|
||||
NetworkServer::NetworkServer()
|
||||
: m_config(ASSETS_PATH "server-config.toml"), m_world(m_config) {
|
||||
m_port = m_config.get("port", 25530);
|
||||
}
|
||||
|
||||
NetworkServer::~NetworkServer() { stop(); }
|
||||
|
||||
@@ -84,6 +87,11 @@ void NetworkServer::net_run() {
|
||||
|
||||
void NetworkServer::start_server(int port) {
|
||||
m_port = port;
|
||||
m_config.set("port", m_port);
|
||||
start_server();
|
||||
}
|
||||
|
||||
void NetworkServer::start_server() {
|
||||
m_world.init_world();
|
||||
net_run();
|
||||
m_started = true;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "Cubed/gameplay/server_world.hpp"
|
||||
|
||||
#include "Cubed/config.hpp"
|
||||
#include "Cubed/gameplay/packet.hpp"
|
||||
#include "Cubed/gameplay/session.hpp"
|
||||
#include "Cubed/tools/cubed_assert.hpp"
|
||||
@@ -14,7 +13,7 @@ using namespace std::chrono_literals;
|
||||
using namespace google::protobuf;
|
||||
|
||||
namespace Cubed {
|
||||
ServerWorld::ServerWorld() {}
|
||||
ServerWorld::ServerWorld(Config& config) : m_config(config) {}
|
||||
|
||||
ServerWorld::~ServerWorld() { stop(); }
|
||||
|
||||
@@ -501,8 +500,7 @@ bool ServerWorld::set_block(const glm::ivec3& block_pos, unsigned id) {
|
||||
}
|
||||
|
||||
void ServerWorld::hot_reload() {
|
||||
auto& config = Config::get();
|
||||
int dist = config.get<int>("world.rendering_distance");
|
||||
int dist = m_config.get("server_distance", 24);
|
||||
m_rendering_distance = dist <= MAX_DISTANCE ? dist : MAX_DISTANCE;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,64 +5,60 @@
|
||||
namespace Cubed {
|
||||
VertexData::VertexData(ClientWorld& world) : m_world(world) {}
|
||||
VertexData::~VertexData() {
|
||||
if (m_vbo != 0) {
|
||||
|
||||
m_world.push_delete_vbo(m_vbo);
|
||||
}
|
||||
if (m_vao != 0) {
|
||||
|
||||
m_world.push_delete_vao(m_vao);
|
||||
}
|
||||
}
|
||||
VertexData::VertexData(VertexData&& o) noexcept
|
||||
: m_vertices(std::move(o.m_vertices)), m_vbo(o.m_vbo), m_vao(o.m_vao),
|
||||
m_sum(o.m_sum.load()), m_world(o.m_world) {
|
||||
o.m_vbo = 0;
|
||||
o.m_sum = 0;
|
||||
o.m_vao = 0;
|
||||
}
|
||||
: m_vertices(std::move(o.m_vertices)), m_vbo(std::move(o.m_vbo)),
|
||||
m_vao(std::move(o.m_vao)), m_sum(o.m_sum.exchange(0)),
|
||||
m_world(o.m_world) {}
|
||||
VertexData& VertexData::operator=(VertexData&& o) noexcept {
|
||||
m_vbo = o.m_vbo;
|
||||
o.m_vbo = 0;
|
||||
m_sum = o.m_sum.load();
|
||||
o.m_sum = 0;
|
||||
if (this == &o) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
m_world.push_delete_vao(m_vao);
|
||||
m_world.push_delete_vbo(m_vbo);
|
||||
|
||||
m_vbo = std::move(o.m_vbo);
|
||||
m_vao = std::move(o.m_vao);
|
||||
|
||||
m_sum = o.m_sum.exchange(0);
|
||||
|
||||
m_vertices = std::move(o.m_vertices);
|
||||
m_vao = o.m_vao;
|
||||
o.m_vao = 0;
|
||||
|
||||
return *this;
|
||||
}
|
||||
void VertexData::upload() {
|
||||
if (m_vertices.size() == 0) {
|
||||
return;
|
||||
}
|
||||
if (m_vao == 0) {
|
||||
glGenVertexArrays(1, &m_vao);
|
||||
if (!m_vao) {
|
||||
m_vao = std::make_unique<VertexArray>();
|
||||
}
|
||||
if (m_vbo == 0) {
|
||||
glGenBuffers(1, &m_vbo);
|
||||
if (!m_vbo) {
|
||||
m_vbo = std::make_unique<VertexBuffer>();
|
||||
}
|
||||
glBindVertexArray(m_vao);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, m_vertices.size() * sizeof(Vertex3D),
|
||||
m_vertices.data(), GL_DYNAMIC_DRAW);
|
||||
m_vao->bind();
|
||||
m_vbo->buffer_data(m_vertices.data(), m_vertices.size() * sizeof(Vertex3D),
|
||||
BufferUsage::DYNAMIC_DRAW);
|
||||
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex3D), (void*)0);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex3D),
|
||||
m_vao->attribute(0, 3, GL_FLOAT, sizeof(Vertex3D), (void*)0);
|
||||
m_vao->attribute(1, 2, GL_FLOAT, sizeof(Vertex3D),
|
||||
(void*)offsetof(Vertex3D, s));
|
||||
glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, sizeof(Vertex3D),
|
||||
m_vao->attribute(2, 1, GL_FLOAT, sizeof(Vertex3D),
|
||||
(void*)offsetof(Vertex3D, layer));
|
||||
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex3D),
|
||||
m_vao->attribute(3, 3, GL_FLOAT, sizeof(Vertex3D),
|
||||
(void*)offsetof(Vertex3D, nx));
|
||||
glVertexAttribPointer(4, 1, GL_FLOAT, GL_FALSE, sizeof(Vertex3D),
|
||||
m_vao->attribute(4, 1, GL_FLOAT, sizeof(Vertex3D),
|
||||
(void*)offsetof(Vertex3D, roughness));
|
||||
glVertexAttribPointer(5, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex3D),
|
||||
m_vao->attribute(5, 3, GL_FLOAT, sizeof(Vertex3D),
|
||||
(void*)offsetof(Vertex3D, tx));
|
||||
glEnableVertexAttribArray(0);
|
||||
glEnableVertexAttribArray(1);
|
||||
glEnableVertexAttribArray(2);
|
||||
glEnableVertexAttribArray(3);
|
||||
glEnableVertexAttribArray(4);
|
||||
glEnableVertexAttribArray(5);
|
||||
glBindVertexArray(0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
VertexArray::unbind();
|
||||
VertexBuffer::unbind();
|
||||
|
||||
// Release memory
|
||||
m_vertices.clear();
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
#include "Cubed/map_table.hpp"
|
||||
|
||||
namespace Cubed {
|
||||
/*
|
||||
std::string_view MapTable::get_name_from_id(unsigned id) {
|
||||
auto it = id_to_name_map.find(id);
|
||||
ASSERT_MSG(it != id_to_name_map.end(),
|
||||
"Id: " + std::to_string(id) + " is not exist");
|
||||
return it->second;
|
||||
}
|
||||
|
||||
unsigned MapTable::get_id_from_name(const std::string& name) {
|
||||
auto it = name_to_id_map.find(HASH::str(name));
|
||||
ASSERT_MSG(it != name_to_id_map.end(), "Name " + name + " is not exist");
|
||||
return it->second;
|
||||
}
|
||||
|
||||
std::string_view MapTable::item_name(unsigned id) {
|
||||
ASSERT_MSG(id < item_id_to_name.size(), "ID is invalid");
|
||||
return item_id_to_name[id];
|
||||
}
|
||||
|
||||
const std::vector<std::string>& MapTable::item_map() { return item_id_to_name; }
|
||||
*/
|
||||
void MapTable::init_map() {
|
||||
/*
|
||||
id_to_name_map.reserve(MAX_BLOCK_NUM);
|
||||
name_to_id_map.reserve(MAX_BLOCK_NUM);
|
||||
|
||||
for (int i = 0; i < MAX_BLOCK_NUM; i++) {
|
||||
id_to_name_map[i] = BLOCK_REISTER[i];
|
||||
name_to_id_map[HASH::str(BLOCK_REISTER[i])] = i;
|
||||
}
|
||||
for (auto s : BLOCK_REISTER) {
|
||||
item_id_to_name.emplace_back(s);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
} // namespace Cubed
|
||||
79
src/render/frame_buffer.cpp
Normal file
79
src/render/frame_buffer.cpp
Normal file
@@ -0,0 +1,79 @@
|
||||
#include "Cubed/render/frame_buffer.hpp"
|
||||
|
||||
#include "Cubed/tools/log.hpp"
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace Cubed {
|
||||
FrameBuffer::FrameBuffer() { glGenFramebuffers(1, &m_fbo); }
|
||||
FrameBuffer::~FrameBuffer() {
|
||||
if (m_fbo) {
|
||||
glDeleteFramebuffers(1, &m_fbo);
|
||||
}
|
||||
}
|
||||
|
||||
FrameBuffer::FrameBuffer(FrameBuffer&& o) noexcept
|
||||
: m_fbo(std::exchange(o.m_fbo, 0)) {}
|
||||
|
||||
FrameBuffer& FrameBuffer::operator=(FrameBuffer&& o) noexcept {
|
||||
if (this == &o) {
|
||||
return *this;
|
||||
}
|
||||
if (m_fbo) {
|
||||
glDeleteFramebuffers(1, &m_fbo);
|
||||
}
|
||||
m_fbo = std::exchange(o.m_fbo, 0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
GLuint FrameBuffer::id() const { return m_fbo; }
|
||||
|
||||
void FrameBuffer::bind(FrameBufferType type) const {
|
||||
glBindFramebuffer(std::to_underlying(type), m_fbo);
|
||||
}
|
||||
void FrameBuffer::unbind() {
|
||||
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
void FrameBuffer::attach(Attachment attachment, const Texture& texture,
|
||||
GLint level) const {
|
||||
bind();
|
||||
auto type = texture.type();
|
||||
if (type == TextureType::TEXTURE_2D) {
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, std::to_underlying(attachment),
|
||||
std::to_underlying(type), texture.id(), level);
|
||||
}
|
||||
}
|
||||
|
||||
bool FrameBuffer::check_status() const {
|
||||
bind();
|
||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
||||
Logger::error("FBO incomplete after resize!");
|
||||
return false;
|
||||
} else {
|
||||
Logger::info("Frame Buffer Complete!");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void FrameBuffer::draw_buffer(GLenum buf) const {
|
||||
bind();
|
||||
glDrawBuffer(buf);
|
||||
}
|
||||
void FrameBuffer::read_buffer(GLenum src) const {
|
||||
bind();
|
||||
glReadBuffer(src);
|
||||
}
|
||||
void FrameBuffer::draw_buffer(GLsizei n, const GLenum* bufs) const {
|
||||
bind();
|
||||
glDrawBuffers(n, bufs);
|
||||
}
|
||||
|
||||
void FrameBuffer::draw_buffer(std::span<const GLenum> bufs) const {
|
||||
bind();
|
||||
glDrawBuffers(bufs.size(), bufs.data());
|
||||
}
|
||||
|
||||
} // namespace Cubed
|
||||
@@ -1,9 +1,9 @@
|
||||
#include "Cubed/player_renderer.hpp"
|
||||
#include "Cubed/render/player_renderer.hpp"
|
||||
|
||||
#include "Cubed/camera.hpp"
|
||||
#include "Cubed/gameplay/client_world.hpp"
|
||||
#include "Cubed/primitive_data.hpp"
|
||||
#include "Cubed/renderer.hpp"
|
||||
#include "Cubed/render/renderer.hpp"
|
||||
#include "Cubed/texture_manager.hpp"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
@@ -197,7 +197,7 @@ void PlayerRenderer::render(const Shader& shader) {
|
||||
auto& m_world = m_renderer.world();
|
||||
auto& m_player = m_world.get_player();
|
||||
glm::mat4 m_v_mat = m_camera.get_camera_lookat();
|
||||
glm::mat4 m_p_mat = m_renderer.proj_mat();
|
||||
glm::mat4 m_p_mat = m_renderer.world_proj_matrix();
|
||||
|
||||
auto& players = m_world.render_player_data();
|
||||
shader.set_loc("proj_matrix", m_p_mat);
|
||||
@@ -223,8 +223,7 @@ void PlayerRenderer::render(const Shader& shader) {
|
||||
glm::vec3(0, 1, 0));
|
||||
model = glm::translate(model, glm::vec3(-0.5f, 0.0f, -0.5f));
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, m_renderer.texture_mamger().get_skin());
|
||||
m_renderer.texture_mamger().get_skin()->bind(1);
|
||||
|
||||
auto make_rotated = [&](glm::vec3 pivot, float angle) {
|
||||
glm::mat4 mat = model;
|
||||
296
src/render/renderer.cpp
Normal file
296
src/render/renderer.cpp
Normal file
@@ -0,0 +1,296 @@
|
||||
#include "Cubed/render/renderer.hpp"
|
||||
|
||||
#include "Cubed/camera.hpp"
|
||||
#include "Cubed/config.hpp"
|
||||
#include "Cubed/debug_collector.hpp"
|
||||
#include "Cubed/dev_panel.hpp"
|
||||
#include "Cubed/gameplay/client_player.hpp"
|
||||
#include "Cubed/gameplay/client_world.hpp"
|
||||
#include "Cubed/primitive_data.hpp"
|
||||
#include "Cubed/render/renderer_constants.hpp"
|
||||
#include "Cubed/texture_manager.hpp"
|
||||
#include "Cubed/tools/font.hpp"
|
||||
#include "Cubed/tools/log.hpp"
|
||||
#include "Cubed/tools/shader_tools.hpp"
|
||||
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <format>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
namespace Cubed {
|
||||
|
||||
Renderer::Renderer(const Camera& camera, ClientWorld& world,
|
||||
const TextureManager& texture_manager, DevPanel& dev_panel,
|
||||
Config& config)
|
||||
: m_camera(camera), m_dev_panel(dev_panel),
|
||||
m_texture_manager(texture_manager), m_world(world),
|
||||
m_world_renderer(*this), m_config(config) {}
|
||||
|
||||
Renderer::~Renderer() {
|
||||
if (m_init) {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
m_outline_vbo.reset();
|
||||
m_outline_indices_vbo.reset();
|
||||
m_sky_vbo.reset();
|
||||
m_ui_vbo.reset();
|
||||
m_player_vbo.reset();
|
||||
glBindVertexArray(0);
|
||||
m_vao.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::hot_reload() { update_fov(m_config.get("player.fov", 70.0f)); }
|
||||
|
||||
void Renderer::init(bool debug_on) {
|
||||
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
|
||||
Logger::error("Failed to initialize glad");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
Logger::info("OpenGL Version: {}.{}", GLVersion.major, GLVersion.minor);
|
||||
Logger::info("Renderer: {}",
|
||||
reinterpret_cast<const char*>(glGetString(GL_RENDERER)));
|
||||
|
||||
m_shaders.init();
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
#ifdef DEBUG_MODE
|
||||
if (debug_on) {
|
||||
glEnable(GL_DEBUG_OUTPUT);
|
||||
glDebugMessageCallback(
|
||||
[](GLenum, GLenum, GLuint, GLenum, GLsizei, const GLchar* message,
|
||||
const void*) {
|
||||
Logger::log(Logger::Level::L_DEBUG,
|
||||
std::source_location::current(), "GL Debug: {}",
|
||||
reinterpret_cast<const char*>(message));
|
||||
},
|
||||
nullptr);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
m_vao.resize(NUM_VAO);
|
||||
VertexArray::unbind();
|
||||
|
||||
m_outline_vbo = std::make_unique<VertexBuffer>();
|
||||
m_outline_indices_vbo =
|
||||
std::make_unique<VertexBuffer>(BufferType::ELEMENT_ARRAY_BUFFER);
|
||||
m_player_vbo = std::make_unique<VertexBuffer>();
|
||||
m_quad_vbo = std::make_unique<VertexBuffer>();
|
||||
m_sky_vbo = std::make_unique<VertexBuffer>();
|
||||
m_ui_vbo = std::make_unique<VertexBuffer>();
|
||||
|
||||
m_vao[2].bind();
|
||||
|
||||
m_outline_vbo->buffer_data(CUBE_VER, sizeof(CUBE_VER));
|
||||
m_vao[2].attribute(0, 3, GL_FLOAT, 0, 0);
|
||||
m_outline_indices_vbo->buffer_data(OUTLINE_CUBE_INDICES,
|
||||
sizeof(OUTLINE_CUBE_INDICES));
|
||||
|
||||
m_vao[1].bind();
|
||||
m_sky_vbo->buffer_data(VERTICES_POS, sizeof(VERTICES_POS));
|
||||
|
||||
m_vao[1].attribute(0, 3, GL_FLOAT, 0, 0);
|
||||
|
||||
m_vao[3].bind();
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
Vertex2D vex{SQUARE_VERTICES[i][0], SQUARE_VERTICES[i][1],
|
||||
SQUARE_TEXTURE_POS[i][0], SQUARE_TEXTURE_POS[i][1], 0};
|
||||
m_ui.emplace_back(vex);
|
||||
}
|
||||
m_ui_vbo->buffer_data(m_ui.data(), m_ui.size() * sizeof(Vertex2D));
|
||||
|
||||
m_vao[3].attribute(0, 3, GL_FLOAT, sizeof(Vertex2D), (void*)0);
|
||||
m_vao[3].attribute(1, 2, GL_FLOAT, sizeof(Vertex2D),
|
||||
(void*)offsetof(Vertex2D, s));
|
||||
m_vao[3].attribute(2, 1, GL_FLOAT, sizeof(Vertex2D),
|
||||
(void*)offsetof(Vertex2D, layer));
|
||||
|
||||
init_quad();
|
||||
init_text();
|
||||
hot_reload();
|
||||
|
||||
m_world_renderer.init();
|
||||
|
||||
VertexArray::unbind();
|
||||
VertexBuffer::unbind();
|
||||
m_init = true;
|
||||
}
|
||||
|
||||
const Shader& Renderer::get_shader(const std::string& name) const {
|
||||
return m_shaders.get_shader(name);
|
||||
}
|
||||
|
||||
void Renderer::init_quad() {
|
||||
m_vao[0].bind();
|
||||
m_quad_vbo->buffer_data(QUAD_VERTICES, sizeof(QUAD_VERTICES));
|
||||
|
||||
m_vao[0].attribute(0, 2, GL_FLOAT, 4 * sizeof(float), (void*)0);
|
||||
|
||||
m_vao[0].attribute(1, 2, GL_FLOAT, 4 * sizeof(float),
|
||||
(void*)(2 * sizeof(float)));
|
||||
}
|
||||
|
||||
void Renderer::init_text() {
|
||||
m_vao[4].bind();
|
||||
|
||||
DebugCollector::get().init_text();
|
||||
}
|
||||
|
||||
void Renderer::render() {
|
||||
glDisable(GL_FRAMEBUFFER_SRGB);
|
||||
// clear screen
|
||||
glClearColor(0.0, 0.0, 0.0, 1.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
m_world_renderer.render();
|
||||
|
||||
render_ui();
|
||||
|
||||
render_text();
|
||||
|
||||
render_dev_panel();
|
||||
}
|
||||
|
||||
void Renderer::render_text() {
|
||||
|
||||
const auto& shader = get_shader("text");
|
||||
|
||||
shader.use();
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
shader.set_loc("projection", m_ui_proj_matrix);
|
||||
|
||||
auto& texts = DebugCollector::get().all_texts();
|
||||
for (auto& t : texts) {
|
||||
t.second.render(shader);
|
||||
}
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
void Renderer::render_ui() {
|
||||
const auto& shader = get_shader("ui");
|
||||
shader.use();
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
shader.set_loc("m_matrix", m_ui_model_matrix);
|
||||
shader.set_loc("proj_matrix", m_ui_proj_matrix);
|
||||
|
||||
m_vao[3].bind();
|
||||
m_texture_manager.get_ui_array()->bind(0);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
Tools::check_opengl_error();
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
void Renderer::update(float delta_time) { m_delta_time = delta_time; }
|
||||
|
||||
void Renderer::update_fov(float fov) {
|
||||
m_fov = fov;
|
||||
|
||||
m_world_proj_matrix =
|
||||
glm::perspective(glm::radians(fov), m_aspect, NEAR_PLANE, FAR_PLANE);
|
||||
}
|
||||
|
||||
void Renderer::update_proj_matrix(float aspect, float width, float height) {
|
||||
m_aspect = aspect;
|
||||
|
||||
m_world_proj_matrix =
|
||||
glm::perspective(glm::radians(m_fov), aspect, NEAR_PLANE, FAR_PLANE);
|
||||
|
||||
m_ui_proj_matrix = glm::ortho(0.0f, width, height, 0.0f, -1.0f, 1.0f);
|
||||
// scale and then translate
|
||||
m_ui_model_matrix =
|
||||
glm::translate(glm::mat4(1.0f),
|
||||
glm::vec3(width / 2.0f, height / 2.0f, 0.0)) *
|
||||
glm::scale(glm::mat4(1.0f), glm::vec3(50.0f, 50.0f, 1.0f));
|
||||
}
|
||||
|
||||
void Renderer::updata_framebuffer(int width, int height) {
|
||||
if (width <= 0 || height <= 0)
|
||||
return;
|
||||
|
||||
m_world_renderer.updata_framebuffer(width, height);
|
||||
|
||||
FrameBuffer::unbind();
|
||||
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
}
|
||||
|
||||
void Renderer::render_dev_panel() {
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
m_dev_panel.render();
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
float& Renderer::ambient_strength() {
|
||||
return m_world_renderer.ambient_strength();
|
||||
}
|
||||
bool& Renderer::discard_transparent() {
|
||||
return m_world_renderer.discard_transparent();
|
||||
}
|
||||
bool& Renderer::shader_on() { return m_world_renderer.shader_on(); }
|
||||
bool& Renderer::water_perturb() { return m_world_renderer.water_perturb(); }
|
||||
bool& Renderer::water_depth_fade() {
|
||||
return m_world_renderer.water_depth_fade();
|
||||
}
|
||||
bool& Renderer::pbr() { return m_world_renderer.pbr(); }
|
||||
bool& Renderer::flip_y() { return m_world_renderer.flip_y(); }
|
||||
int& Renderer::shadow_mode() { return m_world_renderer.shadow_mode(); }
|
||||
int& Renderer::light_cull_face() { return m_world_renderer.light_cull_face(); }
|
||||
int& Renderer::light_size_uv() { return m_world_renderer.light_size_uv(); }
|
||||
float& Renderer::min_radius() { return m_world_renderer.min_radius(); }
|
||||
float& Renderer::max_radius() { return m_world_renderer.max_radius(); }
|
||||
int& Renderer::samples() { return m_world_renderer.samples(); }
|
||||
float& Renderer::specular_strength() {
|
||||
return m_world_renderer.specular_strength();
|
||||
}
|
||||
float& Renderer::cloud_speed() { return m_world_renderer.cloud_speed(); }
|
||||
float& Renderer::cloud_threshold_low() {
|
||||
return m_world_renderer.cloud_threshold_low();
|
||||
}
|
||||
float& Renderer::cloud_threshold_high() {
|
||||
return m_world_renderer.cloud_threshold_high();
|
||||
}
|
||||
float& Renderer::refract_strength() {
|
||||
return m_world_renderer.refract_strength();
|
||||
}
|
||||
float& Renderer::underwater_fog_density() {
|
||||
return m_world_renderer.underwater_fog_density();
|
||||
}
|
||||
float& Renderer::water_density() { return m_world_renderer.water_density(); }
|
||||
|
||||
const Camera& Renderer::camera() const { return m_camera; }
|
||||
const ClientWorld& Renderer::world() const { return m_world; }
|
||||
ClientWorld& Renderer::world() { return m_world; }
|
||||
const glm::mat4& Renderer::world_proj_matrix() const {
|
||||
return m_world_proj_matrix;
|
||||
}
|
||||
const TextureManager& Renderer::texture_mamger() const {
|
||||
return m_texture_manager;
|
||||
}
|
||||
|
||||
float Renderer::delta_time() const { return m_delta_time; }
|
||||
|
||||
float Renderer::height() const { return m_height; }
|
||||
float Renderer::width() const { return m_width; }
|
||||
const glm::mat4& Renderer::p_mat() const { return m_world_proj_matrix; }
|
||||
const std::vector<VertexArray>& Renderer::vao() const { return m_vao; }
|
||||
} // namespace Cubed
|
||||
61
src/render/shader_manager.cpp
Normal file
61
src/render/shader_manager.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
#include "Cubed/render/shader_manager.hpp"
|
||||
|
||||
#include "Cubed/tools/cubed_assert.hpp"
|
||||
|
||||
namespace Cubed {
|
||||
ShaderManager::ShaderManager() {}
|
||||
ShaderManager::~ShaderManager() {}
|
||||
|
||||
void ShaderManager::init() {
|
||||
register_shader("normal_block", "shaders/block_v_shader.glsl",
|
||||
"shaders/block_f_shader.glsl");
|
||||
register_shader("outline", "shaders/outline_v_shader.glsl",
|
||||
"shaders/outline_f_shader.glsl");
|
||||
register_shader("sky", "shaders/sky_v_shader.glsl",
|
||||
"shaders/sky_f_shader.glsl");
|
||||
register_shader("ui", "shaders/ui_v_shader.glsl",
|
||||
"shaders/ui_f_shader.glsl");
|
||||
register_shader("text", "shaders/text_v_shader.glsl",
|
||||
"shaders/text_f_shader.glsl");
|
||||
register_shader("under_water", "shaders/under_water_v_shader.glsl",
|
||||
"shaders/under_water_f_shader.glsl");
|
||||
register_shader("accum", "shaders/block_accumulation_v_shader.glsl",
|
||||
"shaders/block_accumulation_f_shader.glsl");
|
||||
register_shader("composite", "shaders/block_composite_v_shader.glsl",
|
||||
"shaders/block_composite_f_shader.glsl");
|
||||
register_shader("depth_shader", "shaders/depth_shader.glsl",
|
||||
"shaders/depth_fragment_shader.glsl");
|
||||
register_shader("billboard", "shaders/billboard_v_shader.glsl",
|
||||
"shaders/billboard_f_shader.glsl");
|
||||
register_shader("water", "shaders/water_v_shader.glsl",
|
||||
"shaders/water_f_shader.glsl");
|
||||
register_shader("player", "shaders/player_v_shader.glsl",
|
||||
"shaders/player_f_shader.glsl");
|
||||
register_shader("player_depth", "shaders/depth_player_shader.glsl",
|
||||
"shaders/depth_player_fragment_shader.glsl");
|
||||
}
|
||||
|
||||
void ShaderManager::register_shader(const std::string& name,
|
||||
const std::string& v_shader,
|
||||
const std::string& f_shader) {
|
||||
|
||||
auto [_, inserted] = m_shaders.try_emplace(name, name, v_shader, f_shader);
|
||||
|
||||
if (!inserted) {
|
||||
std::string msg = std::format("Shader name {} already esist!", name);
|
||||
ASSERT_MSG(false, msg);
|
||||
throw std::runtime_error(msg);
|
||||
}
|
||||
}
|
||||
|
||||
const Shader& ShaderManager::get_shader(const std::string& name) const {
|
||||
auto it = m_shaders.find(name);
|
||||
if (it == m_shaders.end()) {
|
||||
std::string msg = std::format("Shader name {} not find", name);
|
||||
ASSERT_MSG(false, msg);
|
||||
throw std::runtime_error(msg);
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
} // namespace Cubed
|
||||
149
src/render/texture.cpp
Normal file
149
src/render/texture.cpp
Normal file
@@ -0,0 +1,149 @@
|
||||
#include "Cubed/render/texture.hpp"
|
||||
|
||||
#include "Cubed/tools/cubed_assert.hpp"
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace Cubed {
|
||||
Texture::Texture(TextureType type) : M_TYPE(type) { glGenTextures(1, &m_id); }
|
||||
Texture::~Texture() {
|
||||
if (m_id) {
|
||||
glDeleteTextures(1, &m_id);
|
||||
}
|
||||
}
|
||||
Texture::Texture(Texture&& o) noexcept
|
||||
: m_id(std::exchange(o.m_id, 0)), M_TYPE(o.M_TYPE) {}
|
||||
|
||||
Texture& Texture::operator=(Texture&& o) noexcept {
|
||||
if (this == &o) {
|
||||
return *this;
|
||||
}
|
||||
if (M_TYPE != o.M_TYPE) {
|
||||
ASSERT_MSG(false, "Texture Type is not same");
|
||||
}
|
||||
if (m_id) {
|
||||
glDeleteTextures(1, &m_id);
|
||||
}
|
||||
|
||||
m_id = std::exchange(o.m_id, 0);
|
||||
return *this;
|
||||
}
|
||||
void Texture::bind() const { glBindTexture(get_gl_texture_type(), m_id); }
|
||||
|
||||
void Texture::bind(size_t unit) const {
|
||||
active(unit);
|
||||
bind();
|
||||
}
|
||||
|
||||
GLuint Texture::id() const { return m_id; }
|
||||
|
||||
void Texture::parameter(TexturePname pname, TextureParam param) const {
|
||||
bind();
|
||||
glTexParameteri(get_gl_texture_type(), std::to_underlying(pname),
|
||||
std::to_underlying(param));
|
||||
}
|
||||
void Texture::parameterfv(TexturePname pname, const float* param) const {
|
||||
bind();
|
||||
glTexParameterfv(get_gl_texture_type(), std::to_underlying(pname), param);
|
||||
}
|
||||
void Texture::tex_image_2d(TextureFormat internalformat, TextureFormat format,
|
||||
GLenum type, const void* data, GLsizei width,
|
||||
GLsizei height, GLint level, GLint border) const {
|
||||
bind();
|
||||
glTexImage2D(get_gl_texture_type(), level,
|
||||
std::to_underlying(internalformat), width, height, border,
|
||||
std::to_underlying(format), type, data);
|
||||
}
|
||||
|
||||
void Texture::tex_image_3d(TextureFormat internalformat, TextureFormat format,
|
||||
GLenum type, const void* data, GLsizei width,
|
||||
GLsizei height, GLsizei depth, GLint level,
|
||||
GLint border) const {
|
||||
bind();
|
||||
glTexImage3D(get_gl_texture_type(), level,
|
||||
std::to_underlying(internalformat), width, height, depth,
|
||||
border, std::to_underlying(format), type, data);
|
||||
}
|
||||
void Texture::tex_sub_image_3d(TextureFormat format, GLenum type,
|
||||
const void* data, GLint xoffset, GLint yoffset,
|
||||
GLint zoffset, GLsizei width, GLsizei height,
|
||||
GLsizei depth, GLint level) const {
|
||||
bind();
|
||||
glTexSubImage3D(get_gl_texture_type(), level, xoffset, yoffset, zoffset,
|
||||
width, height, depth, std::to_underlying(format), type,
|
||||
data);
|
||||
}
|
||||
void Texture::set_aniso(int aniso) const {
|
||||
if (aniso >= 1) {
|
||||
bind();
|
||||
glTexParameterf(get_gl_texture_type(), GL_TEXTURE_MAX_ANISOTROPY,
|
||||
static_cast<GLfloat>(aniso));
|
||||
}
|
||||
}
|
||||
|
||||
void Texture::gen_mipmap() const {
|
||||
bind();
|
||||
glGenerateMipmap(get_gl_texture_type());
|
||||
}
|
||||
|
||||
void Texture::set_linear() const {
|
||||
parameter(TexturePname::MIN_FILTER, TextureParam::LINEAR);
|
||||
parameter(TexturePname::MAG_FILTER, TextureParam::LINEAR);
|
||||
}
|
||||
void Texture::set_nearest_and_minpmap() const {
|
||||
parameter(TexturePname::MAG_FILTER, TextureParam::NEAREST);
|
||||
parameter(TexturePname::MIN_FILTER, TextureParam::LINEAR_MIPMAP_LINEAR);
|
||||
gen_mipmap();
|
||||
}
|
||||
void Texture::set_nearest() const {
|
||||
parameter(TexturePname::MAG_FILTER, TextureParam::NEAREST);
|
||||
parameter(TexturePname::MIN_FILTER, TextureParam::NEAREST);
|
||||
}
|
||||
void Texture::set_repeat(bool r, bool s, bool t) const {
|
||||
if (r) {
|
||||
parameter(TexturePname::WRAP_R, TextureParam::REPEAT);
|
||||
}
|
||||
if (s) {
|
||||
parameter(TexturePname::WRAP_S, TextureParam::REPEAT);
|
||||
}
|
||||
if (t) {
|
||||
parameter(TexturePname::WRAP_T, TextureParam::REPEAT);
|
||||
}
|
||||
}
|
||||
void Texture::set_clamp_to_border(bool r, bool s, bool t) const {
|
||||
if (r) {
|
||||
parameter(TexturePname::WRAP_R, TextureParam::CLAMP_TO_BORDER);
|
||||
}
|
||||
if (s) {
|
||||
parameter(TexturePname::WRAP_S, TextureParam::CLAMP_TO_BORDER);
|
||||
}
|
||||
if (t) {
|
||||
parameter(TexturePname::WRAP_T, TextureParam::CLAMP_TO_BORDER);
|
||||
}
|
||||
}
|
||||
|
||||
void Texture::set_clamp_to_edge(bool r, bool s, bool t) const {
|
||||
if (r) {
|
||||
parameter(TexturePname::WRAP_R, TextureParam::CLAMP_TO_EDGE);
|
||||
}
|
||||
if (s) {
|
||||
parameter(TexturePname::WRAP_S, TextureParam::CLAMP_TO_EDGE);
|
||||
}
|
||||
if (t) {
|
||||
parameter(TexturePname::WRAP_T, TextureParam::CLAMP_TO_EDGE);
|
||||
}
|
||||
}
|
||||
|
||||
TextureType Texture::type() const { return M_TYPE; }
|
||||
|
||||
void Texture::unbind() {
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
|
||||
}
|
||||
void Texture::active(size_t id) { glActiveTexture(GL_TEXTURE0 + id); }
|
||||
|
||||
GLenum Texture::get_gl_texture_type() const {
|
||||
return std::to_underlying(M_TYPE);
|
||||
}
|
||||
|
||||
} // namespace Cubed
|
||||
39
src/render/vertex_array.cpp
Normal file
39
src/render/vertex_array.cpp
Normal file
@@ -0,0 +1,39 @@
|
||||
#include "Cubed/render/vertex_array.hpp"
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace Cubed {
|
||||
VertexArray::VertexArray() { glGenVertexArrays(1, &m_vao); }
|
||||
VertexArray::~VertexArray() {
|
||||
if (m_vao) {
|
||||
glDeleteVertexArrays(1, &m_vao);
|
||||
}
|
||||
}
|
||||
VertexArray::VertexArray(VertexArray&& o) noexcept
|
||||
: m_vao(std::exchange(o.m_vao, 0)) {}
|
||||
|
||||
VertexArray& VertexArray::operator=(VertexArray&& o) noexcept {
|
||||
if (this != &o) {
|
||||
if (m_vao) {
|
||||
glDeleteVertexArrays(1, &m_vao);
|
||||
}
|
||||
m_vao = std::exchange(o.m_vao, 0);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void VertexArray::bind() const { glBindVertexArray(m_vao); }
|
||||
void VertexArray::unbind() { glBindVertexArray(0); }
|
||||
|
||||
GLuint VertexArray::id() const { return m_vao; }
|
||||
|
||||
void VertexArray::attribute(GLuint index, GLint size, GLenum type,
|
||||
GLsizei stride, const void* ptr,
|
||||
bool normalized) const {
|
||||
bind();
|
||||
glVertexAttribPointer(index, size, type, normalized ? GL_TRUE : GL_FALSE,
|
||||
stride, ptr);
|
||||
glEnableVertexAttribArray(index);
|
||||
}
|
||||
|
||||
} // namespace Cubed
|
||||
52
src/render/vertex_buffer.cpp
Normal file
52
src/render/vertex_buffer.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
#include "Cubed/render/vertex_buffer.hpp"
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace Cubed {
|
||||
VertexBuffer::VertexBuffer(BufferType type) : m_type(type) {
|
||||
glGenBuffers(1, &m_vbo);
|
||||
}
|
||||
VertexBuffer::~VertexBuffer() {
|
||||
if (m_vbo) {
|
||||
glDeleteBuffers(1, &m_vbo);
|
||||
}
|
||||
}
|
||||
|
||||
VertexBuffer::VertexBuffer(VertexBuffer&& o) noexcept
|
||||
: m_vbo(std::exchange(o.m_vbo, 0)), m_type(o.m_type) {}
|
||||
|
||||
VertexBuffer& VertexBuffer::operator=(VertexBuffer&& o) noexcept {
|
||||
if (this != &o) {
|
||||
if (m_vbo) {
|
||||
glDeleteBuffers(1, &m_vbo);
|
||||
}
|
||||
m_vbo = std::exchange(o.m_vbo, 0);
|
||||
m_type = o.m_type;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void VertexBuffer::bind() const { glBindBuffer(get_buffer_target(), m_vbo); }
|
||||
|
||||
void VertexBuffer::unbind() {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
GLuint VertexBuffer::id() const { return m_vbo; }
|
||||
|
||||
GLenum VertexBuffer::get_buffer_target() const {
|
||||
return std::to_underlying(m_type);
|
||||
}
|
||||
|
||||
void VertexBuffer::buffer_data(const void* data, GLsizeiptr size,
|
||||
BufferUsage usage) const {
|
||||
bind();
|
||||
|
||||
GLenum target = get_buffer_target();
|
||||
|
||||
glBufferData(target, size, data, std::to_underlying(usage));
|
||||
}
|
||||
|
||||
} // namespace Cubed
|
||||
851
src/render/world_renderer.cpp
Normal file
851
src/render/world_renderer.cpp
Normal file
@@ -0,0 +1,851 @@
|
||||
#include "Cubed/render/world_renderer.hpp"
|
||||
|
||||
#include "Cubed/camera.hpp"
|
||||
#include "Cubed/debug_collector.hpp"
|
||||
#include "Cubed/gameplay/client_world.hpp"
|
||||
#include "Cubed/render/renderer.hpp"
|
||||
#include "Cubed/render/renderer_constants.hpp"
|
||||
#include "Cubed/texture_manager.hpp"
|
||||
#include "Cubed/tools/math_tools.hpp"
|
||||
namespace Cubed {
|
||||
WorldRenderer::WorldRenderer(Renderer& renderer)
|
||||
: m_renderer(renderer), m_player_renderer(renderer),
|
||||
m_world(renderer.world()), m_camera(renderer.camera()),
|
||||
m_texture_manager(renderer.texture_mamger()) {}
|
||||
WorldRenderer::~WorldRenderer() {
|
||||
m_accum_texture.reset();
|
||||
m_reveal_texture.reset();
|
||||
|
||||
m_world_fbo.reset();
|
||||
m_screen_texture.reset();
|
||||
m_screen_depth_texture.reset();
|
||||
|
||||
m_oit_fbo.reset();
|
||||
|
||||
m_oit_depth_texture.reset();
|
||||
|
||||
m_depth_map_fbo.reset();
|
||||
m_depth_map_texture.reset();
|
||||
}
|
||||
|
||||
void WorldRenderer::init() { m_player_renderer.init(); }
|
||||
|
||||
void WorldRenderer::render() {
|
||||
// update view matrix;
|
||||
view_matrix = m_renderer.camera().get_camera_lookat();
|
||||
|
||||
m_world_fbo->bind();
|
||||
// clear world framebuffer
|
||||
glClearColor(0.0, 0.0, 0.0, 1.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
day_night_calculation();
|
||||
|
||||
render_sky();
|
||||
render_world();
|
||||
render_outline();
|
||||
render_player();
|
||||
|
||||
FrameBuffer::unbind();
|
||||
|
||||
glEnable(GL_FRAMEBUFFER_SRGB);
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
// clear screen
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
render_underwater();
|
||||
glDisable(GL_FRAMEBUFFER_SRGB);
|
||||
}
|
||||
|
||||
void WorldRenderer::day_night_calculation() {
|
||||
|
||||
m_parallel_light.sundir = glm::normalize(m_renderer.world().sunlight_dir());
|
||||
m_parallel_light.sun_height = (-m_parallel_light.sundir).y;
|
||||
m_parallel_light.lightdir = m_parallel_light.sundir;
|
||||
|
||||
m_parallel_light.day_light =
|
||||
glm::smoothstep(0.15f, 0.3f, m_parallel_light.sun_height);
|
||||
|
||||
m_parallel_light.sun_color = mix(SUNSET_SUNLIGHT_COLOR, NOON_SUNLIGHT_COLOR,
|
||||
m_parallel_light.day_light);
|
||||
|
||||
glm::vec3 ambient_color = mix(SUNSET_AMBIENT_COLOR, NOON_AMBIENT_COLOR,
|
||||
m_parallel_light.day_light);
|
||||
|
||||
m_parallel_light.day_factor =
|
||||
glm::smoothstep(-0.15f, 0.05f, m_parallel_light.sun_height);
|
||||
|
||||
auto day_factor = m_parallel_light.day_factor;
|
||||
|
||||
float light_intensity =
|
||||
glm::smoothstep(moon_intensity, sun_intensity, day_factor);
|
||||
|
||||
m_parallel_light.directional_light_color =
|
||||
glm::mix(MOON_COLOR, m_parallel_light.sun_color, day_factor) *
|
||||
light_intensity;
|
||||
|
||||
m_parallel_light.finnal_ambient_color =
|
||||
glm::mix(NIGHT_AMBIENT_COLOR, ambient_color, day_factor);
|
||||
|
||||
m_ambient_strength = glm::mix(0.45f, 0.25f, day_factor);
|
||||
}
|
||||
|
||||
void WorldRenderer::render_sky() {
|
||||
|
||||
glm::vec3 zenith = {0.20f, 0.45f, 0.95f};
|
||||
|
||||
glm::vec3 horizon = {0.55f, 0.75f, 1.00f};
|
||||
|
||||
glm::vec3 sunset_zenith = {0.05f, 0.10f, 0.25f};
|
||||
|
||||
glm::vec3 sunset_horizon = {1.0f, 0.35f, 0.10f};
|
||||
|
||||
glm::vec3 night_zenith = {0.018f, 0.023f, 0.048f};
|
||||
glm::vec3 night_horizon = {0.022f, 0.027f, 0.052f};
|
||||
|
||||
constexpr float NIGHT_SHARPNESS = 0.35f;
|
||||
constexpr float SUNSET_SHARPNESS = 0.6f;
|
||||
constexpr float NOON_SHARPNESS = 0.35f;
|
||||
|
||||
constexpr float NIGHT_CLOUD_MIX = 0.3f;
|
||||
constexpr float SUNSET_CLOUD_MIX = 0.4f;
|
||||
constexpr float NOON_CLOUD_MIX = 0.7;
|
||||
|
||||
glm::vec3 day_top = mix(sunset_zenith, zenith, m_parallel_light.day_light);
|
||||
|
||||
glm::vec3 day_bottom =
|
||||
mix(sunset_horizon, horizon, m_parallel_light.day_light);
|
||||
|
||||
m_sky_uniform.sky_top =
|
||||
mix(night_zenith, day_top, m_parallel_light.day_factor);
|
||||
|
||||
m_sky_uniform.sky_bottom =
|
||||
mix(night_horizon, day_bottom, m_parallel_light.day_factor);
|
||||
|
||||
float day_sharpness =
|
||||
glm::mix(SUNSET_SHARPNESS, NOON_SHARPNESS, m_parallel_light.day_light);
|
||||
|
||||
m_sky_uniform.horizon_sharpness =
|
||||
glm::mix(NIGHT_SHARPNESS, day_sharpness, m_parallel_light.day_factor);
|
||||
|
||||
float day_cloud_mix =
|
||||
glm::mix(SUNSET_CLOUD_MIX, NOON_CLOUD_MIX, m_parallel_light.day_light);
|
||||
|
||||
m_sky_uniform.cloud_white_mix =
|
||||
glm::mix(NIGHT_CLOUD_MIX, day_cloud_mix, m_parallel_light.day_factor);
|
||||
|
||||
m_cloud_time += m_renderer.delta_time() * m_cloud_speed;
|
||||
|
||||
const auto& sky_shader = m_renderer.get_shader("sky");
|
||||
|
||||
sky_shader.use();
|
||||
|
||||
glm::mat4 model_mat =
|
||||
glm::translate(glm::mat4(1.0f),
|
||||
m_camera.get_camera_pos() - glm::vec3(0.5f, 0.5f, 0.5f));
|
||||
|
||||
glm::mat4 mv_mat = view_matrix * model_mat;
|
||||
|
||||
auto& proj_mat = m_renderer.p_mat();
|
||||
|
||||
m_sky_uniform.sun_dir_view = (-m_parallel_light.sundir);
|
||||
|
||||
sky_shader.set_loc("mv_matrix", mv_mat);
|
||||
sky_shader.set_loc("proj_matrix", proj_mat);
|
||||
sky_shader.set_loc("skyTop", m_sky_uniform.sky_top);
|
||||
sky_shader.set_loc("skyBottom", m_sky_uniform.sky_bottom);
|
||||
sky_shader.set_loc("sunDir", m_sky_uniform.sun_dir_view);
|
||||
sky_shader.set_loc("sunColor", m_parallel_light.directional_light_color);
|
||||
sky_shader.set_loc("horizonSharpness", m_sky_uniform.horizon_sharpness);
|
||||
sky_shader.set_loc("time", m_cloud_time);
|
||||
sky_shader.set_loc("cloudWhiteMix", m_sky_uniform.cloud_white_mix);
|
||||
sky_shader.set_loc("cloudThresholdLow", m_cloud_threshold_low);
|
||||
sky_shader.set_loc("cloudThresholdHigh", m_cloud_threshold_high);
|
||||
|
||||
auto& m_vao = m_renderer.vao();
|
||||
|
||||
m_vao[1].bind();
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
// draw sun and moon
|
||||
const auto& billboard = m_renderer.get_shader("billboard");
|
||||
billboard.use();
|
||||
glDepthMask(GL_FALSE);
|
||||
|
||||
m_vao[0].bind();
|
||||
auto billboard_drawer = [this, &billboard,
|
||||
&proj_mat](const glm::vec3& pos, float size,
|
||||
const glm::vec3& color) {
|
||||
glm::vec3 view_pos = glm::vec3(view_matrix * glm::vec4(pos, 1.0f));
|
||||
glm::mat4 mv_mat =
|
||||
glm::translate(glm::mat4(1.0f), view_pos) *
|
||||
glm::scale(glm::mat4(1.0f), glm::vec3(size)) *
|
||||
glm::translate(glm::mat4(1.0f), glm::vec3(-0.5f, -0.5f, 0.0f));
|
||||
|
||||
billboard.set_loc("mv_matrix", mv_mat);
|
||||
billboard.set_loc("proj_matrix", proj_mat);
|
||||
billboard.set_loc("color", color);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
};
|
||||
// draw sun
|
||||
glm::vec3 sun_pos = m_camera.get_camera_pos() +
|
||||
normalize(-m_world.sunlight_dir()) * (FAR_PLANE * 0.9f);
|
||||
billboard_drawer(sun_pos, SUN_SIZE, SUN_COLOR);
|
||||
|
||||
// draw moon
|
||||
|
||||
glm::vec3 moon_pos = m_camera.get_camera_pos() +
|
||||
normalize(m_world.sunlight_dir()) * (FAR_PLANE * 0.9f);
|
||||
billboard_drawer(moon_pos, MOON_SIZE, MOON_COLOR);
|
||||
|
||||
glDepthMask(GL_TRUE);
|
||||
}
|
||||
|
||||
void WorldRenderer::render_world() {
|
||||
|
||||
// shader map
|
||||
|
||||
auto m_height = m_renderer.height();
|
||||
auto m_width = m_renderer.width();
|
||||
|
||||
glm::mat4 model_mat =
|
||||
glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, 0.0f));
|
||||
|
||||
glm::mat4 mv_mat = view_matrix * model_mat;
|
||||
|
||||
glm::mat4 norm_mat = glm::transpose(glm::inverse(mv_mat));
|
||||
|
||||
if (m_shader_on) {
|
||||
shadow_map_generate();
|
||||
}
|
||||
|
||||
m_world_fbo->bind();
|
||||
|
||||
glCullFace(GL_BACK);
|
||||
glViewport(0, 0, m_width, m_height);
|
||||
|
||||
render_normal_block(model_mat, mv_mat, norm_mat);
|
||||
|
||||
// copy depth buffer
|
||||
m_world_fbo->bind(FrameBufferType::READ_FRAMEBUFFER);
|
||||
|
||||
m_oit_fbo->bind(FrameBufferType::DRAW_FRAMEBUFFER);
|
||||
|
||||
glBlitFramebuffer(0, 0, m_width, m_height, 0, 0, m_width, m_height,
|
||||
GL_DEPTH_BUFFER_BIT, GL_NEAREST);
|
||||
m_oit_fbo->bind(FrameBufferType::DRAW_FRAMEBUFFER);
|
||||
|
||||
// pass one accumulate
|
||||
m_oit_fbo->bind();
|
||||
|
||||
glClearBufferfv(GL_COLOR, 0, glm::value_ptr(glm::vec4(0.0f)));
|
||||
float one = 1.0f;
|
||||
glClearBufferfv(GL_COLOR, 1, &one);
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_FALSE);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunci(0, GL_ONE, GL_ONE);
|
||||
|
||||
glBlendFunci(1, GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
|
||||
render_transparent_block(mv_mat, norm_mat);
|
||||
}
|
||||
|
||||
void WorldRenderer::render_outline() {
|
||||
const auto& shader = m_renderer.get_shader("outline");
|
||||
shader.use();
|
||||
|
||||
const auto& block_pos = m_renderer.world().get_look_block_pos();
|
||||
|
||||
if (block_pos != std::nullopt) {
|
||||
|
||||
glm::mat4 model_mat =
|
||||
glm::translate(glm::mat4(1.0f), glm::vec3(block_pos.value().pos));
|
||||
|
||||
glm::mat4 m_mv_mat = view_matrix * model_mat;
|
||||
auto& proj_mat = m_renderer.p_mat();
|
||||
shader.set_loc("mv_matrix", m_mv_mat);
|
||||
shader.set_loc("proj_matrix", proj_mat);
|
||||
|
||||
auto& m_vao = m_renderer.vao();
|
||||
m_vao[2].bind();
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
glLineWidth(4.0f);
|
||||
glDrawElements(GL_LINES, 24, GL_UNSIGNED_INT, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void WorldRenderer::shadow_map_generate() {
|
||||
float texels_per_unit = 0.0f;
|
||||
const auto& lightdir = m_parallel_light.lightdir;
|
||||
|
||||
auto m_delta_time = m_renderer.delta_time();
|
||||
|
||||
// shader map
|
||||
glm::mat4& light_space_matrix = m_parallel_light.light_space_matrix;
|
||||
|
||||
auto& m_render_snapshots = m_world.render_snapshots();
|
||||
auto& camera_pos = m_camera.get_camera_pos();
|
||||
|
||||
const auto& depth_shader = m_renderer.get_shader("depth_shader");
|
||||
|
||||
depth_shader.use();
|
||||
|
||||
glm::vec3 cam_pos = m_camera.get_camera_pos();
|
||||
glm::vec3 cam_fwd = m_camera.get_camera_front();
|
||||
float half_extent = 128.0f;
|
||||
|
||||
glm::vec3 center = cam_pos + cam_fwd * (half_extent * 0.5f);
|
||||
|
||||
glm::vec3 raw_shadow_lightdir =
|
||||
quantize_sun_direction(lightdir, ANGLE_STEP_DEG);
|
||||
glm::vec3 shadow_lightdir =
|
||||
get_smoothed_shadow_lightdir(raw_shadow_lightdir, m_delta_time);
|
||||
glm::vec3 up = fabs(shadow_lightdir.y) > 0.99f ? glm::vec3(0, 0, 1)
|
||||
: glm::vec3(0, 1, 0);
|
||||
|
||||
glm::mat4 light_basis = glm::lookAt(glm::vec3(0.0f), shadow_lightdir, up);
|
||||
texels_per_unit = DEPTH_MAP_SIZE / (half_extent * 2.0f);
|
||||
glm::vec3 ls_center = glm::vec3(light_basis * glm::vec4(center, 1.0f));
|
||||
ls_center.x = std::round(ls_center.x * texels_per_unit) / texels_per_unit;
|
||||
ls_center.y = std::round(ls_center.y * texels_per_unit) / texels_per_unit;
|
||||
glm::vec3 snapped_center =
|
||||
glm::vec3(glm::inverse(light_basis) * glm::vec4(ls_center, 1.0f));
|
||||
|
||||
float distance = half_extent * 1.5f;
|
||||
float near_plane = 1.0f;
|
||||
float far_plane = distance + half_extent * 2.0f;
|
||||
glm::vec3 light_pos = snapped_center - shadow_lightdir * distance;
|
||||
glm::mat4 light_view = glm::lookAt(light_pos, snapped_center, up);
|
||||
glm::mat4 light_projection =
|
||||
glm::ortho(-half_extent, half_extent, -half_extent, half_extent,
|
||||
near_plane, far_plane);
|
||||
|
||||
light_space_matrix = light_projection * light_view;
|
||||
depth_shader.set_loc("lightSpaceMatrix", light_space_matrix);
|
||||
depth_shader.set_loc("is_discard_tranparent", m_discard_tranparent);
|
||||
|
||||
glViewport(0, 0, DEPTH_MAP_SIZE, DEPTH_MAP_SIZE);
|
||||
if (m_light_cull_face == 0) {
|
||||
glCullFace(GL_FRONT);
|
||||
} else if (m_light_cull_face == 1) {
|
||||
glCullFace(GL_BACK);
|
||||
} else {
|
||||
Logger::warn("Light Cull Face {} Over The Max Selection",
|
||||
m_light_cull_face);
|
||||
glCullFace(GL_BACK);
|
||||
}
|
||||
|
||||
m_depth_map_fbo->bind();
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
for (const auto& snapshot : m_render_snapshots) {
|
||||
if (!snapshot) {
|
||||
continue;
|
||||
}
|
||||
m_texture_manager.get_texture_array()->bind(1);
|
||||
glBindVertexArray(snapshot->normal_vao);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, snapshot->normal_vertices_count);
|
||||
}
|
||||
|
||||
// cross_plane and discard
|
||||
|
||||
for (const auto& snapshot : m_render_snapshots) {
|
||||
if (!snapshot) {
|
||||
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) {
|
||||
m_texture_manager.get_cross_plane_array()->bind(1);
|
||||
glBindVertexArray(snapshot->cross_vao);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, snapshot->cross_vertices_count);
|
||||
}
|
||||
}
|
||||
if (snapshot->normal_discard_vertices_count != 0) {
|
||||
|
||||
m_texture_manager.get_texture_array()->bind(1);
|
||||
|
||||
glBindVertexArray(snapshot->normal_discard_vao);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0,
|
||||
snapshot->normal_discard_vertices_count);
|
||||
}
|
||||
}
|
||||
// player
|
||||
auto& player_shadow = m_renderer.get_shader("player_depth");
|
||||
m_player_renderer.shadow_render(player_shadow, light_space_matrix);
|
||||
}
|
||||
|
||||
void WorldRenderer::render_underwater() {
|
||||
|
||||
const auto& shader = m_renderer.get_shader("under_water");
|
||||
|
||||
shader.use();
|
||||
|
||||
auto& m_vao = m_renderer.vao();
|
||||
|
||||
m_vao[0].bind();
|
||||
|
||||
auto& proj_mat = m_renderer.p_mat();
|
||||
|
||||
shader.set_loc("u_sceneTexture", 0);
|
||||
shader.set_loc("u_time", static_cast<float>(glfwGetTime()));
|
||||
shader.set_loc("u_underwater", m_camera.is_under_water());
|
||||
shader.set_loc("u_waterColor", glm::vec3(0.1f, 0.25f, 0.35f));
|
||||
shader.set_loc("u_fogDensity", m_underwater_fog_density);
|
||||
shader.set_loc("cameraPos", m_camera.get_camera_pos());
|
||||
shader.set_loc("sunDir", -m_parallel_light.sundir);
|
||||
shader.set_loc("waterDensity", m_water_density);
|
||||
shader.set_loc("InverseViewProjection",
|
||||
glm::inverse(proj_mat * view_matrix));
|
||||
shader.set_loc("sunColor", m_parallel_light.sun_color);
|
||||
shader.set_loc("u_lightSpaceMatrix", m_parallel_light.light_space_matrix);
|
||||
|
||||
m_screen_texture->bind(0);
|
||||
m_screen_depth_texture->bind(1);
|
||||
m_depth_map_texture->bind(2);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
void WorldRenderer::render_normal_block(const glm::mat4& model_mat,
|
||||
const glm::mat4& mv_mat,
|
||||
const glm::mat4& norm_mat) {
|
||||
|
||||
// shader map
|
||||
glm::mat4& light_space_matrix = m_parallel_light.light_space_matrix;
|
||||
|
||||
auto& m_render_snapshots = m_world.render_snapshots();
|
||||
auto& camera_pos = m_camera.get_camera_pos();
|
||||
|
||||
const auto& lightdir = m_parallel_light.lightdir;
|
||||
|
||||
const auto& normal_block_shader = m_renderer.get_shader("normal_block");
|
||||
|
||||
normal_block_shader.use();
|
||||
|
||||
glm::vec3 light_dir_view =
|
||||
glm::normalize(glm::mat3(view_matrix) * lightdir);
|
||||
auto& proj_mat = m_renderer.p_mat();
|
||||
auto m_pbr = m_renderer.pbr();
|
||||
|
||||
normal_block_shader.set_loc("enablePBR", m_pbr);
|
||||
normal_block_shader.set_loc("model_matrix", model_mat);
|
||||
normal_block_shader.set_loc("mv_matrix", mv_mat);
|
||||
normal_block_shader.set_loc("proj_matrix", proj_mat);
|
||||
normal_block_shader.set_loc("norm_matrix", norm_mat);
|
||||
normal_block_shader.set_loc("lightSpaceMatrix", light_space_matrix);
|
||||
normal_block_shader.set_loc("ambientStrength", m_ambient_strength);
|
||||
normal_block_shader.set_loc("sunlightColor",
|
||||
m_parallel_light.directional_light_color);
|
||||
normal_block_shader.set_loc("ambientColor",
|
||||
m_parallel_light.finnal_ambient_color);
|
||||
normal_block_shader.set_loc("sunlightDir", light_dir_view);
|
||||
normal_block_shader.set_loc("shadowMode", m_shadow_mode);
|
||||
normal_block_shader.set_loc("shader_on", m_shader_on);
|
||||
normal_block_shader.set_loc("lightSizeUV",
|
||||
static_cast<float>(m_light_size_uv));
|
||||
|
||||
normal_block_shader.set_loc("minRadius", m_min_radius);
|
||||
normal_block_shader.set_loc("maxRadius", m_max_radius);
|
||||
normal_block_shader.set_loc("samples", m_samples);
|
||||
normal_block_shader.set_loc("specularStrength", m_specular_strength);
|
||||
normal_block_shader.set_loc("cameraPos", m_camera.get_camera_pos());
|
||||
normal_block_shader.set_loc("flipY", m_flip_y);
|
||||
normal_block_shader.set_loc("renderDistance", m_world.rendering_distance());
|
||||
normal_block_shader.set_loc("skyColor", m_sky_uniform.sky_top);
|
||||
|
||||
glm::mat4 mvp_mat = proj_mat * mv_mat;
|
||||
|
||||
auto& m_planes = m_world.planes();
|
||||
|
||||
Math::extract_frustum_planes(mvp_mat, m_planes);
|
||||
|
||||
int rendered_sum = 0;
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
m_depth_map_texture->bind(0);
|
||||
|
||||
m_texture_manager.get_texture_array()->bind(1);
|
||||
|
||||
m_texture_manager.get_pbr_texture()->bind(2);
|
||||
// normal block
|
||||
for (const auto& snapshot : m_render_snapshots) {
|
||||
if (!snapshot) {
|
||||
continue;
|
||||
}
|
||||
if (Math::is_aabb_in_frustum(snapshot->center, snapshot->half_extents,
|
||||
m_planes)) {
|
||||
|
||||
glBindVertexArray(snapshot->normal_vao);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, snapshot->normal_vertices_count);
|
||||
|
||||
rendered_sum++;
|
||||
}
|
||||
}
|
||||
// discard
|
||||
for (const auto& snapshot : m_render_snapshots) {
|
||||
if (!snapshot) {
|
||||
continue;
|
||||
}
|
||||
if (!Math::is_aabb_in_frustum(snapshot->center, snapshot->half_extents,
|
||||
m_planes)) {
|
||||
continue;
|
||||
}
|
||||
if (snapshot->normal_discard_vertices_count != 0) {
|
||||
glBindVertexArray(snapshot->normal_discard_vao);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0,
|
||||
snapshot->normal_discard_vertices_count);
|
||||
}
|
||||
}
|
||||
// cross_plane
|
||||
m_texture_manager.get_cross_plane_array()->bind(1);
|
||||
normal_block_shader.set_loc("enablePBR", false);
|
||||
for (const auto& snapshot : m_render_snapshots) {
|
||||
if (!snapshot) {
|
||||
continue;
|
||||
}
|
||||
if (!Math::is_aabb_in_frustum(snapshot->center, snapshot->half_extents,
|
||||
m_planes)) {
|
||||
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) {
|
||||
glBindVertexArray(snapshot->cross_vao);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, snapshot->cross_vertices_count);
|
||||
}
|
||||
}
|
||||
}
|
||||
DebugCollector::get().report(
|
||||
"rendered_chunk", "Rendered Chunk: " + std::to_string(rendered_sum));
|
||||
}
|
||||
|
||||
void WorldRenderer::render_transparent_block(const glm::mat4& mv_mat,
|
||||
const glm::mat4& norm_mat) {
|
||||
|
||||
auto& m_render_snapshots = m_world.render_snapshots();
|
||||
|
||||
const auto& lightdir = m_parallel_light.lightdir;
|
||||
glm::vec3 light_dir_view =
|
||||
glm::normalize(glm::mat3(view_matrix) * lightdir);
|
||||
|
||||
auto& m_p_mat = m_renderer.p_mat();
|
||||
|
||||
auto set_accum_loc = [&](const Shader& accum_shader) {
|
||||
accum_shader.set_loc("mv_matrix", mv_mat);
|
||||
accum_shader.set_loc("proj_matrix", m_p_mat);
|
||||
accum_shader.set_loc("norm_matrix", norm_mat);
|
||||
accum_shader.set_loc("ambientStrength", m_ambient_strength);
|
||||
accum_shader.set_loc("sunlightColor",
|
||||
m_parallel_light.directional_light_color);
|
||||
accum_shader.set_loc("ambientColor",
|
||||
m_parallel_light.finnal_ambient_color);
|
||||
accum_shader.set_loc("sunlightDir", light_dir_view);
|
||||
accum_shader.set_loc("shader_on", m_shader_on);
|
||||
accum_shader.set_loc("specularStrength", m_specular_strength);
|
||||
};
|
||||
// accum pass
|
||||
auto& accum_shader = m_renderer.get_shader("accum");
|
||||
accum_shader.use();
|
||||
|
||||
set_accum_loc(accum_shader);
|
||||
accum_shader.set_loc("cameraPos", m_camera.get_camera_pos());
|
||||
|
||||
m_texture_manager.get_texture_array()->bind(0);
|
||||
|
||||
auto& m_planes = m_world.planes();
|
||||
|
||||
for (const auto& snapshot : m_render_snapshots) {
|
||||
if (!snapshot) {
|
||||
continue;
|
||||
}
|
||||
if (!Math::is_aabb_in_frustum(snapshot->center, snapshot->half_extents,
|
||||
m_planes)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (snapshot->normal_blend_vertices_count != 0) {
|
||||
|
||||
glBindVertexArray(snapshot->normal_blend_vao);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0,
|
||||
snapshot->normal_blend_vertices_count);
|
||||
}
|
||||
}
|
||||
|
||||
// use SSR
|
||||
|
||||
auto& water_shader = m_renderer.get_shader("water");
|
||||
water_shader.use();
|
||||
|
||||
set_accum_loc(water_shader);
|
||||
|
||||
water_shader.set_loc("sceneColorTex", 1);
|
||||
water_shader.set_loc("sceneDepthTex", 2);
|
||||
water_shader.set_loc("inv_proj_matrix", glm::inverse(m_p_mat));
|
||||
water_shader.set_loc("inv_view_matrix", glm::inverse(view_matrix));
|
||||
|
||||
// sky loc
|
||||
water_shader.set_loc("skyTop", m_sky_uniform.sky_top);
|
||||
water_shader.set_loc("skyBottom", m_sky_uniform.sky_bottom);
|
||||
water_shader.set_loc("sunDir", m_sky_uniform.sun_dir_view);
|
||||
water_shader.set_loc("sunColor", m_parallel_light.directional_light_color);
|
||||
water_shader.set_loc("horizonSharpness", m_sky_uniform.horizon_sharpness);
|
||||
water_shader.set_loc("time", glfwGetTime());
|
||||
water_shader.set_loc("cloudWhiteMix", m_sky_uniform.cloud_white_mix);
|
||||
water_shader.set_loc("cloudThresholdLow", m_cloud_threshold_low);
|
||||
water_shader.set_loc("cloudThresholdHigh", m_cloud_threshold_high);
|
||||
water_shader.set_loc("underwater", m_camera.is_under_water());
|
||||
water_shader.set_loc("refractStrength", m_refract_strength);
|
||||
water_shader.set_loc("enablePerturb", m_water_perturb);
|
||||
water_shader.set_loc("enableDepthFade", m_water_depth_fade);
|
||||
|
||||
m_screen_texture->bind(1);
|
||||
m_screen_depth_texture->bind(2);
|
||||
m_texture_manager.get_texture_array()->bind(0);
|
||||
|
||||
for (const auto& snapshot : m_render_snapshots) {
|
||||
if (!snapshot) {
|
||||
continue;
|
||||
}
|
||||
if (!Math::is_aabb_in_frustum(snapshot->center, snapshot->half_extents,
|
||||
m_planes)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (snapshot->water_vertices_count != 0) {
|
||||
|
||||
glBindVertexArray(snapshot->water_vao);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, snapshot->water_vertices_count);
|
||||
}
|
||||
}
|
||||
// composite pass
|
||||
|
||||
auto& composite_shader = m_renderer.get_shader("composite");
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
composite_shader.use();
|
||||
composite_shader.set_loc("u_accumTex", 0);
|
||||
composite_shader.set_loc("u_revealTex", 1);
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_TRUE);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
auto& m_vao = m_renderer.vao();
|
||||
m_vao[0].bind();
|
||||
|
||||
m_accum_texture->bind(0);
|
||||
m_reveal_texture->bind(1);
|
||||
|
||||
m_world_fbo->bind();
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
void WorldRenderer::render_player() {
|
||||
auto& shader = m_renderer.get_shader("player");
|
||||
shader.use();
|
||||
glm::vec3 light_dir_view =
|
||||
glm::normalize(glm::mat3(view_matrix) * m_parallel_light.lightdir);
|
||||
|
||||
shader.set_loc("lightSpaceMatrix", m_parallel_light.light_space_matrix);
|
||||
shader.set_loc("ambientStrength", m_ambient_strength);
|
||||
shader.set_loc("sunlightColor", m_parallel_light.directional_light_color);
|
||||
shader.set_loc("ambientColor", m_parallel_light.finnal_ambient_color);
|
||||
shader.set_loc("sunlightDir", light_dir_view);
|
||||
shader.set_loc("shadowMode", m_shadow_mode);
|
||||
shader.set_loc("shader_on", m_shader_on);
|
||||
shader.set_loc("lightSizeUV", static_cast<float>(m_light_size_uv));
|
||||
shader.set_loc("minRadius", m_min_radius);
|
||||
shader.set_loc("maxRadius", m_max_radius);
|
||||
shader.set_loc("samples", m_samples);
|
||||
|
||||
// shader.set_loc("renderDistance", m_world.rendering_distance());
|
||||
// shader.set_loc("skyColor", m_sky_uniform.sky_top);
|
||||
|
||||
m_depth_map_texture->bind(0);
|
||||
m_player_renderer.render(shader);
|
||||
}
|
||||
|
||||
glm::vec3 WorldRenderer::quantize_sun_direction(const glm::vec3& lightdir,
|
||||
float angle_step_deg) const {
|
||||
float elevation = std::asin(glm::clamp(lightdir.y, -1.0f, 1.0f));
|
||||
float azimuth = std::atan2(lightdir.z, lightdir.x);
|
||||
|
||||
float step = glm::radians(angle_step_deg);
|
||||
|
||||
float quantized_elevation = std::round(elevation / step) * step;
|
||||
float quantized_azimuth = std::round(azimuth / step) * step;
|
||||
|
||||
glm::vec3 quantized_dir;
|
||||
quantized_dir.x =
|
||||
std::cos(quantized_elevation) * std::cos(quantized_azimuth);
|
||||
quantized_dir.z =
|
||||
std::cos(quantized_elevation) * std::sin(quantized_azimuth);
|
||||
quantized_dir.y = std::sin(quantized_elevation);
|
||||
|
||||
return glm::normalize(quantized_dir);
|
||||
}
|
||||
|
||||
glm::vec3 WorldRenderer::get_smoothed_shadow_lightdir(
|
||||
const glm::vec3& raw_shadow_lightdir, float dt) {
|
||||
if (!m_blend_initialized) {
|
||||
|
||||
m_blend_from_lightdir = raw_shadow_lightdir;
|
||||
m_blend_to_lightdir = raw_shadow_lightdir;
|
||||
m_blend_t = 1.0f;
|
||||
m_blend_initialized = true;
|
||||
return raw_shadow_lightdir;
|
||||
}
|
||||
|
||||
if (raw_shadow_lightdir != m_blend_to_lightdir) {
|
||||
glm::vec3 current_displayed = glm::normalize(
|
||||
Math::slerp(m_blend_from_lightdir, m_blend_to_lightdir, m_blend_t));
|
||||
|
||||
m_blend_from_lightdir = current_displayed;
|
||||
m_blend_to_lightdir = raw_shadow_lightdir;
|
||||
m_blend_t = 0.0f;
|
||||
}
|
||||
|
||||
m_blend_t = glm::min(m_blend_t + dt / BLEND_DURATION, 1.0f);
|
||||
|
||||
return glm::normalize(
|
||||
Math::slerp(m_blend_from_lightdir, m_blend_to_lightdir, m_blend_t));
|
||||
}
|
||||
|
||||
void WorldRenderer::updata_framebuffer(int width, int height) {
|
||||
if (width <= 0 || height <= 0)
|
||||
return;
|
||||
if (m_world_fbo == 0) {
|
||||
m_world_fbo = std::make_unique<FrameBuffer>();
|
||||
}
|
||||
if (m_oit_fbo == 0) {
|
||||
m_oit_fbo = std::make_unique<FrameBuffer>();
|
||||
}
|
||||
|
||||
m_screen_texture = std::make_unique<Texture>(TextureType::TEXTURE_2D);
|
||||
m_screen_texture->tex_image_2d(TextureFormat::RGB, TextureFormat::RGB,
|
||||
GL_UNSIGNED_BYTE, nullptr, width, height);
|
||||
|
||||
m_screen_texture->set_linear();
|
||||
|
||||
m_world_fbo->attach(Attachment::COLOR_ATTACHMENT0, *m_screen_texture);
|
||||
|
||||
m_screen_depth_texture = std::make_unique<Texture>(TextureType::TEXTURE_2D);
|
||||
m_screen_depth_texture->tex_image_2d(TextureFormat::DEPTH_COMPONENT32F,
|
||||
TextureFormat::DEPTH_COMPONENT,
|
||||
GL_FLOAT, nullptr, width, height);
|
||||
// m_screen_depth_texture->set_nearest();
|
||||
m_screen_depth_texture->set_linear();
|
||||
m_world_fbo->attach(Attachment::DEPTH_ATTACHMENT, *m_screen_depth_texture);
|
||||
|
||||
m_world_fbo->check_status();
|
||||
m_accum_texture = std::make_unique<Texture>(TextureType::TEXTURE_2D);
|
||||
m_accum_texture->tex_image_2d(TextureFormat::RGBA16F, TextureFormat::RGBA,
|
||||
GL_HALF_FLOAT, nullptr, width, height);
|
||||
m_accum_texture->set_linear();
|
||||
|
||||
m_oit_fbo->attach(Attachment::COLOR_ATTACHMENT0, *m_accum_texture);
|
||||
m_reveal_texture = std::make_unique<Texture>(TextureType::TEXTURE_2D);
|
||||
m_reveal_texture->tex_image_2d(TextureFormat::R16F, TextureFormat::RED,
|
||||
GL_HALF_FLOAT, nullptr, width, height);
|
||||
m_reveal_texture->set_linear();
|
||||
m_oit_fbo->attach(Attachment::COLOR_ATTACHMENT1, *m_reveal_texture);
|
||||
m_oit_depth_texture = std::make_unique<Texture>(TextureType::TEXTURE_2D);
|
||||
m_oit_depth_texture->tex_image_2d(TextureFormat::DEPTH_COMPONENT32F,
|
||||
TextureFormat::DEPTH_COMPONENT, GL_FLOAT,
|
||||
nullptr, width, height);
|
||||
// m_oit_depth_texture->set_nearest();
|
||||
m_oit_depth_texture->set_linear();
|
||||
m_oit_fbo->attach(Attachment::DEPTH_ATTACHMENT, *m_oit_depth_texture);
|
||||
|
||||
std::array<GLenum, 2> draw_buffer = {GL_COLOR_ATTACHMENT0,
|
||||
GL_COLOR_ATTACHMENT1};
|
||||
m_oit_fbo->draw_buffer(draw_buffer);
|
||||
|
||||
m_oit_fbo->check_status();
|
||||
|
||||
// depth map fbo
|
||||
if (m_depth_map_fbo == 0) {
|
||||
m_depth_map_fbo = std::make_unique<FrameBuffer>();
|
||||
}
|
||||
|
||||
m_depth_map_texture = std::make_unique<Texture>(TextureType::TEXTURE_2D);
|
||||
|
||||
m_depth_map_texture->tex_image_2d(TextureFormat::DEPTH_COMPONENT32F,
|
||||
TextureFormat::DEPTH_COMPONENT, GL_FLOAT,
|
||||
nullptr, DEPTH_MAP_SIZE, DEPTH_MAP_SIZE);
|
||||
m_depth_map_texture->set_linear();
|
||||
m_depth_map_texture->set_clamp_to_border(false, true, true);
|
||||
float border_color[] = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
// Manually compare shadows
|
||||
m_depth_map_texture->parameterfv(TexturePname::BORDER_COLOR, border_color);
|
||||
m_depth_map_texture->parameter(TexturePname::COMPARE_MODE,
|
||||
TextureParam::T_NONE);
|
||||
|
||||
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE,
|
||||
// GL_COMPARE_REF_TO_TEXTURE);
|
||||
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
|
||||
m_depth_map_fbo->attach(Attachment::DEPTH_ATTACHMENT, *m_depth_map_texture);
|
||||
m_depth_map_fbo->draw_buffer(GL_NONE);
|
||||
m_depth_map_fbo->read_buffer(GL_NONE);
|
||||
m_depth_map_fbo->check_status();
|
||||
|
||||
FrameBuffer::unbind();
|
||||
}
|
||||
|
||||
float& WorldRenderer::underwater_fog_density() {
|
||||
return m_underwater_fog_density;
|
||||
}
|
||||
float& WorldRenderer::water_density() { return m_water_density; }
|
||||
const FrameBuffer* WorldRenderer::world_fbo() const {
|
||||
return m_world_fbo.get();
|
||||
}
|
||||
float& WorldRenderer::ambient_strength() { return m_ambient_strength; }
|
||||
bool& WorldRenderer::discard_transparent() { return m_discard_tranparent; }
|
||||
bool& WorldRenderer::shader_on() { return m_shader_on; }
|
||||
bool& WorldRenderer::water_perturb() { return m_water_perturb; }
|
||||
bool& WorldRenderer::water_depth_fade() { return m_water_depth_fade; }
|
||||
bool& WorldRenderer::pbr() { return m_pbr; }
|
||||
bool& WorldRenderer::flip_y() { return m_flip_y; }
|
||||
int& WorldRenderer::shadow_mode() { return m_shadow_mode; }
|
||||
int& WorldRenderer::light_cull_face() { return m_light_cull_face; }
|
||||
int& WorldRenderer::light_size_uv() { return m_light_size_uv; }
|
||||
float& WorldRenderer::min_radius() { return m_min_radius; }
|
||||
float& WorldRenderer::max_radius() { return m_max_radius; }
|
||||
int& WorldRenderer::samples() { return m_samples; }
|
||||
float& WorldRenderer::specular_strength() { return m_specular_strength; }
|
||||
float& WorldRenderer::cloud_speed() { return m_cloud_speed; }
|
||||
float& WorldRenderer::cloud_threshold_low() { return m_cloud_threshold_low; }
|
||||
float& WorldRenderer::cloud_threshold_high() { return m_cloud_threshold_high; }
|
||||
float& WorldRenderer::refract_strength() { return m_refract_strength; }
|
||||
|
||||
} // namespace Cubed
|
||||
1079
src/renderer.cpp
1079
src/renderer.cpp
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,6 @@
|
||||
|
||||
#include "Cubed/config.hpp"
|
||||
#include "Cubed/constants.hpp"
|
||||
#include "Cubed/map_table.hpp"
|
||||
#include "Cubed/tools/cubed_assert.hpp"
|
||||
#include "Cubed/tools/log.hpp"
|
||||
#include "Cubed/tools/shader_tools.hpp"
|
||||
@@ -32,55 +31,60 @@ unsigned char* generate_flat_normal_map(int width = BLOCK_NORMAL_SIZE,
|
||||
|
||||
namespace Cubed {
|
||||
|
||||
TextureManager::TextureManager() {}
|
||||
TextureManager::TextureManager(Config& config) : m_config(config) {}
|
||||
|
||||
TextureManager::~TextureManager() { delet_texture(); }
|
||||
TextureManager::~TextureManager() { delete_texture(); }
|
||||
|
||||
void TextureManager::delet_texture() {
|
||||
void TextureManager::delete_texture() {
|
||||
if (m_init) {
|
||||
glDeleteTextures(1, &m_texture_array);
|
||||
glDeleteTextures(1, &m_block_status_array);
|
||||
glDeleteTextures(1, &m_cross_plane_array);
|
||||
glDeleteTextures(1, &m_normal_texture_array);
|
||||
for (auto& id : m_item_textures) {
|
||||
glDeleteTextures(1, &id);
|
||||
}
|
||||
glDeleteTextures(1, &m_skin);
|
||||
m_texture_array.reset();
|
||||
m_block_status_array.reset();
|
||||
m_cross_plane_array.reset();
|
||||
m_normal_texture_array.reset();
|
||||
m_item_textures.clear();
|
||||
m_skin.reset();
|
||||
Logger::info("Successfully delete all texture");
|
||||
}
|
||||
}
|
||||
|
||||
GLuint TextureManager::get_block_status_array() const {
|
||||
return m_block_status_array;
|
||||
const Texture* TextureManager::get_block_status_array() const {
|
||||
return m_block_status_array.get();
|
||||
}
|
||||
|
||||
GLuint TextureManager::get_texture_array() const { return m_texture_array; }
|
||||
|
||||
GLuint TextureManager::get_cross_plane_array() const {
|
||||
return m_cross_plane_array;
|
||||
}
|
||||
GLuint TextureManager::get_ui_array() const { return m_ui_array; }
|
||||
|
||||
GLuint TextureManager::get_pbr_texture() const {
|
||||
return m_normal_texture_array;
|
||||
const Texture* TextureManager::get_texture_array() const {
|
||||
return m_texture_array.get();
|
||||
}
|
||||
|
||||
const std::vector<GLuint>& TextureManager::item_textures() const {
|
||||
const Texture* TextureManager::get_cross_plane_array() const {
|
||||
return m_cross_plane_array.get();
|
||||
}
|
||||
const Texture* TextureManager::get_ui_array() const { return m_ui_array.get(); }
|
||||
|
||||
const Texture* TextureManager::get_pbr_texture() const {
|
||||
return m_normal_texture_array.get();
|
||||
}
|
||||
|
||||
const std::vector<std::unique_ptr<Texture>>&
|
||||
TextureManager::item_textures() const {
|
||||
return m_item_textures;
|
||||
}
|
||||
|
||||
GLuint TextureManager::get_skin() const { return m_skin; }
|
||||
const Texture* TextureManager::get_skin() const { return m_skin.get(); }
|
||||
|
||||
void TextureManager::load_block_status(unsigned id) {
|
||||
|
||||
ASSERT_MSG(id < MAX_BLOCK_STATUS, "Exceed the max status sum limit");
|
||||
|
||||
std::string path = "texture/status/" + std::to_string(id) + ".png";
|
||||
|
||||
unsigned char* image_data = nullptr;
|
||||
|
||||
image_data = (Tools::load_image_data(path));
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, m_block_status_array);
|
||||
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, id, BLOCK_STATUS_SIZE,
|
||||
BLOCK_STATUS_SIZE, 1, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
image_data);
|
||||
|
||||
m_block_status_array->tex_sub_image_3d(
|
||||
TextureFormat::RGBA, GL_UNSIGNED_BYTE, image_data, 0, 0, id,
|
||||
BLOCK_STATUS_SIZE, BLOCK_STATUS_SIZE);
|
||||
|
||||
Tools::delete_image_data(image_data);
|
||||
}
|
||||
|
||||
@@ -107,12 +111,11 @@ void TextureManager::load_block_texture(unsigned id) {
|
||||
image_data[4] = (Tools::load_image_data(block_texture_path + "/top.png"));
|
||||
image_data[5] = (Tools::load_image_data(block_texture_path + "/base.png"));
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture_array);
|
||||
Tools::check_opengl_error();
|
||||
for (int i = 0; i < 6; i++) {
|
||||
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, id * 6 + i, BLOCK_SIZE,
|
||||
BLOCK_SIZE, 1, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
image_data[i]);
|
||||
m_texture_array->tex_sub_image_3d(TextureFormat::RGBA, GL_UNSIGNED_BYTE,
|
||||
image_data[i], 0, 0, id * 6 + i,
|
||||
BLOCK_SIZE, BLOCK_SIZE);
|
||||
Tools::check_opengl_error();
|
||||
Tools::delete_image_data(image_data[i]);
|
||||
}
|
||||
@@ -126,21 +129,16 @@ void TextureManager::load_block_item_texture(unsigned id) {
|
||||
std::string path = "texture/item/block/" + name + ".png";
|
||||
unsigned char* data = nullptr;
|
||||
data = Tools::load_image_data(path);
|
||||
GLuint texture;
|
||||
glGenTextures(1, &texture);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, BLOCK_ITEM_SIZE, BLOCK_ITEM_SIZE,
|
||||
0, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||
std::unique_ptr<Texture> texture =
|
||||
std::make_unique<Texture>(TextureType::TEXTURE_2D);
|
||||
texture->tex_image_2d(TextureFormat::RGBA8, TextureFormat::RGBA,
|
||||
GL_UNSIGNED_BYTE, data, BLOCK_ITEM_SIZE,
|
||||
BLOCK_ITEM_SIZE);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
|
||||
GL_LINEAR_MIPMAP_LINEAR);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
if (m_aniso >= 1) {
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY,
|
||||
static_cast<GLfloat>(m_aniso));
|
||||
}
|
||||
m_item_textures.push_back(texture);
|
||||
texture->set_nearest();
|
||||
texture->set_clamp_to_border();
|
||||
|
||||
m_item_textures.push_back(std::move(texture));
|
||||
Tools::delete_image_data(data);
|
||||
}
|
||||
|
||||
@@ -148,10 +146,10 @@ void TextureManager::load_cross_plane_texture(unsigned id) {
|
||||
std::string path =
|
||||
"texture/block/" + BlockManager::name_form_id(id) + "/cross.png";
|
||||
unsigned char* image_data = Tools::load_image_data(path);
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, m_cross_plane_array);
|
||||
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0,
|
||||
BlockManager::cross_plane_index(id), CROSS_PLANE_SIZE,
|
||||
CROSS_PLANE_SIZE, 1, GL_RGBA, GL_UNSIGNED_BYTE, image_data);
|
||||
m_cross_plane_array->tex_sub_image_3d(TextureFormat::RGBA, GL_UNSIGNED_BYTE,
|
||||
image_data, 0, 0,
|
||||
BlockManager::cross_plane_index(id),
|
||||
CROSS_PLANE_SIZE, CROSS_PLANE_SIZE);
|
||||
Tools::delete_image_data(image_data);
|
||||
}
|
||||
|
||||
@@ -161,9 +159,8 @@ void TextureManager::load_ui_texture(unsigned id) {
|
||||
std::string path = "texture/ui/" + std::to_string(id) + ".png";
|
||||
unsigned char* image_data = nullptr;
|
||||
image_data = (Tools::load_image_data(path));
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, m_ui_array);
|
||||
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, id, UI_SIZE, UI_SIZE, 1,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, image_data);
|
||||
m_ui_array->tex_sub_image_3d(TextureFormat::RGBA, GL_UNSIGNED_BYTE,
|
||||
image_data, 0, 0, id, UI_SIZE, UI_SIZE);
|
||||
Tools::delete_image_data(image_data);
|
||||
}
|
||||
|
||||
@@ -189,7 +186,6 @@ void TextureManager::load_pbr_texture(unsigned id) {
|
||||
image_data[4] = (Tools::load_image_data(path + "/top_n.png", false));
|
||||
image_data[5] = (Tools::load_image_data(path + "/base_n.png", false));
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, m_normal_texture_array);
|
||||
for (int i = 0; i < 6; i++) {
|
||||
unsigned char* data = image_data[i];
|
||||
bool is_fallback = false;
|
||||
@@ -197,9 +193,10 @@ void TextureManager::load_pbr_texture(unsigned id) {
|
||||
is_fallback = true;
|
||||
data = generate_flat_normal_map();
|
||||
}
|
||||
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, id * 6 + i,
|
||||
BLOCK_NORMAL_SIZE, BLOCK_NORMAL_SIZE, 1, GL_RGBA,
|
||||
GL_UNSIGNED_BYTE, data);
|
||||
m_normal_texture_array->tex_sub_image_3d(
|
||||
TextureFormat::RGBA, GL_UNSIGNED_BYTE, data, 0, 0, id * 6 + i,
|
||||
BLOCK_NORMAL_SIZE, BLOCK_NORMAL_SIZE);
|
||||
|
||||
if (is_fallback) {
|
||||
delete[] data;
|
||||
} else {
|
||||
@@ -209,125 +206,78 @@ void TextureManager::load_pbr_texture(unsigned id) {
|
||||
}
|
||||
|
||||
void TextureManager::init_block() {
|
||||
m_texture_array = std::make_unique<Texture>(TextureType::TEXTURE_2D_ARRAY);
|
||||
m_texture_array->tex_image_3d(TextureFormat::RGBA, TextureFormat::RGBA,
|
||||
GL_UNSIGNED_BYTE, nullptr, BLOCK_SIZE,
|
||||
BLOCK_SIZE, BlockManager::sums() * 6);
|
||||
|
||||
glGenTextures(1, &m_texture_array);
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture_array);
|
||||
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, BLOCK_SIZE, BLOCK_SIZE,
|
||||
BlockManager::sums() * 6, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
nullptr);
|
||||
m_cross_plane_array =
|
||||
std::make_unique<Texture>(TextureType::TEXTURE_2D_ARRAY);
|
||||
m_cross_plane_array->tex_image_3d(
|
||||
TextureFormat::RGBA, TextureFormat::RGBA, GL_UNSIGNED_BYTE, nullptr,
|
||||
CROSS_PLANE_SIZE, CROSS_PLANE_SIZE, BlockManager::cross_plane_sum());
|
||||
|
||||
glGenTextures(1, &m_cross_plane_array);
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, m_cross_plane_array);
|
||||
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, CROSS_PLANE_SIZE,
|
||||
CROSS_PLANE_SIZE, BlockManager::cross_plane_sum(), 0, GL_RGBA,
|
||||
GL_UNSIGNED_BYTE, nullptr);
|
||||
glGenTextures(1, &m_normal_texture_array);
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, m_normal_texture_array);
|
||||
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, BLOCK_NORMAL_SIZE,
|
||||
BLOCK_NORMAL_SIZE, BlockManager::sums() * 6, 0, GL_RGBA,
|
||||
GL_UNSIGNED_BYTE, nullptr);
|
||||
m_normal_texture_array =
|
||||
std::make_unique<Texture>(TextureType::TEXTURE_2D_ARRAY);
|
||||
m_normal_texture_array->tex_image_3d(
|
||||
TextureFormat::RGBA8, TextureFormat::RGBA, GL_UNSIGNED_BYTE, nullptr,
|
||||
BLOCK_NORMAL_SIZE, BLOCK_NORMAL_SIZE, BlockManager::sums() * 6);
|
||||
for (unsigned i = 0; i < BlockManager::sums(); i++) {
|
||||
load_block_texture(i);
|
||||
load_block_item_texture(i);
|
||||
load_pbr_texture(i);
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture_array);
|
||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER,
|
||||
GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
|
||||
if (m_aniso >= 1) {
|
||||
glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_ANISOTROPY,
|
||||
static_cast<GLfloat>(m_aniso));
|
||||
}
|
||||
m_texture_array->set_nearest_and_minpmap();
|
||||
m_texture_array->set_repeat(false, true, true);
|
||||
m_texture_array->set_aniso(m_aniso);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, m_cross_plane_array);
|
||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER,
|
||||
GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
|
||||
if (m_aniso >= 1) {
|
||||
glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_ANISOTROPY,
|
||||
static_cast<GLfloat>(m_aniso));
|
||||
}
|
||||
m_cross_plane_array->set_nearest_and_minpmap();
|
||||
m_texture_array->set_repeat(false, true, true);
|
||||
m_cross_plane_array->set_clamp_to_edge(m_aniso);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, m_normal_texture_array);
|
||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER,
|
||||
GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
|
||||
if (m_aniso >= 1) {
|
||||
glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_ANISOTROPY,
|
||||
static_cast<GLfloat>(m_aniso));
|
||||
}
|
||||
m_normal_texture_array->set_nearest_and_minpmap();
|
||||
m_normal_texture_array->set_repeat(false, true, true);
|
||||
m_normal_texture_array->set_aniso(m_aniso);
|
||||
|
||||
Logger::info("Block Texture Load Success");
|
||||
}
|
||||
void TextureManager::init_ui() {
|
||||
glGenTextures(1, &m_ui_array);
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, m_ui_array);
|
||||
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, UI_SIZE, UI_SIZE, MAX_UI_NUM,
|
||||
0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||
m_ui_array = std::make_unique<Texture>(TextureType::TEXTURE_2D_ARRAY);
|
||||
m_ui_array->tex_image_3d(TextureFormat::RGBA, TextureFormat::RGBA,
|
||||
GL_UNSIGNED_BYTE, nullptr, UI_SIZE, UI_SIZE,
|
||||
MAX_UI_NUM);
|
||||
for (int i = 0; i < MAX_UI_NUM; i++) {
|
||||
load_ui_texture(i);
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, m_ui_array);
|
||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
m_ui_array->set_nearest();
|
||||
}
|
||||
|
||||
void TextureManager::init_skin() {
|
||||
|
||||
glGenTextures(1, &m_skin);
|
||||
glBindTexture(GL_TEXTURE_2D, m_skin);
|
||||
m_skin = std::make_unique<Texture>(TextureType::TEXTURE_2D);
|
||||
std::string path = "texture/skin/player001.png";
|
||||
unsigned char* image_data = nullptr;
|
||||
image_data = (Tools::load_image_data(path));
|
||||
glBindTexture(GL_TEXTURE_2D, m_skin);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SKIN_SIZE, SKIN_SIZE, 0, GL_RGBA,
|
||||
GL_UNSIGNED_BYTE, image_data);
|
||||
m_skin->tex_image_2d(TextureFormat::RGBA, TextureFormat::RGBA,
|
||||
GL_UNSIGNED_BYTE, image_data, SKIN_SIZE, SKIN_SIZE);
|
||||
Tools::delete_image_data(image_data);
|
||||
glBindTexture(GL_TEXTURE_2D, m_skin);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
|
||||
GL_LINEAR_MIPMAP_LINEAR);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
if (m_aniso >= 1) {
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY,
|
||||
static_cast<GLfloat>(m_aniso));
|
||||
}
|
||||
m_skin->set_nearest_and_minpmap();
|
||||
m_skin->set_aniso(m_aniso);
|
||||
}
|
||||
|
||||
void TextureManager::init_block_status() {
|
||||
glGenTextures(1, &m_block_status_array);
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, m_block_status_array);
|
||||
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, BLOCK_STATUS_SIZE,
|
||||
BLOCK_STATUS_SIZE, MAX_BLOCK_STATUS, 0, GL_RGBA,
|
||||
GL_UNSIGNED_BYTE, nullptr);
|
||||
m_block_status_array =
|
||||
std::make_unique<Texture>(TextureType::TEXTURE_2D_ARRAY);
|
||||
m_block_status_array->tex_image_3d(
|
||||
TextureFormat::RGBA, TextureFormat::RGBA, GL_UNSIGNED_BYTE, nullptr,
|
||||
BLOCK_STATUS_SIZE, BLOCK_STATUS_SIZE, MAX_BLOCK_STATUS);
|
||||
for (int i = 0; i < MAX_BLOCK_STATUS; i++) {
|
||||
load_block_status(i);
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, m_block_status_array);
|
||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER,
|
||||
GL_LINEAR_MIPMAP_LINEAR);
|
||||
glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
|
||||
|
||||
if (m_aniso >= 1) {
|
||||
glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_ANISOTROPY,
|
||||
static_cast<GLfloat>(m_aniso));
|
||||
}
|
||||
m_block_status_array->set_nearest_and_minpmap();
|
||||
m_block_status_array->set_aniso(m_aniso);
|
||||
}
|
||||
void TextureManager::init_texture() {
|
||||
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY, &m_max_aniso);
|
||||
@@ -335,10 +285,9 @@ void TextureManager::init_texture() {
|
||||
Logger::info("Support anisotropic filtering max_aniso is {}",
|
||||
m_max_aniso);
|
||||
}
|
||||
m_aniso = Config::get().get<int>("texture.aniso");
|
||||
m_aniso = m_config.get("texture.aniso", 1);
|
||||
m_aniso = std::min(static_cast<int>(m_max_aniso), m_aniso);
|
||||
Logger::info("Setting Texture Aniso is {}", m_aniso);
|
||||
MapTable::init_map();
|
||||
Logger::info("Map Init Success");
|
||||
|
||||
init_block();
|
||||
@@ -357,7 +306,7 @@ void TextureManager::update() {
|
||||
void TextureManager::need_reload() { m_need_reload = true; }
|
||||
|
||||
void TextureManager::hot_reload() {
|
||||
delet_texture();
|
||||
delete_texture();
|
||||
|
||||
init_texture();
|
||||
m_need_reload = false;
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
#include "Cubed/tools/font.hpp"
|
||||
|
||||
#include "Cubed/constants.hpp"
|
||||
#include "Cubed/shader.hpp"
|
||||
#include "Cubed/tools/log.hpp"
|
||||
#include "Cubed/tools/shader_tools.hpp"
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
@@ -26,7 +24,6 @@ Font::~Font() {
|
||||
|
||||
FT_Done_Face(m_face);
|
||||
FT_Done_FreeType(m_ft);
|
||||
glDeleteTextures(1, &m_text_texture);
|
||||
}
|
||||
|
||||
void Font::load_character(char8_t c) {
|
||||
@@ -36,10 +33,9 @@ void Font::load_character(char8_t c) {
|
||||
}
|
||||
const auto& width = m_face->glyph->bitmap.width;
|
||||
const auto& height = m_face->glyph->bitmap.rows;
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, m_text_texture);
|
||||
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, static_cast<int>(c), width,
|
||||
height, 1, GL_RED, GL_UNSIGNED_BYTE,
|
||||
m_face->glyph->bitmap.buffer);
|
||||
m_text_texture->tex_sub_image_3d(TextureFormat::RED, GL_UNSIGNED_BYTE,
|
||||
m_face->glyph->bitmap.buffer, 0, 0,
|
||||
static_cast<int>(c), width, height);
|
||||
|
||||
Character character = {
|
||||
glm::vec2{0.0f, 0.0f},
|
||||
@@ -54,22 +50,16 @@ void Font::load_character(char8_t c) {
|
||||
|
||||
void Font::setup_font_character() {
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
glGenTextures(1, &m_text_texture);
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, m_text_texture);
|
||||
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RED, m_texture_width,
|
||||
m_texture_height, MAX_CHARACTER, 0, GL_RED, GL_UNSIGNED_BYTE,
|
||||
nullptr);
|
||||
m_text_texture = std::make_unique<Texture>(TextureType::TEXTURE_2D_ARRAY);
|
||||
m_text_texture->tex_image_3d(TextureFormat::RED, TextureFormat::RED,
|
||||
GL_UNSIGNED_BYTE, nullptr, m_texture_width,
|
||||
m_texture_height, MAX_CHARACTER);
|
||||
|
||||
for (char8_t c = 0; c < 128; c++) {
|
||||
load_character(c);
|
||||
}
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
|
||||
m_text_texture->set_linear();
|
||||
m_text_texture->set_clamp_to_edge(false, true, true);
|
||||
}
|
||||
|
||||
std::vector<Vertex2D> Font::vertices(const std::string& text, float x, float y,
|
||||
@@ -110,7 +100,7 @@ std::vector<Vertex2D> Font::vertices(const std::string& text, float x, float y,
|
||||
return vertices;
|
||||
}
|
||||
|
||||
GLuint Font::text_texture() { return m_text_texture; }
|
||||
const Texture* Font::text_texture() { return m_text_texture.get(); }
|
||||
|
||||
const std::string& Font::font_path() { return m_font_path; }
|
||||
|
||||
|
||||
@@ -9,30 +9,30 @@
|
||||
|
||||
namespace Cubed {
|
||||
|
||||
Text::Text(std::string_view name) : NAME(name), UUID(HASH::str(name)) {}
|
||||
Text::Text(std::string_view name)
|
||||
: NAME(name), UUID(HASH::str(name)),
|
||||
m_vbo(std::make_unique<VertexBuffer>()),
|
||||
m_vao(std::make_unique<VertexArray>()) {}
|
||||
|
||||
Text::Text(std::string_view name, std::string_view str, glm::vec2 pos,
|
||||
Color color)
|
||||
: NAME(name), UUID(HASH::str(name)) {
|
||||
: NAME(name), UUID(HASH::str(name)),
|
||||
m_vbo(std::make_unique<VertexBuffer>()),
|
||||
m_vao(std::make_unique<VertexArray>()) {
|
||||
m_text.assign(str);
|
||||
m_pos = pos;
|
||||
m_color = color_value(color);
|
||||
update_vertices();
|
||||
}
|
||||
|
||||
Text::~Text() {
|
||||
if (m_vbo != 0) {
|
||||
glDeleteBuffers(1, &m_vbo);
|
||||
}
|
||||
}
|
||||
Text::~Text() { m_vbo.reset(); }
|
||||
|
||||
Text::Text(Text&& other) noexcept
|
||||
: m_scale(other.m_scale), m_pos(other.m_pos), NAME(other.NAME),
|
||||
UUID(other.UUID), m_text(std::move(other.m_text)), m_color(other.m_color),
|
||||
m_model_matrix(other.m_model_matrix),
|
||||
m_vertices(std::move(other.m_vertices)), m_vbo(other.m_vbo) {
|
||||
other.m_vbo = 0;
|
||||
}
|
||||
m_vertices(std::move(other.m_vertices)), m_vbo(std::move(other.m_vbo)),
|
||||
m_vao(std::move(other.m_vao)) {}
|
||||
|
||||
Text& Text::color(Color color) {
|
||||
m_color = color_value(color);
|
||||
@@ -51,45 +51,24 @@ Text& Text::scale(float s) {
|
||||
|
||||
std::size_t Text::uuid() const { return UUID; }
|
||||
|
||||
void Text::set_loc(const Shader& shader) {
|
||||
m_color_loc = shader.loc("textColor");
|
||||
m_mv_loc = shader.loc("mv_matrix");
|
||||
}
|
||||
|
||||
Text& Text::text(std::string_view str) {
|
||||
m_text.assign(str);
|
||||
update_vertices();
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Text::render() {
|
||||
void Text::render(const Shader& shader) {
|
||||
ASSERT_MSG(m_vbo != 0, "VBO not initialized!");
|
||||
ASSERT_MSG(!m_vertices.empty(), "Text String Not Set");
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, Font::text_texture());
|
||||
ASSERT_MSG(m_color_loc, "m_color_loc is null");
|
||||
|
||||
Font::text_texture()->bind(0);
|
||||
m_vao->bind();
|
||||
m_model_matrix =
|
||||
glm::translate(glm::mat4(1.0f), glm::vec3(m_pos.x, m_pos.y, 0.0f)) *
|
||||
glm::scale(glm::mat4(1.0f), glm::vec3(m_scale, m_scale, 1.0f));
|
||||
|
||||
glUniform3f(m_color_loc, m_color.x, m_color.y, m_color.z);
|
||||
glUniformMatrix4fv(m_mv_loc, 1, GL_FALSE, glm::value_ptr(m_model_matrix));
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
|
||||
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex2D), (void*)0);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex2D),
|
||||
(void*)offsetof(Vertex2D, s));
|
||||
glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, sizeof(Vertex2D),
|
||||
(void*)offsetof(Vertex2D, layer));
|
||||
|
||||
glEnableVertexAttribArray(0);
|
||||
glEnableVertexAttribArray(1);
|
||||
glEnableVertexAttribArray(2);
|
||||
|
||||
shader.set_loc("textColor", glm::vec3(m_color.x, m_color.y, m_color.z));
|
||||
shader.set_loc("mv_matrix", m_model_matrix);
|
||||
glDrawArrays(GL_TRIANGLES, 0, m_vertices.size());
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
|
||||
}
|
||||
|
||||
void Text::update_vertices() {
|
||||
@@ -98,13 +77,15 @@ void Text::update_vertices() {
|
||||
}
|
||||
|
||||
void Text::upload_to_gpu() {
|
||||
if (m_vbo == 0) {
|
||||
glGenBuffers(1, &m_vbo);
|
||||
}
|
||||
ASSERT_MSG(m_vbo, "Vbo Is Not Gen");
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, m_vertices.size() * sizeof(Vertex2D),
|
||||
m_vertices.data(), GL_DYNAMIC_DRAW);
|
||||
m_vao->bind();
|
||||
m_vbo->buffer_data(m_vertices.data(), m_vertices.size() * sizeof(Vertex2D),
|
||||
BufferUsage::DYNAMIC_DRAW);
|
||||
m_vao->attribute(0, 2, GL_FLOAT, sizeof(Vertex2D), (void*)0);
|
||||
m_vao->attribute(1, 2, GL_FLOAT, sizeof(Vertex2D),
|
||||
(void*)offsetof(Vertex2D, s));
|
||||
m_vao->attribute(2, 1, GL_FLOAT, sizeof(Vertex2D),
|
||||
(void*)offsetof(Vertex2D, layer));
|
||||
}
|
||||
|
||||
bool Text::operator==(const Text& other) const { return UUID == other.uuid(); }
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include "Cubed/window.hpp"
|
||||
|
||||
#include "Cubed/config.hpp"
|
||||
#include "Cubed/renderer.hpp"
|
||||
#include "Cubed/render/renderer.hpp"
|
||||
#include "Cubed/tools/cubed_assert.hpp"
|
||||
#include "Cubed/tools/font.hpp"
|
||||
#include "Cubed/tools/log.hpp"
|
||||
@@ -15,7 +14,8 @@ namespace Cubed {
|
||||
static int windowed_xpos = 0, windowed_ypos = 0;
|
||||
static int windowed_width = 800, windowed_height = 600;
|
||||
|
||||
Window::Window(Renderer& renderer) : m_renderer(renderer) {}
|
||||
Window::Window(Renderer& renderer, Config& config)
|
||||
: m_renderer(renderer), m_config(config) {}
|
||||
|
||||
Window::~Window() {
|
||||
if (m_imgui_init) {
|
||||
@@ -47,9 +47,8 @@ void Window::update_viewport() {
|
||||
glViewport(0, 0, m_width, m_height);
|
||||
m_renderer.update_proj_matrix(m_aspect, m_width, m_height);
|
||||
m_renderer.updata_framebuffer(m_width, m_height);
|
||||
auto& config = Config::get();
|
||||
config.set("window.width", windowed_width);
|
||||
config.set("window.height", windowed_height);
|
||||
m_config.set("window.width", windowed_width);
|
||||
m_config.set("window.height", windowed_height);
|
||||
}
|
||||
|
||||
void Window::init() {
|
||||
@@ -61,10 +60,9 @@ void Window::init() {
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
|
||||
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
|
||||
auto& config = Config::get();
|
||||
m_width = config.get<int>("window.width");
|
||||
m_height = config.get<int>("window.height");
|
||||
if (config.get<bool>("window.fullscreen")) {
|
||||
m_width = m_config.get("window.width", 800);
|
||||
m_height = m_config.get("window.height", 600);
|
||||
if (m_config.get("window.fullscreen", false)) {
|
||||
GLFWmonitor* primary_monitor = glfwGetPrimaryMonitor();
|
||||
const GLFWvidmode* mode = glfwGetVideoMode(primary_monitor);
|
||||
m_window = glfwCreateWindow(mode->width, mode->height, "Cubed",
|
||||
@@ -74,7 +72,7 @@ void Window::init() {
|
||||
}
|
||||
|
||||
glfwMakeContextCurrent(m_window);
|
||||
if (config.get<bool>("window.V-Sync")) {
|
||||
if (m_config.get("window.V-Sync", true)) {
|
||||
glfwSwapInterval(1);
|
||||
} else {
|
||||
glfwSwapInterval(0);
|
||||
@@ -94,18 +92,17 @@ void Window::init() {
|
||||
}
|
||||
|
||||
void Window::hot_reload() {
|
||||
auto& config = Config::get();
|
||||
// V-Sync
|
||||
if (config.get<bool>("window.V-Sync")) {
|
||||
if (m_config.get("window.V-Sync", true)) {
|
||||
glfwSwapInterval(1);
|
||||
} else {
|
||||
glfwSwapInterval(0);
|
||||
}
|
||||
// Window
|
||||
windowed_width = config.get<int>("window.width");
|
||||
windowed_height = config.get<int>("window.height");
|
||||
windowed_width = m_config.get("window.width", 800);
|
||||
windowed_height = m_config.get("window.height", 600);
|
||||
|
||||
if (config.get<bool>("window.fullscreen")) {
|
||||
if (m_config.get("window.fullscreen", false)) {
|
||||
glfwGetWindowPos(m_window, &windowed_xpos, &windowed_ypos);
|
||||
glfwGetWindowSize(m_window, &windowed_width, &windowed_height);
|
||||
|
||||
@@ -134,13 +131,12 @@ void Window::hot_reload() {
|
||||
|
||||
void Window::toggle_fullscreen() {
|
||||
|
||||
auto& config = Config::get();
|
||||
GLFWmonitor* monitor = glfwGetWindowMonitor(m_window);
|
||||
if (monitor != nullptr) {
|
||||
glfwSetWindowMonitor(m_window, nullptr, windowed_xpos, windowed_ypos,
|
||||
windowed_width, windowed_height, 0);
|
||||
|
||||
config.set("window.fullscreen", false);
|
||||
m_config.set("window.fullscreen", false);
|
||||
} else {
|
||||
glfwGetWindowPos(m_window, &windowed_xpos, &windowed_ypos);
|
||||
glfwGetWindowSize(m_window, &windowed_width, &windowed_height);
|
||||
@@ -150,7 +146,7 @@ void Window::toggle_fullscreen() {
|
||||
|
||||
glfwSetWindowMonitor(m_window, primary, 0, 0, mode->width, mode->height,
|
||||
GL_DONT_CARE);
|
||||
config.set("window.fullscreen", true);
|
||||
m_config.set("window.fullscreen", true);
|
||||
}
|
||||
update_viewport();
|
||||
}
|
||||
@@ -194,14 +190,14 @@ void Window::imgui_init() {
|
||||
// the game to fully control
|
||||
// cursor appearance (e.g.,
|
||||
// hidden/disabled custom cursor).
|
||||
auto theme = Config::get().get<int>("devpanel.theme");
|
||||
auto theme = m_config.get("devpanel.theme", 0);
|
||||
if (theme == 0) {
|
||||
ImGui::StyleColorsDark();
|
||||
} else if (theme == 1) {
|
||||
ImGui::StyleColorsLight();
|
||||
} else {
|
||||
ImGui::StyleColorsDark();
|
||||
Config::get().set("devpanel.theme", 0);
|
||||
m_config.set("devpanel.theme", 0);
|
||||
}
|
||||
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
|
||||
Reference in New Issue
Block a user