От перспективы к орфографическим проекциям

Я пытаюсь изменить проекцию камеры с перспективы на орфографическую. На данный момент мой код отлично работает с перспективной проекцией

m_prespective = glm::perspective(70.0f, (float)DISPLAY_WIDTH / (float)DISPLAY_HEIGHT, 0.01f, 1000.0f);
m_position = glm::vec3(mesh.centre.x, mesh.centre.y, -mesh.radius);
m_forward = centre;
m_up = glm::vec3(0.0f, 1.0f, 0.0f);
return m_prespective * glm::lookAt(m_position, m_forward, m_up);

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

m_ortho = glm::ortho(0.0f, (float)DISPLAY_WIDTH, (float)DISPLAY_HEIGHT,5.0f, 0.01f, 1000.0f);
m_position = glm::vec3(mesh.centre.x, mesh.centre.y, -mesh.radius);
m_forward = centre;
m_up = glm::vec3(0.0f, 1.0f, 0.0f);
return m_ortho * glm::lookAt(m_position, m_forward, m_up);

Я не понимаю, что я делаю неправильно.


person Izzy88    schedule 08.07.2016    source источник
comment
Вы случайно не поменяли аргументы на ortho? Подпись должна быть ortho(left, right, bottom, top, near, far). Это что 5.0?   -  person peppe    schedule 08.07.2016
comment
На самом деле да, установка top на 0.0f позволяет мне видеть, по крайней мере, очень маленькую группу пикселей в верхнем левом углу моего окна. Однако при использовании перспективной проекции моя сетка отображается в центре экрана и имеет нормальный размер. Тем не менее, я не понимаю, почему он отображается так далеко и не по центру. У вас есть какие-нибудь подсказки?   -  person Izzy88    schedule 08.07.2016
comment
Учитывая, что мои DISPLAY_WIDTH и DISPLAY_HEIGHT соответственно равны 800 и 600, изменение этих значений с m_ortho = glm::ortho(0.0f, 800.0f, 600.0f ,5.0f, 0.01f, 1000.0f); на m_ortho = glm::ortho(8.0f, 0.0f,0.0f,6.0f, 0.1f, 100.0f); возвращает размер к нормальному (более или менее). Но я не понимаю, есть ли правило или конкретное отношение для изменения значений размера с перспективной проекции на орфографическую проекцию. (Просто чтобы не менять их каждый раз вручную)   -  person Izzy88    schedule 08.07.2016
comment
@ Izzy88: Вот предложение. Не пытайтесь бездумно перетасовывать переменные на основе кода, который вы где-то видели. Если вы делаете это, вы являетесь карго-культовым программистом: вы делаете вещи, которые каким-то образом напоминают то, как другие люди пишут код, но вы никогда не заставите самолеты приземляться, ошибаетесь, заставляйте свой код делать то, что вы хотите, потому что вы не вообще не понимаю, что ты там делаешь. Поймите, что параметры для перспективы и орфографической проекции означают в геометрическом выражении, и почему и как вы должны выбрать их, чтобы получить желаемые результаты. Возьмите ручку и бумагу и начните рисовать.   -  person datenwolf    schedule 08.07.2016


Ответы (1)


В перспективной проекции термин (float)DISPLAY_WIDTH / (float)DISPLAY_HEIGHT оценивает соотношение сторон изображения. Это число будет близко к 1. Расстояние между левой и правой плоскостями отсечения в ближней плоскости для перспективной проекции равно aspect * near_distance. Однако более интересным является пространство влево-вправо на расстоянии просмотра, которое в вашем случае составляет abs(m_position.z)= abs(mesh.radius).

Перенося это в ортогональную проекцию, расстояния между плоскостями отсечения слева, справа, сверху и снизу должны быть одного порядка, поэтому, учитывая, что аспект близок к 1, значения для левого, правого, нижнего и верхнего должны быть близки к значению из abs(mesh.radius). Разрешение дисплея в пикселях совершенно не имеет значения, за исключением соотношения сторон.

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

float const view_distance = mesh.radius + 1;

float const aspect = (float)DISPLAY_WIDTH / (float)DISPLAY_HEIGHT;
switch( typeof_projection ){
case perspective:
    m_projection = glm::perspective(70.0f, aspect, 1.f, 1000.0f);
    break;

case ortho:
    m_projection = glm::ortho(
        -aspect * view_distance,
         aspect * view_distance,
        view_distance,
        view_distance,
        -1000, 1000 );
    break;
}

m_position = glm::vec3(mesh.centre.x, mesh.centre.y, -view_distance);
m_forward = centre;
m_up = glm::vec3(0.0f, 1.0f, 0.0f);

return m_projection * glm::lookAt(m_position, m_forward, m_up);
person datenwolf    schedule 08.07.2016
comment
Большое спасибо @datenwolf, как за ваше объяснение, так и за ваше очень мудрое предложение в вашем предыдущем сообщении. Я полностью согласен с вами, и это то, что я обычно делаю. К сожалению, в данном случае у меня осталось не так много времени, чтобы углубиться и изучить эту тему, плюс это не совсем ключевой аргумент в пользу того, что я пытаюсь создать прямо сейчас. Это начало сильно раздражать. Спасибо и за ваш код, он работает отлично (мне просто нужно было добавить - перед третьим параметром на случай, если это кому-то еще понадобится). - person Izzy88; 08.07.2016