Glsl 在Vulkan中翻转视口

Glsl 在Vulkan中翻转视口,glsl,viewport,vulkan,Glsl,Viewport,Vulkan,根据规范: VK_KHR_维护1 允许在slink::VkViewport::height字段中指定负高度,以执行 剪辑空间到帧缓冲区空间变换。这使得应用程序可以避免 还必须在着色器中使用gl_Position.y=-gl_Position.y 其他API 我的物理设备支持版本1.0.42,并且我已经启用了VK\u KHR\u维护1。 在VkViewportstruct中执行负高度时,我没有收到任何验证错误/警告 vkCmdSetViewport(vkContext.commandBuffer,

根据规范:

VK_KHR_维护1

允许在slink::VkViewport::height字段中指定负高度,以执行 剪辑空间到帧缓冲区空间变换。这使得应用程序可以避免 还必须在着色器中使用gl_Position.y=-gl_Position.y 其他API

我的物理设备支持版本
1.0.42
,并且我已经启用了
VK\u KHR\u维护1
。 在
VkViewport
struct中执行负高度时,我没有收到任何验证错误/警告

vkCmdSetViewport(vkContext.commandBuffer, 0, 1, &viewport);
但是,如果我删除
视口中的负值,我也看不到屏幕上的任何内容,它是黑色的,所有内容都按预期渲染。我是否需要执行其他操作以使用
VK_KHR_maintenance1扩展翻转视口?我只是在屏幕上渲染一个带有全屏视口的红色四边形

VkViewport viewport = {};
viewport.x = 0.0f;
viewport.y = 0.0f;
viewport.width = 1024.0f;
viewport.height = -1024.0f;
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;
vkCmdSetViewport(vkContext.commandBuffer, 0, 1, &viewport);
顶点着色器:

void main() {
        vec4 positions[3] = {
        vec4(-1.0, -1.0, 0.0, 1.0),
        vec4(3.0, -1.0, 0.0, 1.0),
        vec4(-1.0, 3.0, 0.0, 1.0)
    };
    gl_Position = positions[gl_VertexIndex % 3];
}
片段着色器:

void main() {
    outFragColor = vec4(1,0,0,1);
}

把数学做完就行了。您拥有所有的数字,规范明确地列出了所有数字

帧缓冲区空间顶点坐标的Y分量的方程式为:

Yf = (Py / 2) Yd + Oy
Oy = viewport.y + viewport.height / 2.0
Py = viewport.height
其中,
Yf
是帧缓冲区空间Y分量,
Yd
是NDC空间Y分量

如果插入1024的正
高度
,得到的数字是多少?如果
Yd
为-1,则得到
Yf
为0.0。如果
Yd
为3,则得到
Yf
为2048

在Vulkan中,“自然”视口变换通过在
viewport.x/y
中放置-1,在
viewport.width/height中放置1来映射NDC空间。请记住:Vulkan的图像有一个左上角原点,正值向下和向右移动。因此,0.0的
Yf
位于顶部,2048的
Yf
位于屏幕底部。因此,三角形(部分)位于视口的可见区域中

考虑到这一点,当使用负的
高度时会发生什么?数学没有改变;只是结果。对于-1的
Yd
,您将得到0.0的
Yf
,与之前的情况非常相似。如果
Yd
为3,则得到
Yf
为-2048

那是什么样子的?嗯,视口的含义没有改变;只是数字。这意味着帧缓冲区图像的可见区域仍然位于左上角,向下移动。因此,视口上方的值为-2048

VkViewport viewport = {};
viewport.x = 0.0f;
viewport.y = 0.0f;
viewport.width = 1024.0f;
viewport.height = -1024.0f;
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;
vkCmdSetViewport(vkContext.commandBuffer, 0, 1, &viewport);
简而言之,负高度将翻转视口。但这会在视口原点而不是屏幕中心翻转它。视口原点位于左上角,向下和向右。因此,翻转它将翻转屏幕上以前可见的所有内容。您现在看到的是屏幕的另一个区域,在您的情况下,该区域是空白的


如果要围绕视口中心翻转所有对象,则需要调整
viewport.y
以补偿负高度。具体来说,它需要是正高度。

“但是我也看不到屏幕上的任何内容”您正在渲染什么?你的VS看起来像什么?你的投影矩阵是什么样子的?
viewport
包含什么?等等如果不看你的代码,我们就无法知道发生了什么。@NicolBolas添加了顶点和碎片着色器谢谢,这是一个非常好的解释,我认为Vulkan是在翻转视口并移动场景后面的原点,当你设置负高度时:)NicolBolas引用的公式可以在中找到。