feat(renderer): add runtime shader and shadow mode controls

Introduce user-controllable shader on/off, shadow mode (rotated Poisson disk, 3x3 grid, or off), light cull face, and discard transparent in depth pass. Expose all settings in new dev panel "shader" tab. Move ambient strength slider to the new tab.
This commit is contained in:
2026-06-17 20:16:20 +08:00
parent 74b0aebc9f
commit e224110452
6 changed files with 174 additions and 102 deletions

View File

@@ -12,6 +12,8 @@ layout (binding = 1) uniform sampler2DArray samp;
uniform float ambientStrength; uniform float ambientStrength;
uniform vec3 sunlightColor; uniform vec3 sunlightColor;
uniform vec3 sunlightDir; uniform vec3 sunlightDir;
uniform bool shader_on;
uniform int shadowMode;
const vec2 poissonDisk[8] = vec2[]( const vec2 poissonDisk[8] = vec2[](
vec2( 0.1440, 0.7659), vec2(-0.5761, 0.4479), vec2( 0.1440, 0.7659), vec2(-0.5761, 0.4479),
@@ -43,6 +45,8 @@ float ShadowCalculation(vec4 fragPosLightSpace, vec3 norm, vec3 lightDir)
0.0003, 0.0003,
0.001 * (1.0 - dot(norm, lightDir)) 0.001 * (1.0 - dot(norm, lightDir))
); );
if (shadowMode == 0) {
vec3 seed = vert_pos * 37.0 + sin(vert_pos * 91.7) * 13.0; vec3 seed = vert_pos * 37.0 + sin(vert_pos * 91.7) * 13.0;
float angle = random(seed) * 6.2831853;; // 2*PI float angle = random(seed) * 6.2831853;; // 2*PI
float s = sin(angle), c = cos(angle); float s = sin(angle), c = cos(angle);
@@ -58,8 +62,7 @@ float ShadowCalculation(vec4 fragPosLightSpace, vec3 norm, vec3 lightDir)
shadow += (currentDepth - bias > pcfDepth ? 1.0 : 0.0); shadow += (currentDepth - bias > pcfDepth ? 1.0 : 0.0);
} }
shadow /= float(samples); shadow /= float(samples);
} else if (shadowMode == 1) {
/*
for (int x = -1; x <= 1; ++x) { for (int x = -1; x <= 1; ++x) {
for (int y = -1; y <= 1; ++y) { for (int y = -1; y <= 1; ++y) {
vec2 offset = vec2(x, y) * texelSize; vec2 offset = vec2(x, y) * texelSize;
@@ -68,15 +71,26 @@ float ShadowCalculation(vec4 fragPosLightSpace, vec3 norm, vec3 lightDir)
} }
} }
shadow /= 9.0; shadow /= 9.0;
*/ } else if (shadowMode == 2) {
// pcf off // pcf off
//float pcfDepth = float pcfDepth =
//texture(shadowMap, projCoords.xy).r; 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;
}
//shadow =
// currentDepth - bias > pcfDepth
// ? 1.0
// : 0.0;
return shadow; return shadow;
} }
@@ -87,6 +101,11 @@ void main(void) {
if (objectColor.a < 0.8) { if (objectColor.a < 0.8) {
discard; discard;
} }
if (!shader_on) {
color = objectColor;
return;
}
vec3 lightDir = normalize(-sunlightDir); vec3 lightDir = normalize(-sunlightDir);

View File

@@ -4,9 +4,13 @@ in vec2 tc;
flat in int tex_layer; flat in int tex_layer;
layout (binding = 1) uniform sampler2DArray samp; layout (binding = 1) uniform sampler2DArray samp;
uniform bool is_discard_tranparent;
void main() { void main() {
if (is_discard_tranparent) {
vec4 texColor = texture(samp, vec3(tc, tex_layer)); vec4 texColor = texture(samp, vec3(tc, tex_layer));
if (texColor.a < 0.8) if (texColor.a < 0.8)
discard; discard;
}
//gl_FragDepth = gl_FragCoord.z; //gl_FragDepth = gl_FragCoord.z;
} }

View File

@@ -56,6 +56,7 @@ private:
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();

View File

@@ -30,6 +30,11 @@ public:
void updata_framebuffer(int width, int height); void updata_framebuffer(int width, int height);
float& ambient_strength(); 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 SUNLIGHT_COLOR{1.0f, 1.0f, 1.0f};
static constexpr glm::vec3 SUN_COLOR{1.00f, 0.95f, 0.80f}; static constexpr glm::vec3 SUN_COLOR{1.00f, 0.95f, 0.80f};
@@ -47,6 +52,10 @@ private:
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;

View File

@@ -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");
@@ -361,10 +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::SliderFloat("AmbientStrength",
&m_app.renderer().ambient_strength(), 0.0f,
0.35f))
;
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",
@@ -610,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 =

