Я пытаюсь создать программу для работы с 3D, используя C ++ и openGL. Я относительно новичок в openGL, поэтому мне часто приходится искать документацию, чтобы найти подходящую функцию для выполнения того, что я хочу. Я думал, что у меня было хорошее понимание ортогональных и перспективных проекций (в этом glOrtho
создает ортогональную проекцию, где разные значения z не выглядят по-разному и glFrustum
создает перспективную проекцию, где значения z, которые ближе, выглядят больше). Тем не менее, когда я меняю glOrtho
а также glFrustum
в моей программе я не вижу никакой разницы. Я воспроизвел небольшую программу ниже, которая показывает эффекты. Для справки я использую openGL с freeglut.
#include "GL/freeglut.h"void initFunc()
{
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1, 1, -1, 1, -1, 1);
}
void displayFunc()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glColor3f(1.0f, 1.0f, 0.0f);
glLineWidth(1.0f);
glutWireTeapot(0.3);
glTranslatef(0, -0.5, -0.5);
glutWireTeapot(0.3);
glutSwapBuffers();
}
int main(int argc, char ** argv)
{
glutInit(&argc, argv);
glutInitWindowSize(600, 600);
glutInitWindowPosition(0, 0);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutCreateWindow("Teapot Perspective");
initFunc();
glutDisplayFunc(displayFunc);
glutMainLoop();
}
Я рисую два чайника, слегка смещенных по осям y и z. Из того, что я понимаю, glOrtho
следует сделать оба чайника идентичными, только со смещением y, тогда как glFrustum
должен сделать один из них больше другого. Тем не менее, оба они делают чайники одинаково.
Я что-то здесь упускаю? Есть ли другие шаги, которые я должен предпринять, чтобы правильно настроить перспективную проекцию? Или я неправильно понимаю, как glFrustum
работает? Я также пытался использовать gluPerspective
вместо glFrustum
но я не могу найти правильные значения для использования. Я экспериментировал с полем зрения 90, аспектом 1 и различными значениями z, но все они либо не производят чайник, либо чайник искажается до неузнаваемости. Кроме того, gluPerspective
похоже, имеет другое поведение, чем glFrustum
вызов с соответствующими параметрами. Я не уверен, что мне здесь не хватает.
В ортогональной проекции координаты в пространстве вида линейно отображаются на координаты пространства отсечения, а координаты пространства отсчета равны нормализованным координатам устройства, поскольку w
Компонент равен 1 (для декартовой входной координаты).
Значения слева, справа, снизу, сверху, близко и далеко определяют поле. Вся геометрия, которая находится внутри объема окна, «видна» в окне просмотра.
Матрица ортогональной проекции, определяемая glOrtho
является:
r = right, l = left, b = bottom, t = top, n = near, f = far
x: 2/(r-l) 0 0 0
y: 0 2/(t-b) 0 0
z: 0 0 -2/(f-n) 0
t: -(r+l)/(r-l) -(t+b)/(t-b) -(f+n)/(f-n) 1
В перспективной проекции матрица проекции описывает отображение из трехмерных точек в мире, как они видны с камеры-обскуры, в двумерные точки видового экрана.
Координаты пространства глаза в усеченной области камеры (усеченная пирамида) отображаются в куб (нормализованные координаты устройства).
Матрица перспективной проекции может быть определена усечением (glFrustum
).
Расстояния left
, right
, bottom
а также top
, — расстояния от центра вида до боковых граней усеченного конуса в ближней плоскости. near
а также far
Укажите расстояния до ближней и дальней плоскости на усеченном конусе.
r = right, l = left, b = bottom, t = top, n = near, f = far
x: 2*n/(r-l) 0 0 0
y: 0 2*n/(t-b) 0 0
z: (r+l)/(r-l) (t+b)/(t-b) -(f+n)/(f-n) -1
t: 0 0 -2*f*n/(f-n) 0
Спецификация, как это от вас вопрос:
glFrustum(-1, 1, -1, 1, -1, 1);
не определяет правильный усеченный, потому что значение для ближней плоскости является отрицательным, а значение для дальней плоскости положительным.
Если вы будете проверять наличие ошибок OpenGL (по glGetError
), тогда вы получите INVALID_OPERATION
ошибка.
void Frustum( double l, double r, double b, double t, double n, double f );
координаты (
l
b
−n
) Т а (r
t
−n
) T указывает точки на ближней плоскости отсечения, которые отображаются в нижний левый и верхний правый углы окна соответственно (при условии, что глаз расположен в точке (0 0 0) T).f
дает расстояние от глаза до дальней плоскости отсечения.ошибки
Ошибка INVALID_VALUE генерируется, еслиn <= 0
,f <= 0
,l == r
,b == t
, или жеn == f
,
Других решений пока нет …