在 Vulkan/Opengl 视口外绘制
Drawing outside the viewport in Vulkan/Opengl
我有一个 viewport
是 screen 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 10
:
https://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:: pScissors
或 vkCmdSetScissor
中为每个视口在帧缓冲区坐标中指定一个剪刀矩形。此矩形 之外的像素被 丢弃。但是你必须自己设置剪刀矩形,而且它不一定要匹配视口体积。
编辑:在 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,则很可能是这种情况。
我有一个 viewport
是 screen 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 10
:
https://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:: pScissors
或 vkCmdSetScissor
中为每个视口在帧缓冲区坐标中指定一个剪刀矩形。此矩形 之外的像素被 丢弃。但是你必须自己设置剪刀矩形,而且它不一定要匹配视口体积。
编辑:在 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,则很可能是这种情况。