Получение координат для 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
также объясняется здесь, здесь, здесь, здесь, здесь и, самое главное, здесь.
Также есть одно хорошее объяснение здесь.