OpenGL: вычисление z-значения для отношения пикселей 1: 1 - PullRequest
1 голос
/ 20 января 2010

У меня есть текстура 256x256 в окне просмотра, которую мне нужно переместить в z-позицию, где текстура реплицируется на экране при фактическом размере.

То, что я имею до сих пор:

    const float zForTrueScale = -((itemSize/2) / tanf(DEGREES_TO_RADIANS(fieldOfView/2)) ) * 2;     

где itemSize - размер моей текстуры в мировом пространстве (2,0 единицы). Это необходимо для вычисления значения Z (смежного), когда itemSize / 2 (противоположный) равен 1,0. Я думал, что это будет работать.

Эта формула показывает, что текстура постоянно слишком мала примерно на 10%, независимо от того, какой FOV я использую.

Спасибо

РЕДАКТИРОВАТЬ: я перемещаюсь по изображениям в трехмерном пространстве и мне нужен плавный переход к правильному z-расстоянию. Я не могу использовать ортогональную проекцию, она должна быть в усечённом виде.

Ответы [ 4 ]

6 голосов
/ 21 января 2010

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

Таким образом, ваша матрица проекции будет выглядеть так:

xScale     0               0                     0
0        yScale            0                     0
0          0     -(zf + zn)/(zf - zn)  -(2 * zf) / (zf-zn) 
0          0              -1                     0

Где известны значения z-Far (zf) и z-Near (zn), xScale и yScale.

Чтобы выбрать правильную Z-глубину, мы начнем с того, что w будет равен 1. Таким образом, когда мы делим на w, это ничего не изменит.

К счастью, к нам очень легко добраться. Это просто отрицание ввода z. Таким образом, ввод -1 в z вернет a w 1.

Предположим, вы используете разрешение 1024x768, а требуемая текстура в правильном масштабе - 256x256.

Мы также будем предполагать, что ваш прямоугольник настроен так, что верхний левый угол находится в положении -1, 1, а нижний правый - в 1, -1.

Итак, давайте подключим их и отработаем z.

если мы используем следующее:

-1, 1, -1, 1
1, -1, -1, 1

мы что-нибудь получим следующим образом.

1 / xScale, -1 / yScale, someZThatIsn'tImportant, 1
-1 / xScale, 1 / yScale, someZThatIsn'tImportant, 1

Преобразование области просмотра преобразует эти значения таким образом, что -1, 1 равно 0, 0 и 1, -1 равно 1024,768

Итак, мы можем видеть, что работает, выполняя ((x + 1) / 2) * 1024 и ((1 - y) / 2) * 768

Итак, если мы примем xScale 3/4 и yScale 1, мы можем увидеть это, подключив его, и получим следующее:

Для левого верхнего угла:

x = -3/4
=> ((-3/4 + 1) / 2) * 1024
=> 128
y = 1
=> ((1 - 1) / 2) * 768
=> 0

Для нижнего правого:

x = 3/4
=> ((3/4 + 1) / 2) * 1024
=> 896
y = -1
=> ((1 + 1) / 2) * 768
=> 768

Таким образом, вы можете видеть, что у нас есть изображение размером 768x768 пикселей по центру экрана. Очевидно, что для получения 256x256 нам нужно получить значение w равным 3, чтобы после деления w мы получили эти координаты, равные трети размера ((xScale * 1024) / 256 должны быть равны (yScale * 768) / 256, чтобы получить квадрат проекция.

Так что, если наши окончательные координаты следующие:

-1, 1, -3, 1
and
1, -1, -3, 1

мы получим следующее (после w-деления):

-0.25, 0.333, unimportantZ, 1
and
0.25, -0.333, unimportantZ, 1

Запустите те через уравнения экрана выше, и мы получим

Для левого верхнего угла:

x = -0.25
=> ((-0.25 + 1) / 2) * 1024
=> 384
y = 0.3333
=> ((1 - 0.3333) / 2) * 768
=> 256

Для нижнего правого:

x = 0.25
=> ((0.25 + 1) / 2) * 1024
=> 640
y = -0.333
=> ((1 + 0.33333) / 2) * 768
=> 512

640 - 384 = 256
512 - 256 = 256

Таким образом, теперь у нас есть последний прямоугольник с правильным размером пикселя ...

2 голосов
/ 20 января 2010

Не зная слишком много о вашей ситуации, почти наверняка проще вставить ортогональную проекцию в стек матрицы проекций, нарисовать текстуру и затем снова вытолкнуть ее.

0 голосов
/ 20 января 2010

Ваш квадратный буфер?

Если нет, то у вас горизонтальное поле зрения и вертикальное. Вы используете правильный? Кроме того, как вы точно знаете, что хотите, чтобы оно составляло 2,0 единицы в мировых координатах? Если ваша конечная цель состоит в том, чтобы сопоставить его с пикселями, то вам необходимо принять во внимание область просмотра и вернуться к этому.

Я также согласен с Pike65, что я не понимаю, откуда взялся * 2.

0 голосов
/ 20 января 2010

Хотя это будет медленно, вы можете просто использовать glDrawPixels() и покончить с этим.

... нет, если это критично для производительности!

...