From b36c5f3f699ef35788e0ebb064d62bcb66af7648 Mon Sep 17 00:00:00 2001 From: 1sgtpepper <165563006+1sgtpepper@users.noreply.github.com> Date: Thu, 29 Oct 2026 00:53:36 +0800 Subject: [PATCH] Clarify viewport Y-flipping and front-face winding --- .../00_Descriptor_set_layout_and_buffer.adoc | 11 +++++++---- .../01_Descriptor_pool_and_sets.adoc | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) 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 5be0ec1d..d9d8e1b2 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 @@ -333,8 +333,8 @@ GLM was originally designed for OpenGL, where the Y coordinate of the clip coord 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. +That changes the clip-space Y coordinates and, after perspective division, the normalized device coordinates. +Instead, we'll apply the same correction at the viewport stage, leaving the projection matrix and those coordinates unchanged. Go back to the `vk::Viewport` you set up in xref:03_Drawing_a_triangle/03_Drawing/01_Command_buffers.adoc[Command buffers] and give it a negative height: [,c++] @@ -342,8 +342,11 @@ Go back to the `vk::Viewport` you set up in xref:03_Drawing_a_triangle/03_Drawin commandBuffer.setViewport(0, vk::Viewport(0.0f, static_cast(swapChainExtent.height), static_cast(swapChainExtent.width), -static_cast(swapChainExtent.height), 0.0f, 1.0f)); ---- -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. +Setting `y` to the full height and `height` to its negative flips the Y axis during the viewport transform, which is applied after clipping. +Both approaches reverse triangle winding in framebuffer coordinates, which Vulkan uses to determine link:https://docs.vulkan.org/refpages/latest/refpages/source/VkFrontFace.html[front-facing triangles]. +A negative viewport height therefore does not remove the need to choose `frontFace` consistently with that winding when culling is enabled. +We'll make the corresponding `frontFace` adjustment for this tutorial in the xref:./01_Descriptor_pool_and_sets.adoc[next chapter]. +Negative viewport height 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/05_Uniform_buffers/01_Descriptor_pool_and_sets.adoc b/en/05_Uniform_buffers/01_Descriptor_pool_and_sets.adoc index 1aba2cba..f32fac01 100644 --- a/en/05_Uniform_buffers/01_Descriptor_pool_and_sets.adoc +++ b/en/05_Uniform_buffers/01_Descriptor_pool_and_sets.adoc @@ -188,7 +188,7 @@ The last parameter specifies an array of offsets that are used for dynamic descr We'll look at these in a future chapter. If you run your program now, then you'll notice that unfortunately nothing is visible. -The problem is that because of the Y-flip we did in the projection matrix, the vertices are now being drawn in counter-clockwise order instead of clockwise order. +The problem is that because of the Y-flip we applied using a negative viewport height, the vertices now have counter-clockwise winding in framebuffer coordinates instead of clockwise winding. This causes backface culling to kick in and prevents any geometry from being drawn. Go to the `createGraphicsPipeline` function and modify the `frontFace` in `vk::PipelineRasterizationStateCreateInfo` to correct this: