mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-06-18 00:27:02 +08:00
Compare commits
11 Commits
main
...
feat/light
| Author | SHA1 | Date | |
|---|---|---|---|
| c00f05aafd | |||
| dc1ef70231 | |||
| e224110452 | |||
| 74b0aebc9f | |||
| be425a705c | |||
| 31bf337f6f | |||
| 662f10047a | |||
| 943c6f1f46 | |||
| 7ede49da72 | |||
| a4f92e3659 | |||
| f43ef64691 |
@@ -1,15 +1,125 @@
|
|||||||
#version 460
|
#version 460
|
||||||
|
|
||||||
in vec2 tc;
|
in vec2 tc;
|
||||||
|
in vec3 normal;
|
||||||
|
in vec3 vert_pos;
|
||||||
|
in vec4 FragPosLightSpace;
|
||||||
flat in int tex_layer;
|
flat in int tex_layer;
|
||||||
out vec4 color;
|
out vec4 color;
|
||||||
|
layout (binding = 0) uniform sampler2D shadowMap;
|
||||||
|
layout (binding = 1) uniform sampler2DArray samp;
|
||||||
|
|
||||||
|
uniform float ambientStrength;
|
||||||
|
uniform vec3 sunlightColor;
|
||||||
|
uniform vec3 sunlightDir;
|
||||||
|
uniform bool shader_on;
|
||||||
|
uniform int shadowMode;
|
||||||
|
|
||||||
|
const vec2 poissonDisk[8] = vec2[](
|
||||||
|
vec2( 0.1440, 0.7659), vec2(-0.5761, 0.4479),
|
||||||
|
vec2(-0.3220, -0.6058), vec2( 0.5693, -0.4048),
|
||||||
|
vec2(-0.1276, 0.1657), vec2(-0.0649, -0.0165),
|
||||||
|
vec2( 0.2773, -0.0305), vec2(-0.1134, -0.2122)
|
||||||
|
);
|
||||||
|
|
||||||
|
float random(vec3 seed) {
|
||||||
|
return fract(sin(dot(seed, vec3(12.9898,78.233,45.5432))) * 43758.5453);
|
||||||
|
}
|
||||||
|
|
||||||
|
float ShadowCalculation(vec4 fragPosLightSpace, vec3 norm, vec3 lightDir)
|
||||||
|
{
|
||||||
|
|
||||||
|
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
|
||||||
|
|
||||||
|
projCoords = projCoords * 0.5 + 0.5;
|
||||||
|
if (projCoords.x < 0.0 || projCoords.x > 1.0 ||
|
||||||
|
projCoords.y < 0.0 || projCoords.y > 1.0 ||
|
||||||
|
projCoords.z < 0.0 || projCoords.z > 1.0) {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
float currentDepth = projCoords.z;
|
||||||
|
vec2 texelSize = 1.0 / vec2(textureSize(shadowMap, 0));
|
||||||
|
float shadow = 0.0;
|
||||||
|
float bias =
|
||||||
|
max(
|
||||||
|
0.0003,
|
||||||
|
0.001 * (1.0 - dot(norm, lightDir))
|
||||||
|
);
|
||||||
|
|
||||||
|
if (shadowMode == 0) {
|
||||||
|
vec3 seed = vert_pos * 37.0 + sin(vert_pos * 91.7) * 13.0;
|
||||||
|
float angle = random(seed) * 6.2831853;; // 2*PI
|
||||||
|
float s = sin(angle), c = cos(angle);
|
||||||
|
mat2 rot = mat2(c, -s, s, c);
|
||||||
|
|
||||||
|
float radius = 0.7;
|
||||||
|
|
||||||
|
|
||||||
|
const int samples = 8;
|
||||||
|
for (int i = 0; i < samples; ++i) {
|
||||||
|
vec2 offset = rot * poissonDisk[i] * radius * texelSize;
|
||||||
|
float pcfDepth = texture(shadowMap, projCoords.xy + offset).r;
|
||||||
|
shadow += (currentDepth - bias > pcfDepth ? 1.0 : 0.0);
|
||||||
|
}
|
||||||
|
shadow /= float(samples);
|
||||||
|
} else if (shadowMode == 1) {
|
||||||
|
for (int x = -1; x <= 1; ++x) {
|
||||||
|
for (int y = -1; y <= 1; ++y) {
|
||||||
|
vec2 offset = vec2(x, y) * texelSize;
|
||||||
|
float pcfDepth = texture(shadowMap, projCoords.xy + offset).r;
|
||||||
|
shadow += (currentDepth - bias > pcfDepth ? 1.0 : 0.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
shadow /= 9.0;
|
||||||
|
} else if (shadowMode == 2) {
|
||||||
|
// pcf off
|
||||||
|
float pcfDepth =
|
||||||
|
texture(shadowMap, projCoords.xy).r;
|
||||||
|
|
||||||
|
shadow =
|
||||||
|
currentDepth - bias > pcfDepth
|
||||||
|
? 1.0
|
||||||
|
: 0.0;
|
||||||
|
} else {
|
||||||
|
float pcfDepth =
|
||||||
|
texture(shadowMap, projCoords.xy).r;
|
||||||
|
|
||||||
|
shadow =
|
||||||
|
currentDepth - bias > pcfDepth
|
||||||
|
? 1.0
|
||||||
|
: 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return shadow;
|
||||||
|
}
|
||||||
|
|
||||||
layout (binding = 0) uniform sampler2DArray samp;
|
|
||||||
|
|
||||||
void main(void) {
|
void main(void) {
|
||||||
color = texture(samp, vec3(tc, tex_layer));
|
vec4 objectColor = texture(samp, vec3(tc, tex_layer));
|
||||||
if (color.a < 0.8) {
|
|
||||||
|
if (objectColor.a < 0.8) {
|
||||||
discard;
|
discard;
|
||||||
}
|
}
|
||||||
|
if (!shader_on) {
|
||||||
|
color = objectColor;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
vec3 lightDir = normalize(-sunlightDir);
|
||||||
|
|
||||||
|
vec3 ambient = ambientStrength * sunlightColor;
|
||||||
|
|
||||||
|
vec3 norm = normalize(normal);
|
||||||
|
|
||||||
|
float diff = max(dot(norm, lightDir), 0.0);
|
||||||
|
|
||||||
|
vec3 diffuse = diff * sunlightColor;
|
||||||
|
|
||||||
|
float shadow = ShadowCalculation(FragPosLightSpace, norm, lightDir);
|
||||||
|
|
||||||
|
color = vec4((ambient + (1.0 - shadow) * (diffuse)) * objectColor.rgb, objectColor.a);
|
||||||
|
|
||||||
//color = varyingColor;
|
//color = varyingColor;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,12 @@
|
|||||||
layout (location = 0) in vec3 pos;
|
layout (location = 0) in vec3 pos;
|
||||||
layout (location = 1) in vec2 texCoord;
|
layout (location = 1) in vec2 texCoord;
|
||||||
layout (location = 2) in float layer;
|
layout (location = 2) in float layer;
|
||||||
|
layout (location = 3) in vec3 aNormal;
|
||||||
out vec2 tc;
|
out vec2 tc;
|
||||||
|
out vec3 normal;
|
||||||
|
out vec3 vert_pos;
|
||||||
flat out int tex_layer;
|
flat out int tex_layer;
|
||||||
|
out vec4 FragPosLightSpace;
|
||||||
|
|
||||||
mat4 buildRotateX(float rad);
|
mat4 buildRotateX(float rad);
|
||||||
mat4 buildRotateY(float rad);
|
mat4 buildRotateY(float rad);
|
||||||
@@ -13,13 +17,21 @@ mat4 buildTranslate(float x, float y, float z);
|
|||||||
|
|
||||||
uniform mat4 mv_matrix;
|
uniform mat4 mv_matrix;
|
||||||
uniform mat4 proj_matrix;
|
uniform mat4 proj_matrix;
|
||||||
|
uniform mat4 norm_matrix;
|
||||||
|
uniform mat4 lightSpaceMatrix;
|
||||||
|
|
||||||
void main(void) {
|
void main(void) {
|
||||||
gl_Position = proj_matrix * mv_matrix * vec4(pos, 1.0);
|
vec4 viewPos = mv_matrix * vec4(pos, 1.0);
|
||||||
|
|
||||||
|
vert_pos = pos;
|
||||||
|
|
||||||
tc = texCoord;
|
tc = texCoord;
|
||||||
|
|
||||||
tex_layer = int(layer);
|
tex_layer = int(layer);
|
||||||
|
|
||||||
|
normal = mat3(norm_matrix) * aNormal;
|
||||||
|
FragPosLightSpace = lightSpaceMatrix * vec4(pos, 1.0);
|
||||||
|
gl_Position = proj_matrix * viewPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
mat4 buildTranslate(float x, float y, float z) {
|
mat4 buildTranslate(float x, float y, float z) {
|
||||||
|
|||||||
16
assets/shaders/depth_fragment_shader.glsl
Normal file
16
assets/shaders/depth_fragment_shader.glsl
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#version 460
|
||||||
|
|
||||||
|
in vec2 tc;
|
||||||
|
flat in int tex_layer;
|
||||||
|
layout (binding = 1) uniform sampler2DArray samp;
|
||||||
|
|
||||||
|
uniform bool is_discard_tranparent;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
if (is_discard_tranparent) {
|
||||||
|
vec4 texColor = texture(samp, vec3(tc, tex_layer));
|
||||||
|
if (texColor.a < 0.8)
|
||||||
|
discard;
|
||||||
|
}
|
||||||
|
//gl_FragDepth = gl_FragCoord.z;
|
||||||
|
}
|
||||||
12
assets/shaders/depth_shader.glsl
Normal file
12
assets/shaders/depth_shader.glsl
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#version 460
|
||||||
|
layout (location = 0) in vec3 pos;
|
||||||
|
layout (location = 1) in vec2 texCoord;
|
||||||
|
layout (location = 2) in float layer;
|
||||||
|
uniform mat4 lightSpaceMatrix;
|
||||||
|
out vec2 tc;
|
||||||
|
flat out int tex_layer;
|
||||||
|
void main() {
|
||||||
|
tc = texCoord;
|
||||||
|
tex_layer = int(layer);
|
||||||
|
gl_Position = lightSpaceMatrix * vec4(pos, 1.0);
|
||||||
|
}
|
||||||
@@ -2,8 +2,10 @@
|
|||||||
|
|
||||||
out vec4 frag_color;
|
out vec4 frag_color;
|
||||||
|
|
||||||
|
uniform vec3 color;
|
||||||
|
|
||||||
void main(void) {
|
void main(void) {
|
||||||
|
|
||||||
frag_color = vec4(0.529, 0.808, 0.922, 1.0);
|
frag_color = vec4(color, 1.0);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -32,6 +32,7 @@ public:
|
|||||||
const glm::vec3& get_camera_pos() const;
|
const glm::vec3& get_camera_pos() const;
|
||||||
|
|
||||||
bool is_under_water() const;
|
bool is_under_water() const;
|
||||||
|
glm::vec3 get_camera_front() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Cubed
|
} // namespace Cubed
|
||||||
|
|||||||
@@ -23,9 +23,9 @@ constexpr float DEFAULT_MAX_RUN_SPEED = 7.0f;
|
|||||||
constexpr float DEFAULT_ACCELERATION = 10.0f;
|
constexpr float DEFAULT_ACCELERATION = 10.0f;
|
||||||
constexpr float DEFAULT_DECELERATION = 15.0f;
|
constexpr float DEFAULT_DECELERATION = 15.0f;
|
||||||
constexpr float DEFAULT_G = 22.5f;
|
constexpr float DEFAULT_G = 22.5f;
|
||||||
static constexpr int SIZE_X = CHUNK_SIZE;
|
constexpr int SIZE_X = CHUNK_SIZE;
|
||||||
static constexpr int SIZE_Y = WORLD_SIZE_Y;
|
constexpr int SIZE_Y = WORLD_SIZE_Y;
|
||||||
static constexpr int SIZE_Z = CHUNK_SIZE;
|
constexpr int SIZE_Z = CHUNK_SIZE;
|
||||||
|
|
||||||
constexpr ChunkPos CHUNK_DIR[]{{1, 0}, {-1, 0}, {0, 1}, {0, -1},
|
constexpr ChunkPos CHUNK_DIR[]{{1, 0}, {-1, 0}, {0, 1}, {0, -1},
|
||||||
{1, 1}, {-1, 1}, {1, -1}, {-1, -1}};
|
{1, 1}, {-1, 1}, {1, -1}, {-1, -1}};
|
||||||
|
|||||||
@@ -44,14 +44,19 @@ private:
|
|||||||
bool m_need_save_config = false;
|
bool m_need_save_config = false;
|
||||||
bool m_gen_thread_running = true;
|
bool m_gen_thread_running = true;
|
||||||
int m_theme = 0;
|
int m_theme = 0;
|
||||||
|
int m_pre_set_day_tick = 0;
|
||||||
|
int m_pre_set_tick_speed = 1;
|
||||||
|
bool m_tick_frezze = false;
|
||||||
void show_about_table_bar();
|
void show_about_table_bar();
|
||||||
void show_biome_table_bar();
|
void show_biome_table_bar();
|
||||||
|
void show_time_table_bar();
|
||||||
void show_cave_table_bar();
|
void show_cave_table_bar();
|
||||||
void show_river_table_bar();
|
void show_river_table_bar();
|
||||||
void show_settings_tab_item();
|
void show_settings_tab_item();
|
||||||
void show_world_tab_item();
|
void show_world_tab_item();
|
||||||
void show_player_tab_item();
|
void show_player_tab_item();
|
||||||
void show_items_tab_item();
|
void show_items_tab_item();
|
||||||
|
void show_shader_tab_item();
|
||||||
|
|
||||||
void update_config_view();
|
void update_config_view();
|
||||||
void update_player_profile();
|
void update_player_profile();
|
||||||
|
|||||||
10
include/Cubed/gameplay/game_time.hpp
Normal file
10
include/Cubed/gameplay/game_time.hpp
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Prevent unsigned underflow issues in subtraction
|
||||||
|
using TickType = long long;
|
||||||
|
|
||||||
|
constexpr int DEFAULT_PER_TICK_TIME = 50;
|
||||||
|
|
||||||
|
constexpr TickType DAY_TIME = 24000;
|
||||||
|
|
||||||
|
constexpr TickType PER_HOUR = 1000;
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
namespace Cubed {
|
namespace Cubed {
|
||||||
class World;
|
class World;
|
||||||
struct VertexData {
|
struct VertexData {
|
||||||
std::vector<Vertex> m_vertices;
|
std::vector<Vertex3D> m_vertices;
|
||||||
GLuint m_vbo = 0;
|
GLuint m_vbo = 0;
|
||||||
GLuint m_vao = 0;
|
GLuint m_vao = 0;
|
||||||
std::atomic<std::size_t> m_sum{0};
|
std::atomic<std::size_t> m_sum{0};
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include "Cubed/AABB.hpp"
|
#include "Cubed/AABB.hpp"
|
||||||
#include "Cubed/gameplay/cave_carver.hpp"
|
#include "Cubed/gameplay/cave_carver.hpp"
|
||||||
#include "Cubed/gameplay/chunk.hpp"
|
#include "Cubed/gameplay/chunk.hpp"
|
||||||
|
#include "Cubed/gameplay/game_time.hpp"
|
||||||
#include "Cubed/gameplay/river_worm.hpp"
|
#include "Cubed/gameplay/river_worm.hpp"
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
@@ -39,12 +40,21 @@ private:
|
|||||||
std::unordered_map<ChunkPos, const Chunk*, ChunkPos::Hash>;
|
std::unordered_map<ChunkPos, const Chunk*, ChunkPos::Hash>;
|
||||||
using ChunkPosSet = std::unordered_set<ChunkPos, ChunkPos::Hash>;
|
using ChunkPosSet = std::unordered_set<ChunkPos, ChunkPos::Hash>;
|
||||||
using ChunkHashMap = std::unordered_map<ChunkPos, Chunk, ChunkPos::Hash>;
|
using ChunkHashMap = std::unordered_map<ChunkPos, Chunk, ChunkPos::Hash>;
|
||||||
|
|
||||||
glm::vec3 m_gen_player_pos{0.0f, 0.0f, 0.0f};
|
glm::vec3 m_gen_player_pos{0.0f, 0.0f, 0.0f};
|
||||||
ChunkHashMap m_chunks;
|
ChunkHashMap m_chunks;
|
||||||
std::unordered_map<std::size_t, Player> m_players;
|
std::unordered_map<std::size_t, Player> m_players;
|
||||||
std::vector<glm::vec4> m_planes;
|
std::vector<glm::vec4> m_planes;
|
||||||
|
|
||||||
std::thread m_gen_thread;
|
std::thread m_gen_thread;
|
||||||
|
std::thread m_server_thread;
|
||||||
|
|
||||||
|
std::stop_source m_server_stop_source;
|
||||||
|
|
||||||
|
std::atomic<int> m_per_tick_time = DEFAULT_PER_TICK_TIME; // ms
|
||||||
|
|
||||||
|
std::atomic<TickType> m_day_tick = 6000;
|
||||||
|
|
||||||
mutable std::mutex m_chunks_mutex;
|
mutable std::mutex m_chunks_mutex;
|
||||||
std::mutex m_gen_signal_mutex;
|
std::mutex m_gen_signal_mutex;
|
||||||
std::mutex m_new_chunk_queue_mutex;
|
std::mutex m_new_chunk_queue_mutex;
|
||||||
@@ -59,8 +69,12 @@ private:
|
|||||||
std::atomic<bool> m_is_rebuilding{false};
|
std::atomic<bool> m_is_rebuilding{false};
|
||||||
std::atomic<bool> m_chunk_gen_finished{false};
|
std::atomic<bool> m_chunk_gen_finished{false};
|
||||||
std::atomic<bool> m_could_gen{true};
|
std::atomic<bool> m_could_gen{true};
|
||||||
|
std::atomic<bool> m_tick_running{true};
|
||||||
std::atomic<int> m_rendering_distance{24};
|
std::atomic<int> m_rendering_distance{24};
|
||||||
std::atomic<float> m_chunk_gen_fraction{0.0f};
|
std::atomic<float> m_chunk_gen_fraction{0.0f};
|
||||||
|
|
||||||
|
std::atomic<TickType> m_game_ticks{0};
|
||||||
|
|
||||||
std::vector<ChunkPos> m_dirty_queue;
|
std::vector<ChunkPos> m_dirty_queue;
|
||||||
std::vector<ChunkRenderSnapshot> m_render_snapshots;
|
std::vector<ChunkRenderSnapshot> m_render_snapshots;
|
||||||
std::vector<std::pair<ChunkPos, Chunk>> m_new_chunk;
|
std::vector<std::pair<ChunkPos, Chunk>> m_new_chunk;
|
||||||
@@ -119,12 +133,25 @@ public:
|
|||||||
int rendering_distance() const;
|
int rendering_distance() const;
|
||||||
void rendering_distance(int rendering_distance);
|
void rendering_distance(int rendering_distance);
|
||||||
void start_gen_thread();
|
void start_gen_thread();
|
||||||
|
void start_server_thread();
|
||||||
void stop_gen_thread();
|
void stop_gen_thread();
|
||||||
|
void stop_server_thread();
|
||||||
|
void serever_run(std::stop_token stoken);
|
||||||
|
|
||||||
CaveCarver& cave_carcer();
|
CaveCarver& cave_carcer();
|
||||||
RiverWorm& river_worm();
|
RiverWorm& river_worm();
|
||||||
std::vector<glm::vec4>& planes();
|
std::vector<glm::vec4>& planes();
|
||||||
std::vector<ChunkRenderSnapshot>& render_snapshots();
|
std::vector<ChunkRenderSnapshot>& render_snapshots();
|
||||||
|
|
||||||
|
glm::vec3 sunlight_dir() const;
|
||||||
|
TickType game_tick() const;
|
||||||
|
TickType day_tick() const;
|
||||||
|
void day_tick(TickType tick);
|
||||||
|
int per_tick_time() const;
|
||||||
|
void per_tick_time(int ms);
|
||||||
|
|
||||||
|
bool is_tick_running() const;
|
||||||
|
void tick_running(bool run);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Cubed
|
} // namespace Cubed
|
||||||
|
|||||||
@@ -91,6 +91,51 @@ constexpr float TEX_COORDS[6][6][2] = {
|
|||||||
{0.0f, 1.0f}, // back left
|
{0.0f, 1.0f}, // back left
|
||||||
{0.0f, 0.0f}} // front left
|
{0.0f, 0.0f}} // front left
|
||||||
};
|
};
|
||||||
|
|
||||||
|
constexpr float NORMALS[6][6][3] = {
|
||||||
|
// ===== front (z = +1) =====
|
||||||
|
{{0.0f, 0.0f, 1.0f},
|
||||||
|
{0.0f, 0.0f, 1.0f},
|
||||||
|
{0.0f, 0.0f, 1.0f},
|
||||||
|
{0.0f, 0.0f, 1.0f},
|
||||||
|
{0.0f, 0.0f, 1.0f},
|
||||||
|
{0.0f, 0.0f, 1.0f}},
|
||||||
|
// ===== right (x = +1) =====
|
||||||
|
{{1.0f, 0.0f, 0.0f},
|
||||||
|
{1.0f, 0.0f, 0.0f},
|
||||||
|
{1.0f, 0.0f, 0.0f},
|
||||||
|
{1.0f, 0.0f, 0.0f},
|
||||||
|
{1.0f, 0.0f, 0.0f},
|
||||||
|
{1.0f, 0.0f, 0.0f}},
|
||||||
|
// ===== back (z = -1) =====
|
||||||
|
{{0.0f, 0.0f, -1.0f},
|
||||||
|
{0.0f, 0.0f, -1.0f},
|
||||||
|
{0.0f, 0.0f, -1.0f},
|
||||||
|
{0.0f, 0.0f, -1.0f},
|
||||||
|
{0.0f, 0.0f, -1.0f},
|
||||||
|
{0.0f, 0.0f, -1.0f}},
|
||||||
|
// ===== left (x = -1) =====
|
||||||
|
{{-1.0f, 0.0f, 0.0f},
|
||||||
|
{-1.0f, 0.0f, 0.0f},
|
||||||
|
{-1.0f, 0.0f, 0.0f},
|
||||||
|
{-1.0f, 0.0f, 0.0f},
|
||||||
|
{-1.0f, 0.0f, 0.0f},
|
||||||
|
{-1.0f, 0.0f, 0.0f}},
|
||||||
|
// ===== top (y = +1) =====
|
||||||
|
{{0.0f, 1.0f, 0.0f},
|
||||||
|
{0.0f, 1.0f, 0.0f},
|
||||||
|
{0.0f, 1.0f, 0.0f},
|
||||||
|
{0.0f, 1.0f, 0.0f},
|
||||||
|
{0.0f, 1.0f, 0.0f},
|
||||||
|
{0.0f, 1.0f, 0.0f}},
|
||||||
|
// ===== bottom (y = -1) =====
|
||||||
|
{{0.0f, -1.0f, 0.0f},
|
||||||
|
{0.0f, -1.0f, 0.0f},
|
||||||
|
{0.0f, -1.0f, 0.0f},
|
||||||
|
{0.0f, -1.0f, 0.0f},
|
||||||
|
{0.0f, -1.0f, 0.0f},
|
||||||
|
{0.0f, -1.0f, 0.0f}}};
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
constexpr float CUBE_VER[24] = {0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0,
|
constexpr float CUBE_VER[24] = {0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0,
|
||||||
0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0,
|
0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0,
|
||||||
@@ -148,6 +193,24 @@ constexpr float CROSS_TEX_COORDS[2][6][2] = {
|
|||||||
{1.0f, 1.0f}, // bottom right
|
{1.0f, 1.0f}, // bottom right
|
||||||
{0.0f, 1.0f}}, // bottom left
|
{0.0f, 1.0f}}, // bottom left
|
||||||
};
|
};
|
||||||
|
|
||||||
|
constexpr float CROSS_NORMALS[2][6][3] = {
|
||||||
|
// ===== Plane 1: upward =====
|
||||||
|
{{0.0f, 1.0f, 0.0f},
|
||||||
|
{0.0f, 1.0f, 0.0f},
|
||||||
|
{0.0f, 1.0f, 0.0f},
|
||||||
|
{0.0f, 1.0f, 0.0f},
|
||||||
|
{0.0f, 1.0f, 0.0f},
|
||||||
|
{0.0f, 1.0f, 0.0f}},
|
||||||
|
|
||||||
|
// ===== Plane 2: upward =====
|
||||||
|
{{0.0f, 1.0f, 0.0f},
|
||||||
|
{0.0f, 1.0f, 0.0f},
|
||||||
|
{0.0f, 1.0f, 0.0f},
|
||||||
|
{0.0f, 1.0f, 0.0f},
|
||||||
|
{0.0f, 1.0f, 0.0f},
|
||||||
|
{0.0f, 1.0f, 0.0f}}};
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
constexpr float QUAD_VERTICES[] = {
|
constexpr float QUAD_VERTICES[] = {
|
||||||
@@ -156,10 +219,11 @@ constexpr float QUAD_VERTICES[] = {
|
|||||||
|
|
||||||
-1.0f, 1.0f, 0.0f, 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f};
|
-1.0f, 1.0f, 0.0f, 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f};
|
||||||
|
|
||||||
struct Vertex {
|
struct Vertex3D {
|
||||||
float x = 0.0f, y = 0.0f, z = 0.0f;
|
float x = 0.0f, y = 0.0f, z = 0.0f;
|
||||||
float s = 0.0f, t = 0.0f;
|
float s = 0.0f, t = 0.0f;
|
||||||
float layer = 0.0f;
|
float layer = 0.0f;
|
||||||
|
float nx = 0.0f, ny = 0.0f, nz = 0.0f;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Vertex2D {
|
struct Vertex2D {
|
||||||
|
|||||||
@@ -28,13 +28,35 @@ public:
|
|||||||
void update_fov(float fov);
|
void update_fov(float fov);
|
||||||
void update_proj_matrix(float aspect, float width, float height);
|
void update_proj_matrix(float aspect, float width, float height);
|
||||||
void updata_framebuffer(int width, int height);
|
void updata_framebuffer(int width, int height);
|
||||||
|
float& ambient_strength();
|
||||||
|
|
||||||
|
bool& discard_transparent();
|
||||||
|
bool& shader_on();
|
||||||
|
int& shadow_mode();
|
||||||
|
int& light_cull_face();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static constexpr glm::vec3 SUNLIGHT_COLOR{1.0f, 1.0f, 1.0f};
|
||||||
|
static constexpr glm::vec3 SUN_COLOR{1.00f, 0.95f, 0.80f};
|
||||||
|
static constexpr glm::vec3 MOON_COLOR{0.75f, 0.80f, 1.00f};
|
||||||
|
static constexpr glm::vec3 SKY_COLOR{0.529, 0.808, 0.922};
|
||||||
|
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;
|
||||||
|
|
||||||
const Camera& m_camera;
|
const Camera& m_camera;
|
||||||
DevPanel& m_dev_panel;
|
DevPanel& m_dev_panel;
|
||||||
const TextureManager& m_texture_manager;
|
const TextureManager& m_texture_manager;
|
||||||
World& m_world;
|
World& m_world;
|
||||||
|
|
||||||
|
bool m_discard_tranparent = true;
|
||||||
|
bool m_shader_on = true;
|
||||||
|
int m_shadow_mode = 0;
|
||||||
|
int m_light_cull_face = 0;
|
||||||
float m_aspect = 0.0f;
|
float m_aspect = 0.0f;
|
||||||
float m_fov = DEFAULT_FOV;
|
float m_fov = DEFAULT_FOV;
|
||||||
|
|
||||||
@@ -43,7 +65,7 @@ private:
|
|||||||
float m_width = 0.0f;
|
float m_width = 0.0f;
|
||||||
float m_height = 0.0f;
|
float m_height = 0.0f;
|
||||||
|
|
||||||
glm::mat4 m_p_mat, m_v_mat, m_m_mat, m_mv_mat, m_mvp_mat;
|
glm::mat4 m_p_mat, m_v_mat, m_m_mat, m_mv_mat, m_mvp_mat, m_norm_mat;
|
||||||
|
|
||||||
GLuint m_mv_loc = 0;
|
GLuint m_mv_loc = 0;
|
||||||
GLuint m_proj_loc = 0;
|
GLuint m_proj_loc = 0;
|
||||||
@@ -62,18 +84,29 @@ private:
|
|||||||
GLuint m_accum_texture = 0;
|
GLuint m_accum_texture = 0;
|
||||||
GLuint m_reveal_texture = 0;
|
GLuint m_reveal_texture = 0;
|
||||||
GLuint m_oit_depth_render_buffer = 0;
|
GLuint m_oit_depth_render_buffer = 0;
|
||||||
|
|
||||||
|
GLuint m_depth_map_fbo = 0;
|
||||||
|
GLuint m_depth_map_texture = 0;
|
||||||
|
|
||||||
GLuint m_quad_vbo = 0;
|
GLuint m_quad_vbo = 0;
|
||||||
|
|
||||||
glm::mat4 m_ui_proj;
|
glm::mat4 m_ui_proj;
|
||||||
glm::mat4 m_ui_m_matrix;
|
glm::mat4 m_ui_m_matrix;
|
||||||
std::unordered_map<std::size_t, Shader> m_shaders;
|
std::unordered_map<std::size_t, Shader> m_shaders;
|
||||||
|
|
||||||
|
glm::vec3 m_blend_from_sundir;
|
||||||
|
glm::vec3 m_blend_to_sundir;
|
||||||
|
float m_blend_t = 1.0f;
|
||||||
|
bool m_blend_initialized = false;
|
||||||
|
static constexpr float BLEND_DURATION = 0.15f;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
0 - quad vao
|
0 - quad vao
|
||||||
1 - sky vao
|
1 - sky vao
|
||||||
2 - outline vao
|
2 - outline vao
|
||||||
3 - ui vao
|
3 - ui vao
|
||||||
4 - text vao
|
4 - text vao
|
||||||
|
|
||||||
*/
|
*/
|
||||||
std::vector<GLuint> m_vao;
|
std::vector<GLuint> m_vao;
|
||||||
std::vector<Vertex2D> m_ui;
|
std::vector<Vertex2D> m_ui;
|
||||||
@@ -88,6 +121,11 @@ private:
|
|||||||
void render_world();
|
void render_world();
|
||||||
void render_underwater();
|
void render_underwater();
|
||||||
void render_dev_panel();
|
void render_dev_panel();
|
||||||
|
|
||||||
|
glm::vec3 quantize_sun_direction(const glm::vec3& sundir,
|
||||||
|
float angle_step_deg) const;
|
||||||
|
glm::vec3 get_smoothed_shadow_sundir(const glm::vec3& raw_shadow_sundir,
|
||||||
|
float dt);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Cubed
|
} // namespace Cubed
|
||||||
@@ -12,6 +12,8 @@ float smootherstep(float edge0, float edge1, float x);
|
|||||||
bool is_aabb_in_frustum(const glm::vec3& center, const glm::vec3& half_extents,
|
bool is_aabb_in_frustum(const glm::vec3& center, const glm::vec3& half_extents,
|
||||||
const std::vector<glm::vec4>& planes);
|
const std::vector<glm::vec4>& planes);
|
||||||
float deterministic_random(int x, int z, uint64_t seed);
|
float deterministic_random(int x, int z, uint64_t seed);
|
||||||
|
glm::vec3 slerp(const glm::vec3& from, const glm::vec3& to, float t);
|
||||||
|
|
||||||
} // namespace Math
|
} // namespace Math
|
||||||
|
|
||||||
} // namespace Cubed
|
} // namespace Cubed
|
||||||
@@ -60,4 +60,6 @@ const glm::vec3& Camera::get_camera_pos() const { return m_camera_pos; }
|
|||||||
|
|
||||||
bool Camera::is_under_water() const { return m_under_water; }
|
bool Camera::is_under_water() const { return m_under_water; }
|
||||||
|
|
||||||
|
glm::vec3 Camera::get_camera_front() const { return m_player->get_front(); }
|
||||||
|
|
||||||
} // namespace Cubed
|
} // namespace Cubed
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ void DevPanel::render() {
|
|||||||
show_world_tab_item();
|
show_world_tab_item();
|
||||||
show_player_tab_item();
|
show_player_tab_item();
|
||||||
show_items_tab_item();
|
show_items_tab_item();
|
||||||
|
show_shader_tab_item();
|
||||||
show_about_table_bar();
|
show_about_table_bar();
|
||||||
|
|
||||||
ImGui::EndTabBar();
|
ImGui::EndTabBar();
|
||||||
@@ -107,6 +108,7 @@ void DevPanel::show_about_table_bar() {
|
|||||||
ImGui::Text("FreeType");
|
ImGui::Text("FreeType");
|
||||||
ImGui::Text("toml++");
|
ImGui::Text("toml++");
|
||||||
ImGui::Text("Dear ImGui");
|
ImGui::Text("Dear ImGui");
|
||||||
|
ImGui::Text("Tbb");
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
ImGui::Text("Special Thanks");
|
ImGui::Text("Special Thanks");
|
||||||
ImGui::Text("TANGERIME");
|
ImGui::Text("TANGERIME");
|
||||||
@@ -263,6 +265,31 @@ void DevPanel::show_biome_table_bar() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DevPanel::show_time_table_bar() {
|
||||||
|
World& world = m_app.world();
|
||||||
|
ImGui::Text("Game Tick %llu", world.game_tick());
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::Text("Day Tick %llu", world.day_tick());
|
||||||
|
m_tick_frezze = !world.is_tick_running();
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::Checkbox("Tick Frezze", &m_tick_frezze)) {
|
||||||
|
world.tick_running(!m_tick_frezze);
|
||||||
|
}
|
||||||
|
if (ImGui::SliderInt("SetDayTick", &m_pre_set_day_tick, 0, DAY_TIME)) {
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::Button("Set##DayTick")) {
|
||||||
|
world.day_tick(static_cast<TickType>(m_pre_set_day_tick));
|
||||||
|
}
|
||||||
|
ImGui::Text("MSPT %d", world.per_tick_time());
|
||||||
|
if (ImGui::SliderInt("SetMSPT", &m_pre_set_tick_speed, 1, 200)) {
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::Button("Set##MSPT")) {
|
||||||
|
world.per_tick_time(m_pre_set_tick_speed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DevPanel::show_cave_table_bar() {
|
void DevPanel::show_cave_table_bar() {
|
||||||
auto& cave_carcer = m_app.world().cave_carcer();
|
auto& cave_carcer = m_app.world().cave_carcer();
|
||||||
|
|
||||||
@@ -336,6 +363,7 @@ void DevPanel::show_settings_tab_item() {
|
|||||||
static_cast<double>(m_config.mouse_sensitivity));
|
static_cast<double>(m_config.mouse_sensitivity));
|
||||||
m_player->hot_reload();
|
m_player->hot_reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui::SliderInt("Distance", &m_config.rendering_distance, 2,
|
if (ImGui::SliderInt("Distance", &m_config.rendering_distance, 2,
|
||||||
128)) {
|
128)) {
|
||||||
Config::get().set("world.rendering_distance",
|
Config::get().set("world.rendering_distance",
|
||||||
@@ -457,6 +485,10 @@ void DevPanel::show_world_tab_item() {
|
|||||||
ImGui::Text("Chunk Build Progress\n");
|
ImGui::Text("Chunk Build Progress\n");
|
||||||
ImGui::ProgressBar(m_app.world().chunk_gen_fraction());
|
ImGui::ProgressBar(m_app.world().chunk_gen_fraction());
|
||||||
if (ImGui::BeginTabBar("World Settings")) {
|
if (ImGui::BeginTabBar("World Settings")) {
|
||||||
|
if (ImGui::BeginTabItem("Time")) {
|
||||||
|
show_time_table_bar();
|
||||||
|
ImGui::EndTabItem();
|
||||||
|
}
|
||||||
if (ImGui::BeginTabItem("Cave")) {
|
if (ImGui::BeginTabItem("Cave")) {
|
||||||
show_cave_table_bar();
|
show_cave_table_bar();
|
||||||
ImGui::EndTabItem();
|
ImGui::EndTabItem();
|
||||||
@@ -577,6 +609,27 @@ void DevPanel::show_items_tab_item() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DevPanel::show_shader_tab_item() {
|
||||||
|
|
||||||
|
static const char* shader_mode[] = {"Rotated Poisson Disk PCF",
|
||||||
|
"3x3 Square Grid PCF", "PCF off"};
|
||||||
|
static const char* cull_face_mode[] = {"Front", "Back"};
|
||||||
|
if (ImGui::BeginTabItem("shader")) {
|
||||||
|
ImGui::Checkbox("Shader", &m_app.renderer().shader_on());
|
||||||
|
if (ImGui::SliderFloat("AmbientStrength",
|
||||||
|
&m_app.renderer().ambient_strength(), 0.0f,
|
||||||
|
0.35f))
|
||||||
|
;
|
||||||
|
ImGui::Checkbox("Discard Transparent",
|
||||||
|
&m_app.renderer().discard_transparent());
|
||||||
|
ImGui::Combo("ShaderMode", &m_app.renderer().shadow_mode(), shader_mode,
|
||||||
|
IM_ARRAYSIZE(shader_mode));
|
||||||
|
ImGui::Combo("LightCullFaceMode", &m_app.renderer().light_cull_face(),
|
||||||
|
cull_face_mode, IM_ARRAYSIZE(cull_face_mode));
|
||||||
|
ImGui::EndTabItem();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DevPanel::update_config_view() {
|
void DevPanel::update_config_view() {
|
||||||
auto config = Config::get();
|
auto config = Config::get();
|
||||||
m_config.fov =
|
m_config.fov =
|
||||||
|
|||||||
@@ -366,13 +366,18 @@ void Chunk::gen_vertices(const OptionalBlockVectorArray& neighbor_block) {
|
|||||||
cur_id);
|
cur_id);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < 6; i++) {
|
for (int i = 0; i < 6; i++) {
|
||||||
Vertex vex = {
|
Vertex3D vex = {
|
||||||
VERTICES_POS[face][i][0] + (float)world_x * 1.0f,
|
VERTICES_POS[face][i][0] + (float)world_x * 1.0f,
|
||||||
VERTICES_POS[face][i][1] + (float)world_y * 1.0f,
|
VERTICES_POS[face][i][1] + (float)world_y * 1.0f,
|
||||||
VERTICES_POS[face][i][2] + (float)world_z * 1.0f,
|
VERTICES_POS[face][i][2] + (float)world_z * 1.0f,
|
||||||
TEX_COORDS[face][i][0],
|
TEX_COORDS[face][i][0],
|
||||||
TEX_COORDS[face][i][1],
|
TEX_COORDS[face][i][1],
|
||||||
static_cast<float>(cur_id * 6 + face)
|
|
||||||
|
static_cast<float>(cur_id * 6 + face),
|
||||||
|
|
||||||
|
NORMALS[face][i][0],
|
||||||
|
NORMALS[face][i][1],
|
||||||
|
NORMALS[face][i][2]
|
||||||
|
|
||||||
};
|
};
|
||||||
if (BlockManager::is_transparent(cur_id)) {
|
if (BlockManager::is_transparent(cur_id)) {
|
||||||
@@ -413,13 +418,16 @@ void Chunk::gen_cross_plane_vertices(int world_x, int world_y, int world_z,
|
|||||||
}
|
}
|
||||||
for (int face = 0; face < 2; face++) {
|
for (int face = 0; face < 2; face++) {
|
||||||
for (int i = 0; i < 6; i++) {
|
for (int i = 0; i < 6; i++) {
|
||||||
Vertex vex = {
|
Vertex3D vex = {
|
||||||
CROSS_VERTICES_POS[face][i][0] + (float)world_x * 1.0f,
|
CROSS_VERTICES_POS[face][i][0] + (float)world_x * 1.0f,
|
||||||
CROSS_VERTICES_POS[face][i][1] + (float)world_y * 1.0f,
|
CROSS_VERTICES_POS[face][i][1] + (float)world_y * 1.0f,
|
||||||
CROSS_VERTICES_POS[face][i][2] + (float)world_z * 1.0f,
|
CROSS_VERTICES_POS[face][i][2] + (float)world_z * 1.0f,
|
||||||
CROSS_TEX_COORDS[face][i][0],
|
CROSS_TEX_COORDS[face][i][0],
|
||||||
CROSS_TEX_COORDS[face][i][1],
|
CROSS_TEX_COORDS[face][i][1],
|
||||||
static_cast<float>(BlockManager::cross_plane_index(id))
|
static_cast<float>(BlockManager::cross_plane_index(id)),
|
||||||
|
CROSS_NORMALS[face][i][0],
|
||||||
|
CROSS_NORMALS[face][i][1],
|
||||||
|
CROSS_NORMALS[face][i][2]
|
||||||
|
|
||||||
};
|
};
|
||||||
m_vertex_data[1].m_vertices.emplace_back(vex);
|
m_vertex_data[1].m_vertices.emplace_back(vex);
|
||||||
|
|||||||
@@ -41,18 +41,20 @@ void VertexData::upload() {
|
|||||||
}
|
}
|
||||||
glBindVertexArray(m_vao);
|
glBindVertexArray(m_vao);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
|
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
|
||||||
glBufferData(GL_ARRAY_BUFFER, m_vertices.size() * sizeof(Vertex),
|
glBufferData(GL_ARRAY_BUFFER, m_vertices.size() * sizeof(Vertex3D),
|
||||||
m_vertices.data(), GL_DYNAMIC_DRAW);
|
m_vertices.data(), GL_DYNAMIC_DRAW);
|
||||||
|
|
||||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex3D), (void*)0);
|
||||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex),
|
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex3D),
|
||||||
(void*)offsetof(Vertex, s));
|
(void*)offsetof(Vertex3D, s));
|
||||||
glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, sizeof(Vertex),
|
glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, sizeof(Vertex3D),
|
||||||
(void*)offsetof(Vertex, layer));
|
(void*)offsetof(Vertex3D, layer));
|
||||||
|
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex3D),
|
||||||
|
(void*)offsetof(Vertex3D, nx));
|
||||||
glEnableVertexAttribArray(0);
|
glEnableVertexAttribArray(0);
|
||||||
glEnableVertexAttribArray(1);
|
glEnableVertexAttribArray(1);
|
||||||
glEnableVertexAttribArray(2);
|
glEnableVertexAttribArray(2);
|
||||||
|
glEnableVertexAttribArray(3);
|
||||||
|
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
|||||||
@@ -6,6 +6,9 @@
|
|||||||
#include "Cubed/tools/cubed_hash.hpp"
|
#include "Cubed/tools/cubed_hash.hpp"
|
||||||
|
|
||||||
#include <execution>
|
#include <execution>
|
||||||
|
#include <glm/gtc/constants.hpp>
|
||||||
|
#include <numbers>
|
||||||
|
using namespace std::chrono;
|
||||||
|
|
||||||
namespace Cubed {
|
namespace Cubed {
|
||||||
|
|
||||||
@@ -18,6 +21,7 @@ World::World() {}
|
|||||||
|
|
||||||
World::~World() {
|
World::~World() {
|
||||||
stop_gen_thread();
|
stop_gen_thread();
|
||||||
|
stop_server_thread();
|
||||||
m_chunks.clear();
|
m_chunks.clear();
|
||||||
{
|
{
|
||||||
std::lock_guard lk(m_delete_vbo_mutex);
|
std::lock_guard lk(m_delete_vbo_mutex);
|
||||||
@@ -86,6 +90,8 @@ void World::init_world() {
|
|||||||
auto d = std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1);
|
auto d = std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1);
|
||||||
Logger::info("Chunk Block Init Finish, Time Consuming: {}", d);
|
Logger::info("Chunk Block Init Finish, Time Consuming: {}", d);
|
||||||
|
|
||||||
|
start_server_thread();
|
||||||
|
|
||||||
Logger::info("TestPlayer Create Finish");
|
Logger::info("TestPlayer Create Finish");
|
||||||
}
|
}
|
||||||
void World::init_chunks() {
|
void World::init_chunks() {
|
||||||
@@ -727,6 +733,11 @@ void World::start_gen_thread() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void World::start_server_thread() {
|
||||||
|
m_server_thread = std::thread(
|
||||||
|
[this]() { serever_run(m_server_stop_source.get_token()); });
|
||||||
|
}
|
||||||
|
|
||||||
void World::stop_gen_thread() {
|
void World::stop_gen_thread() {
|
||||||
m_gen_running = false;
|
m_gen_running = false;
|
||||||
m_gen_cv.notify_all();
|
m_gen_cv.notify_all();
|
||||||
@@ -736,6 +747,25 @@ void World::stop_gen_thread() {
|
|||||||
Logger::info("Gen Thread Stopped");
|
Logger::info("Gen Thread Stopped");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void World::stop_server_thread() {
|
||||||
|
m_server_stop_source.request_stop();
|
||||||
|
if (m_server_thread.joinable()) {
|
||||||
|
m_server_thread.join();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void World::serever_run(std::stop_token stoken) {
|
||||||
|
Logger::info("Server Thread Started!");
|
||||||
|
while (!stoken.stop_requested()) {
|
||||||
|
std::this_thread::sleep_for(milliseconds(m_per_tick_time));
|
||||||
|
if (m_tick_running) {
|
||||||
|
++m_game_ticks;
|
||||||
|
m_day_tick = (m_day_tick + 1) % DAY_TIME;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Logger::info("Server Thread Stopped!");
|
||||||
|
}
|
||||||
|
|
||||||
void World::need_gen() {
|
void World::need_gen() {
|
||||||
if (!m_could_gen) {
|
if (!m_could_gen) {
|
||||||
Logger::warn("It is generating or consuming new chunks");
|
Logger::warn("It is generating or consuming new chunks");
|
||||||
@@ -1006,4 +1036,49 @@ std::vector<glm::vec4>& World::planes() { return m_planes; }
|
|||||||
std::vector<ChunkRenderSnapshot>& World::render_snapshots() {
|
std::vector<ChunkRenderSnapshot>& World::render_snapshots() {
|
||||||
return m_render_snapshots;
|
return m_render_snapshots;
|
||||||
};
|
};
|
||||||
|
/*
|
||||||
|
glm::vec3 World::sunlight_dir() const {
|
||||||
|
float t = static_cast<float>(m_day_tick) / DAY_TIME;
|
||||||
|
|
||||||
|
float azimuth = glm::radians(90.0f - t * 360.0f);
|
||||||
|
|
||||||
|
float altitude =
|
||||||
|
glm::half_pi<float>() * sin((t - 0.25f) * glm::two_pi<float>());
|
||||||
|
|
||||||
|
glm::vec3 dir{cos(altitude) * cos(azimuth), sin(altitude),
|
||||||
|
cos(altitude) * sin(azimuth)};
|
||||||
|
|
||||||
|
return glm::normalize(-dir);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
glm::vec3 World::sunlight_dir() const {
|
||||||
|
float altitude = sin((m_day_tick - 6 * PER_HOUR) /
|
||||||
|
static_cast<float>(DAY_TIME / 2) * std::numbers::pi) *
|
||||||
|
90.0f;
|
||||||
|
|
||||||
|
float t = static_cast<float>(m_day_tick) / DAY_TIME;
|
||||||
|
float azimuth = 90.0f - 360.0f * (t - 0.25f);
|
||||||
|
|
||||||
|
float alt = glm::radians(altitude);
|
||||||
|
float az = glm::radians(azimuth);
|
||||||
|
glm::vec3 dir;
|
||||||
|
dir.x = cos(alt) * sin(az);
|
||||||
|
dir.y = sin(alt);
|
||||||
|
dir.z = cos(alt) * cos(az);
|
||||||
|
|
||||||
|
return glm::normalize(-dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
TickType World::game_tick() const { return m_game_ticks.load(); }
|
||||||
|
TickType World::day_tick() const { return m_day_tick.load(); }
|
||||||
|
void World::day_tick(TickType tick) {
|
||||||
|
tick %= DAY_TIME;
|
||||||
|
m_day_tick = tick;
|
||||||
|
}
|
||||||
|
int World::per_tick_time() const { return m_per_tick_time.load(); }
|
||||||
|
void World::per_tick_time(int ms) { m_per_tick_time = ms; }
|
||||||
|
|
||||||
|
bool World::is_tick_running() const { return m_tick_running.load(); }
|
||||||
|
void World::tick_running(bool run) { m_tick_running = run; }
|
||||||
} // namespace Cubed
|
} // namespace Cubed
|
||||||
255
src/renderer.cpp
255
src/renderer.cpp
@@ -18,6 +18,7 @@
|
|||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
#include <format>
|
#include <format>
|
||||||
#include <glm/gtc/type_ptr.hpp>
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
|
|
||||||
namespace Cubed {
|
namespace Cubed {
|
||||||
|
|
||||||
Renderer::Renderer(const Camera& camera, World& world,
|
Renderer::Renderer(const Camera& camera, World& world,
|
||||||
@@ -42,6 +43,9 @@ Renderer::~Renderer() {
|
|||||||
glDeleteTextures(1, &m_accum_texture);
|
glDeleteTextures(1, &m_accum_texture);
|
||||||
glDeleteTextures(1, &m_reveal_texture);
|
glDeleteTextures(1, &m_reveal_texture);
|
||||||
glDeleteRenderbuffers(1, &m_oit_depth_render_buffer);
|
glDeleteRenderbuffers(1, &m_oit_depth_render_buffer);
|
||||||
|
|
||||||
|
glDeleteFramebuffers(1, &m_depth_map_fbo);
|
||||||
|
glDeleteTextures(1, &m_depth_map_texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::hot_reload() {
|
void Renderer::hot_reload() {
|
||||||
@@ -76,6 +80,8 @@ void Renderer::init() {
|
|||||||
Shader composite_block_shader{"composite",
|
Shader composite_block_shader{"composite",
|
||||||
"shaders/block_composite_v_shader.glsl",
|
"shaders/block_composite_v_shader.glsl",
|
||||||
"shaders/block_composite_f_shader.glsl"};
|
"shaders/block_composite_f_shader.glsl"};
|
||||||
|
Shader depth_shader{"depth_shader", "shaders/depth_shader.glsl",
|
||||||
|
"shaders/depth_fragment_shader.glsl"};
|
||||||
m_shaders.insert({world_shader.hash(), std::move(world_shader)});
|
m_shaders.insert({world_shader.hash(), std::move(world_shader)});
|
||||||
m_shaders.insert({outline_shader.hash(), std::move(outline_shader)});
|
m_shaders.insert({outline_shader.hash(), std::move(outline_shader)});
|
||||||
m_shaders.insert({sky_shdaer.hash(), std::move(sky_shdaer)});
|
m_shaders.insert({sky_shdaer.hash(), std::move(sky_shdaer)});
|
||||||
@@ -86,6 +92,7 @@ void Renderer::init() {
|
|||||||
m_shaders.insert({accum_shader.hash(), std::move(accum_shader)});
|
m_shaders.insert({accum_shader.hash(), std::move(accum_shader)});
|
||||||
m_shaders.insert(
|
m_shaders.insert(
|
||||||
{composite_block_shader.hash(), std::move(composite_block_shader)});
|
{composite_block_shader.hash(), std::move(composite_block_shader)});
|
||||||
|
m_shaders.insert({depth_shader.hash(), std::move(depth_shader)});
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
glDepthFunc(GL_LEQUAL);
|
glDepthFunc(GL_LEQUAL);
|
||||||
|
|
||||||
@@ -192,8 +199,8 @@ void Renderer::init_text() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::render() {
|
void Renderer::render() {
|
||||||
|
glDisable(GL_FRAMEBUFFER_SRGB);
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
|
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
|
||||||
|
|
||||||
glClearColor(0.0, 0.0, 0.0, 1.0);
|
glClearColor(0.0, 0.0, 0.0, 1.0);
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
@@ -202,12 +209,13 @@ void Renderer::render() {
|
|||||||
render_outline();
|
render_outline();
|
||||||
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
glEnable(GL_FRAMEBUFFER_SRGB);
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0);
|
glClearColor(0.0f, 0.0f, 0.0f, 1.0);
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
render_underwater();
|
render_underwater();
|
||||||
|
glDisable(GL_FRAMEBUFFER_SRGB);
|
||||||
render_ui();
|
render_ui();
|
||||||
render_text();
|
render_text();
|
||||||
render_dev_panel();
|
render_dev_panel();
|
||||||
@@ -257,13 +265,44 @@ void Renderer::render_sky() {
|
|||||||
|
|
||||||
glUniformMatrix4fv(m_mv_loc, 1, GL_FALSE, glm::value_ptr(m_mv_mat));
|
glUniformMatrix4fv(m_mv_loc, 1, GL_FALSE, glm::value_ptr(m_mv_mat));
|
||||||
glUniformMatrix4fv(m_proj_loc, 1, GL_FALSE, glm::value_ptr(m_p_mat));
|
glUniformMatrix4fv(m_proj_loc, 1, GL_FALSE, glm::value_ptr(m_p_mat));
|
||||||
|
glUniform3fv(shader.loc("color"), 1, glm::value_ptr(SKY_COLOR));
|
||||||
glBindVertexArray(m_vao[1]);
|
glBindVertexArray(m_vao[1]);
|
||||||
|
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
|
// draw sun and moon
|
||||||
|
glDepthMask(GL_FALSE);
|
||||||
|
|
||||||
|
glBindVertexArray(m_vao[0]);
|
||||||
|
// draw sum
|
||||||
|
glm::vec3 sun_pos = m_camera.get_camera_pos() +
|
||||||
|
normalize(-m_world.sunlight_dir()) * (FAR_PLANE * 0.9f);
|
||||||
|
glm::vec3 sun_view_pos = glm::vec3(m_v_mat * glm::vec4(sun_pos, 1.0f));
|
||||||
|
m_mv_mat = glm::translate(glm::mat4(1.0f), sun_view_pos) *
|
||||||
|
glm::scale(glm::mat4(1.0f), glm::vec3(SUN_SIZE)) *
|
||||||
|
glm::translate(glm::mat4(1.0f), glm::vec3(-0.5f, -0.5f, 0.0f));
|
||||||
|
glUniformMatrix4fv(m_mv_loc, 1, GL_FALSE, glm::value_ptr(m_mv_mat));
|
||||||
|
glUniformMatrix4fv(m_proj_loc, 1, GL_FALSE, glm::value_ptr(m_p_mat));
|
||||||
|
glUniform3fv(shader.loc("color"), 1, glm::value_ptr(SUN_COLOR));
|
||||||
|
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||||
|
|
||||||
|
glm::vec3 moon_pos = m_camera.get_camera_pos() +
|
||||||
|
normalize(m_world.sunlight_dir()) * (FAR_PLANE * 0.9f);
|
||||||
|
glm::vec3 moon_view_pos = glm::vec3(m_v_mat * glm::vec4(moon_pos, 1.0f));
|
||||||
|
m_mv_mat = glm::translate(glm::mat4(1.0f), moon_view_pos) *
|
||||||
|
glm::scale(glm::mat4(1.0f), glm::vec3(MOON_SIZE)) *
|
||||||
|
glm::translate(glm::mat4(1.0f), glm::vec3(-0.5f, -0.5f, 0.0f));
|
||||||
|
glUniformMatrix4fv(m_mv_loc, 1, GL_FALSE, glm::value_ptr(m_mv_mat));
|
||||||
|
glUniformMatrix4fv(m_proj_loc, 1, GL_FALSE, glm::value_ptr(m_p_mat));
|
||||||
|
glUniform3fv(shader.loc("color"), 1, glm::value_ptr(MOON_COLOR));
|
||||||
|
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||||
|
|
||||||
|
glDepthMask(GL_TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::render_text() {
|
void Renderer::render_text() {
|
||||||
@@ -343,7 +382,8 @@ void Renderer::update_fov(float fov) {
|
|||||||
|
|
||||||
void Renderer::update_proj_matrix(float aspect, float width, float height) {
|
void Renderer::update_proj_matrix(float aspect, float width, float height) {
|
||||||
m_aspect = aspect;
|
m_aspect = aspect;
|
||||||
m_p_mat = glm::perspective(glm::radians(m_fov), aspect, 0.1f, 1000.0f);
|
m_p_mat =
|
||||||
|
glm::perspective(glm::radians(m_fov), aspect, NEAR_PLANE, FAR_PLANE);
|
||||||
m_ui_proj = glm::ortho(0.0f, width, height, 0.0f, -1.0f, 1.0f);
|
m_ui_proj = glm::ortho(0.0f, width, height, 0.0f, -1.0f, 1.0f);
|
||||||
// scale and then translate
|
// scale and then translate
|
||||||
m_ui_m_matrix =
|
m_ui_m_matrix =
|
||||||
@@ -423,11 +463,146 @@ void Renderer::updata_framebuffer(int width, int height) {
|
|||||||
}
|
}
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
|
||||||
|
// depth map fbo
|
||||||
|
if (m_depth_map_fbo == 0) {
|
||||||
|
glGenFramebuffers(1, &m_depth_map_fbo);
|
||||||
|
}
|
||||||
|
glDeleteTextures(1, &m_depth_map_texture);
|
||||||
|
glGenTextures(1, &m_depth_map_texture);
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, m_depth_map_texture);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, DEPTH_MAP_SIZE,
|
||||||
|
DEPTH_MAP_SIZE, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
|
||||||
|
float border_color[] = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||||
|
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border_color);
|
||||||
|
// Manually compare shadows
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
|
||||||
|
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE,
|
||||||
|
// GL_COMPARE_REF_TO_TEXTURE);
|
||||||
|
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, m_depth_map_fbo);
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D,
|
||||||
|
m_depth_map_texture, 0);
|
||||||
|
glDrawBuffer(GL_NONE);
|
||||||
|
glReadBuffer(GL_NONE);
|
||||||
|
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
||||||
|
Logger::error("FBO incomplete after resize!");
|
||||||
|
} else {
|
||||||
|
Logger::info("Frame Buffer Complete!");
|
||||||
|
}
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
m_width = width;
|
m_width = width;
|
||||||
m_height = height;
|
m_height = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::render_world() {
|
void Renderer::render_world() {
|
||||||
|
// shader map
|
||||||
|
glm::mat4 light_space_matrix;
|
||||||
|
auto& m_render_snapshots = m_world.render_snapshots();
|
||||||
|
auto& camera_pos = m_camera.get_camera_pos();
|
||||||
|
if (m_shader_on) {
|
||||||
|
const auto& depth_shader = 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 sundir = glm::normalize(m_world.sunlight_dir());
|
||||||
|
glm::vec3 raw_shadow_sundir =
|
||||||
|
quantize_sun_direction(sundir, ANGLE_STEP_DEG);
|
||||||
|
glm::vec3 shadow_sundir =
|
||||||
|
get_smoothed_shadow_sundir(raw_shadow_sundir, m_delta_time);
|
||||||
|
glm::vec3 up = fabs(shadow_sundir.y) > 0.99f ? glm::vec3(0, 0, 1)
|
||||||
|
: glm::vec3(0, 1, 0);
|
||||||
|
|
||||||
|
glm::mat4 light_basis = glm::lookAt(glm::vec3(0.0f), shadow_sundir, up);
|
||||||
|
float 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_sundir * 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;
|
||||||
|
glUniformMatrix4fv(depth_shader.loc("lightSpaceMatrix"), 1, GL_FALSE,
|
||||||
|
glm::value_ptr(light_space_matrix));
|
||||||
|
glUniform1i(depth_shader.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);
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, m_depth_map_fbo);
|
||||||
|
glClear(GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
glActiveTexture(GL_TEXTURE1);
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
for (const auto& snapshot : m_render_snapshots) {
|
||||||
|
glBindTexture(GL_TEXTURE_2D_ARRAY,
|
||||||
|
m_texture_manager.get_texture_array());
|
||||||
|
glBindVertexArray(snapshot.normal_vao);
|
||||||
|
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, snapshot.normal_vertices_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
// cross_plane and discard
|
||||||
|
|
||||||
|
for (const auto& snapshot : m_render_snapshots) {
|
||||||
|
|
||||||
|
glm::vec2 camera_pos_xz{camera_pos.x, camera_pos.z};
|
||||||
|
if (snapshot.cross_vertices_count != 0) {
|
||||||
|
glm::vec2 center_xz{snapshot.center.x, snapshot.center.z};
|
||||||
|
float dist2d = glm::distance(camera_pos_xz, center_xz);
|
||||||
|
if (dist2d <= CROSS_PLANE_DISTANCE * 16) {
|
||||||
|
glBindTexture(GL_TEXTURE_2D_ARRAY,
|
||||||
|
m_texture_manager.get_texture_array());
|
||||||
|
glBindVertexArray(snapshot.cross_vao);
|
||||||
|
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0,
|
||||||
|
snapshot.cross_vertices_count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (snapshot.normal_discard_vertices_count != 0) {
|
||||||
|
glBindTexture(GL_TEXTURE_2D_ARRAY,
|
||||||
|
m_texture_manager.get_texture_array());
|
||||||
|
glBindVertexArray(snapshot.normal_discard_vao);
|
||||||
|
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0,
|
||||||
|
snapshot.normal_discard_vertices_count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
|
||||||
|
|
||||||
|
glCullFace(GL_BACK);
|
||||||
|
glViewport(0, 0, m_width, m_height);
|
||||||
const auto& normal_block_shader = get_shader("normal_block");
|
const auto& normal_block_shader = get_shader("normal_block");
|
||||||
normal_block_shader.use();
|
normal_block_shader.use();
|
||||||
|
|
||||||
@@ -435,17 +610,32 @@ void Renderer::render_world() {
|
|||||||
m_proj_loc = normal_block_shader.loc("proj_matrix");
|
m_proj_loc = normal_block_shader.loc("proj_matrix");
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, m_depth_map_texture);
|
||||||
|
glActiveTexture(GL_TEXTURE1);
|
||||||
|
|
||||||
m_m_mat = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, 0.0f));
|
m_m_mat = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, 0.0f));
|
||||||
m_v_mat = m_camera.get_camera_lookat();
|
m_v_mat = m_camera.get_camera_lookat();
|
||||||
m_mv_mat = m_v_mat * m_m_mat;
|
m_mv_mat = m_v_mat * m_m_mat;
|
||||||
|
m_norm_mat = glm::transpose(glm::inverse(m_mv_mat));
|
||||||
|
glm::vec3 light_dir_view =
|
||||||
|
glm::normalize(glm::mat3(m_v_mat) * m_world.sunlight_dir());
|
||||||
|
|
||||||
glUniformMatrix4fv(m_mv_loc, 1, GL_FALSE, glm::value_ptr(m_mv_mat));
|
glUniformMatrix4fv(m_mv_loc, 1, GL_FALSE, glm::value_ptr(m_mv_mat));
|
||||||
glUniformMatrix4fv(m_proj_loc, 1, GL_FALSE, glm::value_ptr(m_p_mat));
|
glUniformMatrix4fv(m_proj_loc, 1, GL_FALSE, glm::value_ptr(m_p_mat));
|
||||||
|
glUniformMatrix4fv(normal_block_shader.loc("norm_matrix"), 1, GL_FALSE,
|
||||||
|
glm::value_ptr(m_norm_mat));
|
||||||
|
glUniformMatrix4fv(normal_block_shader.loc("lightSpaceMatrix"), 1, GL_FALSE,
|
||||||
|
glm::value_ptr(light_space_matrix));
|
||||||
|
glUniform1f(normal_block_shader.loc("ambientStrength"), m_ambient_strength);
|
||||||
|
glUniform3fv(normal_block_shader.loc("sunlightColor"), 1,
|
||||||
|
glm::value_ptr(SUNLIGHT_COLOR));
|
||||||
|
glUniform3fv(normal_block_shader.loc("sunlightDir"), 1,
|
||||||
|
glm::value_ptr(light_dir_view));
|
||||||
|
glUniform1i(normal_block_shader.loc("shadowMode"), m_shadow_mode);
|
||||||
|
glUniform1i(normal_block_shader.loc("shader_on"), m_shader_on);
|
||||||
m_mvp_mat = m_p_mat * m_mv_mat;
|
m_mvp_mat = m_p_mat * m_mv_mat;
|
||||||
|
|
||||||
auto& camera_pos = m_camera.get_camera_pos();
|
|
||||||
auto& m_planes = m_world.planes();
|
auto& m_planes = m_world.planes();
|
||||||
auto& m_render_snapshots = m_world.render_snapshots();
|
|
||||||
|
|
||||||
Math::extract_frustum_planes(m_mvp_mat, m_planes);
|
Math::extract_frustum_planes(m_mvp_mat, m_planes);
|
||||||
|
|
||||||
@@ -526,6 +716,7 @@ void Renderer::render_world() {
|
|||||||
glBlendFunci(0, GL_ONE, GL_ONE);
|
glBlendFunci(0, GL_ONE, GL_ONE);
|
||||||
|
|
||||||
glBlendFunci(1, GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
|
glBlendFunci(1, GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
for (const auto& snapshot : m_render_snapshots) {
|
for (const auto& snapshot : m_render_snapshots) {
|
||||||
if (!Math::is_aabb_in_frustum(snapshot.center, snapshot.half_extents,
|
if (!Math::is_aabb_in_frustum(snapshot.center, snapshot.half_extents,
|
||||||
m_planes)) {
|
m_planes)) {
|
||||||
@@ -571,4 +762,56 @@ void Renderer::render_dev_panel() {
|
|||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glm::vec3 Renderer::quantize_sun_direction(const glm::vec3& sundir,
|
||||||
|
float angle_step_deg) const {
|
||||||
|
float elevation = std::asin(glm::clamp(sundir.y, -1.0f, 1.0f));
|
||||||
|
float azimuth = std::atan2(sundir.z, sundir.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
|
||||||
|
Renderer::get_smoothed_shadow_sundir(const glm::vec3& raw_shadow_sundir,
|
||||||
|
float dt) {
|
||||||
|
if (!m_blend_initialized) {
|
||||||
|
|
||||||
|
m_blend_from_sundir = raw_shadow_sundir;
|
||||||
|
m_blend_to_sundir = raw_shadow_sundir;
|
||||||
|
m_blend_t = 1.0f;
|
||||||
|
m_blend_initialized = true;
|
||||||
|
return raw_shadow_sundir;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (raw_shadow_sundir != m_blend_to_sundir) {
|
||||||
|
glm::vec3 current_displayed = glm::normalize(
|
||||||
|
Math::slerp(m_blend_from_sundir, m_blend_to_sundir, m_blend_t));
|
||||||
|
|
||||||
|
m_blend_from_sundir = current_displayed;
|
||||||
|
m_blend_to_sundir = raw_shadow_sundir;
|
||||||
|
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_sundir, m_blend_to_sundir, m_blend_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
float& Renderer::ambient_strength() { return m_ambient_strength; }
|
||||||
|
bool& Renderer::discard_transparent() { return m_discard_tranparent; }
|
||||||
|
bool& Renderer::shader_on() { return m_shader_on; }
|
||||||
|
int& Renderer::shadow_mode() { return m_shadow_mode; }
|
||||||
|
int& Renderer::light_cull_face() { return m_light_cull_face; }
|
||||||
} // namespace Cubed
|
} // namespace Cubed
|
||||||
@@ -164,6 +164,8 @@ void TextureManager::init_block() {
|
|||||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER,
|
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER,
|
||||||
GL_LINEAR_MIPMAP_LINEAR);
|
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);
|
glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
|
||||||
if (m_aniso >= 1) {
|
if (m_aniso >= 1) {
|
||||||
glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_ANISOTROPY,
|
glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_ANISOTROPY,
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
#include "Cubed/tools/math_tools.hpp"
|
#include "Cubed/tools/math_tools.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <glm/glm.hpp>
|
||||||
#include <glm/gtc/type_ptr.hpp>
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
|
|
||||||
namespace Cubed {
|
namespace Cubed {
|
||||||
|
|
||||||
namespace Math {
|
namespace Math {
|
||||||
@@ -65,6 +67,39 @@ float deterministic_random(int x, int z, uint64_t seed) {
|
|||||||
h = h * 6364136223846793005ULL + (uint64_t)z;
|
h = h * 6364136223846793005ULL + (uint64_t)z;
|
||||||
return (float)(h >> 40) / (float)(1 << 24);
|
return (float)(h >> 40) / (float)(1 << 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glm::vec3 slerp(const glm::vec3& from, const glm::vec3& to, float t) {
|
||||||
|
|
||||||
|
float cos_theta = glm::clamp(glm::dot(from, to), -1.0f, 1.0f);
|
||||||
|
|
||||||
|
if (cos_theta > 0.9995f) {
|
||||||
|
return glm::normalize(glm::mix(from, to, t));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cos_theta < -0.9995f) {
|
||||||
|
|
||||||
|
glm::vec3 axis = (std::fabs(from.x) < 0.9f)
|
||||||
|
? glm::vec3(1.0f, 0.0f, 0.0f)
|
||||||
|
: glm::vec3(0.0f, 1.0f, 0.0f);
|
||||||
|
glm::vec3 ortho = glm::normalize(glm::cross(from, axis));
|
||||||
|
|
||||||
|
float angle = glm::pi<float>() * t;
|
||||||
|
|
||||||
|
glm::vec3 rotated =
|
||||||
|
from * std::cos(angle) + glm::cross(ortho, from) * std::sin(angle);
|
||||||
|
|
||||||
|
return glm::normalize(rotated);
|
||||||
|
}
|
||||||
|
|
||||||
|
float theta = std::acos(cos_theta);
|
||||||
|
float sin_theta = std::sin(theta);
|
||||||
|
|
||||||
|
float a = std::sin((1.0f - t) * theta) / sin_theta;
|
||||||
|
float b = std::sin(t * theta) / sin_theta;
|
||||||
|
|
||||||
|
return glm::normalize(a * from + b * to);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Math
|
} // namespace Math
|
||||||
|
|
||||||
} // namespace Cubed
|
} // namespace Cubed
|
||||||
Reference in New Issue
Block a user