glViewport:宽度/高度是整数(即像素)。
但是 glViewportIndexed 有这些浮点值。让它们浮动有什么好处。我的理解是基于像素总是整数的事实。
看起来glViewport*()
调用指定了像素矩形。但如果你看一下 OpenGL 渲染管道的细节,情况并非如此。它们指定视口转换的参数。这是将标准化设备坐标 (NDC) 映射到窗口坐标的转换。
如果x
、y
和是您指定的视口尺寸w
和NDC 坐标,则视口转换可以这样写:h
xNdc
yNdc
xWin = x + 0.5 * (xNdc + 1.0) * w;
yWin = y + 0.5 * (yNdc + 1.0) * h;
在这个计算中xNdc
,yNdc
当然是浮点值,在它们通常的 (-1.0, 1.0) 范围内。我看不出有什么充分的理由为什么x
,和在此计算y
中应该限制为整数值。此转换在光栅化之前应用,因此无需将任何内容四舍五入为像素单位。w
h
视口尺寸不需要整数值甚至可能实际上很有用。假设你有一个大小为 1000x1000 的窗口,并且你想在窗口中渲染 9 个大小相等的子视图。API 没有理由阻止您做最自然的事情:使每个子视图的大小为 333.3333x333.3333,并将这些大小用于glViewport()
.
如果您glScissorIndexed()
进行比较,您会注意到它仍然采用整数坐标。这是完全有道理的,因为gScissor()
实际上确实指定了窗口中的像素区域,不像glViewport()
.
在评论中回答你的新问题会很困难,所以即使 Reto Koradi 已经回答了你的问题,我也会在这里尝试回答。
@AndonM.Coleman,好的。但是为什么 glViewport 的 x,y,w,h 是整数呢?
可能是因为在glViewport (...)
创建的时候,没有可编程的管道。即使在那个时候,有时也会使用亚像素偏移(特别是在尝试匹配 和 之类的光栅化覆盖规则时GL_LINES
)GL_TRIANGLES
,但它们必须应用于变换矩阵。
现在您可以使用视口变换来做同样的事情,这比将一个巨大的mat4
(16 个标量)传递给几何着色器要简单得多(视口需要 4 个标量)。
它是将视口转换应用于所有视口还是仅应用于第一个视口。
GL_ARB_viewport_array
扩展规范:
glViewport
将所有视口的参数设置为相同的值,并且等效于(假设没有生成错误):for (GLuint i = 0; i < GL_MAX_VIEWPORTS; i++) glViewportIndexedf(i, 1, (GLfloat)x, (GLfloat)y, (GLfloat)w, (GLfloat)h);
@AndonM.Coleman,第二个问题:如果 VIEWPORT_SUBPIXEL_BITS 返回值 4,那么 gl_FragCoord.xy 的值是否具有偏移量 (0,0) (0.5, 0) (0, 0.5) 和 (0.5, 0.5) ?
如果您有 4 位的亚像素精度,那么这意味着转换后的顶点位置将被捕捉到像素宽度的1 / 16的位置。GL 在这里实际上不需要任何子像素位;在这种情况下,您在转换为窗口空间后的顶点位置将一次跳跃 1 个像素的距离,并且当您在场景中移动任何东西时,您会看到很多“闪光”。
看到相机移动时的白点了吗?如果在转换顶点时没有足够的亚像素精度,则光栅化器将难以正确处理应该相邻的边缘。技术术语是 T-Junction Error,但我非常喜欢“闪亮”这个词;)
至于gl_FragCoord.xy
,在顶点变换期间实际上不受您的子像素精度的影响。那是您片段中的样本位置(通常与您指出的... + 0.5对齐),它与顶点处理无关。