From 41fe5a6fb5e5a3379b1368c615ec4f6ac00094b2 Mon Sep 17 00:00:00 2001 From: swinston Date: Thu, 20 Aug 2026 20:05:02 -0700 Subject: [PATCH] Flip Y at the viewport stage instead of in the projection matrix --- attachments/22_descriptor_layout.cpp | 4 ++-- attachments/23_descriptor_sets.cpp | 4 ++-- attachments/24_texture_image.cpp | 4 ++-- attachments/25_sampler.cpp | 4 ++-- attachments/26_texture_mapping.cpp | 4 ++-- attachments/27_depth_buffering.cpp | 4 ++-- attachments/28_model_loading.cpp | 4 ++-- attachments/29_mipmapping.cpp | 4 ++-- attachments/30_multisampling.cpp | 4 ++-- attachments/32_ecosystem_utilities.cpp | 4 ++-- attachments/33_vulkan_profiles.cpp | 6 +++--- attachments/34_android.cpp | 6 +++--- attachments/35_gltf_ktx.cpp | 4 ++-- attachments/36_multiple_objects.cpp | 4 ++-- attachments/38_ray_tracing.cpp | 4 ++-- .../00_Descriptor_set_layout_and_buffer.adoc | 15 +++++++++++---- en/16_Multiple_Objects.adoc | 1 - 17 files changed, 43 insertions(+), 37 deletions(-) diff --git a/attachments/22_descriptor_layout.cpp b/attachments/22_descriptor_layout.cpp index 833553111..15d2f6c22 100644 --- a/attachments/22_descriptor_layout.cpp +++ b/attachments/22_descriptor_layout.cpp @@ -600,7 +600,8 @@ class HelloTriangleApplication .pColorAttachments = &attachmentInfo}; commandBuffer.beginRendering(renderingInfo); commandBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, *graphicsPipeline); - commandBuffer.setViewport(0, vk::Viewport(0.0f, 0.0f, static_cast(swapChainExtent.width), static_cast(swapChainExtent.height), 0.0f, 1.0f)); + // Negative height flips Y for Vulkan; see Uniform buffers. + commandBuffer.setViewport(0, vk::Viewport(0.0f, static_cast(swapChainExtent.height), static_cast(swapChainExtent.width), -static_cast(swapChainExtent.height), 0.0f, 1.0f)); commandBuffer.setScissor(0, vk::Rect2D(vk::Offset2D(0, 0), swapChainExtent)); commandBuffer.bindVertexBuffers(0, *vertexBuffer, {0}); commandBuffer.bindIndexBuffer(*indexBuffer, 0, vk::IndexTypeValue::value); @@ -680,7 +681,6 @@ class HelloTriangleApplication ubo.view = lookAt(glm::vec3(2.0f, 2.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f)); ubo.proj = glm::perspective(glm::radians(45.0f), static_cast(swapChainExtent.width) / static_cast(swapChainExtent.height), 0.1f, 10.0f); - ubo.proj[1][1] *= -1; memcpy(uniformBuffersMapped[currentImage], &ubo, sizeof(ubo)); } diff --git a/attachments/23_descriptor_sets.cpp b/attachments/23_descriptor_sets.cpp index 881abc5c4..2c9b99b43 100644 --- a/attachments/23_descriptor_sets.cpp +++ b/attachments/23_descriptor_sets.cpp @@ -634,7 +634,8 @@ class HelloTriangleApplication .pColorAttachments = &attachmentInfo}; commandBuffer.beginRendering(renderingInfo); commandBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, *graphicsPipeline); - commandBuffer.setViewport(0, vk::Viewport(0.0f, 0.0f, static_cast(swapChainExtent.width), static_cast(swapChainExtent.height), 0.0f, 1.0f)); + // Negative height flips Y for Vulkan; see Uniform buffers. + commandBuffer.setViewport(0, vk::Viewport(0.0f, static_cast(swapChainExtent.height), static_cast(swapChainExtent.width), -static_cast(swapChainExtent.height), 0.0f, 1.0f)); commandBuffer.setScissor(0, vk::Rect2D(vk::Offset2D(0, 0), swapChainExtent)); commandBuffer.bindVertexBuffers(0, *vertexBuffer, {0}); commandBuffer.bindIndexBuffer(*indexBuffer, 0, vk::IndexTypeValue::value); @@ -715,7 +716,6 @@ class HelloTriangleApplication ubo.view = lookAt(glm::vec3(2.0f, 2.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f)); ubo.proj = glm::perspective(glm::radians(45.0f), static_cast(swapChainExtent.width) / static_cast(swapChainExtent.height), 0.1f, 10.0f); - ubo.proj[1][1] *= -1; memcpy(uniformBuffersMapped[currentImage], &ubo, sizeof(ubo)); } diff --git a/attachments/24_texture_image.cpp b/attachments/24_texture_image.cpp index b8d61315d..6f652530d 100644 --- a/attachments/24_texture_image.cpp +++ b/attachments/24_texture_image.cpp @@ -761,7 +761,8 @@ class HelloTriangleApplication .pColorAttachments = &attachmentInfo}; commandBuffer.beginRendering(renderingInfo); commandBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, *graphicsPipeline); - commandBuffer.setViewport(0, vk::Viewport(0.0f, 0.0f, static_cast(swapChainExtent.width), static_cast(swapChainExtent.height), 0.0f, 1.0f)); + // Negative height flips Y for Vulkan; see Uniform buffers. + commandBuffer.setViewport(0, vk::Viewport(0.0f, static_cast(swapChainExtent.height), static_cast(swapChainExtent.width), -static_cast(swapChainExtent.height), 0.0f, 1.0f)); commandBuffer.setScissor(0, vk::Rect2D(vk::Offset2D(0, 0), swapChainExtent)); commandBuffer.bindVertexBuffers(0, *vertexBuffer, {0}); commandBuffer.bindIndexBuffer(*indexBuffer, 0, vk::IndexTypeValue::value); @@ -842,7 +843,6 @@ class HelloTriangleApplication ubo.view = lookAt(glm::vec3(2.0f, 2.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f)); ubo.proj = glm::perspective(glm::radians(45.0f), static_cast(swapChainExtent.width) / static_cast(swapChainExtent.height), 0.1f, 10.0f); - ubo.proj[1][1] *= -1; memcpy(uniformBuffersMapped[currentImage], &ubo, sizeof(ubo)); } diff --git a/attachments/25_sampler.cpp b/attachments/25_sampler.cpp index 0608f1727..55e25d79e 100644 --- a/attachments/25_sampler.cpp +++ b/attachments/25_sampler.cpp @@ -787,7 +787,8 @@ class HelloTriangleApplication .pColorAttachments = &attachmentInfo}; commandBuffer.beginRendering(renderingInfo); commandBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, *graphicsPipeline); - commandBuffer.setViewport(0, vk::Viewport(0.0f, 0.0f, static_cast(swapChainExtent.width), static_cast(swapChainExtent.height), 0.0f, 1.0f)); + // Negative height flips Y for Vulkan; see Uniform buffers. + commandBuffer.setViewport(0, vk::Viewport(0.0f, static_cast(swapChainExtent.height), static_cast(swapChainExtent.width), -static_cast(swapChainExtent.height), 0.0f, 1.0f)); commandBuffer.setScissor(0, vk::Rect2D(vk::Offset2D(0, 0), swapChainExtent)); commandBuffer.bindVertexBuffers(0, *vertexBuffer, {0}); commandBuffer.bindIndexBuffer(*indexBuffer, 0, vk::IndexTypeValue::value); @@ -868,7 +869,6 @@ class HelloTriangleApplication ubo.view = lookAt(glm::vec3(2.0f, 2.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f)); ubo.proj = glm::perspective(glm::radians(45.0f), static_cast(swapChainExtent.width) / static_cast(swapChainExtent.height), 0.1f, 10.0f); - ubo.proj[1][1] *= -1; memcpy(uniformBuffersMapped[currentImage], &ubo, sizeof(ubo)); } diff --git a/attachments/26_texture_mapping.cpp b/attachments/26_texture_mapping.cpp index 268111919..0c971c299 100644 --- a/attachments/26_texture_mapping.cpp +++ b/attachments/26_texture_mapping.cpp @@ -803,7 +803,8 @@ class HelloTriangleApplication .pColorAttachments = &attachmentInfo}; commandBuffer.beginRendering(renderingInfo); commandBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, *graphicsPipeline); - commandBuffer.setViewport(0, vk::Viewport(0.0f, 0.0f, static_cast(swapChainExtent.width), static_cast(swapChainExtent.height), 0.0f, 1.0f)); + // Negative height flips Y for Vulkan; see Uniform buffers. + commandBuffer.setViewport(0, vk::Viewport(0.0f, static_cast(swapChainExtent.height), static_cast(swapChainExtent.width), -static_cast(swapChainExtent.height), 0.0f, 1.0f)); commandBuffer.setScissor(0, vk::Rect2D(vk::Offset2D(0, 0), swapChainExtent)); commandBuffer.bindVertexBuffers(0, *vertexBuffer, {0}); commandBuffer.bindIndexBuffer(*indexBuffer, 0, vk::IndexTypeValue::value); @@ -884,7 +885,6 @@ class HelloTriangleApplication ubo.view = lookAt(glm::vec3(2.0f, 2.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f)); ubo.proj = glm::perspective(glm::radians(45.0f), static_cast(swapChainExtent.width) / static_cast(swapChainExtent.height), 0.1f, 10.0f); - ubo.proj[1][1] *= -1; memcpy(uniformBuffersMapped[currentImage], &ubo, sizeof(ubo)); } diff --git a/attachments/27_depth_buffering.cpp b/attachments/27_depth_buffering.cpp index dfb24250e..6e6f58945 100644 --- a/attachments/27_depth_buffering.cpp +++ b/attachments/27_depth_buffering.cpp @@ -881,7 +881,8 @@ class HelloTriangleApplication commandBuffer.beginRendering(renderingInfo); commandBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, *graphicsPipeline); - commandBuffer.setViewport(0, vk::Viewport(0.0f, 0.0f, static_cast(swapChainExtent.width), static_cast(swapChainExtent.height), 0.0f, 1.0f)); + // Negative height flips Y for Vulkan; see Uniform buffers. + commandBuffer.setViewport(0, vk::Viewport(0.0f, static_cast(swapChainExtent.height), static_cast(swapChainExtent.width), -static_cast(swapChainExtent.height), 0.0f, 1.0f)); commandBuffer.setScissor(0, vk::Rect2D(vk::Offset2D(0, 0), swapChainExtent)); commandBuffer.bindVertexBuffers(0, *vertexBuffer, {0}); commandBuffer.bindIndexBuffer(*indexBuffer, 0, vk::IndexTypeValue::value); @@ -963,7 +964,6 @@ class HelloTriangleApplication ubo.view = lookAt(glm::vec3(2.0f, 2.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f)); ubo.proj = glm::perspective(glm::radians(45.0f), static_cast(swapChainExtent.width) / static_cast(swapChainExtent.height), 0.1f, 10.0f); - ubo.proj[1][1] *= -1; memcpy(uniformBuffersMapped[currentImage], &ubo, sizeof(ubo)); } diff --git a/attachments/28_model_loading.cpp b/attachments/28_model_loading.cpp index fe4ada523..29944e923 100644 --- a/attachments/28_model_loading.cpp +++ b/attachments/28_model_loading.cpp @@ -935,7 +935,8 @@ class HelloTriangleApplication commandBuffer.beginRendering(renderingInfo); commandBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, *graphicsPipeline); - commandBuffer.setViewport(0, vk::Viewport(0.0f, 0.0f, static_cast(swapChainExtent.width), static_cast(swapChainExtent.height), 0.0f, 1.0f)); + // Negative height flips Y for Vulkan; see Uniform buffers. + commandBuffer.setViewport(0, vk::Viewport(0.0f, static_cast(swapChainExtent.height), static_cast(swapChainExtent.width), -static_cast(swapChainExtent.height), 0.0f, 1.0f)); commandBuffer.setScissor(0, vk::Rect2D(vk::Offset2D(0, 0), swapChainExtent)); commandBuffer.bindVertexBuffers(0, *vertexBuffer, {0}); commandBuffer.bindIndexBuffer(*indexBuffer, 0, vk::IndexTypeValue::value); @@ -1017,7 +1018,6 @@ class HelloTriangleApplication ubo.view = lookAt(glm::vec3(2.0f, 2.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f)); ubo.proj = glm::perspective(glm::radians(45.0f), static_cast(swapChainExtent.width) / static_cast(swapChainExtent.height), 0.1f, 10.0f); - ubo.proj[1][1] *= -1; memcpy(uniformBuffersMapped[currentImage], &ubo, sizeof(ubo)); } diff --git a/attachments/29_mipmapping.cpp b/attachments/29_mipmapping.cpp index d80a73cb1..8913e0287 100644 --- a/attachments/29_mipmapping.cpp +++ b/attachments/29_mipmapping.cpp @@ -1021,7 +1021,8 @@ class HelloTriangleApplication commandBuffer.beginRendering(renderingInfo); commandBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, *graphicsPipeline); - commandBuffer.setViewport(0, vk::Viewport(0.0f, 0.0f, static_cast(swapChainExtent.width), static_cast(swapChainExtent.height), 0.0f, 1.0f)); + // Negative height flips Y for Vulkan; see Uniform buffers. + commandBuffer.setViewport(0, vk::Viewport(0.0f, static_cast(swapChainExtent.height), static_cast(swapChainExtent.width), -static_cast(swapChainExtent.height), 0.0f, 1.0f)); commandBuffer.setScissor(0, vk::Rect2D(vk::Offset2D(0, 0), swapChainExtent)); commandBuffer.bindVertexBuffers(0, *vertexBuffer, {0}); commandBuffer.bindIndexBuffer(*indexBuffer, 0, vk::IndexTypeValue::value); @@ -1103,7 +1104,6 @@ class HelloTriangleApplication ubo.view = lookAt(glm::vec3(2.0f, 2.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f)); ubo.proj = glm::perspective(glm::radians(45.0f), static_cast(swapChainExtent.width) / static_cast(swapChainExtent.height), 0.1f, 10.0f); - ubo.proj[1][1] *= -1; memcpy(uniformBuffersMapped[currentImage], &ubo, sizeof(ubo)); } diff --git a/attachments/30_multisampling.cpp b/attachments/30_multisampling.cpp index 9a312fa2b..ea7d9a4e4 100644 --- a/attachments/30_multisampling.cpp +++ b/attachments/30_multisampling.cpp @@ -1097,7 +1097,8 @@ class HelloTriangleApplication .pDepthAttachment = &depthAttachment}; commandBuffer.beginRendering(renderingInfo); commandBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, *graphicsPipeline); - commandBuffer.setViewport(0, vk::Viewport(0.0f, 0.0f, static_cast(swapChainExtent.width), static_cast(swapChainExtent.height), 0.0f, 1.0f)); + // Negative height flips Y for Vulkan; see Uniform buffers. + commandBuffer.setViewport(0, vk::Viewport(0.0f, static_cast(swapChainExtent.height), static_cast(swapChainExtent.width), -static_cast(swapChainExtent.height), 0.0f, 1.0f)); commandBuffer.setScissor(0, vk::Rect2D(vk::Offset2D(0, 0), swapChainExtent)); commandBuffer.bindVertexBuffers(0, *vertexBuffer, {0}); commandBuffer.bindIndexBuffer(*indexBuffer, 0, vk::IndexTypeValue::value); @@ -1179,7 +1180,6 @@ class HelloTriangleApplication ubo.view = lookAt(glm::vec3(2.0f, 2.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f)); ubo.proj = glm::perspective(glm::radians(45.0f), static_cast(swapChainExtent.width) / static_cast(swapChainExtent.height), 0.1f, 10.0f); - ubo.proj[1][1] *= -1; memcpy(uniformBuffersMapped[currentImage], &ubo, sizeof(ubo)); } diff --git a/attachments/32_ecosystem_utilities.cpp b/attachments/32_ecosystem_utilities.cpp index a0a4c2d2f..51b8ceb01 100644 --- a/attachments/32_ecosystem_utilities.cpp +++ b/attachments/32_ecosystem_utilities.cpp @@ -1482,7 +1482,8 @@ class HelloTriangleApplication // Common rendering commands commandBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, *graphicsPipeline); - commandBuffer.setViewport(0, vk::Viewport(0.0f, 0.0f, static_cast(swapChainExtent.width), static_cast(swapChainExtent.height), 0.0f, 1.0f)); + // Negative height flips Y for Vulkan; see Uniform buffers. + commandBuffer.setViewport(0, vk::Viewport(0.0f, static_cast(swapChainExtent.height), static_cast(swapChainExtent.width), -static_cast(swapChainExtent.height), 0.0f, 1.0f)); commandBuffer.setScissor(0, vk::Rect2D(vk::Offset2D(0, 0), swapChainExtent)); commandBuffer.bindVertexBuffers(0, *vertexBuffer, {0}); commandBuffer.bindIndexBuffer(*indexBuffer, 0, vk::IndexType::eUint32); @@ -1582,7 +1583,6 @@ class HelloTriangleApplication ubo.model = rotate(glm::mat4(1.0f), time * glm::radians(90.0f), glm::vec3(0.0f, 0.0f, 1.0f)); ubo.view = lookAt(glm::vec3(2.0f, 2.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f)); ubo.proj = glm::perspective(glm::radians(45.0f), static_cast(swapChainExtent.width) / static_cast(swapChainExtent.height), 0.1f, 10.0f); - ubo.proj[1][1] *= -1; memcpy(uniformBuffersMapped[currentImage], &ubo, sizeof(ubo)); } diff --git a/attachments/33_vulkan_profiles.cpp b/attachments/33_vulkan_profiles.cpp index 4b1268e57..f53b25562 100644 --- a/attachments/33_vulkan_profiles.cpp +++ b/attachments/33_vulkan_profiles.cpp @@ -1443,11 +1443,12 @@ class HelloTriangleApplication commandBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, *graphicsPipeline); + // Negative height flips Y for Vulkan; see Uniform buffers. vk::Viewport viewport{ .x = 0.0f, - .y = 0.0f, + .y = static_cast(swapChainExtent.height), .width = static_cast(swapChainExtent.width), - .height = static_cast(swapChainExtent.height), + .height = -static_cast(swapChainExtent.height), .minDepth = 0.0f, .maxDepth = 1.0f}; commandBuffer.setViewport(0, viewport); @@ -1554,7 +1555,6 @@ class HelloTriangleApplication ubo.model = glm::rotate(glm::mat4(1.0f), time * glm::radians(90.0f), glm::vec3(0.0f, 0.0f, 1.0f)); ubo.view = glm::lookAt(glm::vec3(2.0f, 2.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f)); ubo.proj = glm::perspective(glm::radians(45.0f), swapChainExtent.width / (float) swapChainExtent.height, 0.1f, 10.0f); - ubo.proj[1][1] *= -1; memcpy(uniformBuffersMapped[currentImage], &ubo, sizeof(ubo)); } diff --git a/attachments/34_android.cpp b/attachments/34_android.cpp index c32c63610..5956949d1 100644 --- a/attachments/34_android.cpp +++ b/attachments/34_android.cpp @@ -1293,11 +1293,12 @@ class HelloTriangleApplication commandBuffer.beginRenderPass(renderPassInfo, vk::SubpassContents::eInline); commandBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, *graphicsPipeline); + // Negative height flips Y for Vulkan; see Uniform buffers. vk::Viewport viewport{ .x = 0.0f, - .y = 0.0f, + .y = static_cast(swapChainExtent.height), .width = static_cast(swapChainExtent.width), - .height = static_cast(swapChainExtent.height), + .height = -static_cast(swapChainExtent.height), .minDepth = 0.0f, .maxDepth = 1.0f}; commandBuffer.setViewport(0, viewport); @@ -1750,7 +1751,6 @@ class HelloTriangleApplication ubo.model = glm::rotate(glm::mat4(1.0f), time * glm::radians(90.0f), glm::vec3(0.0f, 0.0f, 1.0f)); ubo.view = glm::lookAt(glm::vec3(2.0f, 2.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f)); ubo.proj = glm::perspective(glm::radians(45.0f), swapChainExtent.width / (float) swapChainExtent.height, 0.1f, 10.0f); - ubo.proj[1][1] *= -1; void *data; data = uniformBuffersMemory[currentImage].mapMemory(0, sizeof(ubo)); diff --git a/attachments/35_gltf_ktx.cpp b/attachments/35_gltf_ktx.cpp index 777010f40..617f1ea2e 100644 --- a/attachments/35_gltf_ktx.cpp +++ b/attachments/35_gltf_ktx.cpp @@ -1299,7 +1299,8 @@ class VulkanApplication .pDepthAttachment = &depthAttachmentInfo}; commandBuffer.beginRendering(renderingInfo); commandBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, *graphicsPipeline); - commandBuffer.setViewport(0, vk::Viewport(0.0f, 0.0f, static_cast(swapChainExtent.width), static_cast(swapChainExtent.height), 0.0f, 1.0f)); + // Negative height flips Y for Vulkan; see Uniform buffers. + commandBuffer.setViewport(0, vk::Viewport(0.0f, static_cast(swapChainExtent.height), static_cast(swapChainExtent.width), -static_cast(swapChainExtent.height), 0.0f, 1.0f)); commandBuffer.setScissor(0, vk::Rect2D(vk::Offset2D(0, 0), swapChainExtent)); commandBuffer.bindVertexBuffers(0, *vertexBuffer, {0}); commandBuffer.bindIndexBuffer(*indexBuffer, 0, vk::IndexType::eUint32); @@ -1381,7 +1382,6 @@ class VulkanApplication ubo.model = continuousRotation * initialRotation; ubo.view = lookAt(glm::vec3(2.0f, 2.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f)); ubo.proj = glm::perspective(glm::radians(45.0f), static_cast(swapChainExtent.width) / static_cast(swapChainExtent.height), 0.1f, 10.0f); - ubo.proj[1][1] *= -1; memcpy(uniformBuffersMapped[currentImage], &ubo, sizeof(ubo)); } diff --git a/attachments/36_multiple_objects.cpp b/attachments/36_multiple_objects.cpp index 9afc90037..b7c8bbac9 100644 --- a/attachments/36_multiple_objects.cpp +++ b/attachments/36_multiple_objects.cpp @@ -1399,7 +1399,8 @@ class VulkanApplication .pDepthAttachment = &depthAttachmentInfo}; commandBuffer.beginRendering(renderingInfo); commandBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, *graphicsPipeline); - commandBuffer.setViewport(0, vk::Viewport(0.0f, 0.0f, static_cast(swapChainExtent.width), static_cast(swapChainExtent.height), 0.0f, 1.0f)); + // Negative height flips Y for Vulkan; see Uniform buffers. + commandBuffer.setViewport(0, vk::Viewport(0.0f, static_cast(swapChainExtent.height), static_cast(swapChainExtent.width), -static_cast(swapChainExtent.height), 0.0f, 1.0f)); commandBuffer.setScissor(0, vk::Rect2D(vk::Offset2D(0, 0), swapChainExtent)); // Bind vertex and index buffers (shared by all objects) @@ -1496,7 +1497,6 @@ class VulkanApplication // Camera and projection matrices (shared by all objects) glm::mat4 view = glm::lookAt(glm::vec3(2.0f, 2.0f, 6.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f)); glm::mat4 proj = glm::perspective(glm::radians(45.0f), static_cast(swapChainExtent.width) / static_cast(swapChainExtent.height), 0.1f, 20.0f); - proj[1][1] *= -1; // Update uniform buffers for each object for (auto &gameObject : gameObjects) diff --git a/attachments/38_ray_tracing.cpp b/attachments/38_ray_tracing.cpp index e0843931c..d12972fa7 100644 --- a/attachments/38_ray_tracing.cpp +++ b/attachments/38_ray_tracing.cpp @@ -1636,7 +1636,8 @@ class VulkanRaytracingApplication commandBuffer.beginRendering(renderingInfo); commandBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, *graphicsPipeline); - commandBuffer.setViewport(0, vk::Viewport(0.0f, 0.0f, static_cast(swapChainExtent.width), static_cast(swapChainExtent.height), 0.0f, 1.0f)); + // Negative height flips Y for Vulkan; see Uniform buffers. + commandBuffer.setViewport(0, vk::Viewport(0.0f, static_cast(swapChainExtent.height), static_cast(swapChainExtent.width), -static_cast(swapChainExtent.height), 0.0f, 1.0f)); commandBuffer.setScissor(0, vk::Rect2D(vk::Offset2D(0, 0), swapChainExtent)); commandBuffer.bindVertexBuffers(0, *vertexBuffer, {0}); commandBuffer.bindIndexBuffer(*indexBuffer, 0, vk::IndexType::eUint32); @@ -1736,7 +1737,6 @@ class VulkanRaytracingApplication ubo.model = rotate(glm::mat4(1.0f), time * 0.1f * glm::radians(90.0f), glm::vec3(0.0f, 0.0f, 1.0f)); ubo.view = lookAt(eye, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f)); ubo.proj = glm::perspective(glm::radians(45.0f), static_cast(swapChainExtent.width) / static_cast(swapChainExtent.height), 0.1f, 10.0f); - ubo.proj[1][1] *= -1; ubo.cameraPos = eye; memcpy(uniformBuffersMapped[currentImage], &ubo, sizeof(ubo)); diff --git a/en/05_Uniform_buffers/00_Descriptor_set_layout_and_buffer.adoc b/en/05_Uniform_buffers/00_Descriptor_set_layout_and_buffer.adoc index 7c43b218a..2569b9841 100644 --- a/en/05_Uniform_buffers/00_Descriptor_set_layout_and_buffer.adoc +++ b/en/05_Uniform_buffers/00_Descriptor_set_layout_and_buffer.adoc @@ -329,14 +329,21 @@ I've chosen to use a perspective projection with a 45 degree vertical field-of-v The other parameters are the aspect ratio, near and far view planes. It is important to use the current swap chain extent to calculate the aspect ratio to take into account the new width and height of the window after a resize. +GLM was originally designed for OpenGL, where the Y coordinate of the clip coordinates is inverted compared to Vulkan. +If you don't compensate for that somewhere, the image will be rendered upside down. + +One common way to compensate is to flip the sign of the Y scaling factor in the projection matrix (`ubo.proj[1][1] *= -1;`). +That works, but it also flips the handedness of the projection matrix, which then requires flipping `frontFace` wherever back-face culling is enabled, and can trip up anything downstream that assumes a standard right-handed projection. +Instead, we'll apply the same correction at the viewport stage, where it doesn't affect the projection matrix at all. +Go back to the `vk::Viewport` you set up in xref:03_Drawing/01_Command_buffers.adoc[Command buffers] and give it a negative height: + [,c++] ---- -ubo.proj[1][1] *= -1; +commandBuffer.setViewport(0, vk::Viewport(0.0f, static_cast(swapChainExtent.height), static_cast(swapChainExtent.width), -static_cast(swapChainExtent.height), 0.0f, 1.0f)); ---- -GLM was originally designed for OpenGL, where the Y coordinate of the clip coordinates is inverted. -The easiest way to compensate for that is to flip the sign on the scaling factor of the Y axis in the projection matrix. -If you don't do this, then the image will be rendered upside down. +Setting `y` to the full height and `height` to its negative flips the Y axis during the viewport transform, which is applied after clipping - the net effect on the final image is identical to flipping the projection matrix, but the projection matrix itself, and therefore its handedness, is left alone. +This is core Vulkan functionality (promoted from `VK_KHR_maintenance1`), so no extra feature or extension needs to be enabled. All of the transformations are defined now, so we can copy the data in the uniform buffer object to the current uniform buffer. This happens in exactly the same way as we did for vertex buffers, except without a staging buffer. diff --git a/en/16_Multiple_Objects.adoc b/en/16_Multiple_Objects.adoc index c84b017e5..852c599fe 100644 --- a/en/16_Multiple_Objects.adoc +++ b/en/16_Multiple_Objects.adoc @@ -238,7 +238,6 @@ void updateUniformBuffers() { glm::mat4 proj = glm::perspective(glm::radians(45.0f), static_cast(swapChainExtent.width) / static_cast(swapChainExtent.height), 0.1f, 20.0f); - proj[1][1] *= -1; // Flip Y for Vulkan // Update uniform buffers for each object for (auto& gameObject : gameObjects) {