mirror of
https://github.com/bailwillharr/engine.git
synced 2024-09-21 04:51:18 +00:00
Fix shadow mapping for alpha-clipped meshes
This commit is contained in:
parent
dfd892b146
commit
716dc8f5f0
@ -34,6 +34,10 @@ float GGXDist(float alpha_2, float N_dot_H) {
|
|||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
|
||||||
|
const vec4 albedo_alpha = texture(materialSetAlbedoSampler, fragUV);
|
||||||
|
if (albedo_alpha.a < 0.9) discard; // discard fragments without alpha = 1.0
|
||||||
|
const vec3 albedo = albedo_alpha.xyz;
|
||||||
|
|
||||||
const vec3 occlusion_roughness_metallic = vec3(texture(materialSetOcclusionRoughnessMetallic, fragUV));
|
const vec3 occlusion_roughness_metallic = vec3(texture(materialSetOcclusionRoughnessMetallic, fragUV));
|
||||||
const float ao = occlusion_roughness_metallic.r;
|
const float ao = occlusion_roughness_metallic.r;
|
||||||
const float roughness = occlusion_roughness_metallic.g;
|
const float roughness = occlusion_roughness_metallic.g;
|
||||||
@ -52,7 +56,6 @@ void main() {
|
|||||||
|
|
||||||
const vec3 emission = vec3(0.0, 0.0, 0.0);
|
const vec3 emission = vec3(0.0, 0.0, 0.0);
|
||||||
|
|
||||||
const vec3 albedo = vec3(texture(materialSetAlbedoSampler, fragUV));
|
|
||||||
const vec3 N = GetNormal();
|
const vec3 N = GetNormal();
|
||||||
|
|
||||||
const vec3 V = normalize(fragViewPosTangentSpace - fragPosTangentSpace);
|
const vec3 V = normalize(fragViewPosTangentSpace - fragPosTangentSpace);
|
||||||
@ -91,19 +94,19 @@ void main() {
|
|||||||
projCoords.y = projCoords.y * 0.5 + 0.5;
|
projCoords.y = projCoords.y * 0.5 + 0.5;
|
||||||
//float closestDepth = texture(globalSetShadowmap, projCoords.xy).r;
|
//float closestDepth = texture(globalSetShadowmap, projCoords.xy).r;
|
||||||
const float currentDepth = max(projCoords.z, 0.0);
|
const float currentDepth = max(projCoords.z, 0.0);
|
||||||
const float bias = max(0.02 * (1.0 - L_dot_N), 0.005);
|
const float bias = max(0.01 * (1.0 - L_dot_N), 0.005);
|
||||||
//float shadow = currentDepth - bias > closestDepth ? 0.0 : 1.0;
|
//float shadow = currentDepth - bias > closestDepth ? 0.0 : 1.0;
|
||||||
float shadow = 0.0;
|
float shadow = 0.0;
|
||||||
vec2 texelSize = 1.0 / textureSize(globalSetShadowmap, 0);
|
vec2 texelSize = 1.0 / textureSize(globalSetShadowmap, 0);
|
||||||
for(int x = -1; x <= 1; ++x)
|
for(int x = -2; x <= 2; ++x)
|
||||||
{
|
{
|
||||||
for(int y = -1; y <= 1; ++y)
|
for(int y = -2; y <= 2; ++y)
|
||||||
{
|
{
|
||||||
float pcfDepth = texture(globalSetShadowmap, projCoords.xy + vec2(x, y) * texelSize).r;
|
float pcfDepth = texture(globalSetShadowmap, projCoords.xy + vec2(x, y) * texelSize).r;
|
||||||
shadow += currentDepth - bias > pcfDepth ? 1.0 : 0.0;
|
shadow += currentDepth - bias > pcfDepth ? 1.0 : 0.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
shadow /= 9.0;
|
shadow /= 25.0;
|
||||||
|
|
||||||
lighting *= (1.0 - shadow);
|
lighting *= (1.0 - shadow);
|
||||||
|
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
|
layout(set = 2, binding = 0) uniform sampler2D materialSetAlbedoSampler;
|
||||||
|
|
||||||
|
layout(location = 0) in vec2 fragUV;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
// empty fragment shader
|
if (texture(materialSetAlbedoSampler, fragUV).a < 1.0) discard;
|
||||||
}
|
}
|
||||||
|
@ -10,8 +10,12 @@ layout( push_constant ) uniform Constants {
|
|||||||
} constants;
|
} constants;
|
||||||
|
|
||||||
layout(location = 0) in vec3 inPosition;
|
layout(location = 0) in vec3 inPosition;
|
||||||
|
layout(location = 1) in vec2 inUV;
|
||||||
|
|
||||||
|
layout(location = 0) out vec2 fragUV;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
fragUV = inUV;
|
||||||
gl_Position = globalSetUniformBuffer.lightSpaceMatrix * constants.model * vec4(inPosition, 1.0);
|
gl_Position = globalSetUniformBuffer.lightSpaceMatrix * constants.model * vec4(inPosition, 1.0);
|
||||||
//gl_Position.y *= -1.0;
|
//gl_Position.y *= -1.0;
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,7 @@ static constexpr uint32_t FRAMES_IN_FLIGHT = 2; // This improved FPS by 5x
|
|||||||
static constexpr size_t PUSH_CONSTANT_MAX_SIZE = 128; // bytes
|
static constexpr size_t PUSH_CONSTANT_MAX_SIZE = 128; // bytes
|
||||||
static constexpr VkIndexType INDEX_TYPE = VK_INDEX_TYPE_UINT32;
|
static constexpr VkIndexType INDEX_TYPE = VK_INDEX_TYPE_UINT32;
|
||||||
|
|
||||||
static constexpr int kShadowmapSize = 2048;
|
static constexpr int kShadowmapSize = 4096;
|
||||||
|
|
||||||
// structures and enums
|
// structures and enums
|
||||||
|
|
||||||
|
@ -33,9 +33,9 @@ Renderer::Renderer(Application& app, gfx::GraphicsSettings settings) : Applicati
|
|||||||
global_uniform.layout = device_->CreateDescriptorSetLayout(globalSetBindings);
|
global_uniform.layout = device_->CreateDescriptorSetLayout(globalSetBindings);
|
||||||
global_uniform.set = device_->AllocateDescriptorSet(global_uniform.layout);
|
global_uniform.set = device_->AllocateDescriptorSet(global_uniform.layout);
|
||||||
const glm::vec3 light_location = glm::vec3{-0.4278, 0.7923, 0.43502} * 40.0f;
|
const glm::vec3 light_location = glm::vec3{-0.4278, 0.7923, 0.43502} * 40.0f;
|
||||||
//const glm::vec3 light_location = glm::vec3{10.0f, 0.0f, 10.0f};
|
// const glm::vec3 light_location = glm::vec3{10.0f, 0.0f, 10.0f};
|
||||||
const glm::mat4 light_proj = glm::orthoRH_ZO(-24.0f, 24.0f, -15.0f, 15.0f, 10.0f, 65.0f);
|
const glm::mat4 light_proj = glm::orthoRH_ZO(-24.0f, 24.0f, -15.0f, 15.0f, 10.0f, 65.0f);
|
||||||
//const glm::mat4 light_proj = glm::perspectiveFovRH_ZO(glm::radians(90.0f), 1.0f, 1.0f, 5.0f, 50.0f);
|
// const glm::mat4 light_proj = glm::perspectiveFovRH_ZO(glm::radians(90.0f), 1.0f, 1.0f, 5.0f, 50.0f);
|
||||||
const glm::mat4 light_view = glm::lookAtRH(light_location, glm::vec3{0.0f, 0.0f, 0.0f}, glm::vec3{0.0f, 0.0f, 1.0f});
|
const glm::mat4 light_view = glm::lookAtRH(light_location, glm::vec3{0.0f, 0.0f, 0.0f}, glm::vec3{0.0f, 0.0f, 1.0f});
|
||||||
global_uniform.uniform_buffer_data.data.proj = light_proj;
|
global_uniform.uniform_buffer_data.data.proj = light_proj;
|
||||||
global_uniform.uniform_buffer_data.data.lightSpaceMatrix = light_proj * light_view;
|
global_uniform.uniform_buffer_data.data.lightSpaceMatrix = light_proj * light_view;
|
||||||
@ -195,6 +195,7 @@ Renderer::Renderer(Application& app, gfx::GraphicsSettings settings) : Applicati
|
|||||||
gfx::VertexFormat shadowVertexFormat{};
|
gfx::VertexFormat shadowVertexFormat{};
|
||||||
shadowVertexFormat.stride = sizeof(float) * 12; // using the full meshes so a lot of data is skipped
|
shadowVertexFormat.stride = sizeof(float) * 12; // using the full meshes so a lot of data is skipped
|
||||||
shadowVertexFormat.attribute_descriptions.emplace_back(0, gfx::VertexAttribFormat::kFloat3, 0); // position
|
shadowVertexFormat.attribute_descriptions.emplace_back(0, gfx::VertexAttribFormat::kFloat3, 0); // position
|
||||||
|
shadowVertexFormat.attribute_descriptions.emplace_back(1, gfx::VertexAttribFormat::kFloat2, sizeof(float) * 10); // uv
|
||||||
gfx::PipelineInfo shadowPipelineInfo{};
|
gfx::PipelineInfo shadowPipelineInfo{};
|
||||||
shadowPipelineInfo.vert_shader_path = GetResourcePath("engine/shaders/shadow.vert");
|
shadowPipelineInfo.vert_shader_path = GetResourcePath("engine/shaders/shadow.vert");
|
||||||
shadowPipelineInfo.frag_shader_path = GetResourcePath("engine/shaders/shadow.frag");
|
shadowPipelineInfo.frag_shader_path = GetResourcePath("engine/shaders/shadow.frag");
|
||||||
@ -205,6 +206,8 @@ Renderer::Renderer(Application& app, gfx::GraphicsSettings settings) : Applicati
|
|||||||
shadowPipelineInfo.line_primitives = false;
|
shadowPipelineInfo.line_primitives = false;
|
||||||
shadowPipelineInfo.depth_attachment_only = true;
|
shadowPipelineInfo.depth_attachment_only = true;
|
||||||
shadowPipelineInfo.descriptor_set_layouts.emplace_back(GetGlobalSetLayout());
|
shadowPipelineInfo.descriptor_set_layouts.emplace_back(GetGlobalSetLayout());
|
||||||
|
shadowPipelineInfo.descriptor_set_layouts.emplace_back(GetFrameSetLayout());
|
||||||
|
shadowPipelineInfo.descriptor_set_layouts.emplace_back(GetMaterialSetLayout());
|
||||||
shadow_pipeline = device_->CreatePipeline(shadowPipelineInfo);
|
shadow_pipeline = device_->CreatePipeline(shadowPipelineInfo);
|
||||||
|
|
||||||
// shadow map image and sampler
|
// shadow map image and sampler
|
||||||
@ -212,7 +215,7 @@ Renderer::Renderer(Application& app, gfx::GraphicsSettings settings) : Applicati
|
|||||||
gfx::SamplerInfo sampler_info{};
|
gfx::SamplerInfo sampler_info{};
|
||||||
sampler_info.magnify = gfx::Filter::kLinear;
|
sampler_info.magnify = gfx::Filter::kLinear;
|
||||||
sampler_info.minify = gfx::Filter::kLinear;
|
sampler_info.minify = gfx::Filter::kLinear;
|
||||||
sampler_info.mipmap = gfx::Filter::kLinear; // trilinear is apparently good for shadow maps
|
sampler_info.mipmap = gfx::Filter::kNearest; // bilinear is apparently good for shadow maps, mips aren't used anyway
|
||||||
sampler_info.wrap_u = gfx::WrapMode::kClampToBorder; // sampler reads 1.0 out of bounds which ensures no shadowing there
|
sampler_info.wrap_u = gfx::WrapMode::kClampToBorder; // sampler reads 1.0 out of bounds which ensures no shadowing there
|
||||||
sampler_info.wrap_v = gfx::WrapMode::kClampToBorder;
|
sampler_info.wrap_v = gfx::WrapMode::kClampToBorder;
|
||||||
sampler_info.wrap_w = gfx::WrapMode::kClampToBorder;
|
sampler_info.wrap_w = gfx::WrapMode::kClampToBorder;
|
||||||
@ -272,10 +275,11 @@ void Renderer::Render(const RenderList* static_list, const RenderList* dynamic_l
|
|||||||
gfx::DrawBuffer* shadow_draw = device_->BeginShadowmapRender(shadow_map);
|
gfx::DrawBuffer* shadow_draw = device_->BeginShadowmapRender(shadow_map);
|
||||||
device_->CmdBindPipeline(shadow_draw, shadow_pipeline);
|
device_->CmdBindPipeline(shadow_draw, shadow_pipeline);
|
||||||
device_->CmdBindDescriptorSet(shadow_draw, shadow_pipeline, global_uniform.set, 0); // only need light space matrix
|
device_->CmdBindDescriptorSet(shadow_draw, shadow_pipeline, global_uniform.set, 0); // only need light space matrix
|
||||||
if (static_list) { // only create shadow map with static meshes
|
if (static_list) { // only create shadow map with static meshes
|
||||||
if (!static_list->empty()) {
|
if (!static_list->empty()) {
|
||||||
for (const auto& entry : *static_list) {
|
for (const auto& entry : *static_list) {
|
||||||
device_->CmdPushConstants(shadow_draw, shadow_pipeline, 0, sizeof(entry.model_matrix), &entry.model_matrix);
|
device_->CmdPushConstants(shadow_draw, shadow_pipeline, 0, sizeof(entry.model_matrix), &entry.model_matrix);
|
||||||
|
device_->CmdBindDescriptorSet(shadow_draw, shadow_pipeline, entry.material_set, 2);
|
||||||
device_->CmdBindVertexBuffer(shadow_draw, 0, entry.vertex_buffer);
|
device_->CmdBindVertexBuffer(shadow_draw, 0, entry.vertex_buffer);
|
||||||
device_->CmdBindIndexBuffer(shadow_draw, entry.index_buffer);
|
device_->CmdBindIndexBuffer(shadow_draw, entry.index_buffer);
|
||||||
device_->CmdDrawIndexed(shadow_draw, entry.index_count, 1, 0, 0, 0);
|
device_->CmdDrawIndexed(shadow_draw, entry.index_count, 1, 0, 0, 0);
|
||||||
|
BIN
test/res/models/floorwhite.glb
Normal file
BIN
test/res/models/floorwhite.glb
Normal file
Binary file not shown.
BIN
test/res/models/tree.glb
Normal file
BIN
test/res/models/tree.glb
Normal file
Binary file not shown.
@ -14,6 +14,7 @@
|
|||||||
#include "scene_manager.h"
|
#include "scene_manager.h"
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
#include <systems/collisions.h>
|
#include <systems/collisions.h>
|
||||||
|
#include <components/mesh_renderable.h>
|
||||||
|
|
||||||
CameraControllerSystem::CameraControllerSystem(engine::Scene* scene)
|
CameraControllerSystem::CameraControllerSystem(engine::Scene* scene)
|
||||||
: System(scene, {typeid(engine::TransformComponent).hash_code(), typeid(CameraControllerComponent).hash_code()})
|
: System(scene, {typeid(engine::TransformComponent).hash_code(), typeid(CameraControllerComponent).hash_code()})
|
||||||
@ -212,6 +213,8 @@ void CameraControllerSystem::OnUpdate(float ts)
|
|||||||
LOG_INFO("Ray direction: {} {} {}", ray.direction.x, ray.direction.y, ray.direction.z);
|
LOG_INFO("Ray direction: {} {} {}", ray.direction.x, ray.direction.y, ray.direction.z);
|
||||||
LOG_INFO("Hit Entity: {}", scene_->GetComponent<engine::TransformComponent>(cast.hit_entity)->tag);
|
LOG_INFO("Hit Entity: {}", scene_->GetComponent<engine::TransformComponent>(cast.hit_entity)->tag);
|
||||||
c->perm_lines.emplace_back(ray.origin, cast.location, glm::vec3{0.0f, 0.0f, 1.0f});
|
c->perm_lines.emplace_back(ray.origin, cast.location, glm::vec3{0.0f, 0.0f, 1.0f});
|
||||||
|
scene_->GetComponent<engine::MeshRenderableComponent>(cast.hit_entity)->visible ^= true;
|
||||||
|
scene_->GetSystem<engine::MeshRenderSystem>()->RebuildStaticRenderList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ void PlayGame(GameSettings settings)
|
|||||||
engine::gfx::GraphicsSettings graphics_settings{};
|
engine::gfx::GraphicsSettings graphics_settings{};
|
||||||
graphics_settings.enable_validation = settings.enable_validation;
|
graphics_settings.enable_validation = settings.enable_validation;
|
||||||
graphics_settings.vsync = true;
|
graphics_settings.vsync = true;
|
||||||
graphics_settings.wait_for_present = false;
|
graphics_settings.wait_for_present = true;
|
||||||
graphics_settings.msaa_level = engine::gfx::MSAALevel::kOff;
|
graphics_settings.msaa_level = engine::gfx::MSAALevel::kOff;
|
||||||
graphics_settings.enable_anisotropy = true;
|
graphics_settings.enable_anisotropy = true;
|
||||||
|
|
||||||
@ -94,7 +94,7 @@ void PlayGame(GameSettings settings)
|
|||||||
|
|
||||||
/* floor */
|
/* floor */
|
||||||
engine::Entity floor = engine::util::LoadGLTF(*main_scene, app.GetResourcePath("models/floor.glb"), true);
|
engine::Entity floor = engine::util::LoadGLTF(*main_scene, app.GetResourcePath("models/floor.glb"), true);
|
||||||
// main_scene->GetComponent<engine::MeshRenderableComponent>(main_scene->GetEntity("Cube", floor))->visible = false;
|
//main_scene->GetComponent<engine::MeshRenderableComponent>(main_scene->GetEntity("Cube", floor))->visible = false;
|
||||||
|
|
||||||
engine::Entity monke = engine::util::LoadGLTF(*main_scene, app.GetResourcePath("models/monke.glb"), true);
|
engine::Entity monke = engine::util::LoadGLTF(*main_scene, app.GetResourcePath("models/monke.glb"), true);
|
||||||
main_scene->GetComponent<engine::TransformComponent>(monke)->position.y += 10.0f;
|
main_scene->GetComponent<engine::TransformComponent>(monke)->position.y += 10.0f;
|
||||||
@ -141,6 +141,9 @@ void PlayGame(GameSettings settings)
|
|||||||
main_scene->GetPosition(teapot).y += 5.0f;
|
main_scene->GetPosition(teapot).y += 5.0f;
|
||||||
main_scene->GetPosition(teapot).x -= 5.0f;
|
main_scene->GetPosition(teapot).x -= 5.0f;
|
||||||
main_scene->GetScale(teapot) *= 5.0f;
|
main_scene->GetScale(teapot) *= 5.0f;
|
||||||
|
|
||||||
|
engine::Entity tree = engine::util::LoadGLTF(*main_scene, app.GetResourcePath("models/tree.glb"), true);
|
||||||
|
main_scene->GetPosition(tree) = glm::vec3{-5.0f, -5.0f, 0.0f};
|
||||||
}
|
}
|
||||||
|
|
||||||
start_scene->GetSystem<CameraControllerSystem>()->next_scene_ = main_scene;
|
start_scene->GetSystem<CameraControllerSystem>()->next_scene_ = main_scene;
|
||||||
|
Loading…
Reference in New Issue
Block a user