의 사용법을 이해할 수 없습니다 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 테스트를 제외하고 위치에 영향을 미치지 않는 것처럼 보입니다.
z= -2
. 내가 사용하는 경우 삼각형은 눈에 보이지 않는이었다 glOrtho(.., 0.0f, -4.0f);
, ..-1.0f, -3.0f)
또는 ..-3.0f, -1.0f)
. 표시하려면 far 매개 변수가 POSITIVE 2 이상이어야합니다. near 매개 변수가 무엇인지는 중요하지 않은 것 같습니다. 이들 중 어떤 일 : ..0.0f, 2.0f)
, ..-1.0f, 2.0f)
, ..-3.0f, 2.0f)
, 또는 ..0.0f, 1000.0f
.
최소 실행 가능 예
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 : 카메라는 포인트, 가시적 볼륨, 피라미드 조각 :
이미지 소스 .
매개 변수
우리는 항상 + 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
지금은 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 문서 에서 언급했듯이 .
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 문서 (내 굵은 글씨)
숫자는 클리핑 평면의 위치를 정의합니다 (왼쪽, 오른쪽, 아래쪽, 위쪽, 근거리 및 원거리).
"일반"투영은 깊이의 환상을 제공하는 원근 투영입니다. Wikipedia 는 병렬 투영을 다음과 같이 정의합니다.
평행 투영에는 실제와 투영 평면 모두에서 평행 한 투영 선이 있습니다.
평행 투영은 가상의 관점을 갖는 투시 투영에 해당합니다. 예를 들어, 카메라가 물체로부터 무한 거리에 있고 무한 초점 거리 또는 "줌"을 갖는 관점이 있습니다.