sirve que para gluortho2d glortho glmatrixmode glfrustum ejemplo c++ c opengl

c++ - que - glortho opengl



¿Cómo usar glOrtho() en OpenGL? (3)

No puedo entender el uso de glOrtho . ¿Alguien puede explicar para qué se usa?

¿Se usa para establecer el rango del límite de coordenadas xy y z?

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

Significa que el rango x, y y z es de -1 a 1?


glOrtho describe una transformación que produce una proyección paralela . La matriz actual (ver glMatrixMode) se multiplica por esta matriz y el resultado reemplaza a la matriz actual, como si se llamara a glMultMatrix con la siguiente matriz como argumento:

Documentación de OpenGL (mi negrita)

Los números definen las ubicaciones de los planos de recorte (izquierda, derecha, abajo, arriba, cerca y lejos).

La proyección "normal" es una proyección en perspectiva que proporciona la ilusión de profundidad. Wikipedia define una proyección paralela como:

Las proyecciones paralelas tienen líneas de proyección que son paralelas tanto en la realidad como en el plano de proyección.

La proyección paralela corresponde a una proyección en perspectiva con un punto de vista hipotético, por ejemplo, uno donde la cámara se encuentra a una distancia infinita del objeto y tiene una distancia focal infinita, o "zoom".


Eche un vistazo a esta imagen: Proyecciones gráficas

El comando glOrtho produce una proyección "Oblicua" que ves en la fila inferior. No importa cuán lejos estén los vértices en la dirección z, no retrocederán en la distancia.

Uso glOrtho cada vez que necesito hacer gráficos 2D en OpenGL (como barras de estado, menús, etc.) utilizando el siguiente código cada vez que se cambia el tamaño de la ventana:

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

Esto reasignará las coordenadas de OpenGL en los valores de píxel equivalentes (X va de 0 a windowWidth e Y va de 0 a windowHeight). Tenga en cuenta que he volteado los valores Y porque las coordenadas OpenGL comienzan desde la esquina inferior izquierda de la ventana. Así que volteando, me sale más convencional (0,0) empezando por la esquina superior izquierda de la ventana.


glOrtho : juegos 2D, objetos cercanos y lejanos que aparecen del mismo tamaño:

glFrustrum : más en la vida real como 3D, los objetos idénticos más alejados parecen más pequeños:

Código

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

Esquema

Ortho: cámara es un avión, volumen visible un rectángulo:

Frustrum: cámara es un punto, volumen visible una porción de una pirámide:

Fuente de la imagen

Parámetros

Siempre estamos mirando de + z a -z con + y hacia arriba:

glOrtho(left, right, bottom, top, near, far)

  • left : mínimo x vemos
  • right : máximo x que vemos
  • bottom : mínimo y vemos
  • top : máximo y vemos
  • -near : mínimo z vemos. , esto es -1 veces near . Entonces, una entrada negativa significa una z positiva.
  • -far : máximo z que vemos. También negativo.

Esquema:

Fuente de la imagen

Cómo funciona bajo el capó

Al final, OpenGL siempre "usa":

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

Si no usamos glOrtho ni glFrustrum , eso es lo que obtenemos.

glOrtho y glFrustrum son solo transformaciones lineales (AKA, matriz de multiplicación) tales que:

  • glOrtho : toma un rectángulo 3D dado en el cubo predeterminado
  • glFrustrum : toma una sección de pirámide dada en el cubo predeterminado

Esta transformación se aplica a todos los vértices. Esto es lo que quiero decir en 2D:

Fuente de la imagen

El último paso después de la transformación es simple:

  • eliminar cualquier punto fuera del cubo (eliminación): solo asegúrese de que x , y y z estén en [-1, +1]
  • ignora el componente z y toma solo x e y , que ahora se puede poner en una pantalla 2D

Con glOrtho , se ignora z , por lo que también podría usar siempre 0 .

Una razón por la que quizás desee usar z != 0 es hacer que los sprites oculten el fondo con el búfer de profundidad.

Deprecación

glOrtho está en desuso a partir de OpenGL 4.5 : el perfil de compatibilidad 12.1. "TRANSFORMACIONES DE VERTEX DE FUNCIÓN FIJA" está en rojo.

Entonces no lo use para producción. En cualquier caso, entender que es una buena forma de obtener algo de información de OpenGL.

Los modernos programas OpenGL 4 calculan la matriz de transformación (que es pequeña) en la CPU y luego transfieren la matriz y todos los puntos a transformar a OpenGL, que puede hacer miles de multiplicaciones de matrices para diferentes puntos realmente rápidos en paralelo.

Los sombreadores de vértices escritos manualmente realizan la multiplicación de forma explícita, generalmente con los tipos de datos vectoriales convenientes del lenguaje de sombreado OpenGL.

Dado que escribe el sombreador explícitamente, esto le permite ajustar el algoritmo a sus necesidades. Dicha flexibilidad es una característica principal de las GPU más modernas, que a diferencia de las antiguas que realizaban un algoritmo fijo con algunos parámetros de entrada, ahora pueden realizar cálculos arbitrarios. Ver también: https://.com/a/36211337/895245

Con una GLfloat transform[] explícita de GLfloat transform[] se vería algo como esto:

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

Salida generada: http://imgur.com/QVW14Gu

La matriz para glOrtho es realmente simple, compuesta solo de escala y traducción:

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

como se menciona en los documentos de OpenGL 2 .

La matriz glFrustum tampoco es demasiado difícil de calcular a mano, pero comienza a ser molesta. Tenga en cuenta que el triturado no se puede compensar con escalas y traducciones como glOrtho , más información en: https://gamedev.stackexchange.com/a/118848/25171

La biblioteca de matemática GLM OpenGL C ++ es una opción popular para calcular tales matrices. http://glm.g-truc.net/0.9.2/api/a00245.html documenta las operaciones en ortho y frustum .