OpenGL绘制倒三角形

Posted

技术标签:

【中文标题】OpenGL绘制倒三角形【英文标题】:OpenGL drawing Inverted Triangle 【发布时间】:2017-08-01 14:17:43 【问题描述】:

我的三角形顶点位于数组顶点中,这些顶点以这样一种方式指定,即我应该得到一个直立的三角形,但我的三角形围绕 y 轴倒置。 代码如下。

这是一些全球性的东西

#include<GL\glew.h>
#include<GL\freeglut.h>
#include<glm.hpp>
#include<gtc\matrix_transform.hpp>
#include<string>
#include<fstream>
#include<iostream>
using namespace std;

GLfloat vertices[] = 
    -1,-1,
    1,-1,
    0,1
;

GLuint vaoId;
GLuint vboId;

glm::mat4 projectionMatrix = glm::perspective(50.0f, 1.0f / 1.0f, 5.0f, 
20.0f);
glm::mat4 modelViewMatrix = glm::translate(glm::mat4(1), glm::vec3(0, 0, -20));

string parseShader(string fileName) 
    string shaderCode;
    ifstream ifs;
    ifs.open(fileName, ios::in);
    string line;
    while (!ifs.eof()) 
        getline(ifs, line);
        shaderCode += line;
        shaderCode += "\n";
    
    return shaderCode;


GLuint program;

这个函数只是加载着色器

void loadShader() 
    string vShader = parseShader("vShader.txt");
    GLuint vShaderId = glCreateShader(GL_VERTEX_SHADER);
    const GLchar* vShaderSource = vShader.c_str();
    glShaderSource(vShaderId, 1, &vShaderSource, NULL);
    glCompileShader(vShaderId);
    GLint compileStatus;
    glGetShaderiv(vShaderId, GL_COMPILE_STATUS, &compileStatus);
    if (!compileStatus) 
        cout << "Cannot compile shader\n";
        glDeleteShader(vShaderId);
        return;
    

    string fShader = parseShader("fShader.txt");
    GLuint fShaderId = glCreateShader(GL_FRAGMENT_SHADER);
    const GLchar* fShaderSource = fShader.c_str();
    glShaderSource(fShaderId, 1, &fShaderSource, NULL);
    glCompileShader(fShaderId);
    glGetShaderiv(fShaderId, GL_COMPILE_STATUS, &compileStatus);
    if (!compileStatus) 
        cout << "Cannot compile fragment Shader\n";
        glDeleteShader(fShaderId);
        return;
    

    GLuint programId;
    programId = glCreateProgram();
    glAttachShader(programId, vShaderId);
    glAttachShader(programId, fShaderId);
    glLinkProgram(programId);
    GLint linkStatus;
    glGetProgramiv(programId, GL_LINK_STATUS, &linkStatus);
    if (!linkStatus) 
        cout << "Cannot link program\n";
        glDeleteShader(vShaderId);
        glDeleteShader(fShaderId);
        glDeleteProgram(programId);
        return;
    
    glUseProgram(programId);

这会在 VBO 中加载数据

void loadDataInBuffers() 
    glGenBuffers(1, &vboId);
    glBindBuffer(GL_ARRAY_BUFFER, vboId);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

此函数用于将状态绑定到 VAO

void loadVao() 
    glBindBuffer(GL_ARRAY_BUFFER, vboId);
    glGenVertexArrays(1, &vaoId);
    glBindVertexArray(vaoId);
    glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0);
    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

这是渲染函数

void display() 
    glClear(GL_COLOR_BUFFER_BIT);
    glBindVertexArray(vaoId);
    glDrawArrays(GL_TRIANGLES, 0, 3);
    glutSwapBuffers();

这会调用上面定义的所有其他函数

void init() 
    glClearColor(0, 0, 0, 0);
    loadDataInBuffers();
    loadShader();
    loadVao();
    glUniformMatrix4fv(1, 1, GL_FALSE, &projectionMatrix[0][0]);
    glUniformMatrix4fv(2, 1, GL_FALSE, &modelViewMatrix[0][0]);

我的主要方法是这样的

int main(int argc, char** argv) 
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
    glutInitWindowSize(500, 500);
    glutInitWindowPosition(100, 100);
    glutCreateWindow("Simple Window");
    glewInit();
    init();
    glutDisplayFunc(display);
    glutMainLoop();
    return 0;

下面是顶点着色器

#version 430

layout(location = 0) in vec2 pos;
layout(location = 1) uniform mat4 projectionMatrix;
layout(location = 2) uniform mat4 modelViewMatrix;

void main()
    vec4 position = vec4(pos,0,1);
    gl_Position = projectionMatrix*modelViewMatrix*position;

下面是片段着色器

#version 430

void main()
    gl_FragColor = vec4(1,0,0,1);

这就是我得到的

我不应该得到这样的东西吗

【问题讨论】:

有很多方法可以做到这一点,这取决于你想做什么。你可以弄乱你的矩阵,你可以弄乱顶点数据,你可以在顶点着色器中硬编码一个镜像。如果没有更多上下文,这有点难以回答。 您可以发布 2 个屏幕截图:一个是实际结果,另一个是它的外观(使用油漆)。这样,我们就有了更多的想法。 @HannesHauptmann 我已经编辑了我的帖子并包含了图片。 @Frank 我猜顶点着色器会按照指定的顺序接收顶点,这样我的三角形应该是倒置的。 但是你想反转什么?三角形本身?最后的图?三角形的变换方式?结果都一样,但意图却大不相同。 【参考方案1】:

已编辑:

您似乎遇到了此处描述的问题:https://www.opengl.org/discussion_boards/showthread.php/185661-glm-perspective-inverts-image

glm::mat4 projectionMatrix = glm::perspective(50.0f, 1.0f / 1.0f, 5.0f, 20.0f);

您已经以度为单位指定了角度 (50.0);它应该以弧度表示。 50 弧度是一个奇怪的数字,可能不是你想要的。

显然,此功能的单位没有详细记录(我无法访问文档站点,所以我不知道)。将 50.0 替换为以弧度表示的任何值,看看是否可行。

glm::mat4 projectionMatrix = glm::perspective(50.0f * M_PI / 180.0f, 1.0f / 1.0f, 5.0f, 20.0f);

【讨论】:

这使三角形消失了。我的相机位于原点,向下看负 Z 轴,我的近剪裁平面和远剪裁平面分别为 5 和 20。所以我将我的三角形在负 z 轴上向下移动,使其位于近剪裁平面和远剪裁平面之间。【参考方案2】:

如果您只关心反转最终图像,最简单的方法是在坐标位于剪辑空间后在顶点着色器末尾应用镜像操作:

gl_Position = (projectionMatrix*modelViewMatrix*position) * vec4(1, -1, 1, 1);

【讨论】:

当然会正确,但我的意思是我应该没有镜像操作。

以上是关于OpenGL绘制倒三角形的主要内容,如果未能解决你的问题,请参考以下文章

绘制三角形带时,啥控制 OpenGL 的行为?

编程题目:利用Opengl绘制一个三角形。

OpenGL不在C++中绘制三角形

OpenGL不绘制三角形

OpenGL学习——绘制三角形

绘制大量三角形的有效方法(OpenGL)