Development Tip

OpenGL에서 glOrtho ()를 사용하는 방법은 무엇입니까?

yourdevel 2020. 10. 13. 19:27
반응형

OpenGL에서 glOrtho ()를 사용하는 방법은 무엇입니까?


의 사용법을 이해할 수 없습니다 glOrtho. 누군가 그것이 무엇을 위해 사용되는지 설명 할 수 있습니까?

xy 및 z 좌표 제한 범위를 설정하는 데 사용됩니까?

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

x, y 및 z 범위가 -1에서 1까지임을 의미합니까?


이 그림을보십시오 : 그래픽 프로젝션 여기에 이미지 설명 입력

glOrtho명령은 맨 아래 행에 표시되는 "Oblique"투영을 생성합니다. 정점이 z 방향에서 얼마나 멀리 떨어져 있어도 거리로 후퇴하지 않습니다.

창 크기를 조정할 때마다 다음 코드를 사용하여 OpenGL에서 2D 그래픽 (예 : 상태 표시 줄, 메뉴 등)을 수행해야 할 때마다 glOrtho를 사용합니다.

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

이것은 OpenGL 좌표를 동등한 픽셀 값으로 다시 매핑합니다 (X는 0에서 windowWidth로, Y는 0에서 windowHeight로). OpenGL 좌표는 창의 왼쪽 하단에서 시작하기 때문에 Y 값을 뒤집 었습니다. 따라서 뒤집 으면 창의 왼쪽 상단 모서리에서 시작하는보다 일반적인 (0,0)이 표시됩니다.

Z 값은 0에서 1까지 잘립니다. 따라서 정점 위치에 Z 값을 지정할 때주의해야합니다. 해당 범위를 벗어나면 잘립니다. 그렇지 않으면 해당 범위 내에 있으면 Z 테스트를 제외하고 위치에 영향을 미치지 않는 것처럼 보입니다.


최소 실행 가능 예

glOrtho: 2D 게임, 가까운 물체와 멀리있는 물체가 같은 크기로 나타납니다.

여기에 이미지 설명 입력

glFrustrum: 3D와 같은 실제 생활, 멀리 떨어진 동일한 물체는 더 작게 보입니다.

여기에 이미지 설명 입력

main.c

#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;
}

GitHub 업스트림 .

엮다:

gcc -ggdb3 -O0 -o main -std=c99 -Wall -Wextra -pedantic main.c -lGL -lGLU -lglut

다음으로 실행 glOrtho:

./main 1

다음으로 실행 glFrustrum:

./main

Ubuntu 18.10에서 테스트되었습니다.

개요

직교 : 카메라는 평면이고 가시적 볼륨은 직사각형입니다.

여기에 이미지 설명 입력

Frustrum : 카메라는 포인트, 가시적 볼륨, 피라미드 조각 :

여기에 이미지 설명 입력

이미지 소스 .

매개 변수

우리는 항상 + y에서 -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, yz[-1, +1]
  • 무시 z구성 요소 만 가지고 xy지금은 2 차원 화면에 넣을 수있는,

glOrtho, z무시, 그래서 당신은뿐만 아니라 항상 사용할 수 있습니다 0.

사용하고 싶은 한 가지 이유 z != 0는 스프라이트가 깊이 버퍼로 배경을 숨기도록 만드는 것입니다.

천칭

glOrthoOpenGL 4.5 : 호환성 프로파일 12.1부터 더 이상 사용되지 않습니다 . "FIXED-FUNCTION VERTEX TRANSFORMATIONS"가 빨간색으로 표시됩니다.

따라서 생산에 사용하지 마십시오. 어쨌든 그것을 이해하는 것은 OpenGL에 대한 통찰력을 얻는 좋은 방법입니다.

최신 OpenGL 4 프로그램은 CPU에서 변환 행렬 (작은)을 계산 한 다음 행렬과 변환 할 모든 점을 OpenGL로 제공하여 여러 점에 대해 수천 개의 행렬 곱셈을 병렬로 매우 빠르게 수행 할 수 있습니다.

수동으로 작성된 정점 셰이더 는 일반적으로 OpenGL 셰이딩 언어의 편리한 벡터 데이터 유형을 사용하여 명시 적으로 곱셈을 수행합니다.

셰이더를 명시 적으로 작성 했으므로 필요에 따라 알고리즘을 조정할 수 있습니다. 이러한 유연성은 일부 입력 매개 변수를 사용하여 고정 알고리즘을 수행 한 이전 GPU와 달리 이제 임의의 계산을 수행 할 수있는 최신 GPU의 주요 기능입니다. 참조 : 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;
}

GitHub 업스트림 .

산출:

여기에 이미지 설명 입력

매트릭스 glOrtho는 정말 간단하며 크기 조정과 변환으로 만 구성됩니다.

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

OpenGL 2 문서 에서 언급 한대로 .

The glFrustum matrix is not too hard to calculate by hand either, but starts getting annoying. Note how frustum cannot be made up with only scaling and translations like glOrtho, more info at: https://gamedev.stackexchange.com/a/118848/25171

The GLM OpenGL C++ math library is a popular choice for calculating such matrices. http://glm.g-truc.net/0.9.2/api/a00245.html documents both an ortho and frustum operations.


glOrtho describes a transformation that produces a parallel projection. The current matrix (see glMatrixMode) is multiplied by this matrix and the result replaces the current matrix, as if glMultMatrix were called with the following matrix as its argument:

OpenGL documentation (my bold)

숫자는 클리핑 평면의 위치를 ​​정의합니다 (왼쪽, 오른쪽, 아래쪽, 위쪽, 근거리 및 원거리).

"일반"투영은 깊이의 환상을 제공하는 원근 투영입니다. Wikipedia 는 병렬 투영을 다음과 같이 정의합니다.

평행 투영에는 현실과 투영 평면 모두에서 평행 한 투영 선이 있습니다.

평행 투영은 가상의 관점을 갖는 투시 투영에 해당합니다. 예를 들어, 카메라가 물체로부터 무한 거리에 있고 무한 초점 거리 또는 "줌"을 갖는 관점이 있습니다.

참고 URL : https://stackoverflow.com/questions/2571402/how-to-use-glortho-in-opengl

반응형