Таким образом, я пишу свой собственный 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]
Моя камера настраивается с:
Вертикальный FOV в радианах PI/4.
Порция аспекта 1. (Квадрат просматривает порт),
Близкое значение клипа 1.
Далекое значение клипа 1 000.
Начальный мир 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 и далеким клипом 1 000. 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 ясно вне границ даже при том, что я полагаю, что это должно все еще быть в frustrum. W вернулся к 1, который снова имеет смысл.
Снова извинения за роман, но я надеюсь, что кто-то может помочь мне выяснить то, что я делаю неправильно.
Спасибо!
Так, похоже, я понял, в чем была проблема.
Моя матрица проекции была:
[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] и выходят за пределы этого диапазона, только если они находятся за пределами ближней или дальней плоскости клипа.
Единственная проблема теперь заключается в том, что я совершенно не понимаю, какую систему я использую - правостороннюю или левостороннюю.
Все, что я знаю, это то, что теперь это работает...
Возможно, я не в своей тарелке, но я думал, что цель проекционной матрицы и деления перспективы - определить 2D положение точки на экране. В таком случае, оставленное значение z не обязательно будет иметь какое-либо значение, поскольку математика направлена на нахождение этих двух значений x и y.
Обновление: Кажется, я разобрался. Все ваши математические выкладки верны. Камера и frustum, которые вы описываете, имеют близкую плоскость обрезания при Z=1, поэтому ваша точка примера на (-100, 100, 0) фактически находится вне плоскости обрезания, поэтому значение z-буфера чуть ниже -1 имеет смысл.
Попробуйте выбрать точку с координатой z внутри фруста, скажем, с координатой z, равной 2.