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

标签 3d rendering gpu

我本质上是想了解在光栅化期间将 float 顶点坐标转换为定点数时 GPU 是如何工作的。

我读了 excellent article这已经解释了很多事情,但它也让我感到困惑。所以文章解释说,因为我们使用 32 位整数和如下形式的边缘函数 (a - b)*(c - d) - (e - f)*(g - h) ,我们被限制在 [-16384,16383] 范围内。我明白我们是如何得到这个数字的。以下是我的问题:

  • 首先,这表明顶点坐标可以是负数。但是我不明白的是,在那个阶段,顶点坐标在技术上是在光栅空间中,所有的三角形都应该在之前被剪裁过。因此从技术上讲,x坐标应该只有[0,图像宽度]范围内的顶点坐标,y坐标应该只有[0,图像高度]范围内的顶点坐标?那么为什么坐标是负数呢?
  • 所以作者解释范围太有限[-16384,16383]。实际上,如果您的宽度为 2048 像素并使用 256 个子像素,则 x 中点的坐标需要为 4194048。因此您会溢出。作者继续解释他们如何在 GPU 上解决这个问题,但我根本不明白。如果有人也可以解释它实际上是如何在 GPU 上完成的,那就太好了。
  • 最佳答案

    1. First, this suggests that vertex coordinates can be negative. However what I don't understand is that technically at that stage vertex coordinates are in raster space, and all triangles should have been clipped before. Thus technically there should only be vertex coordinates in the range [0, image width] for the x-coordinate and [0, image height] for the y-coordinate? So why are coordinates negative?


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

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

    最重要的是,根据实现,屏幕中心可以在内部定义为 (0,0) 以用于裁剪计算,这意味着屏幕左侧的任何东西都将具有负 x 坐标.

    1. So the author explains the range is too limited [-16384,16383]. Indeed if you have a 2048 pixels in width and use 256 sub-pixels then the coordinate of the point in x would need to be 4194048. Thus you would get overflow. The author keeps going and explains how they do it on the GPU to work around this problem, but I simply don't get it. If someone could also explain how it's practically done on the GPU then it would be great.


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

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

    关于3d - GPU:将浮点顶点坐标转换为定点。如何?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28617839/

    相关文章:

    java - 尝试打印无框图像

    image - Matlab 中图像的 3D 图

    python - 如何在曲面图上投影一条线?

    JavaScript 表格分页呈现 JSON 数据

    android - 统一2017 : Canvas Not Rendering on Build

    multithreading - OpenMP 可以用于 GPU 吗?

    memory - 您可以获得多接近 GPU 理论内存带宽?

    java - 在 OpenGL 中从单个 VBO 渲染任意大小的实例

    c++ - 在 3D 环境中识别模式

    android - 如何拦截 Android OpenGL ES 中的触摸屏事件?