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;
}
엮다:
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
,y
및z
에[-1, +1]
- 무시
z
구성 요소 만 가지고x
와y
지금은 2 차원 화면에 넣을 수있는,
로 glOrtho
, z
무시, 그래서 당신은뿐만 아니라 항상 사용할 수 있습니다 0
.
사용하고 싶은 한 가지 이유 z != 0
는 스프라이트가 깊이 버퍼로 배경을 숨기도록 만드는 것입니다.
천칭
glOrtho
OpenGL 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;
}
산출:
매트릭스 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
'Development Tip' 카테고리의 다른 글
JavaScript에서 페이지가 유효한지 확인-ASP.NET (0) | 2020.10.13 |
---|---|
linq에서 SQL로 모두 선택 (*)하는 방법 (0) | 2020.10.13 |
Arduino에서 int 또는 String을 char 배열로 변환 (0) | 2020.10.13 |
postgresql에서 특정 열이있는 테이블을 찾는 방법 (0) | 2020.10.13 |
Python-루트 프로젝트 구조의 경로 가져 오기 (0) | 2020.10.13 |