C++ 光栅化算法:查找;";二维四边形和逆投影中的点坐标

C++ 光栅化算法:查找;";二维四边形和逆投影中的点坐标,c++,3d,rendering,rasterizing,C++,3d,Rendering,Rasterizing,我的目标是使用光栅化算法渲染四边形的图像。我曾: 在3D中创建四边形 使用透视分割将四边形顶点投影到屏幕上 将结果坐标从屏幕空间转换为光栅空间,并在光栅空间中计算四边形的边界框 在该边界框内的所有像素上循环,并找出当前像素P是否包含在四边形中。为此,我使用了一个简单的测试,包括在四边形的边AB和顶点a和点P之间定义的向量之间取点。我对所有4条边重复此过程,如果符号相同,则该点位于四边形内 我已经成功地实现了这一点(参见下面的代码)。但是我被我想玩的剩下的部分卡住了,基本上就是找到我的四元体的

我的目标是使用光栅化算法渲染四边形的图像。我曾:

  • 在3D中创建四边形
  • 使用透视分割将四边形顶点投影到屏幕上
  • 将结果坐标从屏幕空间转换为光栅空间,并在光栅空间中计算四边形的边界框
  • 在该边界框内的所有像素上循环,并找出当前像素P是否包含在四边形中。为此,我使用了一个简单的测试,包括在四边形的边AB和顶点a和点P之间定义的向量之间取点。我对所有4条边重复此过程,如果符号相同,则该点位于四边形内
我已经成功地实现了这一点(参见下面的代码)。但是我被我想玩的剩下的部分卡住了,基本上就是找到我的四元体的st或纹理坐标

  • 我不知道是否有可能在光栅空间中找到当前像素P的st坐标,然后将其转换回世界空间?你能告诉我正确的方向吗?告诉我怎么做
  • 或者,如何计算四边形中包含的像素的z值或深度值。我想这与在四边形中找到点的st坐标有关,然后插值顶点的z值
附言:这不是家庭作业。我这样做是为了理解光栅化算法,而我现在所处的位置正是我不理解的地方,我相信GPU渲染管道涉及某种反向投影,但我只是在这一点上迷失了方向。谢谢你的帮助

    Vec3f verts[4]; // vertices of the quad in world space
    Vec2f vraster[4]; // vertices of the quad in raster space
    uint8_t outside = 0; // is the quad in raster space visible at all?
    Vec2i bmin(10e8), bmax(-10e8);
    for (uint32_t j = 0; j < 4; ++j) {
        // transform unit quad to world position by transforming each
        // one of its vertices by a transformation matrix (represented
        // here by 3 unit vectors and a translation value)
        verts[j].x = quads[j].x * right.x + quads[j].y * up.x + quads[j].z * forward.x + pt[i].x;
        verts[j].y = quads[j].x * right.y + quads[j].y * up.y + quads[j].z * forward.y + pt[i].y;
        verts[j].z = quads[j].x * right.z + quads[j].y * up.z + quads[j].z * forward.z + pt[i].z;

        // project the vertices on the image plane (perspective divide)
        verts[j].x /= -verts[j].z;
        verts[j].y /= -verts[j].z;

        // assume the image plane is 1 unit away from the eye
        // and fov = 90 degrees, thus bottom-left and top-right
        // coordinates of the screen are (-1,-1) and (1,1) respectively.
        if (fabs(verts[j].x) > 1 || fabs(verts[j].y) > 1) outside |= (1 << j);

        // convert image plane coordinates to raster
        vraster[j].x = (int32_t)((verts[j].x + 1) * 0.5 * width);
        vraster[j].y = (int32_t)((1 - (verts[j].y + 1) * 0.5) * width);


        // compute box of the quad in raster space
        if (vraster[j].x < bmin.x) bmin.x = (int)std::floor(vraster[j].x);
        if (vraster[j].y < bmin.y) bmin.y = (int)std::floor(vraster[j].y);
        if (vraster[j].x > bmax.x) bmax.x = (int)std::ceil(vraster[j].x);
        if (vraster[j].y > bmax.y) bmax.y = (int)std::ceil(vraster[j].y);
    }

    // cull if all vertices are outside the canvas boundaries
    if (outside == 0x0F) continue;

    // precompute edge of quad
    Vec2f edges[4];
    for (uint32_t j = 0; j < 4; ++j) {
        edges[j] = vraster[(j + 1) % 4] - vraster[j];
    }

    // loop over all pixels contained in box
    for (int32_t y = std::max(0, bmin.y); y <= std::min((int32_t)(width -1), bmax.y); ++y) {
        for (int32_t x = std::max(0, bmin.x); x <= std::min((int32_t)(width -1), bmax.x); ++x) {
            bool inside = true;
            for (uint32_t j = 0; j < 4 && inside; ++j) {
                Vec2f v = Vec2f(x + 0.5, y + 0.5) - vraster[j];
                float d = edges[j].x * v.x + edges[j].y * v.y;
                inside &= (d > 0);
            }
            // pixel is inside quad, mark in the image
            if (inside) {
                buffer[y * width + x] = 255;
            }
        }
    }
