解释glOrtho()的用法?
我无法理解glOrtho
的用法。 有人可以解释它用于什么吗?
更新
是否用于设置xy和z坐标限制的范围?
glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
这意味着x,y和z范围从-1到1?
看看这个图片: graphics投影
glOrtho
命令产生一个“斜”的投影,你可以在底部看到。 不pipe多远的顶点在z方向上,它们都不会退到远方。
每当我需要在OpenGL中使用glOrtho(每次窗口大小调整时使用下面的代码)来执行OpenGL中的2Dgraphics(例如健康栏,菜单等)时:
glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0.0f, windowWidth, windowHeight, 0.0f, 0.0f, 1.0f);
这会将OpenGL坐标重新映射到等效像素值(X从0到windowWidth,Y从0到windowHeight)。 请注意,我翻转了Y值,因为OpenGL的坐标是从窗口的左下angular开始的。 所以通过翻转,我得到一个更传统的(0,0)在窗口的左上angular开始。
glOrtho
:2D游戏,近远的物体出现相同的大小:
glFrustrum
:像3D一样更真实,相同的物体越glFrustrum
越显得更小:
码
#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; }
架构
Ortho:摄像头是一个平面,可见卷为一个矩形:
Frustrum:相机是一个点,可见音量一个金字塔片:
图像源 。
参数
我们一直在寻找从+ Z到-Z和+ Y向上:
glOrtho(left, right, bottom, top, near, far)
-
left
:我们看到的最小x
-
right
:最大的x
我们看到 -
bottom
:我们看到的最小 -
top
:我们看到的最大 -
-near
:最小z
我们看到。 是的 ,这是near
-1
倍。 所以负input意味着正z
。 - 我们看到最大的
z
也是负面的。
架构:
图像源 。
它是如何工作的
最后,OpenGL总是“使用”:
glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
如果我们既不使用glOrtho
也不使用glFrustrum
,那就是我们所得到的。
glOrtho
和glFrustrum
只是线性变换(AKAmatrix乘法),所以:
-
glOrtho
:将给定的3D矩形放入默认的立方体中 -
glFrustrum
:将给定的金字塔部分放入默认的多维数据集中
这个转换然后被应用到所有的顶点。 这是我在2D中的意思:
图像源 。
转型后的最后一步很简单:
- 删除立方体外的任何点(剔除):只要确保
x
,y
和z
在[-1, +1]
- 忽略
z
分量,只取x
和y
,现在可以放入2D屏幕
使用glOrtho
, z
被忽略,所以你可能总是使用0
。
你可能想要使用z != 0
一个原因是使精灵隐藏深度缓冲区的背景。
弃用
glOrtho
从OpenGL 4.5开始不推荐使用:兼容性configuration文件12.1。 “固定functionVERTEX转换”是红色的。
所以不要用它来生产。 无论如何,理解这是获得OpenGL洞察力的好方法。
现代OpenGL 4程序在CPU上计算变换matrix(很小),然后给matrix和所有点转换为OpenGL,这样可以对不同的点进行数千个并行的matrix乘法。
手动编写的顶点着色器然后明确地进行乘法运算,通常使用OpenGL Shading Language的便捷vector数据types。
由于您明确地编写着色器,因此可以根据需要调整algorithm。 这种灵活性是更现代化的GPU的一个主要特征,它不同于那些用一些input参数进行固定algorithm的旧的algorithm,现在可以进行任意的计算。 另请参阅: 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; }
生成的输出: http : //imgur.com/QVW14Gu
glOrtho
的matrix非常简单,仅由缩放和平移组成:
scalex, 0, 0, translatex, 0, scaley, 0, translatey, 0, 0, scalez, translatez, 0, 0, 0, 1
正如OpenGL 2文档中提到的那样。
glFrustum
matrix也不是很难计算,但开始变得烦人。 请注意,如果仅仅缩放和翻译,比如glOrtho
,就不能构成glOrtho
,更多信息请 glOrtho
https://gamedev.stackexchange.com/a/118848/25171
GLM OpenGL C ++math库是计算这种matrix的stream行select。 http://glm.g-truc.net/0.9.2/api/a00245.html文件都是一个;ortho
和frustum
操作。
glOrtho描述了一个产生平行投影的变换。 当前matrix(请参阅glMatrixMode)乘以该matrix,结果将replace当前matrix,就像glMultMatrix以下面的matrix作为参数调用一样:
OpenGL文档 (我的粗体)
数字定义剪辑平面的位置(左,右,下,上,近和远)。
“正常”投影是提供深度幻象的透视投影。 维基百科定义了一个平行投影:
平行投影具有在现实中和在投影平面上平行的投影线。
平行投影对应于具有假设视点的透视投影,例如,相机位于距物体无限远处并具有无限焦距或“缩放”的位置。