1

私の目標は、ラスター化アルゴリズムを使用してクワッドの画像をレンダリングすることです。私はこれまでに行ってきました:

  • 3D でクワッドを作成する
  • 透視分割を使用して四角形の頂点を画面に投影する
  • 結果の座標を画面空間からラスター空間に変換し、ラスター空間で四角形の境界ボックスを計算します
  • この境界ボックス内のすべてのピクセルをループし、現在のピクセル P がクワッド内に含まれているかどうかを調べます。このために、クワッドのエッジ AB と、頂点 A と点 P の間で定義されたベクトルの間のドットを取得する簡単なテストを使用しています。4 つのエッジすべてに対してこのプロセスを繰り返し、符号が同じ場合は、ポイントはクワッドの内側にあります。

これを正常に実装しました(以下のコードを参照)。しかし、基本的にクワッドのstまたはテクスチャ座標を見つけることで、遊んでみたい残りのビットで立ち往生しています。

  • ラスター空間のクワッドで現在のピクセル P の st 座標を見つけて、それをワールド空間に変換できるかどうかわかりませんか? これを行う方法を教えてください。
  • または、クワッドに含まれるピクセルの z または深度値を計算するにはどうすればよいですか。クワッド内のポイントの st 座標を見つけて、頂点の z 値を補間することに関連していると思いますか?

PS: これは宿題ではありません。私はラスター化アルゴリズムを理解するためにこれを行いますが、まさに今行き詰まっているのは、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;
            }
        }
    }
4

0 に答える 0