在Vulkan中翻转视口

时间:2017-08-08 13:55:21

标签: glsl viewport vulkan

来自规范:

  

VK_KHR_maintenance1

     

允许在slink :: VkViewport :: height字段中指定负高度以执行y的反转   clip-space to framebuffer-space transform。这允许应用程序避免   必须在着色器中使用gl_Position.y = -gl_Position.y   其他API。

我的物理设备支持版本1.0.42,我启用了VK_KHR_maintenance1。 当我在VkViewport结构中执行负高度时,我没有得到任何验证错误/警告。

vkCmdSetViewport(vkContext.commandBuffer, 0, 1, &viewport);

但是我在屏幕上看不到任何内容,它是黑色的,如果我删除viewport中的负值,则所有内容都按预期呈现。我是否需要执行其他操作才能使用VK_KHR_maintenance1 extension翻转视口?我只是在屏幕上渲染一个红色四边形,带有全屏视口。

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);
}

1 个答案:

答案 0 :(得分:10)

完成数学考试。您拥有所有数字,并且规范明确规定了所有数字。

帧缓冲空间顶点坐标的Y分量的等式是:

Yf = (Py / 2) Yd + Oy
Oy = viewport.y + viewport.height / 2.0
Py = viewport.y

其中Yf是帧缓冲空间Y分量,Yd是NDC空间Y分量。

如果你插入1024的正height,你会得到什么数字?如果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位于屏幕底部。因此,三角形(部分)位于视口的可见区域中。

鉴于此,当您使用否定height时会发生什么?数学不会改变;只是结果。对于Yd的-1,您得到的Yf为0.0,与之前非常相似。如果Yd为3,则得到Yf的-2048。

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

简而言之,负高度会翻转视口。但是它会在视口原点处翻转,而不是在屏幕的中心。视口原点位于左上方和右上方。因此,翻转它将翻转之前在屏幕上可见的所有内容。您现在正在查看屏幕的不同区域,在您的情况下是空白区域。

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