Значение Z после разделения перспективы всегда меньше -1

Поэтому я пишу свой собственный конвейер 3D-преобразования, чтобы лучше понять, как все это работает. Я могу правильно отобразить все на экране, и теперь я собираюсь вернуться и посмотреть на отсечение.

Насколько я понимаю, я должен обрезать точку вершины, если значение x или y после разделения перспективы выходит за пределы [-1, 1] и в моем случае, если значение z выходит за пределы [0, 1] .

Однако, когда я реализую это, мое значение z всегда равно -1.xxxxxxxxxxx, где xxxxxxx - очень маленькое число.

Это немного длинно, и я прошу прощения, но я хотел убедиться, что предоставил всю информацию, которую мог.

Первые соглашения:

Я использую систему для левшей, где матрица выглядит так:

[m00, m01, m02, m03]
[m10, m11, m12, m13]
[m20, m21, m22, m23]
[m30, m31, m32, m33]

И мои векторы представляют собой столбцы, выглядящие так:

[x]
[y]
[z]
[w]

Моя камера настроена так:

Вертикальное поле зрения в радианах PI/4.

Соотношение сторон 1. (квадратное окно просмотра)

Близкое значение клипа равное 1.

Значение дальнего клипа 1000.

Начальная мировая позиция x равна 0.

Начальная мировая позиция y равна 0.

Начальная мировая позиция по оси z -500.

Камера смотрит вниз по оси Z (0, 0, 1)

Учитывая вершину, конвейер работает следующим образом:

Шаг 1. Умножьте вершину на матрицу камеры.

Шаг 2. Умножьте вершину на матрицу проекции.

Матрица проекции:

[2.41421, 0,       0,         0]
[0        2.41421, 0,         0]
[0,       0,       1.001001,  1]
[0,       0,       -1.001001, 0]

Шаг 3. Умножьте компоненты x, y и z на 1/w.

Шаг 4: [Вот в чем проблема] Обрежьте вершину, если она находится за пределами границ.

Шаг 5. Преобразование в экранные координаты.

Пример вершины, которая у меня есть,

(-100, -100, 0, 1)

После умножения на матрицу камеры я получаю:

(-100, -100, 500, 1)

Что имеет смысл, потому что относительно камеры эта вершина находится на 100 единиц влево и вниз и на 500 единиц вперед. Он также находится между ближним клипом 1 и дальним клипом 1000. W по-прежнему 1.

После умножения на матрицу проекции я получаю:

(-241.42135, -241.42135, 601.600600, -600.600600)

Это я не уверен, имеет ли это смысл. X и y кажутся правильными, но я сомневаюсь в z и w, так как следующий шаг разделения перспективы нечетный.

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

(0.401966, 0.401966, -1.001665, 1)

Опять же, x и y имеют смысл, они оба находятся в пределах [-1, 1]. Но значение z явно выходит за пределы, хотя я считаю, что оно все еще должно быть в пределах усеченного конуса. W возвращается к 1, что снова имеет смысл.

Еще раз извиняюсь за роман, но я надеюсь, что кто-то может помочь мне понять, что я делаю неправильно.

Спасибо!


person Jon    schedule 15.07.2010    source источник


Ответы (2)


Хорошо, кажется, я понял, в чем проблема.

Моя проекционная матрица была:

[2.41421, 0,       0,         0]
[0        2.41421, 0,         0]
[0,       0,       1.001001,  1]
[0,       0,       -1.001001, 0]

Но это действительно должно быть транспонировано и быть:

[2.41421, 0,       0,         0]
[0        2.41421, 0,         0]
[0,       0,       1.001001,  -1.001001]
[0,       0,       1,         0]

При использовании этой матрицы мои значения x и y остаются такими же, как и ожидалось, и теперь мои значения z ограничены пределами [0, 1] и превышают этот диапазон только в том случае, если они находятся за пределами ближней или дальней плоскости отсечения.

Единственная проблема сейчас в том, что я совершенно не понимаю, использую ли я правую или левую систему.

Все, что я знаю, это то, что теперь это работает...

person Jon    schedule 16.07.2010
comment
Хорошая вещь. Рад слышать, что ты разобрался :) - person e.James; 16.07.2010
comment
Спасибо за вашу помощь, хотя, я определенно ценю это. - person Jon; 16.07.2010

Я могу быть не в своей лиге здесь, но я думал, что целью проекционной матрицы и перспективного деления было обнаружение 2D-положения этой точки на экране. В этом случае оставшееся значение z больше не обязательно будет иметь какое-либо значение, поскольку вся математика направлена ​​на нахождение этих двух значений x и y.

Обновление: кажется, я разобрался. Вся ваша математика верна. Камера и усеченный конус, которые вы описываете, имеют плоскость отсечения, близкую к Z=1, поэтому точка вашего примера at (-100, 100, 0) на самом деле за пределами плоскости отсечения, так что значение z-буфера чуть ниже -1 имеет смысл.

Попробуйте взять точку образца с координатой z внутри усеченного конуса, скажем, с координатой z 2.

person e.James    schedule 15.07.2010
comment
Хм, хорошо, я думаю, это имеет смысл, поскольку рендеринг все еще правильный. Но разве мне не нужно хранить это значение z в моем буфере глубины? И если я его сохраняю, разве он не должен находиться в пределах [0, 1] или хотя бы [-1, 1]? - person Jon; 15.07.2010
comment
Взгляните на gamedev.net/community/forums/topic.asp? тема_id=483363. Я думаю, вам, возможно, придется сделать отсечение перед делением на w. В этом случае вы можете рассчитать значение буфера z в алгоритме отсечения, где оно будет просто z/1500 (в вашем примере). - person e.James; 15.07.2010
comment
Пожалуйста, проигнорируйте мои предыдущие два комментария и посмотрите обновление, которое я опубликовал. - person e.James; 15.07.2010
comment
Хорошо, круто, поэтому я попробовал это и до сих пор не играю в кости. Это имеет смысл, потому что 0 не выходит за пределы моего диапазона глубины, потому что диапазон определяется относительно камеры, а не в абсолютном выражении. Однако мне удалось решить эту проблему, и я отвечу ниже с ответом. - person Jon; 16.07.2010
comment
e.James, вы упомянули остаточное значение z, но я просто хотел бы указать (на случай, если вы еще этого не выяснили), что это значение z используется как соответствующая глубина xy-координат в Буфер глубины. - person Drout; 09.07.2018