View File

@@ -501,6 +501,10 @@ void Renderer::updata_framebuffer(int width, int height) {
void Renderer::render_world() { void Renderer::render_world() {
// shader map // 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"); const auto& depth_shader = get_shader("depth_shader");
depth_shader.use(); depth_shader.use();
@@ -517,8 +521,10 @@ void Renderer::render_world() {
glm::mat4 light_basis = glm::lookAt(glm::vec3(0.0f), sundir, up); glm::mat4 light_basis = glm::lookAt(glm::vec3(0.0f), sundir, up);
float texels_per_unit = DEPTH_MAP_SIZE / (half_extent * 2.0f); float texels_per_unit = DEPTH_MAP_SIZE / (half_extent * 2.0f);
glm::vec3 ls_center = glm::vec3(light_basis * glm::vec4(center, 1.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.x =
ls_center.y = std::round(ls_center.y * texels_per_unit) / texels_per_unit; 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 snapped_center =
glm::vec3(glm::inverse(light_basis) * glm::vec4(ls_center, 1.0f)); glm::vec3(glm::inverse(light_basis) * glm::vec4(ls_center, 1.0f));
@@ -531,18 +537,25 @@ void Renderer::render_world() {
glm::ortho(-half_extent, half_extent, -half_extent, half_extent, glm::ortho(-half_extent, half_extent, -half_extent, half_extent,
near_plane, far_plane); near_plane, far_plane);
glm::mat4 light_space_matrix = light_projection * light_view; light_space_matrix = light_projection * light_view;
glUniformMatrix4fv(depth_shader.loc("lightSpaceMatrix"), 1, GL_FALSE, glUniformMatrix4fv(depth_shader.loc("lightSpaceMatrix"), 1, GL_FALSE,
glm::value_ptr(light_space_matrix)); 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); glViewport(0, 0, DEPTH_MAP_SIZE, DEPTH_MAP_SIZE);
if (m_light_cull_face == 0) {
glCullFace(GL_FRONT); 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); glBindFramebuffer(GL_FRAMEBUFFER, m_depth_map_fbo);
glClear(GL_DEPTH_BUFFER_BIT); glClear(GL_DEPTH_BUFFER_BIT);
auto& m_render_snapshots = m_world.render_snapshots();
auto& camera_pos = m_camera.get_camera_pos();
glActiveTexture(GL_TEXTURE1); glActiveTexture(GL_TEXTURE1);
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
for (const auto& snapshot : m_render_snapshots) { for (const auto& snapshot : m_render_snapshots) {
@@ -566,7 +579,8 @@ void Renderer::render_world() {
m_texture_manager.get_texture_array()); m_texture_manager.get_texture_array());
glBindVertexArray(snapshot.cross_vao); glBindVertexArray(snapshot.cross_vao);
glDrawArrays(GL_TRIANGLES, 0, snapshot.cross_vertices_count); glDrawArrays(GL_TRIANGLES, 0,
snapshot.cross_vertices_count);
} }
} }
if (snapshot.normal_discard_vertices_count != 0) { if (snapshot.normal_discard_vertices_count != 0) {
@@ -578,6 +592,7 @@ void Renderer::render_world() {
snapshot.normal_discard_vertices_count); snapshot.normal_discard_vertices_count);
} }
} }
}
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
@@ -611,7 +626,8 @@ void Renderer::render_world() {
glm::value_ptr(SUNLIGHT_COLOR)); glm::value_ptr(SUNLIGHT_COLOR));
glUniform3fv(normal_block_shader.loc("sunlightDir"), 1, glUniform3fv(normal_block_shader.loc("sunlightDir"), 1,
glm::value_ptr(light_dir_view)); 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& m_planes = m_world.planes(); auto& m_planes = m_world.planes();
@@ -742,5 +758,8 @@ void Renderer::render_dev_panel() {
} }
float& Renderer::ambient_strength() { return m_ambient_strength; } 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