ZBuffer не имеет к этому никакого отношения.
Этот ZBuffer полезен только тогда, когда треугольники перекрываются, и вы хотите убедиться, что они правильно нарисованы (например, правильно упорядочены по Z). ZBuffer будет для каждого пикселя треугольника определить, находится ли ранее размещенный пиксель ближе к камере, и если да, не нарисуйте пиксель вашего треугольника.
Поскольку вы рисуете 2 треугольника, которые не пересекаются, это не может быть проблемой.
Я сделал растеризатор программного обеспечения в фиксированной точке один раз (для мобильного телефона), но у меня нет источников на моем ноутбуке. Поэтому позвольте мне проверить сегодня, как я это сделал. По сути, у вас есть неплохо! Подобная вещь может быть вызвана очень маленькой ошибкой
Общие советы по отладке - это иметь несколько тестовых треугольников (угол наклона слева, угол наклона справа, угол 90 градусов и т. Д.) И пройти через него с отладчиком и посмотреть, как ваша логика касается дел.
EDIT:
peudocode моей растеризации (только U, V и Z принимаются во внимание ...если вы также хотите сделать gouraud, вам также нужно сделать все для R G и B, аналогично тому, что вы делаете для U и V и Z:
Идея состоит в том, что треугольник может быть разбит на две части. Верхняя часть и нижняя часть. Верхняя часть от y [0] до y [1], а нижняя часть - от y [1] до y [2]. Для обоих наборов вам нужно вычислить переменные шага, с которыми вы интерполируете. В приведенном ниже примере показано, как сделать верхнюю часть. При необходимости я также могу поставить нижнюю часть.
Пожалуйста, обратите внимание, что я уже рассчитать необходимые смещения интерполяции для нижней части в поле ниже «псевдокода» фрагмент
- первого порядка в Coords (х, у, г, и, v) в порядке так что координата [0] .y < coord [1] .y < coord [2] .y
- Далее проверьте, совпадают ли какие-либо 2 набора координат (только проверка x и y). Если так не нарисовать
- исключение: имеет треугольник плоский верх? если это так, первый наклон будет бесконечным
- исключение2: имеет ли треугольник плоское дно (да, треугольники тоже могут их содержать; ^)), тогда последний наклон тоже будет бесконечным
- вычислить 2 наклона (слева и справа) правая сторона)
leftDeltaX = (x [1] - x [0])/(y [1] -y [0]) и rightDeltaX = (x [2] - x [0])/(y [2] -Y [0])
- вторая часть треугольника рассчитывается в зависимости от: если левая сторона треугольника теперь действительно на LeftSide (или потребности замены) фрагмент
код:
if (leftDeltaX < rightDeltaX)
{
leftDeltaX2 = (x[2]-x[1])/(y[2]-y[1])
rightDeltaX2 = rightDeltaX
leftDeltaU = (u[1]-u[0])/(y[1]-y[0]) //for texture mapping
leftDeltaU2 = (u[2]-u[1])/(y[2]-y[1])
leftDeltaV = (v[1]-v[0])/(y[1]-y[0]) //for texture mapping
leftDeltaV2 = (v[2]-v[1])/(y[2]-y[1])
leftDeltaZ = (z[1]-z[0])/(y[1]-y[0]) //for texture mapping
leftDeltaZ2 = (z[2]-z[1])/(y[2]-y[1])
}
else
{
swap(leftDeltaX, rightDeltaX);
leftDeltaX2 = leftDeltaX;
rightDeltaX2 = (x[2]-x[1])/(y[2]-y[1])
leftDeltaU = (u[2]-u[0])/(y[2]-y[0]) //for texture mapping
leftDeltaU2 = leftDeltaU
leftDeltaV = (v[2]-v[0])/(y[2]-y[0]) //for texture mapping
leftDeltaV2 = leftDeltaV
leftDeltaZ = (z[2]-z[0])/(y[2]-y[0]) //for texture mapping
leftDeltaZ2 = leftDeltaZ
}
- установить currentLeftX и currentRightX как на х [0]
- множество currentLeftU на leftDeltaU, currentLeftV на leftDeltaV и currentLeftZ на leftDeltaZ
- известково начальную и конечную точки для первого диапазона Y: startY = CEIL (у [0]); endY = ceil (y [1])
- prestep x, u, v и z для дробной части y для субпиксельной точности (думаю, это также необходимо для поплавков) Для моих алгоритмов с фиксированной точкой это было необходимо для создания линии и текстуры дают иллюзию перемещения в гораздо более тонких шагах, чем разрешение дисплея)
- вычислить, где x должно быть у y [1]: halfwayX = (x [2] -x [0]) * (y [ 1] -y [0])/(y [2] -y [0]) + x [0] и то же для U и V и z: halfwayU = (u [2] -u [0]) * (y [1] -y [0])/(y [2] -y [0]) + u [0]
- и с использованием halfwayX вычислить шаговый двигатель для U и V и z: , если (halfwayX - x [1] == 0) {slopeU = 0, slopeV = 0, slopeZ = 0} else {slopeU = (halfwayU - U [1])/(halfwayX - x [1])}// (и то же самое для v и z)
- сделать обрезку для вершины Y (так что вычислите, где мы начнем рисовать в случае, если верх треугольника находится за пределами экрана (или от отсекающего прямоугольника))
- для y = startY; y < endY; y ++) {
- есть Y в нижней части экрана? прекратить рендеринг!
- calc startX и endX для первой горизонтальной линии leftCurX = ceil (startx); leftCurY = ceil (endy);
- клип линии будет обращен на левую горизонтальную границу экрана (или область отсечения)
- подготовить указатель на буфер назначения (делать это через индексы массива каждый раз слишком медленно) неподписанных INT ЬиХ = destbuf + (y pitch) + startX; (Беззнаковое целочисленное значение в случае, если вы делаете 24bit или 32 бит рендеринга) также подготовить указатель ZBuffer здесь (если вы используете это)
- для (х = StartX; х < EndX; х ++) {
- Теперь для отображения точки зрения текстуры (не используя bilineair интерполяции вы делаете следующее):
фрагмент кода:
float tv = startV/startZ
float tu = startU/startZ;
tv %= texturePitch; //make sure the texture coordinates stay on the texture if they are too wide/high
tu %= texturePitch; //I'm assuming square textures here. With fixed point you could have used &=
unsigned int *textPtr = textureBuf+tu + (tv*texturePitch); //in case of fixedpoints one could have shifted the tv. Now we have to multiply everytime.
int destColTm = *(textPtr); //this is the color (if we only use texture mapping) we'll be needing for the pixel
- фиктивная линия
- фиктивная линия
- фиктивная линия
- дополнительно: проверить ZBuffer, если ранее нанесены на пиксель этой координаты выше или ниже, то наши.
- plot the pixel
- startZ + = slopeZ; startU + = slopeU; startV + = slopeV; // все обновления интерполяторы
- } конец цикла х
- leftCurX + = leftDeltaX; rightCurX + = rightDeltaX; leftCurU + = rightDeltaU; leftCurV + = rightDeltaV; leftCurZ + = rightDeltaZ; // обновление Y интерполяторы
} конец цикла у
// это конец первой части. Теперь мы нарисовали половину треугольника. от вершины, до средней координаты Y. // теперь мы в основном сделать то же самое, но теперь в нижней части треугольника (с использованием другого набора интерполяторов)
жалкого о «фиктивных линиях» .. они были необходимы, чтобы получить кодов разметки в синхронизации. (взял меня на время, чтобы получить все, чтобы посмотреть все, что было задумано)
Дайте мне знать, если это поможет вам решить проблему, с которой вы столкнулись!
Еще один совет для отладки, вычислить каждую точку текстуры, используя старомодные, неинкрементные U и V координаты для каждого пикселя и сравнить с инкрементными значениями, вычисленными вашим алгоритмом (с учетом некоторого оттока из-за ошибки округления). –
Ничего себе ... это ответ наполовину! : D – Goz
goz: теперь просто надеюсь, что это полезно, поскольку он, вероятно, имеет большую часть этого кода уже на месте, судя по картинке. Я думаю, что, вероятно, он просчитал одно из значений интерполяции. Но, надеюсь, если он заложит свой алгоритм рядом с моим, он сможет выяснить, какой он есть; ^) – Toad