Как использовать glOrtho () в OpenGL?

Я не могу понять использование glOrtho . Может кто-нибудь объяснить, для чего он используется?

Используется ли он для установки диапазона значений xy и z?

 glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); 

Это означает, что диапазоны x, y и z составляют от -1 до 1?

Посмотрите на эту картинку: Графические outlookы введите описание изображения здесь

Команда glOrtho создает проекцию «Oblique», которую вы видите в нижней строке. Независимо от того, насколько далеко вершины находятся в направлении z, они не отступают на расстояние.

Я использую glOrtho каждый раз, когда мне нужно делать 2D-графику в OpenGL (например, панели работоспособности, меню и т. Д.), Используя следующий код при каждом изменении размера windows:

 glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0.0f, windowWidth, windowHeight, 0.0f, 0.0f, 1.0f); 

Это переназначает координаты OpenGL в эквивалентные значения пикселей (X переходит от 0 в windowWidth и Y идет от 0 до windowHeight). Обратите внимание, что я перевернул значения Y, потому что координаты OpenGL начинаются с нижнего левого угла windows. Поэтому, переворачивая, я получаю более условное (0,0), начиная с верхнего левого угла windows.

glOrtho : 2D игры, объекты близкие и далеко выглядят одинакового размера:

glFrustrum : более реалистичные, такие как 3D, одинаковые объекты вдали выглядят меньше:

Код

 #include  #include  #include  #include  static int ortho = 0; static void display(void) { glClear(GL_COLOR_BUFFER_BIT); glLoadIdentity(); if (ortho) { } else { /* This only rotates and translates the world around to look like the camera moved. */ gluLookAt(0.0, 0.0, -3.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); } glColor3f(1.0f, 1.0f, 1.0f); glutWireCube(2); glFlush(); } static void reshape(int w, int h) { glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if (ortho) { glOrtho(-2.0, 2.0, -2.0, 2.0, -1.5, 1.5); } else { glFrustum(-1.0, 1.0, -1.0, 1.0, 1.5, 20.0); } glMatrixMode(GL_MODELVIEW); } int main(int argc, char** argv) { glutInit(&argc, argv); if (argc > 1) { ortho = 1; } glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); glutInitWindowSize(500, 500); glutInitWindowPosition(100, 100); glutCreateWindow(argv[0]); glClearColor(0.0, 0.0, 0.0, 0.0); glShadeModel(GL_FLAT); glutDisplayFunc(display); glutReshapeFunc(reshape); glutMainLoop(); return EXIT_SUCCESS; } 

схема

Ortho: камера представляет собой плоскость, видимый объем прямоугольника:

введите описание изображения здесь

Фрустр: камера – это точка, видимый объем – кусочек пирамиды:

введите описание изображения здесь

Источник изображения .

параметры

Мы всегда смотрим с + z на -z с + y вверх:

 glOrtho(left, right, bottom, top, near, far) 
  • left : минимум x мы видим
  • right : максимум x мы видим
  • bottom : минимум y мы видим
  • top : максимум y мы видим
  • -near : минимум z мы видим. Да , это near -1 раз. Таким образом, отрицательный вход означает положительный z .
  • -far : максимум z мы видим. Также отрицательный.

Схема:

Источник изображения .

Как это работает под капотом

В итоге OpenGL всегда «использует»:

 glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); 

Если мы не используем ни glOrtho ни glFrustrum , это то, что мы получаем.

glOrtho и glFrustrum – это просто линейные преобразования (умножение матрицы AKA) такие, что:

  • glOrtho : принимает заданный 3D-прямоугольник в куб по умолчанию
  • glFrustrum : принимает заданную часть пирамиды в куб по умолчанию

Это преобразование затем применяется ко всем вершинам. Это то, что я имею в виду в 2D:

Источник изображения .

Последний шаг после трансформации прост:

  • удалите любые точки за пределами куба (отбраковывая): просто убедитесь, что x , y и z находятся в [-1, +1]
  • игнорировать компонент z и принимать только x и y , которые теперь можно поместить в 2D-экран

С glOrtho z игнорируется, поэтому вы всегда можете использовать 0 .

Одна из причин, по которой вы, возможно, захотите использовать z != 0 – это заставить спрайты скрыть фон буфером глубины.

неодобрение

glOrtho устарел с OpenGL 4.5 : профиль совместимости 12.1. «FIXED-FUNCTION VERTEX TRANSFORMATIONS» имеет красный цвет.

Поэтому не используйте его для производства. В любом случае, понимание этого – хороший способ получить представление OpenGL.

Современные программы OpenGL 4 вычисляют матрицу преобразования (которая мала) на CPU, а затем дают матрицу и все точки, которые должны быть преобразованы в OpenGL, что может делать тысячи умножений матриц для разных точек очень быстро параллельно.

Вручно написанные вершинные шейдеры затем делают умножение явно, как правило, с удобными векторными типами данных OpenGL Shading Language.

Поскольку вы явно пишете шейдер, это позволяет вам настроить алгоритм в соответствии с вашими потребностями. Такая гибкость является важной особенностью более современных графических процессоров, которые в отличие от старых, которые фиксировали алгоритм с некоторыми входными параметрами, теперь могут выполнять произвольные вычисления. См. Также: https://stackoverflow.com/a/36211337/895245

