Что такое координаты OpenGL? Игнорировать размер окна OpenGL

Я только начал пытаться следовать простой «рисовать куб» учебное пособие по openGl. После окончательной победы над работой OpenGL у меня все еще очень странные результаты. Моя проблема в том, что объекты имеют тенденцию изменять размеры сами, чтобы соответствовать размеру окна. Вместо этого я бы хотел, чтобы размер окна определял область рендеринга — чем больше окно, тем больше вы можете видеть.

Вот несколько скриншотов изменение размера:
Нормальный размер
Измененный размер
Изображения сохраняются как ссылки намеренно!

Такое поведение автоматического изменения размера ставит вопрос о том, какие координаты используются в OpenGL.

0

Решение

Первое, что нужно иметь в виду: OpenGL — это API рисования. Это не поддерживает сцену или что-то в этом роде.

OpenGL сопоставляет входные координаты геометрии в форме атрибутов вершин с пространством экрана. В старой фиксированной функции есть специальный атрибут вершины, называемый «позиция вершины» или просто короткая «вершина» (фактическая вершина — это больше, чем просто позиция).

Позиция преобразуется в пространство окна в три этапа:

1. Преобразование в пространство вида / глаза: это делается путем умножения положения вершины на матрицу вида модели.

Некоторые дальнейшие вычисления, такие как вычисление освещения, выполняются в пространстве обзора.

2. Преобразование в пространство клипа. Позиция пространства просмотра преобразуется в пространство клипа. Обычно это называется проекцией, и, соответственно, матрица, описывающая это преобразование, называется матрицей проекции.

В пространстве клипа происходят некоторые особые вещи, которые сводятся к отсечению, вам пока не о чем беспокоиться.

3. На последнем шаге преобразовали усеченную геометрию в нормализованные координаты устройства (NDC). Пространство NDC является практически отображением 1: 1 в область просмотра, то есть пределы объема NDC непосредственно соответствуют смещению и размеру области просмотра, установленной с помощью glViewport.

Вы не можете изменить способ 3-го шага, а 1-й шаг зарезервирован для преобразования материала в пространство просмотра. Таким образом, любые корректировки должны произойти на втором этапе.

Итак, вот что вы должны сделать: пределы проекции должны быть прямо пропорциональны экстентам области просмотра. Как например

glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-width/2, width/2, -height/2, height/2, -1, 1);

Да, и просто общее примечание: Вы всегда должны устанавливать видовой экран и настройку проекции также в функции рисования. Если вы видите учебник, который помещает эти операторы в обработчик изменения размера окна, просто проигнорируйте его и все равно сделайте это в коде чертежа. В долгосрочной перспективе это действительно упрощает вещи.

2

Другие решения

Интересная часть:

glMatrixMode( GL_PROJECTION );
glLoadIdentity();
double w = glutGet( GLUT_WINDOW_WIDTH ) / 300.0;
double h = glutGet( GLUT_WINDOW_HEIGHT ) / 300.0;
glOrtho( -1 * w, 1 * w, -1 * h, 1 * h, 10, -10);

glMatrixMode( GL_MODELVIEW );
glLoadIdentity();

В контексте:

#include <GL/glut.h>

void display();
void specialKeys();

double rotate_y=0;
double rotate_x=0;

void display(){
//  Clear screen and Z-buffer
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

glMatrixMode( GL_PROJECTION );
glLoadIdentity();
double w = glutGet( GLUT_WINDOW_WIDTH ) / 300.0;
double h = glutGet( GLUT_WINDOW_HEIGHT ) / 300.0;
glOrtho( -1 * w, 1 * w, -1 * h, 1 * h, 10, -10);

glMatrixMode( GL_MODELVIEW );
glLoadIdentity();

// Rotate when user changes rotate_x and rotate_y
glRotatef( rotate_x, 1.0, 0.0, 0.0 );
glRotatef( rotate_y, 0.0, 1.0, 0.0 );

//Multi-colored side - FRONT
glBegin(GL_POLYGON);

glColor3f( 1.0, 0.0, 0.0 );     glVertex3f(  0.5, -0.5, -0.5 );      // P1 is red
glColor3f( 0.0, 1.0, 0.0 );     glVertex3f(  0.5,  0.5, -0.5 );      // P2 is green
glColor3f( 0.0, 0.0, 1.0 );     glVertex3f( -0.5,  0.5, -0.5 );      // P3 is blue
glColor3f( 1.0, 0.0, 1.0 );     glVertex3f( -0.5, -0.5, -0.5 );      // P4 is purple

glEnd();

// White side - BACK
glBegin(GL_POLYGON);
glColor3f(   1.0,  1.0, 1.0 );
glVertex3f(  0.5, -0.5, 0.5 );
glVertex3f(  0.5,  0.5, 0.5 );
glVertex3f( -0.5,  0.5, 0.5 );
glVertex3f( -0.5, -0.5, 0.5 );
glEnd();

// Purple side - RIGHT
glBegin(GL_POLYGON);
glColor3f(  1.0,  0.0,  1.0 );
glVertex3f( 0.5, -0.5, -0.5 );
glVertex3f( 0.5,  0.5, -0.5 );
glVertex3f( 0.5,  0.5,  0.5 );
glVertex3f( 0.5, -0.5,  0.5 );
glEnd();

// Green side - LEFT
glBegin(GL_POLYGON);
glColor3f(   0.0,  1.0,  0.0 );
glVertex3f( -0.5, -0.5,  0.5 );
glVertex3f( -0.5,  0.5,  0.5 );
glVertex3f( -0.5,  0.5, -0.5 );
glVertex3f( -0.5, -0.5, -0.5 );
glEnd();

// Blue side - TOP
glBegin(GL_POLYGON);
glColor3f(   0.0,  0.0,  1.0 );
glVertex3f(  0.5,  0.5,  0.5 );
glVertex3f(  0.5,  0.5, -0.5 );
glVertex3f( -0.5,  0.5, -0.5 );
glVertex3f( -0.5,  0.5,  0.5 );
glEnd();

// Red side - BOTTOM
glBegin(GL_POLYGON);
glColor3f(   1.0,  0.0,  0.0 );
glVertex3f(  0.5, -0.5, -0.5 );
glVertex3f(  0.5, -0.5,  0.5 );
glVertex3f( -0.5, -0.5,  0.5 );
glVertex3f( -0.5, -0.5, -0.5 );
glEnd();

glFlush();
glutSwapBuffers();
}

void specialKeys( int key, int x, int y ) {
//  Right arrow - increase rotation by 5 degree
if (key == GLUT_KEY_RIGHT)
rotate_y += 5;

//  Left arrow - decrease rotation by 5 degree
else if (key == GLUT_KEY_LEFT)
rotate_y -= 5;

else if (key == GLUT_KEY_UP)
rotate_x += 5;

else if (key == GLUT_KEY_DOWN)
rotate_x -= 5;

//  Request display update
glutPostRedisplay();
}

int main(int argc, char* argv[]){
//  Initialize GLUT and process user parameters
glutInit(&argc,argv);

//  Request double buffered true color window with Z-buffer
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);

// Create window
glutCreateWindow("Awesome Cube");

//  Enable Z-buffer depth test
glEnable(GL_DEPTH_TEST);

// Callback functions
glutDisplayFunc(display);
glutSpecialFunc(specialKeys);

//  Pass control to GLUT for events
glutMainLoop();

//  Return to OS
return 0;
}
1

По вопросам рекламы [email protected]