我试图渲染一个单一方向光源在Vulkan产生的基本阴影。
问题是,我得到的结果是没有意义的(至少对我来说)。
阴影映射输出
深度值似乎是正确的。由于右下角的几何部分被着色到更深的颜色,就像预期的那样,因为它们更接近光的视图。也没有出现任何精确性或裁剪问题。
用于呈现调试四角体的着色器代码如下:
# VERT
#version 450 core
layout(location = 0) in vec3 a_Position;
layout(location = 1) in vec2 a_UV;
layout(location = 2) in vec3 a_Normal;
layout(location = 3) in vec3 a_Tangent;
layout(location = 4) in vec3 a_Bitangent;
layout(location = 0) out vec2 v_UV;
layout(binding = 0) uniform ModelMat
{
mat4 Matrix;
} Model;
layout(binding = 1) uniform ProjMatrix
{
mat4 Matrix;
} Proj;
layout(binding = 2) uniform viewMatrix
{
mat4 Matrix;
} View;
void main()
{
v_UV = a_UV;
gl_Position = Proj.Matrix * View.Matrix * Model.Matrix * vec4(a_Position, 1.0);
}
# FRAGMENT
#version 450 core
layout(location = 0) out vec4 FragColor;
layout(location = 0) in vec2 v_UV;
layout(binding = 3) uniform sampler2D depthMap;
void main()
{
float depthValue = texture(depthMap, v_UV).r;
//FragColor = vec4(vec3(depthValue), 1.0);
if(depthValue < 1.0)
{
depthValue = (depthValue / 1.0) * 0.2;
}
FragColor = vec4(vec3(depthValue, 0.0, 0.0), 1.0);
}
这里有几件事要注意:
将阴影映射的最近深度值呈现到几何图形上
我已经尝试过从其他讨论中学到的一些调试技巧。
我将阴影映射中的采样值呈现到模型上,这为我提供了以下结果:
模型。
float near_plane = 20.0f;
float far_plane = 60.0f;
glm::mat4 lightView = glm::lookAt(directionalLightPosition, glm::vec3(0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
glm::mat4 lightProjectionMatrix = glm::ortho(-40.0f, 40.0f, -40.0f, 40.0f, near_plane, far_plane);
glm::vec3 directionalLightPosition = glm::vec3(30.0f, 30.0f, 30.0f);
#version 430 core
// INs
layout(location = 0) in vec3 v_Pos;
layout(location = 1) in vec2 v_UV;
layout(location = 2) in vec3 v_Normal;
layout(location = 3) in vec4 v_FragPosLightSpace;
layout(location = 4) in vec3 v_DirLightPos;
layout(location = 5) in mat3 v_TBN;
layout(binding = 5) uniform CameraPosition
{
vec3 pos;
} camPos;
layout(binding = 6) uniform PointLightPosition
{
vec3 pos;
} pointLightPos;
layout(binding = 7) uniform sampler2D u_DiffuseSampler;
layout(binding = 8) uniform sampler2D u_NormalSampler;
layout(binding = 9) uniform sampler2D u_RoughnessMetallicSampler;
layout(binding = 10) uniform sampler2D u_DirectionalShadowMap;
layout(location = 0) out vec4 FragColor;
void main()
{
// BLINN PHONG
vec3 N = texture(u_NormalSampler, v_UV).rgb;
N = N * 2.0 - 1.0;
N = normalize(v_TBN * N);
vec3 color = texture(u_DiffuseSampler, v_UV).rgb;
vec3 normal = N;
vec3 lightColor = vec3(0.3);
// ambient
vec3 ambient = 0.05 * lightColor;
// diffuse
vec3 lightDir = normalize(v_DirLightPos - v_Pos);
float diff = max(dot(lightDir, normal), 0.0);
vec3 diffuse = diff * lightColor;
// specular
vec3 viewDir = normalize(camPos.pos - v_Pos);
vec3 reflectDir = reflect(-lightDir, normal);
float spec = 0.0;
vec3 halfwayDir = normalize(lightDir + viewDir);
spec = pow(max(dot(normal, halfwayDir), 0.0), 64.0);
vec3 specular = spec * lightColor;
// calculate shadow
//SHADOW
//vec3 projCoords = v_FragPosLightSpace.xyz / v_FragPosLightSpace.w;
vec3 projCoords = v_FragPosLightSpace.xyz;
vec3 altCoords = projCoords * 0.5 + 0.5;
float closestDepth = texture(u_DirectionalShadowMap, altCoords.xy).r;
float bias = 0.005;
float currentDepth = projCoords.z;
float shadow = (currentDepth - bias) > closestDepth ? 1.0 : 0.0;
vec3 lighting = (ambient + (1.0 - shadow) * (diffuse + specular)) * color;
FragColor = vec4(vec3(closestDepth), 1.0);
}
好了!注意:取消注释行//vec3 projCoords = v_FragPosLightSpace.xyz / v_FragPosLightSpace.w;
并注释掉行vec3 projCoords = v_FragPosLightSpace.xyz;
使模型完全变成白色(1.0f深度)。
#version 450
// INs
layout(location = 0) in vec3 a_Position;
layout(location = 1) in vec2 a_UV;
layout(location = 2) in vec3 a_Normal;
layout(location = 3) in vec3 a_Tangent;
layout(location = 4) in vec3 a_Bitangent;
//OUTs
layout(location = 0) out vec3 v_Pos;
layout(location = 1) out vec2 v_UV;
layout(location = 2) out vec3 v_Normal;
layout(location = 3) out vec4 v_FragPosLightSpace;
layout(location = 4) out vec3 v_DirLightPos;
layout(location = 5) out mat3 v_TBN;
layout(binding = 0) uniform ModelMatrix
{
mat4 ModelMat;
} Model;
layout(binding = 1) uniform ViewMatrix
{
mat4 ViewMat;
} View;
layout(binding = 2) uniform ProjectionMatrix
{
mat4 ProjMat;
} Proj;
layout(binding = 3) uniform DirectionalLightPosition
{
vec3 pos;
} dirLightPos;
layout(binding = 4) uniform light
{
mat4 Matrix;
} lightViewProj;
void main()
{
v_UV = a_UV;
v_Pos = vec3(Model.ModelMat * vec4(a_Position, 1.0));
v_Normal = mat3(Model.ModelMat) * a_Normal;
mat3 normalMatrix = transpose(mat3(Model.ModelMat));
vec3 T = normalize(normalMatrix * a_Tangent);
vec3 N = normalize(normalMatrix * a_Normal);
vec3 B = normalize(normalMatrix * a_Bitangent);
T = normalize(T - dot(T, N) * N);
v_TBN = mat3(T, B, N);
gl_Position = Proj.ProjMat * View.ViewMat * Model.ModelMat * vec4(a_Position, 1.0);
v_FragPosLightSpace = (lightViewProj.Matrix * Model.ModelMat) * vec4(v_Pos, 1.0);
v_DirLightPos = dirLightPos.pos;
我在这里的思考过程:
其他地方寻找罪犯
VkAttachmentDescription depthAttachmentDescription;
VkAttachmentReference depthAttachmentRef;
depthAttachmentDescription.format = VK_FORMAT_D16_UNORM;
depthAttachmentDescription.samples = VK_SAMPLE_COUNT_1_BIT;
depthAttachmentDescription.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
depthAttachmentDescription.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
depthAttachmentDescription.flags = 0;
depthAttachmentDescription.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
depthAttachmentDescription.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
depthAttachmentDescription.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
depthAttachmentDescription.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
depthAttachmentRef.attachment = 0;
depthAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
VkSubpassDescription subpass{};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.colorAttachmentCount = 0;
subpass.pColorAttachments = 0;
subpass.pDepthStencilAttachment = &depthAttachmentRef;
std::array<VkSubpassDependency, 2> dependencies;
dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL;
dependencies[0].dstSubpass = 0;
dependencies[0].srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
dependencies[0].dstStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
dependencies[0].srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
dependencies[0].dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
dependencies[1].srcSubpass = 0;
dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL;
dependencies[1].srcStageMask = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
dependencies[1].dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
dependencies[1].srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
dependencies[1].dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
VkRenderPassCreateInfo renderPassInfo{};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
renderPassInfo.attachmentCount = 1;
renderPassInfo.pAttachments = &depthAttachmentDescription;
renderPassInfo.subpassCount = 1;
renderPassInfo.pSubpasses = &subpass;
renderPassInfo.dependencyCount = static_cast<uint32_t>(dependencies.size());
renderPassInfo.pDependencies = dependencies.data();
VkRenderPass renderPass;
ASSERT(vkCreateRenderPass(VulkanApplication::GetVKDevice(), &renderPassInfo, nullptr, &renderPass) == VK_SUCCESS, "Failed to create a render pass.");
VK_FORMAT_D16_UNORM
。任何指点都会受到赞赏。别对我太客气了,我在这方面很新。谢谢!
编辑
我设法调试了一下情况,现在情况看起来好多了。但是阴影仍然不起作用。
我改变的是:
v_FragPosLightSpace = (lightViewProj.Matrix * Model.ModelMat) * vec4(v_Pos, 1.0);
在我的顶点着色器是不正确的。我去掉了多余的* Model.ModelMat
乘法。VkViewport viewport{};
viewport.x = 0.0f;
viewport.y = (float)m_CI.ViewportHeight;
viewport.width = (float)m_CI.ViewportWidth;
viewport.height = -(float)m_CI.ViewportHeight;
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;
出于某种原因,我试图翻转视口,并将阴影呈现为那样。上述代码已转换为以下代码:
VkViewport viewport{};
viewport.x = 0.0f;
viewport.y = 0.0f;
viewport.width = (float)m_CI.ViewportWidth;
viewport.height = (float)m_CI.ViewportHeight;
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;
我现在用矩阵乘法翻转深度图,同时设置投影矩阵:
glm::mat4 clip = glm::mat4(
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, -1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.5f, 0.0f,
0.0f, 0.0f, 0.5f, 1.0f);
glm::mat4 lightProjectionMatrix = clip * glm::ortho(-20.0f, 20.0f, -20.0f, 20.0f, near_plane, far_plane);
这就解决了阴影地图的方向/颠倒问题。
发布于 2022-08-11 21:33:29
我已经成功地让阴影起作用了!如果有人和我犯同样的错误,我会在这里发个答复。Vulkan是一种不同的动物,社区可以利用他们所能得到的所有信息。
所以就这样说:
错误/更改数字1)我不知道这会产生多大的影响,但我已经将投影矩阵从正字法改为透视法。MVP的整个设置如下:
glm::vec3 directionalLightPosition = glm::vec3(200.0f, 000.0f, 0.0f);
float near_plane = 50.0f;
float far_plane = 1000.0f;
glm::mat4 lightView = glm::lookAt(directionalLightPosition, glm::vec3(0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
glm::mat4 lightProjectionMatrix = glm::perspective(glm::radians(45.0f), 1.0f, near_plane, far_plane);
glm::mat4 lightModel = glm::mat4(1.0f);
glm::mat4 depthMVP;
depthMVP = lightProjectionMatrix * lightView * lightModel;
错误2),这是与Vulkan有关的错误。我把不正确的数据传递给我的顶点着色器。我在我的树形着色器中有以下布局:
layout(binding = 0) uniform ModelMatrix
{
mat4 ModelMat;
} Model;
layout(binding = 1) uniform ViewMatrix
{
mat4 ViewMat;
} View;
layout(binding = 2) uniform ProjectionMatrix
{
mat4 ProjMat;
} Proj;
layout(binding = 3) uniform DirectionalLightPosition
{
vec3 pos;
} dirLightPos;
layout(binding = 4) uniform light
{
mat4 Matrix;
} lightViewProj;
绑定号3和4在主机中由于某种原因被交换。我试图传递绑定3到4的数据,反之亦然。这显然是一个毁灭性的错误。这个程序给了我一些类似于我在问题中分享的深度图的图像,这是一个奇迹。
错误/改变数字3) Vulkan的Y轴被翻转,Z范围减半。我在写着色器时没有考虑到这一点。我很快地看了Sascha的影子映射例子,我看到他将方向光的MVP矩阵与偏置矩阵相乘。
我的顶点着色器现在看起来是这样的:
#version 450
// INs
layout(location = 0) in vec3 a_Position;
layout(location = 1) in vec2 a_UV;
layout(location = 2) in vec3 a_Normal;
layout(location = 3) in vec3 a_Tangent;
layout(location = 4) in vec3 a_Bitangent;
//OUTs
layout(location = 0) out vec3 v_Pos;
layout(location = 1) out vec2 v_UV;
layout(location = 2) out vec3 v_Normal;
layout(location = 3) out vec4 v_FragPosLightSpace;
layout(location = 4) out vec3 v_DirLightPos;
layout(location = 5) out mat3 v_TBN;
layout(binding = 0) uniform ModelMatrix
{
mat4 ModelMat;
} Model;
layout(binding = 1) uniform ViewMatrix
{
mat4 ViewMat;
} View;
layout(binding = 2) uniform ProjectionMatrix
{
mat4 ProjMat;
} Proj;
layout(binding = 3) uniform depthMVP
{
mat4 Matrix;
} lightMVP;
layout(binding = 4) uniform DirectionalLightPosition
{
vec3 pos;
} dirLightPos;
const mat4 bias = mat4(
0.5, 0.0, 0.0, 0.0,
0.0, 0.5, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.5, 0.5, 0.0, 1.0 );
void main()
{
v_UV = a_UV;
v_Pos = vec3(Model.ModelMat * vec4(a_Position, 1.0));
v_Normal = mat3(Model.ModelMat) * a_Normal;
mat3 normalMatrix = transpose(mat3(Model.ModelMat));
vec3 T = normalize(normalMatrix * a_Tangent);
vec3 N = normalize(normalMatrix * a_Normal);
vec3 B = normalize(normalMatrix * a_Bitangent);
T = normalize(T - dot(T, N) * N);
v_TBN = mat3(T, B, N);
v_FragPosLightSpace = bias * lightMVP.Matrix * Model.ModelMat * vec4(a_Position, 1.0);
v_DirLightPos = dirLightPos.pos;
gl_Position = Proj.ProjMat * View.ViewMat * Model.ModelMat * vec4(a_Position, 1.0);
}
v_FragPosLightSpace = bias * lightMVP.Matrix * Model.ModelMat * vec4(a_Position, 1.0);
部分碎片着色器是笔直的。我不打算分享整个事情,因为我已经切换到PBR,它是冗长的,但重要的部分如下:
float shadow = 1.0;
vec4 shadowCoords = v_FragPosLightSpace / v_FragPosLightSpace.w;
if( texture( u_DirectionalShadowMap, shadowCoords.xy ).r < shadowCoords.z - 0.005 )
{
shadow = 0.0;
}
https://stackoverflow.com/questions/73284425
复制相似问题