programing

OpenGL에서 glOrtho()를 사용하는 방법

copyandpastes 2022. 7. 20. 22:24
반응형

OpenGL에서 glOrtho()를 사용하는 방법

안 돼요.glOrtho어떤 용도로 사용되는지 설명해 주실 수 있나요?

x y, z 좌표의 한계를 설정하는 데 사용됩니까?

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

x, y, z의 범위는 -1부터 1까지라는 건가요?

이 그림을 보세요:그래픽 투영

glOrtho오블리주하다'정점이 z 방향으로 아무리 멀리 떨어져 있어도, 그들은 거리로 물러나지 않습니다.

OpenGL에서 2D 그래픽(헬스바, 메뉴 등)을 수행해야 할 때마다 glOrtho를 사용합니다.창 크기를 조정할 때마다 다음 코드를 사용합니다.

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

그러면 OpenGL 좌표가 동등한 픽셀 값으로 다시 매핑됩니다(0에서 창으로 X 이동).폭과 Y는 0에서 창으로 이동합니다.높이).OpenGL 좌표가 창의 왼쪽 아래 모서리에서 시작되므로 Y 값을 플립했습니다.따라서 뒤집으면 창의 왼쪽 상단 모서리에서 시작하는 보다 일반적인(0,0)을 얻을 수 있습니다.

Z 값은 0 ~ 1로 잘립니다.따라서 정점의 위치에 Z 값을 지정할 때 해당 범위를 벗어나면 잘립니다.그렇지 않으면 Z 테스트를 제외하고 위치에 영향을 미치지 않는 것으로 나타납니다.

최소 실행 가능 예시

glOrtho 게임, 멀리 는 같습니다 2D 게임, 2D 게임, 2D 게임, 4D 게임, 4D 게임, 4D 게임, 4D 게임:

여기에 이미지 설명 입력

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

GitHub 업스트림

컴파일:

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

「」와 함께 glOrtho:

./main 1

「」와 함께 glFrustrum:

./main

Ubuntu 18.10에서 테스트.

스키마

Ortho: 카메라는 평면, 가시 볼륨은 직사각형:

여기에 이미지 설명 입력

좌절: 카메라는 피라미드의 한 조각의 한 점, 눈에 보이는 볼륨이다.

여기에 이미지 설명 입력

이미지 소스

파라미터

항상 +z부터 -z까지 +y를 위쪽으로 하고 있습니다.

glOrtho(left, right, bottom, top, near, far)
  • left : ""x 수 있다
  • right : 대최x 수 있다
  • bottom : ""y 수 있다
  • top : 대최y 수 있다
  • -near : ""z그렇구나., 이거요.-1near 부정 은 긍정 입력이라는 z.
  • -far : 대최z 이에요.음성이에요.

스키마:

이미지 소스

후드 아래에서의 동작

결국 OpenGL은 항상 다음을 "사용"합니다.

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

쪽도 하지 않는 glOrtho 않다glFrustrum그게 우리가 얻는 거야

glOrtho ★★★★★★★★★★★★★★★★★」glFrustrum는 다음과 선형 곱셈)일입니다.

  • glOrtho 큐브인 "3D"로 .
  • glFrustrum인 " Cube: " Cube: "Default Cube" : "Default Cube" : "Default Cube" 。

그런 다음 이 변환이 모든 정점에 적용됩니다.2D의 의미는 다음과 같습니다.

이미지 소스

변환 후의 마지막 단계는 다음과 같습니다.

  • 바커 바커 커커 ( 넥을 ) remove ensure that that that that that remove that that remove that that that remove that ( 넥을을을을 remove )x,y ★★★★★★★★★★★★★★★★★」z 있다[-1, +1]
  • z및 only only only only 。x ★★★★★★★★★★★★★★★★★」y에 넣을 수

★★★★★★★★★★★★★★★★ glOrtho,z좋습니다.0.

「 」를하는 .z != 0스프라이트가 깊이 버퍼로 배경을 숨기도록 하는 것입니다.

폐지

glOrthoOpenGL 4.5에서 권장되지 않습니다.호환 프로파일 12.1. "FIXED-FUNCTION"은 빨간색으로 표시됩니다.

그러니 생산에 사용하지 마세요.어떤 경우에도 OpenGL에 대한 통찰력을 얻을 수 있는 좋은 방법입니다.

