diff --git a/src/Engine.Graphics.Vulkan/Shaders/fragment.frag b/src/Engine.Graphics.Vulkan/Shaders/fragment.frag index 7fdeaba..5a99f7b 100644 --- a/src/Engine.Graphics.Vulkan/Shaders/fragment.frag +++ b/src/Engine.Graphics.Vulkan/Shaders/fragment.frag @@ -5,7 +5,7 @@ layout(location = 1) in vec3 fragNormal; layout(location = 2) in vec3 fragWorldPos; layout(location = 3) in vec3 fragViewDir; -layout(row_major, set = 0, binding = 0) uniform FrameUBO { +layout(set = 0, binding = 0) uniform FrameUBO { vec3 cameraPosition; uint lightCount; vec3 ambientColor; @@ -47,11 +47,9 @@ void main() { float attenuation; if (dirIntensity.w < 0.0) { - // Directional light: direction stored as xyz, w = intensity (negative marks directional) lightDir = normalize(-dirIntensity.xyz); attenuation = abs(dirIntensity.w); } else { - // Point light: position stored as xyz, w = intensity (positive marks point) vec3 toLight = dirIntensity.xyz - fragWorldPos; float dist = length(toLight); lightDir = toLight / max(dist, 0.001); @@ -63,7 +61,6 @@ void main() { vec3 H = normalize(V + lightDir); float NdotL = max(dot(N, lightDir), 0.0); float NdotH = max(dot(N, H), 0.0); - float VdotH = max(dot(V, H), 0.0); float specPower = mix(128.0, 4.0, roughness); float specIntensity = pow(NdotH, specPower); diff --git a/src/Engine.Graphics.Vulkan/Shaders/fragment.spv b/src/Engine.Graphics.Vulkan/Shaders/fragment.spv index 369001b..1517e3d 100644 Binary files a/src/Engine.Graphics.Vulkan/Shaders/fragment.spv and b/src/Engine.Graphics.Vulkan/Shaders/fragment.spv differ diff --git a/src/Engine.Graphics.Vulkan/Shaders/vertex.spv b/src/Engine.Graphics.Vulkan/Shaders/vertex.spv index 65367c4..a19b2c2 100644 Binary files a/src/Engine.Graphics.Vulkan/Shaders/vertex.spv and b/src/Engine.Graphics.Vulkan/Shaders/vertex.spv differ diff --git a/src/Engine.Graphics.Vulkan/Shaders/vertex.vert b/src/Engine.Graphics.Vulkan/Shaders/vertex.vert index 2524b71..ae10582 100644 --- a/src/Engine.Graphics.Vulkan/Shaders/vertex.vert +++ b/src/Engine.Graphics.Vulkan/Shaders/vertex.vert @@ -4,7 +4,7 @@ layout(location = 0) in vec3 inPosition; layout(location = 1) in vec3 inColor; layout(location = 2) in vec3 inNormal; -layout(row_major, set = 0, binding = 0) uniform FrameUBO { +layout(set = 0, binding = 0) uniform FrameUBO { vec3 cameraPosition; uint lightCount; vec3 ambientColor; @@ -27,6 +27,10 @@ void main() { vec4 worldPos = pc.model * vec4(inPosition, 1.0); gl_Position = pc.mvp * vec4(inPosition, 1.0); + // Vulkan clip space: Y-down, Z [0,1] — convert from OpenGL Y-up, Z [-1,1] + gl_Position.y = -gl_Position.y; + gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5; + fragColor = inColor; fragNormal = normalize(mat3(pc.model) * inNormal); fragWorldPos = worldPos.xyz; diff --git a/src/Engine.Graphics.Vulkan/VulkanPipeline.cs b/src/Engine.Graphics.Vulkan/VulkanPipeline.cs index b69bfaa..333b2ad 100644 --- a/src/Engine.Graphics.Vulkan/VulkanPipeline.cs +++ b/src/Engine.Graphics.Vulkan/VulkanPipeline.cs @@ -14,7 +14,7 @@ public sealed unsafe class VulkanPipeline : IDisposable private readonly VulkanContext _ctx; private bool _disposed; - public const int PushConstantSize = 128; + public const int PushConstantSize = 144; public const int FrameUboSize = 16 + 16 + 16 * 4 * 8; public VulkanPipeline(VulkanContext ctx, VkRenderPass renderPass) @@ -84,8 +84,8 @@ public sealed unsafe class VulkanPipeline : IDisposable primitiveRestartEnable = 0 }; - var viewport = new VkViewport { x = 0, y = 0, width = 0, height = 0, minDepth = 0, maxDepth = 1 }; - var scissor = new VkRect2D { offset = new VkOffset2D { x = 0, y = 0 }, extent = new VkExtent2D { width = 0, height = 0 } }; + var viewport = new VkViewport { x = 0, y = 0, width = 1280, height = 720, minDepth = 0, maxDepth = 1 }; + var scissor = new VkRect2D { offset = new VkOffset2D { x = 0, y = 0 }, extent = new VkExtent2D { width = 1280, height = 720 } }; VkPipelineViewportStateCreateInfo viewportState; viewportState.sType = VkStructureType.PipelineViewportStateCreateInfo; @@ -163,6 +163,15 @@ public sealed unsafe class VulkanPipeline : IDisposable colorBlendState.attachmentCount = 1; colorBlendState.pAttachments = &blendAttachment; + var dynamicStates = stackalloc VkDynamicState[2]; + dynamicStates[0] = VkDynamicState.Viewport; + dynamicStates[1] = VkDynamicState.Scissor; + + VkPipelineDynamicStateCreateInfo dynamicState = default; + dynamicState.sType = VkStructureType.PipelineDynamicStateCreateInfo; + dynamicState.dynamicStateCount = 2; + dynamicState.pDynamicStates = dynamicStates; + var uboBinding = new VkDescriptorSetLayoutBinding { binding = 0, @@ -226,7 +235,7 @@ public sealed unsafe class VulkanPipeline : IDisposable pipelineInfo.pMultisampleState = &multisampleState; pipelineInfo.pDepthStencilState = &depthStencilState; pipelineInfo.pColorBlendState = &colorBlendState; - pipelineInfo.pDynamicState = null; + pipelineInfo.pDynamicState = &dynamicState; pipelineInfo.layout = pipeLayout; pipelineInfo.renderPass = renderPass; pipelineInfo.subpass = 0; diff --git a/src/Engine.Graphics.Vulkan/VulkanRenderer.cs b/src/Engine.Graphics.Vulkan/VulkanRenderer.cs index 556abf7..66209a8 100644 --- a/src/Engine.Graphics.Vulkan/VulkanRenderer.cs +++ b/src/Engine.Graphics.Vulkan/VulkanRenderer.cs @@ -475,7 +475,7 @@ public sealed unsafe class VulkanRenderer : IRenderer, IScreenshotProvider }; Vk.vkCmdSetScissor(cmd, 0, 1, &scissor); - VkDescriptorSet ds = _descriptorSets[_currentFrame]; + var ds = _descriptorSets[_currentFrame]; Vk.vkCmdBindDescriptorSets(cmd, 0, _pipeline.PipelineLayout, 0, 1, &ds, 0, null); world.Each((Entity e, ref Transform transform, ref Mesh mesh, ref Material material) => @@ -502,7 +502,7 @@ public sealed unsafe class VulkanRenderer : IRenderer, IScreenshotProvider proj = cam.GetProjectionMatrix(); }); - var mvp = model * view * proj; + var mvp = proj * view * model; var pushData = new byte[VulkanPipeline.PushConstantSize]; fixed (byte* pPush = pushData) diff --git a/src/Engine.Graphics.Vulkan/VulkanTypes.cs b/src/Engine.Graphics.Vulkan/VulkanTypes.cs index 4bdb763..e2faaa2 100644 --- a/src/Engine.Graphics.Vulkan/VulkanTypes.cs +++ b/src/Engine.Graphics.Vulkan/VulkanTypes.cs @@ -212,6 +212,12 @@ public enum VkCullModeFlags : uint FrontAndBack = 0x00000003, } +public enum VkDynamicState : int +{ + Viewport = 0, + Scissor = 1, +} + public enum VkFrontFace : int { CounterClockwise = 0, @@ -241,10 +247,10 @@ public enum VkBlendOp : int public enum VkColorComponentFlags : uint { - R = 0x00000010, - G = 0x00000020, - B = 0x00000040, - A = 0x00000080, + R = 0x00000001, + G = 0x00000002, + B = 0x00000004, + A = 0x00000008, } public enum VkCompareOp : int @@ -1169,6 +1175,16 @@ unsafe public struct VkPipelineColorBlendStateCreateInfo public fixed float blendConstants[4]; } +[StructLayout(LayoutKind.Sequential)] +unsafe public struct VkPipelineDynamicStateCreateInfo +{ + public VkStructureType sType; + public void* pNext; + public uint flags; + public uint dynamicStateCount; + public VkDynamicState* pDynamicStates; +} + [StructLayout(LayoutKind.Sequential)] unsafe public struct VkGraphicsPipelineCreateInfo { @@ -1310,11 +1326,11 @@ unsafe public struct VkRenderPassBeginInfo public VkClearValue* pClearValues; } -[StructLayout(LayoutKind.Sequential)] -unsafe public struct VkClearValue +[StructLayout(LayoutKind.Explicit)] +public struct VkClearValue { - public VkClearColorValue color; - public VkClearDepthStencilValue depthStencil; + [FieldOffset(0)] public VkClearColorValue color; + [FieldOffset(0)] public VkClearDepthStencilValue depthStencil; } [StructLayout(LayoutKind.Sequential)]