我基本上试图了解在光栅化过程中将浮点顶点坐标转换为定点数时GPU是如何工作的.
我读过这篇很好的文章,它解释了很多东西,但它也让我困惑.所以文章解释说因为我们使用32位整数和边缘函数,如下面的形式(a - b)*(c - d) - (e - f)*(g - h),我们被限制在范围[-16384,16383].我理解我们如何得到这个数字.这是我的问题:
- 首先,这表明顶点坐标可以为负。然而我不明白的是,从技术上讲,在该阶段顶点坐标位于光栅空间中,并且所有三角形之前都应该被剪裁。因此从技术上讲,x 坐标的顶点坐标应该在 [0,图像宽度] 范围内,y 坐标的范围在 [0,图像高度] 范围内?那么为什么坐标是负数呢?
简短的答案是,虽然三角形已被裁剪,但它们尚未被裁剪到视口(0,0 - 图像宽度,图像高度)。相反,它们被剪切到保护带剪切区域,该区域是围绕视口的较大矩形。位于视口外部但位于保护带剪切区域内的顶点坐标可以具有负坐标。
(至少)有三种类型的三角形裁剪。第一个是“分析剪切”,即计算三角形边缘与防护带剪切区域边缘重叠的交集,然后在这些点处切断三角形并将其剩余部分细分为更小的三角形,每个现在都位于剪辑区域内。第二种类型是当三角形边界框相对于视口进行裁剪以查找光栅化时要迭代的像素范围时(请注意,这不会更改三角形顶点坐标)。第三种类型是本文中描述的每像素测试,您在屏幕上迭代并测试每个像素以查看它是否在三角形内。
除此之外,根据实现的不同,屏幕中心可以在内部定义为 (0,0),以便进行裁剪计算,这意味着屏幕左侧的任何内容都将具有负 x 坐标。
- 所以作者解释说范围太有限了[-16384,16383]。事实上,如果宽度为 2048 像素并使用 256 个子像素,则 x 中的点的坐标将需要为 4194048。因此您会溢出。作者继续解释他们如何在 GPU 上解决这个问题,但我就是不明白。如果有人也能解释它是如何在 GPU 上实际完成的,那就太好了。
注意:我不是 GPU 工程师,所以这只是一个高级概念答案:
文章中给出的解释中的关键词是增量评估。看一下orient2d等式:
int orient2d(const Point2D& a, const Point2D& b, const Point2D& c)
{
return (b.x-a.x)*(c.y-a.y) - (b.y-a.y)*(c.x-a.x);
}
Run Code Online (Sandbox Code Playgroud)
点a和b是三角形顶点,而点c是屏幕坐标。对于给定的三角形,当您迭代屏幕坐标范围时,三角形顶点将保持不变,只有点发生c变化。增量评估意味着您只需计算自上次评估方程以来发生的变化。
假设我们对方程求值一次并得到结果w0:
w0 = (b.x-a.x)*(c.y-a.y) - (b.y-a.y)*(c.x-a.x);
Run Code Online (Sandbox Code Playgroud)
然后c.x增加一定量s(每像素步长)。的新值w0将是:
w0_new = (b.x-a.x)*(c.y-a.y) - (b.y-a.y)*(c.x+s-a.x);
Run Code Online (Sandbox Code Playgroud)
用第二个方程减去第一个方程,我们得到:
w0_new - w0 = -(b.y-a.y)*s;
Run Code Online (Sandbox Code Playgroud)
-(b.y-a.y)*s是给定三角形的常数值,因为s每次的量相同(一个像素),并且正如已经提到的,a和b也是常数。我们可以计算一次并将其存储在一个变量中(称为w0_step),然后计算减少为:
w0_new = w0 + w0step;
Run Code Online (Sandbox Code Playgroud)
您可以对w1和执行此操作w2,也可以对步骤执行类似的操作c.y。这允许更高精度的原因是每像素方程不再包含定点乘法,这就是导致溢出的原因。GPU 可以对每个三角形(例如,64 位)进行一次高精度计算,然后对每个像素(例如,32 位)进行一次较低精度的计算。
| 归档时间: |
|
| 查看次数: |
525 次 |
| 最近记录: |