Vec3f顶点[4];//世界空间中四边形的顶点
Vec2f vraster[4];//光栅空间中四边形的顶点
uint8\u t外部=0;//光栅空间中的四边形是否可见?
Vec2i体重指数(10e8),bmax(-10e8);
对于(uint32_t j=0;j<4;++j){
//通过变换每个单元,将单元四边形变换为世界位置
//它的一个顶点由变换矩阵(表示为
//这里由3个单位向量和一个平移值组成)
顶点[j].x=quads[j].x*右.x+quads[j].y*向上.x+quads[j].z*向前.x+pt[i].x;
顶点[j].y=quads[j].x*右.y+quads[j].y*向上.y+quads[j].z*向前.y+pt[i].y;
顶点[j].z=quads[j].x*右.z+quads[j].y*向上.z+quads[j].z*向前.z+pt[i].z;
//在图像平面上投影顶点(透视分割)
顶点[j].x/=-verts[j].z;
顶点[j].y/=-verts[j].z;
//假设图像平面距离眼睛1个单位
//fov=90度,因此为左下角和右上角
//屏幕的坐标分别为(-1,-1)和(1,1)。
如果(fabs(verts[j].x)>1 | | fabs(verts[j].y)>1)外部|=(1 bmax.x)bmax.x=(int)std::ceil(vraster[j].x);
if(vraster[j].y>bmax.y)bmax.y=(int)std::ceil(vraster[j].y);
}
//如果所有顶点都在画布边界之外,则剔除
如果(外部==0x0F)继续;
//四边形边缘的预计算
Vec2f边[4];
对于(uint32_t j=0;j<4;++j){
边[j]=vraster[(j+1)%4]-vraster[j];
}
//循环框中包含的所有像素

对于(Tn32)y= STD::max(0,bmin。y);我认为,你的第一步是考虑三角形的光栅化。这就是现代硬件所做的。四元组有模糊性,例如,它们可能不是共面的。它们可能不是凸的。显然,一个四元可以分解成两个不受这些问题影响的三角形。(尽管三角形可以是背面或退化,如果其点“足够接近”共线(参见:有符号区域测试)。我建议你选择一个像OpenGL那样记录光栅化的API。我鼓励你了解重心坐标,以及插值如何应用于一般顶点属性。谢谢你的评论和鼓励。我会得到一个使用三角形的版本,但最终我也会考虑使用四边形。我正在尝试为了使它尽可能快,当然必须处理2个三角形,而不是1个四边形,这会使事情变慢。稍后将发布工作代码。我理解你所说的三角形,但我想做的是实现REYES算法中使用的技术:“通过插值计算采样点处微多边形的z。”,其中,微多边形是一个四边形,所以我希望也这样做()。我将尝试使用三角形选项,因为它似乎是基本选项,但仍然不知道它们如何使用四边形插值z值。