Получение координат для glFrustum

Я только начал читать о OpenGL темы, особенно о Viewing для моих текущих потребностей. Я пытаюсь понять glFrustum для перспективной проекции объектов, которые я нарисовал на экране и, как я понимаю, glFrustum сделает более отдаленные объекты меньше, чем более близкие объекты.
я использую openFrameworks здесь для рисования объектов, таких как Image / Box и т.д. и вот короткий пример того, что я пытаюсь сделать:

метод рисования openFrameworks

draw()
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-1.0, 1.0, -1.0, 1.0, 3.0, 500.0);
glMatrixMode(GL_MODELVIEW);

sceneImage.draw(0,0,ofGetWidth(), ofGetHeight()); //draw an image on the screen with window's width and dheight 
}

С помощью вышеупомянутого glFrustum я просто пытаюсь обрезать изображение и увидеть определенную часть изображения для первоначального теста. Я не уверен, что эти аргументы glFrustum на самом деле, даже когда я читаю о glFrustum сверху ссылка на Красную книгу. Аргументы, конечно, left, right, bottom, top, near, far, но как 1.0 или же 1.0 рассчитывается? Я ожидал, что там появятся координаты экрана, и попробовал что-то вроде glFrustum(100, 984, 100, 668,3, 500) но ничего не появилось на экране. Как эти аргументы для glFrustum рассчитывается?

1 ответ

Решение

Я надеюсь, что я правильно понял ваш вопрос, если не просто дайте мне знать, но если вы спрашиваете, " как вы должны рассчитать glFrustum Аргументы "это как:

На самом деле все о соотношении сторон и поле зрения. Обычно вы собираетесь найти информацию о том, как сделать матрицу перспективы, используя вертикальное поле обзора, но иногда вам захочется использовать горизонтальное поле зрения. Так вот, что я придумал, я не использую glFrustum но я думаю, что вы можете просто переключить мой perspective работать с ним, и он все еще должен работать:

//--------------------------------------------------------------------------------
// set a perspective frustum (right hand)
// (left, right, bottom, top, near, far)
//--------------------------------------------------------------------------------
void perspective(float l, float r, float b, float t, float n, float f)
{
    m_projection.identity();

    m_projection[0]  =  2.0f * n / (r - l);
    m_projection[2]  =  (r + l) / (r - l);
    m_projection[5]  =  2.0f * n / (t - b);
    m_projection[6]  =  (t + b) / (t - b);
    m_projection[10] = -(f + n) / (f - n);
    m_projection[11] = -(2.0f * f * n) / (f - n);
    m_projection[14] = -1.0f;
    m_projection[15] =  0.0f;

    update();
}

//--------------------------------------------------------------------------------
// set a symmetric perspective frustum
// ((vertical, degrees) field of view, (width/height) aspect ratio, near, far)
//--------------------------------------------------------------------------------
void perspective_vertical(float fov, float aspect, float front, float back)
{
    fov = DEG_TO_RAD(fov);                      // transform fov from degrees to radians

    float tangent = tanf(fov / 2.0f);               // tangent of half vertical fov
    float height = front * tangent;                 // half height of near plane
    float width = height * aspect;                  // half width of near plane

    perspective(-width, width, -height, height, front, back);
}

//--------------------------------------------------------------------------------
// set a symmetric perspective frustum
// ((horizontal, degrees) field of view, (width/height) aspect ratio, near, far)
//--------------------------------------------------------------------------------
void perspective_horizontal(float fov, float aspect, float front, float back)
{
    fov = DEG_TO_RAD(fov);                      // transform fov from degrees to radians
    fov = 2.0f * atanf(tanf(fov * 0.5f) / aspect);  // transform from horizontal fov to vertical fov

    float tangent = tanf(fov / 2.0f);               // tangent of half vertical fov
    float height = front * tangent;                 // half height of near plane
    float width = height * aspect;                  // half width of near plane

    perspective(-width, width, -height, height, front, back);
}

И помогающие макросы:

#define PI_OVER_180 0.0174532925199432957692369076849f
#define 180_OVER_PI 57.2957795130823208767981548141f

#define DEG_TO_RAD(x) (x * PI_OVER_180)
#define RAD_TO_DEG(x) (x * 180_OVER_PI)

Код в основном комментируется и должен иметь смысл без дальнейшего объяснения. Параметры должны быть примерно такими:

perspective_horizontal(85.0f /* fov of 85 degrees */, (float)width/height, 0.001f /* using near of 3.0f is kinda too much, just don't use 0.0f */, 1000.0f)

Если вы хотите углубиться и увидеть, как работают цифры, вы можете поставить несколько точек останова или printf это посмотреть, как это работает. Эквивалент 85 градусов по горизонтали составляет около 45 градусов по вертикали. Кроме того, opengl использует основной столбец, так что если вы в конечном итоге использовать такую ​​матрицу вместо glFrustum убедитесь, что вы перенесли это в первую очередь.


РЕДАКТИРОВАТЬ (подробнее о комментарии ниже):

Давайте возьмем окно, стандартное HD-400 пикселей: (1920-400) в ширину и (1080-400) в высоту. Соотношение сторон стандартного HD составляет 1,77, а версия -400 пикселей (1920-400)/(1080-400) = 2,23.

Сейчас звоню perspective_horizontal функция с соотношением сторон (1920-400)/(1080-400) FOV из 85 и поставить точку останова перед perspective(...) вызов собирается дать нам следующие переменные:

  • fov float 0.778087676
  • аспект поплавок 2.2352941
  • передний поплавок 0.00100000005
  • обратно плавать 100
  • касательное с плавающей точкой 0.40993762
  • высота поплавка 0.000409937638
  • ширина поплавка 0.000916331192

обратите внимание, что 0,000916331192/0,000409937638 = 2,23529412052 и 0,778087676 радиан в градусах = 44,5811399 градусов по вертикали, что эквивалентно 85 градусам по горизонтали.

Также звонит perspective_horizontal функция с соотношением сторон (1920-400)/(1080-400) FOV из 105 вместо этого собирается дать нам следующие переменные:

  • fov float 1.05568409
  • аспект поплавок 2.2352941
  • передний поплавок 0.00100000005
  • обратно плавать 100
  • тангенциальный поплавок 0.583021879
  • высота поплавка 0.000583021902
  • ширина поплавка 0.00130322541

еще раз обратите внимание, что 0,00130322541/0,000583021902 = 2,23529408677 и 1,05568409 радиан в градусах = 60,4862429 градусов по вертикали, что эквивалентно 105 градусам по горизонтали.

Что касается фактической матрицы перспективы, я не могу объяснить вам, как работает формула, но только представьте, что в gpu есть магические единороги, и если вы их кормите gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(inputPosition, 1.0f); они собираются совершить какое-то волшебство, и оно будет отображать красивые вещи на экране; 3.


glFrustum также объясняется здесь, здесь, здесь, здесь, здесь и, самое главное, здесь.

Также есть одно хорошее объяснение здесь.

Другие вопросы по тегам