Моя цель — визуализировать изображение четырехугольника с помощью алгоритма растеризации. Я был так далеко, как:
- создание четырехугольника в 3D
- проецирование вершин четырехугольника на экран с помощью разделения перспективы
- преобразование полученных координат из экранного пространства в растровое пространство и вычисление ограничивающей рамки четырехугольника в растровом пространстве
- перебирая все пиксели внутри этой ограничивающей рамки и выясняя, содержится ли текущий пиксель P в квадрате. Для этого я использую простой тест, который состоит в том, чтобы взять точку между ребром AB четырехугольника и вектором, определенным между вершиной A и точкой P. Я повторяю этот процесс для всех 4 ребер, и если знак тот же, тогда точка находится внутри четырехугольника.
Я успешно реализовал это (см. код ниже). Но я застрял с оставшимися битами, с которыми я хотел бы поиграть, по сути, найти координаты st или текстуры моего четырехугольника.
- Я не знаю, можно ли найти st-координаты текущего пикселя P в квадроцикле в растровом пространстве, а затем преобразовать их обратно в мировое пространство? Не могли бы вы, пожалуйста, указать мне в правильном направлении, скажите мне, как это сделать?
- в качестве альтернативы, как я могу вычислить значение z или глубины пикселя, содержащегося в четырехугольнике. Я предполагаю, что это связано с поиском координат st точки в квадрате, а затем с интерполяцией значений z вершин?
PS: это НЕ домашнее задание. Я делаю это, чтобы понять алгоритм растеризации, и именно там, где я сейчас застрял, я не понимаю, что, как я полагаю, в конвейере рендеринга графического процессора включает какую-то обратную проекцию, но я просто потерялся в этот момент. Спасибо за вашу помощь.
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;
}
}
}