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



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



используется ли он для установки диапазона X Y и Z координат предела?



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


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

5326   3  

3 ответов:

взгляните на эту картинку:Графические Проекции enter image description here

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

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

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

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

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

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

код

#include <stdlib.h>

#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>

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: камера представляет собой плоскость, видимый объем прямоугольник:

enter image description here

разочарование: камера-это точка, видимый объем срез пирамиды:

enter image description here

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

параметры

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

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

схема:

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

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

в конце концов, OpenGL всегда "использует":

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

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

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

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

эта трансформация применяется ко всем вершинам. Вот что я имею в виду 2D:

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

последний шаг после преобразования прост:

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

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

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

осуждение

glOrtho осуждается по состоянию на OpenGL 4.5: профиль совместимости 12.1. "Преобразования вершин с фиксированной функцией" выделены красным цветом.

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

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

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

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

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

#include <math.h>
#include <stdio.h>
#include <stdlib.h>

#define GLEW_STATIC
#include <GL/glew.h>

#include <GLFW/glfw3.h>

#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 docs.

The 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 описывает преобразование, которое производит параллельно проекция. Текущая матрица (см. glMatrixMode) умножается на эту матрицу, и результат заменяет текущую матрицу, как если бы glMultMatrix вызывалась со следующей матрицей в качестве ее аргумента:

документация OpenGL (моя дерзость)

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

" нормальная " проекция-это перспективная проекция, которая создает иллюзию глубины. Википедия определяет параллельную проекцию как:

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

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

Comments

    Ничего не найдено.