当前位置:  开发笔记 > 编程语言 > 正文

如何在OpenGL中使用glOrtho()?

如何解决《如何在OpenGL中使用glOrtho()?》经验,为你挑选了2个好方法。

我无法理解的用法glOrtho.有人可以解释它的用途吗?

是否用于设置xy和z坐标限制的范围?

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

这意味着x,y和z范围是-1到1?



1> Mikepote..:

看看这张图片:图形投影 在此输入图像描述

glOrtho命令会生成一个"倾斜"投影,您可以在底行看到该投影.无论顶点在z方向上有多远,它们都不会退回到距离中.

每次调整窗口大小时,每次我需要在OpenGL中使用以下代码执行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).请注意,我已经翻转了Y值,因为OpenGL坐标从窗口的左下角开始.所以通过翻转,我得到一个更常规的(0,0)从窗口的左上角开始.


哦,天哪,我爱你.您是否知道在线查找/找出这一行代码需要多长时间?谢谢你,我会为你命名我的第一个孩子
OpenGl上有很多糟糕的教程是荒谬的.
非常感谢你澄清这个问题!:)
注意:(在Android上)即使模型仅具有负z值,最终(远)参数似乎也必须具有正值。我做了一个简单的三角形测试(禁用了剔除功能),其顶点位于z = -2处。如果我使用`glOrtho(..,0.0f,-4.0f);`,..- 1.0f,-3.0f)`或`..- 3.0f,-1.0f),则三角形是不可见的。可见,far参数必须为POSITIVE 2或更大;似乎无关紧要的参数是什么。以下任何一项均有效:.0.0f,2.0f),..- 1.0f,2.0f),..- 3.0f,2.0f)或..0.0f,1000.0f。 。

2> Ciro Santill..:

最小的可运行示例

glOrtho:2D游戏,关闭和远处的对象看起来大小相同:

在此输入图像描述

glFrustrum:更像3D的现实生活,更远的相同物体看起来更小:

在此输入图像描述

main.c中

#include 

#include 
#include 
#include 

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:相机是一个平面,可见体积是一个矩形:

在此输入图像描述

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只是线性变换(AKA矩阵乘法),这样:

glOrtho:将给定的3D矩形放入默认的多维数据集中

glFrustrum:将给定的金字塔部分放入默认的多维数据集中

然后将此变换应用于所有顶点.这就是我在2D中的意思:

图像来源.

转型后的最后一步很简单:

删除多维数据集之外的任何点(剔除):只需确保x,yz在其中[-1, +1]

忽略z分量和仅取xy,现在可以被放入2D屏幕

glOrtho,z被忽略,所以你可能总是使用0.

您可能想要使用的一个原因z != 0是使精灵用深度缓冲区隐藏背景.

弃用

glOrtho自OpenGL 4.5起不推荐使用:兼容性配置文件12.1."固定功能VERTEX转换"为红色.

所以不要用它来生产.无论如何,了解它是获得一些OpenGL洞察力的好方法.

现代OpenGL 4程序计算CPU上的变换矩阵(很小),然后将矩阵和所有点转换为OpenGL,这可以非常快速地并行地对不同点进行数千次矩阵乘法.

手动编写的顶点着色器然后显式地进行乘法,通常使用OpenGL着色语言的方便矢量数据类型.

由于您明确编写着色器,因此可以根据需要调整算法.这种灵活性是更现代GPU的一个主要特征,与使用某些输入参数执行固定算法的旧GPU不同,现在可以进行任意计算.另见:https://stackoverflow.com/a/36211337/895245

显式GLfloat transform[]它看起来像这样:

#include 
#include 
#include 

#define GLEW_STATIC
#include 

#include 

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

GitHub上游.

输出:

在此输入图像描述

矩阵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记录orthofrustum操作.

推荐阅读
jerry613
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有