Реализация алгоритма Z-буфера - PullRequest
1 голос
/ 12 января 2020

Я пытаюсь поэкспериментировать с компьютерной графикой и хотел бы реализовать алгоритм Z-буфера для рендеринга в программном обеспечении.

Поэтому я пытаюсь использовать следующее уравнение плоскости:

z = -(ax + by + d)/c

Чтобы вычислить координату Z пикселя, используя уравнение плоской формы, я должен вычислить нормали лица треугольника? или нормали вершины достаточно?

Вот как я это вычисляю:

double zValueOfPoint(float vx, float vy, float vz, float x, float y, float nx, float ny, float nz)
{
    float A = nx;
    float B = ny;
    float C = nz;
    float D = -(nx*vx, +ny * vy + nz * vz);
    float z = -(A*x + B * y + D) / C;
    return z;
}

vx, vy, вершина vz, x, y пиксельная координата, nx, ny, nz нормаль вершины

Теперь для каждого TOP или Bottom Triangle я проверяю пиксель Z Pixel на ZBuffer

// Top of the triangle
    for (int y = y0; y<y2; y++)
    {

        for (int x = xl_edge; x<xr_edge; x++)
        {
            float zOfPixel = zValueOfPoint(vx, vy, vz, x, y, nx, ny, nz);
            if (zOfPixel < zbuffer[int(x + y * m_Width)]) {
                zbuffer[int(x + y*m_Width)] = zOfPixel;
                SetPixel((unsigned int)x, (unsigned int)y, color);
            }

        }//end for loop x

То же самое для нижнего треугольника

Прямо сейчас я получаю полностью сломанную модель. Z-буфер инициализирован правильно.

3

1 Ответ

2 голосов
/ 15 января 2020

Вам не нужно ничего делать с нормалями лица при реализации буферизации Z. Вам нужно только на каждую "глубину" вершины для ваших спроецированных треугольников.

Далее, и я прошу прощения только за просмотр кода вашего вопроса, но если вы хотите сделать перспективу проекция, затем убедитесь, что «глубина», которую вы линейно интерполируете на пиксель, равна не глубина мира / камеры, а что-то пропорциональное (Что? Нет SO на математике?) в 1 / Z_world или 1 / W.

То есть у вас есть спроецированный треугольник, в котором каждая вершина, Vi , имеет {Vi_screenX, Vi_screenY, Vi_projectedDepth} и Vi_projectedDepth = linear_function_of (1 / Vi_Z_camera) .

Очень простые примеры:

Vi_projectedDepth = 1 / Vi_Z_camera или Vi_projectedDepth = 1,0 - 1 / Vi_Z_camera

Затем вы должны линейно интерполировать значения Vi_projectedDepth по всему треугольнику, но вам не нужно нужно брать обратную величину этих интерполированных значений (, по крайней мере, не для Z- упорядочение в буфере. Если вы хотите сделать корректное перспективное текстурирование, OTOH, вам _могут_ в конечном итоге вычислить обратную ).

Если вы этого не сделаете, вы можете получить очень странные результаты, когда геометрия имеет неявное пересечение - я только что вспомнил, что сделал комментарий по этому поводу в SE Graphics .

...