feat: water effects (#19)

* feat(shaders): add lighting to block accumulation OIT shaders

* feat(renderer): add water rendering with OIT and new shaders

* feat(water): implement screen-space reflection and refraction for water with depth fade and perturbation

* refactor(shader): replace glUniform calls with generic set_loc and remove cached locations

* feat(water): add noise-based caustics and configurable fog density

* fix(water shader): update depth fade and remove underwater check

- Increase DEPTH_FADE_DISTANCE from 8 to 10
- Remove conditional so depth fade always applies
- Darken deepColor from (0, 0.08, 0.15) to (0, 0.015, 0.045)

* feat(underwater): add volume scattering and shadow mapping for light shafts
This commit is contained in:
zhenyan121
2026-06-20 09:04:09 +08:00
committed by GitHub
parent ca3fc5e3bf
commit a8d2ddbacd
16 changed files with 813 additions and 126 deletions

View File

@@ -19,7 +19,7 @@ private:
static constexpr int SIZE_X = CHUNK_SIZE;
static constexpr int SIZE_Y = WORLD_SIZE_Y;
static constexpr int SIZE_Z = CHUNK_SIZE;
static constexpr int VERTEX_DATA_SUM = 4;
static constexpr int VERTEX_DATA_SUM = 5;
std::atomic<bool> m_dirty{false};
std::atomic<bool> m_need_upload{true};
std::atomic<bool> m_is_on_gen_vertex_data{false};
@@ -39,6 +39,7 @@ private:
1 - cross_plane
2 - normal_discard
3 - transparent and blend
4 - water
*/
std::vector<VertexData> m_vertex_data;
float frequency = 0.01f;
@@ -113,6 +114,9 @@ public:
GLuint get_normal_blend_vao() const;
size_t get_normal_blend_vertices_sum() const;
GLuint get_water_vao() const;
size_t get_water_vertices_sum() const;
bool is_dirty() const;
void mark_dirty();

View File

@@ -24,6 +24,8 @@ struct ChunkRenderSnapshot {
size_t normal_discard_vertices_count;
GLuint normal_blend_vao;
size_t normal_blend_vertices_count;
GLuint water_vao;
size_t water_vertices_count;
glm::vec3 center;
glm::vec3 half_extents;
};

View File

@@ -212,7 +212,7 @@ constexpr float CROSS_NORMALS[2][6][3] = {
{0.0f, 1.0f, 0.0f}}};
#pragma endregion
// [-1, 1]
constexpr float QUAD_VERTICES[] = {
// postion // texcoorlds
-1.0f, 1.0f, 0.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f,

View File

@@ -32,6 +32,8 @@ public:
bool& discard_transparent();
bool& shader_on();
bool& water_perturb();
bool& water_depth_fade();
int& shadow_mode();
int& light_cull_face();
int& light_size_uv();
@@ -42,10 +44,13 @@ public:
float& cloud_speed();
float& cloud_threshold_low();
float& cloud_threshold_high();
float& refract_strength();
float& underwater_fog_density();
float& water_density();
private:
struct ParallelLight {
glm::vec3 sundir;
glm::vec3 sundir; // direction from sun to vertex
glm::vec3 lightdir;
float sun_height = 0.0f;
float day_light = 0.0f;
@@ -53,6 +58,15 @@ private:
glm::vec3 sun_color;
glm::vec3 directional_light_color;
glm::vec3 finnal_ambient_color;
glm::mat4 light_space_matrix;
};
struct SkyUniform {
glm::vec3 sky_top;
glm::vec3 sky_bottom;
glm::vec3 sun_dir_view;
float horizon_sharpness;
float cloud_white_mix;
};
static constexpr glm::vec3 SUN_COLOR{1.00f, 0.95f, 0.80f};
@@ -79,6 +93,8 @@ private:
bool m_discard_tranparent = true;
bool m_shader_on = true;
bool m_water_perturb = true;
bool m_water_depth_fade = true;
int m_shadow_mode = 0;
int m_light_cull_face = 0;
float m_aspect = 0.0f;
@@ -94,9 +110,6 @@ private:
glm::mat4 m_p_mat, m_v_mat, m_m_mat, m_mv_mat, m_mvp_mat, m_norm_mat;
GLuint m_mv_loc = 0;
GLuint m_proj_loc = 0;
GLuint m_sky_vbo = 0;
GLuint m_text_vbo = 0;
GLuint m_outline_indices_vbo = 0;
@@ -105,12 +118,12 @@ private:
GLuint m_fbo = 0;
GLuint m_screen_texture = 0;
GLuint m_depth_render_buffer = 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_render_buffer = 0;
GLuint m_oit_depth_texture = 0;
GLuint m_depth_map_fbo = 0;
GLuint m_depth_map_texture = 0;
@@ -140,7 +153,14 @@ private:
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;
ParallelLight m_parallel_light;
SkyUniform m_sky_uniform;
/*
0 - quad vao
1 - sky vao

View File

@@ -1,4 +1,7 @@
#pragma once
#include "glm/ext/vector_float3.hpp"
#include "glm/gtc/type_ptr.hpp"
#include <glad/glad.h>
#include <string>
#include <unordered_map>
@@ -21,6 +24,26 @@ public:
GLuint loc(const std::string& loc) const;
const std::string& name() const;
void use() const;
template <typename> struct always_false : std::false_type {}; // NOLINT
template <typename T>
void set_loc(const std::string& location, T&& value) const {
using std::is_same_v;
using dT = std::decay_t<T>;
if constexpr (is_same_v<dT, int> || is_same_v<dT, bool>) {
glUniform1i(loc(location), value);
} else if constexpr (is_same_v<dT, float>) {
glUniform1f(loc(location), value);
} else if constexpr (is_same_v<dT, double>) {
glUniform1f(loc(location), static_cast<float>(value));
} else if constexpr (is_same_v<dT, glm::vec3>) {
glUniform3fv(loc(location), 1, glm::value_ptr(value));
} else if constexpr (is_same_v<dT, glm::mat4>) {
glUniformMatrix4fv(loc(location), 1, GL_FALSE,
glm::value_ptr(value));
} else {
static_assert(always_false<dT>::value, "Unknown Type");
}
};
private:
GLuint m_program = 0;