feat: shadow mapping — depth-only render pass from light POV + PCF

- VulkanShadowMap.cs: 2048x2048 D32_SFLOAT image, sampler (clamp-to-border),
  separate shadow pipeline (depth-only, no color, depth bias enabled, CULL_NONE)
- Shadow shaders: shadow.vert (lightViewProj * model * pos), shadow.frag (empty)
- Main shaders updated: fragLightSpacePos output from vertex, PCF 3x3 in fragment
- Push constants expanded to 160B: model(64) + lightPos(16) + lightColor(16) + lightViewProj(64)
- 3 push constant ranges: Vertex(model), Fragment(light), Vertex|Fragment(lightViewProj)
- Descriptor set: 2 bindings — UBO(vp) + CombinedImageSampler(shadowMap)
- Shadow pass: before main pass, renders scene depth from light position
- Image transitions: shadow map UNDEFINED→DEPTH→SHADER_READ_ONLY each frame
- vkCmdSetDepthBias(1.25, 0, 1.75) for acne prevention
- Light VP: CreateLookAt(lightPos, origin, up) * Perspective(60°, 1.0, 0.1, 60)
- 0 validation errors on build
This commit is contained in:
emil28092005
2026-06-18 20:09:32 +03:00
parent 1dde764342
commit e6e305dfa9
13 changed files with 518 additions and 15 deletions
+19 -5
View File
@@ -150,7 +150,7 @@ internal sealed unsafe class VulkanPipeline : IDisposable
pDynamicStates = dynamicStates,
};
var pushConstantRanges = stackalloc VkPushConstantRange[2];
var pushConstantRanges = stackalloc VkPushConstantRange[3];
pushConstantRanges[0] = new VkPushConstantRange
{
stageFlags = VkShaderStageFlags.Vertex,
@@ -163,6 +163,12 @@ internal sealed unsafe class VulkanPipeline : IDisposable
offset = 64,
size = 32,
};
pushConstantRanges[2] = new VkPushConstantRange
{
stageFlags = VkShaderStageFlags.Vertex | VkShaderStageFlags.Fragment,
offset = 96,
size = 64,
};
var descLayout = DescriptorSetLayout;
var layoutInfo = new VkPipelineLayoutCreateInfo
@@ -170,7 +176,7 @@ internal sealed unsafe class VulkanPipeline : IDisposable
sType = VkStructureType.PipelineLayoutCreateInfo,
setLayoutCount = 1,
pSetLayouts = &descLayout,
pushConstantRangeCount = 2,
pushConstantRangeCount = 3,
pPushConstantRanges = (nint)pushConstantRanges,
};
@@ -221,19 +227,27 @@ internal sealed unsafe class VulkanPipeline : IDisposable
private void CreateDescriptorSetLayout()
{
var binding = new VkDescriptorSetLayoutBinding
var bindings = stackalloc VkDescriptorSetLayoutBinding[2];
bindings[0] = new VkDescriptorSetLayoutBinding
{
binding = 0,
descriptorType = VkDescriptorType.UniformBuffer,
descriptorCount = 1,
stageFlags = VkShaderStageFlags.Vertex,
};
bindings[1] = new VkDescriptorSetLayoutBinding
{
binding = 1,
descriptorType = VkDescriptorType.CombinedImageSampler,
descriptorCount = 1,
stageFlags = VkShaderStageFlags.Fragment,
};
var info = new VkDescriptorSetLayoutCreateInfo
{
sType = VkStructureType.DescriptorSetLayoutCreateInfo,
bindingCount = 1,
pBindings = &binding,
bindingCount = 2,
pBindings = bindings,
};
var descLayout = VkDescriptorSetLayout.Null;