최신 OpenGL 4 프로그램은 CPU의 변환 매트릭스(소형)를 계산한 후 매트릭스와 모든 점을 OpenGL로 변환합니다. OpenGL은 서로 다른 점에 대해 수천 개의 행렬 곱셈을 매우 빠르게 병렬로 수행할 수 있습니다.

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

셰이더를 명시적으로 쓰기 때문에 필요에 따라 알고리즘을 조정할 수 있습니다.이러한 유연성은 일부 입력 매개 변수를 사용하여 고정된 알고리즘을 수행하던 기존 GPU와 달리 이제 임의 연산을 수행할 수 있는 최신 GPU의 주요 기능입니다.참고 항목: https://stackoverflow.com/a/36211337/895245

인 ""를 사용하여"GLfloat transform[]이렇게 생겼을 거예요.

glfw_syslog.c

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

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

#include <GLFW/glfw3.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
};

/* Build and compile shader program, return its ID. */
GLuint common_get_shader_program(
    const char *vertex_shader_source,
    const char *fragment_shader_source
) {
    GLchar *log = NULL;
    GLint log_length, success;
    GLuint fragment_shader, program, vertex_shader;

    /* Vertex shader */
    vertex_shader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertex_shader, 1, &vertex_shader_source, NULL);
    glCompileShader(vertex_shader);
    glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &success);
    glGetShaderiv(vertex_shader, GL_INFO_LOG_LENGTH, &log_length);
    log = malloc(log_length);
    if (log_length > 0) {
        glGetShaderInfoLog(vertex_shader, log_length, NULL, log);
        printf("vertex shader log:\n\n%s\n", log);
    }
    if (!success) {
        printf("vertex shader compile error\n");
        exit(EXIT_FAILURE);
    }

    /* Fragment shader */
    fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragment_shader, 1, &fragment_shader_source, NULL);
    glCompileShader(fragment_shader);
    glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &success);
    glGetShaderiv(fragment_shader, GL_INFO_LOG_LENGTH, &log_length);
    if (log_length > 0) {
        log = realloc(log, log_length);
        glGetShaderInfoLog(fragment_shader, log_length, NULL, log);
        printf("fragment shader log:\n\n%s\n", log);
    }
    if (!success) {
        printf("fragment shader compile error\n");
        exit(EXIT_FAILURE);
    }

    /* Link shaders */
    program = glCreateProgram();
    glAttachShader(program, vertex_shader);
    glAttachShader(program, fragment_shader);
    glLinkProgram(program);
    glGetProgramiv(program, GL_LINK_STATUS, &success);
    glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length);
    if (log_length > 0) {
        log = realloc(log, log_length);
        glGetProgramInfoLog(program, log_length, NULL, log);
        printf("shader link log:\n\n%s\n", log);
    }
    if (!success) {
        printf("shader link error");
        exit(EXIT_FAILURE);
    }

    /* Cleanup. */
    free(log);
    glDeleteShader(vertex_shader);
    glDeleteShader(fragment_shader);
    return program;
}

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 업스트림

컴파일 및 실행:

gcc -ggdb3 -O0 -o glfw_transform.out -std=c99 -Wall -Wextra -pedantic glfw_transform.c -lGL -lGLU -lglut -lGLEW -lglfw -lm
./glfw_transform.out

출력:

여기에 이미지 설명 입력

★★★★★의 glOrtho매우 심플하고 확장과 번역만으로 구성되어 있습니다.

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

OpenGL 2 문서에 기재되어 있습니다.

행렬도 손으로 계산하기 어렵지 않지만 귀찮아지기 시작한다.다음과 같은 확장과 번역만으로는 좌절감을 해소할 수 없습니다.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 문서 (굵은 글씨)

숫자는 클리핑 평면의 위치(왼쪽, 오른쪽, 아래쪽, 위쪽, 가까운 곳 및 먼 곳)를 정의합니다.

"정상" 투영법은 깊이에 대한 착각을 제공하는 투시 투영법입니다.Wikipedia에서는 병렬 투영을 다음과 같이 정의합니다.

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

평행투영은 카메라가 물체로부터 무한히 떨어져 있고 무한 초점 거리 또는 "줌"을 갖는 것과 같은 가상의 시점을 가진 투시 투영에 해당합니다.

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

반응형