GPU:将浮点顶点坐标转换为定点。如何?

时间:2015-02-19 22:01:13

标签: 3d rendering gpu

我基本上试图理解在光栅化过程中将浮点顶点坐标转换为定点数时GPU是如何工作的。

我读了这篇excellent article,它解释了很多东西,但它也让我感到困惑。因此,本文解释了因为我们使用32位整数和边函数,其形式如下(a - b)*(c - d) - (e - f)*(g - h),我们仅限于范围[-16384,16383]。我理解我们如何得到这个数字。以下是我的问题:

  1. 首先,这表明顶点坐标可以是负的。然而,我不明白的是,技术上在那个阶段顶点坐标在光栅空间中,并且所有三角形之前都应该被剪裁。因此,从技术上讲,x坐标的范围[0,图像宽度]和y坐标的[0,图像高度]应该只有顶点坐标?为什么坐标为负?
  2. 所以作者解释说范围太有限[-16384,16383]。实际上,如果你的宽度为2048像素并使用256个子像素,那么x中点的坐标需要为4194048.这样你就会溢出。作者继续说明他们是如何在GPU上解决这个问题的,但我根本就没有得到它。如果有人也可以解释它在GPU上的实际操作情况,那就太棒了。

1 个答案:

答案 0 :(得分:3)

  
      
  1. 首先,这表明顶点坐标可以是负的。然而我不明白的是,技术上在那个阶段顶点坐标在光栅空间中,并且所有三角形之前都应该被剪裁。因此,从技术上讲,x坐标的范围[0,图像宽度]和y坐标的[0,图像高度]应该只有顶点坐标?为什么坐标为负?
  2.   

简短的回答是,虽然三角形已被剪裁,但它们尚未被剪切到视口(0,0 - 图像宽度,图像高度)。相反,它们被裁剪到guard-band剪裁区域,这是一个围绕视口的较大矩形。位于视口外但在保护带剪切区域内的顶点坐标可以具有负坐标。

有(至少)三种类型的三角形剪辑。第一个是“分析裁剪”,当你计算三角形边缘与保护带剪辑区域边缘的交点时,如果它们重叠,然后在这些点处切掉三角形并将其余部分细分为更小的三角形,现在每个都在剪辑区域内。第二种类型是在对着视口剪切三角形边界框时,在光栅化时找到要迭代的像素范围(注意这不会改变三角形顶点坐标)。第三种类型是文章中描述的每像素测试,您在屏幕上迭代并测试每个像素以查看它是否在三角形内。

除此之外,根据实现情况,屏幕中心可以在内部定义为(0,0)以进行剪辑计算,这意味着屏幕左侧的任何内容都将显示为负数x坐标。

  
      
  1. 所以作者解释说范围太有限[-16384,16383]。实际上,如果你的宽度为2048像素并使用256个子像素,那么x中点的坐标需要为4194048.这样你就会溢出。作者继续说明他们是如何在GPU上解决这个问题的,但我根本就没有得到它。如果有人也能解释它在GPU上的实际效果,那就太棒了。
  2.   

注意:我不是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);
}

ab是三角形顶点,而点c是屏幕坐标。对于给定的三角形,当您迭代屏幕坐标范围时,三角形顶点将保持不变,只有点c发生变化。增量评估意味着您只需计算上次评估等式时的变化。

假设我们一次评估等式并得到结果w0

w0 = (b.x-a.x)*(c.y-a.y) - (b.y-a.y)*(c.x-a.x);

然后c.x增加量s(每像素一步)。 w0的新值将是:

w0_new = (b.x-a.x)*(c.y-a.y) - (b.y-a.y)*(c.x+s-a.x);

从第二个等式中减去第一个等式,得到:

w0_new - w0 = -(b.y-a.y)*s;

-(b.y-a.y)*s是给定三角形的常量值,因为s每次都是相同的量(一个像素),而ab已经提到过不变的。我们可以计算一次并将其存储在变量中(称之为w0_step)然后计算减少到:

w0_new = w0 + w0step;

您可以对w1w2执行此操作,并对c.y步骤执行类似操作。这允许更精确的原因是每像素方程不再包含定点乘法,这是导致溢出的原因。 GPU可以每个三角形进行一次高精度计算(例如64位),然后每个像素执行一次精度较低(例如32位)。