С явным GLfloat transform[] это выглядело бы примерно так:

 #include  #include  #include  #define GLEW_STATIC #include  #include  #include "common.h" static const GLuint WIDTH = 800; static const GLuint HEIGHT = 600; /* ourColor is passed on to the fragment shader. */ static const GLchar* vertex_shader_source = "#version 330 core\n" "layout (location = 0) in vec3 position;\n" "layout (location = 1) in vec3 color;\n" "out vec3 ourColor;\n" "uniform mat4 transform;\n" "void main() {\n" " gl_Position = transform * vec4(position, 1.0f);\n" " ourColor = color;\n" "}\n"; static const GLchar* fragment_shader_source = "#version 330 core\n" "in vec3 ourColor;\n" "out vec4 color;\n" "void main() {\n" " color = vec4(ourColor, 1.0f);\n" "}\n"; static GLfloat vertices[] = { /* Positions Colors */ 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f }; int main(void) { GLint shader_program; GLint transform_location; GLuint vbo; GLuint vao; GLFWwindow* window; double time; glfwInit(); window = glfwCreateWindow(WIDTH, HEIGHT, __FILE__, NULL, NULL); glfwMakeContextCurrent(window); glewExperimental = GL_TRUE; glewInit(); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glViewport(0, 0, WIDTH, HEIGHT); shader_program = common_get_shader_program(vertex_shader_source, fragment_shader_source); glGenVertexArrays(1, &vao); glGenBuffers(1, &vbo); glBindVertexArray(vao); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); /* Position attribute */ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0); glEnableVertexAttribArray(0); /* Color attribute */ glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat))); glEnableVertexAttribArray(1); glBindVertexArray(0); while (!glfwWindowShouldClose(window)) { glfwPollEvents(); glClear(GL_COLOR_BUFFER_BIT); glUseProgram(shader_program); transform_location = glGetUniformLocation(shader_program, "transform"); /* THIS is just a dummy transform. */ GLfloat transform[] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, }; time = glfwGetTime(); transform[0] = 2.0f * sin(time); transform[5] = 2.0f * cos(time); glUniformMatrix4fv(transform_location, 1, GL_FALSE, transform); glBindVertexArray(vao); glDrawArrays(GL_TRIANGLES, 0, 3); glBindVertexArray(0); glfwSwapBuffers(window); } glDeleteVertexArrays(1, &vao); glDeleteBuffers(1, &vbo); glfwTerminate(); return EXIT_SUCCESS; } 

Сгенерированный вывод: http://imgur.com/QVW14Gu

Матрица для glOrtho действительно проста, составлена ​​только из масштабирования и перевода:

 scalex, 0, 0, translatex, 0, scaley, 0, translatey, 0, 0, scalez, translatez, 0, 0, 0, 1 

как указано в документах OpenGL 2 .

glFrustum не слишком сложно вычислить вручную, но начинает раздражать. Обратите внимание, что сглаживание не может быть выполнено только с масштабированием и переводами, такими как glOrtho , больше информации по адресу: https://gamedev.stackexchange.com/a/118848/25171

GLM OpenGL C ++ математическая библиотека является популярным выбором для вычисления таких матриц. http://glm.g-truc.net/0.9.2/api/a00245.html документирует операции ortho и frustum .

glOrtho описывает преобразование, которое создает параллельную проекцию. Текущая matrix (см. GlMatrixMode) умножается на эту матрицу, и результат заменяет текущую матрицу, как если бы glMultMatrix вызывались со следующей матрицей в качестве аргумента:

Документация OpenGL (жирная)

Числа определяют расположение плоскостей отсечения (слева, справа, внизу, сверху, ближе и далеко).

«Нормальная» проекция представляет собой перспективную проекцию, которая обеспечивает иллюзию глубины. Википедия определяет параллельную проекцию как:

Параллельные проекции имеют линии проекции, которые параллельны как в реальности, так и в плоскости проекции.

Параллельная проекция соответствует перспективной проекции с гипотетической точкой зрения, например, где камера находится на бесконечном расстоянии от объекта и имеет бесконечное фокусное расстояние или «зум».

  • Как получить библиотеку / заголовки GL?
  • Формирование рендеринга на основе программного обеспечения
  • Отражение и преломление невозможно без рекурсивного отслеживания лучей?
  • Преобразование вращения кватерниона в матрицу вращения?
  • Как реализовать эффект 2D raycasting light в GLSL
  • Класс Mesh, вызванный с конструктором по умолчанию, не работает OpenGL C ++
  • Как OpenGL работает на самом низком уровне?
  • Почему GL разделяет `gl_Position` на W для вас, а не позволяет вам сделать это самостоятельно?
  • как я должен обрабатывать (морфинг) 4D-объекты в opengl?
  • Создание 3D-сферы в Opengl с использованием Visual C ++
  • Как рассчитать Тангенс и Бинормаль?
  • Interesting Posts

    Частные методы в Objective-C, в Xcode 4.3 Мне больше не нужно объявлять их в моем файле реализации?

    Расширение enums через наследование

    Где находится Machine.Config?

    Получить список объектов JSON с Spring RestTemplate

    Как я могу добавить несколько интерактивных ссылок сразу в Microsoft Word?

    Почему возврат 0 необязателен?

    Что означает «Роуминг, не разрешенный сервером» для клиента ssh?

    Почему микрофонный звук не работает в одностороннем режиме в Google Hangouts в Windows 7 и Chrome

    Не удалось вставить новое выходное соединение

    Не удалось прочитать данные из транспортного соединения: существующее соединение было принудительно закрыто удаленным хостом

    Как эта побитовая операция проверяет мощность 2?

    Отладка и производительность релиза

    Сеть WiFi отлично подходит для Macbook Pro и Win XP, но Win Vista «Ограниченная связь»

    Как создать настраиваемый тип исключения в Java?

    «Создание» объекта с возможностью копирования с возможностью memcpy

    Давайте будем гением компьютера.