mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-06-18 00:27:02 +08:00
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:
@@ -12,6 +12,8 @@ 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),
|
||||
@@ -43,50 +45,67 @@ float ShadowCalculation(vec4 fragPosLightSpace, vec3 norm, vec3 lightDir)
|
||||
0.0003,
|
||||
0.001 * (1.0 - dot(norm, lightDir))
|
||||
);
|
||||
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;
|
||||
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);
|
||||
|
||||
|
||||
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);
|
||||
|
||||
/*
|
||||
for (int x = -1; x <= 1; ++x) {
|
||||
for (int y = -1; y <= 1; ++y) {
|
||||
vec2 offset = vec2(x, y) * texelSize;
|
||||
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 /= 9.0;
|
||||
*/
|
||||
// pcf off
|
||||
//float pcfDepth =
|
||||
//texture(shadowMap, projCoords.xy).r;
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
void main(void) {
|
||||
vec4 objectColor = texture(samp, vec3(tc, tex_layer));
|
||||
|
||||
|
||||
if (objectColor.a < 0.8) {
|
||||
discard;
|
||||
}
|
||||
if (!shader_on) {
|
||||
color = objectColor;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
vec3 lightDir = normalize(-sunlightDir);
|
||||
|
||||
|
||||
@@ -4,9 +4,13 @@ in vec2 tc;
|
||||
flat in int tex_layer;
|
||||
layout (binding = 1) uniform sampler2DArray samp;
|
||||
|
||||
uniform bool is_discard_tranparent;
|
||||
|
||||
void main() {
|
||||
vec4 texColor = texture(samp, vec3(tc, tex_layer));
|
||||
if (texColor.a < 0.8)
|
||||
discard;
|
||||
if (is_discard_tranparent) {
|
||||
vec4 texColor = texture(samp, vec3(tc, tex_layer));
|
||||
if (texColor.a < 0.8)
|
||||
discard;
|
||||
}
|
||||
//gl_FragDepth = gl_FragCoord.z;
|
||||
}
|
||||
@@ -56,6 +56,7 @@ private:
|
||||
void show_world_tab_item();
|
||||
void show_player_tab_item();
|
||||
void show_items_tab_item();
|
||||
void show_shader_tab_item();
|
||||
|
||||
void update_config_view();
|
||||
void update_player_profile();
|
||||
|
||||
@@ -30,6 +30,11 @@ public:
|
||||
void updata_framebuffer(int width, int height);
|
||||
float& ambient_strength();
|
||||
|
||||
bool& discard_transparent();
|
||||
bool& shader_on();
|
||||
int& shadow_mode();
|
||||
int& light_cull_face();
|
||||
|
||||
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};
|
||||
@@ -47,6 +52,10 @@ private:
|
||||
const TextureManager& m_texture_manager;
|
||||
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_fov = DEFAULT_FOV;
|
||||
|
||||
|
||||
@@ -84,6 +84,7 @@ void DevPanel::render() {
|
||||
show_world_tab_item();
|
||||
show_player_tab_item();
|
||||
show_items_tab_item();
|
||||
show_shader_tab_item();
|
||||
show_about_table_bar();
|
||||
|
||||
ImGui::EndTabBar();
|
||||
@@ -107,6 +108,7 @@ void DevPanel::show_about_table_bar() {
|
||||
ImGui::Text("FreeType");
|
||||
ImGui::Text("toml++");
|
||||
ImGui::Text("Dear ImGui");
|
||||
ImGui::Text("Tbb");
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Special Thanks");
|
||||
ImGui::Text("TANGERIME");
|
||||
@@ -361,10 +363,7 @@ void DevPanel::show_settings_tab_item() {
|
||||
static_cast<double>(m_config.mouse_sensitivity));
|
||||
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,
|
||||
128)) {
|
||||
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() {
|
||||
auto config = Config::get();
|
||||
m_config.fov =
|
||||
|
||||
151
src/renderer.cpp
151
src/renderer.cpp
@@ -501,81 +501,96 @@ void Renderer::updata_framebuffer(int width, int height) {
|
||||
|
||||
void Renderer::render_world() {
|
||||
// shader map
|
||||
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 up =
|
||||
fabs(sundir.y) > 0.99f ? glm::vec3(0, 0, 1) : glm::vec3(0, 1, 0);
|
||||
|
||||
glm::mat4 light_basis = glm::lookAt(glm::vec3(0.0f), 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 - 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);
|
||||
|
||||
glm::mat4 light_space_matrix = light_projection * light_view;
|
||||
glUniformMatrix4fv(depth_shader.loc("lightSpaceMatrix"), 1, GL_FALSE,
|
||||
glm::value_ptr(light_space_matrix));
|
||||
|
||||
glViewport(0, 0, DEPTH_MAP_SIZE, DEPTH_MAP_SIZE);
|
||||
glCullFace(GL_FRONT);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_depth_map_fbo);
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glm::mat4 light_space_matrix;
|
||||
auto& m_render_snapshots = m_world.render_snapshots();
|
||||
auto& camera_pos = m_camera.get_camera_pos();
|
||||
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);
|
||||
if (m_shader_on) {
|
||||
const auto& depth_shader = get_shader("depth_shader");
|
||||
depth_shader.use();
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, snapshot.normal_vertices_count);
|
||||
}
|
||||
glm::vec3 cam_pos = m_camera.get_camera_pos();
|
||||
glm::vec3 cam_fwd = m_camera.get_camera_front();
|
||||
float half_extent = 128.0f;
|
||||
|
||||
// cross_plane and discard
|
||||
glm::vec3 center = cam_pos + cam_fwd * (half_extent * 0.5f);
|
||||
|
||||
for (const auto& snapshot : m_render_snapshots) {
|
||||
glm::vec3 sundir = glm::normalize(m_world.sunlight_dir());
|
||||
glm::vec3 up =
|
||||
fabs(sundir.y) > 0.99f ? glm::vec3(0, 0, 1) : glm::vec3(0, 1, 0);
|
||||
|
||||
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);
|
||||
glm::mat4 light_basis = glm::lookAt(glm::vec3(0.0f), 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));
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, snapshot.cross_vertices_count);
|
||||
}
|
||||
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 - 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);
|
||||
}
|
||||
if (snapshot.normal_discard_vertices_count != 0) {
|
||||
|
||||
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_discard_vao);
|
||||
glBindVertexArray(snapshot.normal_vao);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0,
|
||||
snapshot.normal_discard_vertices_count);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -611,7 +626,8 @@ void Renderer::render_world() {
|
||||
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;
|
||||
|
||||
auto& m_planes = m_world.planes();
|
||||
@@ -742,5 +758,8 @@ void Renderer::render_dev_panel() {
|
||||
}
|
||||
|
||||
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
|
||||
Reference in New Issue
Block a user