在 Vulkan/Opengl 视口外绘制

Drawing outside the viewport in Vulkan/Opengl

我有一个 viewportscreen size/framebuffer 的一半。

x, y, w, h = 0, 0, 512, 512

我的 scissor 区域是完整的 framebuffer

x, y, w, h = 0, 0, 0 1024, 512

我正在画一条线,从左到右远离 viewport。我希望这条线只在视口内绘制。我已经在三块不同的显卡上对此进行了测试,在其中两块上,我得到了我期望的结果。但是在第三个上,线绘制在 viewport 之外,但在 scissor 区域之内。 哪一个结果是正确的?据我了解,线的两个顶点应该移动到外部 viewport 位置。它不应该画在它外面。

如果您阅读本网站上的陷阱 nr 10https://www.opengl.org/archives/resources/features/KilgardTechniques/oglpitfall/

他们说的是在 viewport 之外绘制,但这只是一些特殊情况,例如你有一条很粗的线,我的线宽是 1

编辑:我下面的回答在技术上是正确的,但没有用。视口变换本身不定义剪辑体积或剪刀。但是由于视锥体的裁剪([-w,+w] 表示 x 和 y,[0,+w] 表示 z),所有进入视口变换的 (x,y) 值都将在 [-1, 1],并且不会被转换到定义视口的矩形之外。

与在 GL 中一样,视口仅定义从规范化设备坐标到帧缓冲区坐标的转换。变换基于视口体积的 width/height/depth/origin,但该体积未定义裁剪体积。 23.5 Controlling the Viewport.

部分描述了数学运算

在 Vulkan 中,您还可以在 VkPipelineViewportStateCreateInfo:: pScissorsvkCmdSetScissor 中为每个视口在帧缓冲区坐标中指定一个剪刀矩形。此矩形 之外的像素被 丢弃。但是你必须自己设置剪刀矩形,而且它不一定要匹配视口体积。

编辑:在 KhronosGroup 的讨论之后: 来自规范 Vulkan 1.0.68:

If either of a line segment’s vertices lie outside of the clip volume, the line segment may be clipped, with new vertex coordinates computed for each vertex that lies outside the clip volume. A clipped line segment endpoint lies on both the original line segment and the boundary of the clip volume.

英伟达:

We intentionally made this change for maintenance2, to allow for pop-free points and lines. Point clipping behavior is queriable but line clipping behavior is not, though I believe the "preferred" behavior for lines is to be pop-free. We changed the NVIDIA driver last year from tight clipping to pop-free, and even changed CTS tests to allow this new behavior. So this is all working as designed.

旧答案:

视口定义了从规范化设备坐标到 window 坐标的转换。视口变换不进行任何裁剪。

但是,裁剪确实发生在NDC space之前,视锥体裁剪确实保证没有顶点可以落在视口之外。如果您使用的是正交投影,剪辑 space 和 NDC space 是相同的。所以 [-1,1] 之外的所有内容都将被剪裁。如果你没有做任何特殊情况,opengl link 谈论顶点应该被剪裁。

如果您的两张显卡在视口内绘制,一张在视口外绘制,则可能是驱动程序错误。如果您使用的是相当新的 Vulkan,则很可能是这种情况。