glFrustum не создает перспективу - PullRequest
0 голосов
/ 23 сентября 2018

Я пытаюсь создать программу для работы с 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 должен отображать два чайника как идентичные, только со смещением yy, тогда как glFrustum должен отображать один из них больше другого.Тем не менее, оба они делают чайники одинаково.

Я что-то здесь упускаю?Есть ли другие шаги, которые я должен предпринять, чтобы правильно настроить перспективную проекцию?Или я неправильно понимаю, как работает glFrustum?Я также пытался использовать gluPerspective вместо glFrustum, но я не могу найти правильные значения для использования.Я экспериментировал с полем зрения 90, аспектом 1 и различными значениями z, но все они либо не производят чайник, либо чайник искажается до неузнаваемости.Кроме того, gluPerspective, похоже, ведет себя иначе, чем вызов glFrustum с соответствующими параметрами.Я не уверен, что мне здесь не хватает.

1 Ответ

0 голосов
/ 30 сентября 2018

В ортогональной проекции координаты в пространстве просмотра линейно отображаются на координаты пространства отсечения, а координаты пространства отсчета равны нормализованным координатам устройства, поскольку компонент 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.

Профиль совместимости API OpenGL 4.6Спецификация;12.1.ФИКСИРОВАННЫЕ ФУНКЦИОНАЛЬНЫЕ ПРЕОБРАЗОВАНИЯ VERTEX;стр. 501 :>

void Frustum( double l, double r, double b, double t, double n, double f );

координаты (l b −n) T и (r t −n) T указывают точки наближняя плоскость отсечения, которая отображается в нижний левый и верхний правый углы окна соответственно (при условии, что глаз расположен в точке (0 0 0) T).f дает расстояние от глаза до дальней плоскости отсечения.

Ошибки Ошибка INVALID_VALUE генерируется, если n <= 0, f <= 0, l == r, b == t,или n == f.

...