OpenGL 忽略四边形并将它们变成三角形

Posted

技术标签:

【中文标题】OpenGL 忽略四边形并将它们变成三角形【英文标题】:OpenGL ignores Quads and makes them Triangles 【发布时间】:2018-11-09 02:18:52 【问题描述】:

这是我第二次制作游戏引擎,但我现在有点卡住了,因为我无法弄清楚为什么会发生这种情况,无论我发送什么对象,OpenGL 只会在上面绘制一个白色三角形屏幕中心,like this.

我什至从渲染器和相机对象上的上一个引擎中复制了我的旧代码,但行为仍然相同,所以我猜它与渲染脚本有关。

渲染器:

Renderer2D::Renderer2D(const Shader& shader) 
    this->shader = shader;
    this->Init();


Renderer2D::~Renderer2D() 
    glDeleteVertexArrays(1, &this->QuadVAO);


void Renderer2D::Render(Texture & texture, iVec2 position, iVec2 size, float rotation, iVec3 color) 
    this->shader.Use();
    iMat4 model;

    using namespace glm;
    model = translate(model, iVec3(position.x, position.y, 0.0f));
    /*
    model = translate(model, iVec3(size.x * 0.5f, size.y * 0.5f, 0.0f));
    model = rotate(model, rotation, iVec3(0.0f, 0.0f, 1.0f));
    model = translate(model, iVec3(size.x * -0.5f, size.y * -0.5f, 0.0f));
    */
    model = glm::scale(model, iVec3(size.x, size.y, 1.0f));

    this->shader.SetMatrix4("model2D", model);
    this->shader.SetVector3f("color2D", color);

    glActiveTexture(GL_TEXTURE0);
    texture.Bind();

    glBindVertexArray(this->QuadVAO);
    glDrawArrays(GL_TRIANGLES, 0, 6);
    glBindVertexArray(0);


void Renderer2D::Init() 
    U16 VBO;

    float vertices[] = 
        // Pos      // Tex
        0.0f, 1.0f, 0.0f, 1.0f,
        1.0f, 0.0f, 1.0f, 0.0f,
        0.0f, 0.0f, 0.0f, 0.0f,

        0.0f, 1.0f, 0.0f, 1.0f,
        1.0f, 1.0f, 1.0f, 1.0f,
        1.0f, 0.0f, 1.0f, 0.0f
    ;

    glGenVertexArrays(1, &this->QuadVAO);
    glGenBuffers(1, &VBO);

    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glBindVertexArray(this->QuadVAO);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0);

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

顶点着色器:

#version 330 core
layout (location = 0) in vec4 vertex; // <vec2 position, vec2 texCoords>

out vec2 TexCoords;

uniform mat4 view2D;
uniform mat4 model2D;
uniform mat4 projection2D;

void main()

    TexCoords = vertex.zw;
    gl_Position = projection2D * view2D * mode2Dl * vec4(vertex.xy, 0.0, 1.0);


编辑:

顶点着色器:

#version 330 core
layout (location = 0) in vec4 vertex; // <vec2 position, vec2 texCoords>

out vec2 TexCoords;

uniform mat4 view2D;
uniform mat4 model2D;
uniform mat4 projection2D;

void main()

    TexCoords = vertex.zw;
    gl_Position = projection2D * view2D * model2D * vec4(vertex.xy, 0.0, 1.0);

片段着色器:

#version 330 core
in vec2 TexCoords;
out vec4 color2D; //Fixed the error!

uniform sampler2D image2D;
uniform vec3 color2D;

void main()
    
    color2D = vec4(color2D, 1.0) * texture(image2D, TexCoords);
  

资源.cpp

Shader Resources::LoadShaderFromFile(const char * vertexSource, const char * fragmentSource) 
    using namespace std;
    string vertexCode;
    string fragmentCode;

    try 
        ifstream vertexShaderFile(vertexSource);
        ifstream fragmentShaderFile(fragmentSource);
        stringstream vShaderStream, fShaderStream;

        vShaderStream << vertexShaderFile.rdbuf();
        fShaderStream << fragmentShaderFile.rdbuf();

        vertexShaderFile.close();
        fragmentShaderFile.close();

        vertexCode = vShaderStream.str();
        fragmentCode = fShaderStream.str();
    
    catch (exception e) 
        cout << "ERROR::SHADER: Failed to read shader files" << std::endl;
    

    const char *vShaderCode = vertexCode.c_str();
    const char *fShaderCode = fragmentCode.c_str();

    Shader shader;
    shader.Compile(vShaderCode, fShaderCode);

    return shader;

【问题讨论】:

您运行的是什么版本的 OpenGL?您是否知道自 OpenGL 3+ 起已弃用四边形? @Patrick 我刚刚在标题上添加了四边形,因为我正在尝试绘制四边形,但实际上我正在绘制两个相邻的三角形,只是用该代码更新了问题。 您可以尝试将三角形的 z 坐标更改为 -1.0f 而不是 0.0f。我相信三角形正在剪裁,因为正 z 超出了屏幕范围。 @Patrick model = translate(model, iVec3(position.x, position.y, -1.0f)); 换了这条线,是这个意思吗? @Patrick 我开始认为是视口错误之类的,因为无论我输入什么坐标,三角形都将始终处于相同位置且没有纹理。 【参考方案1】:

你的着色器甚至没有编译。当您声明矩阵制服时,您使用名称model2Dview2Dprojection2D

uniform mat4 view2D;
uniform mat4 model2D;
uniform mat4 projection2D;

但是当您使用矩阵时,您会使用名称viewmodelprojection

gl_Position = projection * view * model * vec4(vertex.xy, 0.0, 1.0);

我建议检查着色器对象是否编译成功以及程序对象链接是否成功。

可以通过glGetShaderiv和参数GL_COMPILE_STATUS检查着色器是否编译成功。

例如

GLuint shaderObj = .... ;
glCompileShader( shaderObj );

GLint status = GL_TRUE;
glGetShaderiv( shaderObj, GL_COMPILE_STATUS, &status );
if ( status == GL_FALSE )

    GLint logLen;
    glGetShaderiv( shaderObj, GL_INFO_LOG_LENGTH, &logLen );
    std::vector< char >log( logLen );
    GLsizei written;
    glGetShaderInfoLog( shaderObj, logLen, &written, log.data() );
    std::cout << "compile error:" << std::endl << log.data() << std::endl;

可以通过glGetProgramiv和参数GL_LINK_STATUS来检查程序是否链接成功。

例如

GLuint progObj = ....;
glLinkProgram( progObj );

GLint status = GL_TRUE;
glGetProgramiv( progObj, GL_LINK_STATUS, &status );
if ( status == GL_FALSE )

    GLint logLen;
    glGetProgramiv( progObj, GL_INFO_LOG_LENGTH, &logLen );
    std::vector< char >log( logLen );
    GLsizei written;
    glGetProgramInfoLog( progObj, logLen, &written, log.data() );
    std::cout  << "link error:" << std::endl << log.data() << std::endl;

【讨论】:

得到以下错误,链接错误:顶点信息-----------(0):错误C5145:必须写入gl_Position。 刚刚用 Resources.cpp 更新了代码,但我认为加载着色器时没有错误。 @MarceloColonia 您的代码中有错字:mode2Dl 而不是 model2D 抱歉打错了是因为我手动写了更新而不是复制它,原来的代码是正确的。 @MarceloColonia 你得到一个链接错误,可能你交换了顶点和片段着色器,或者你没有从文件中正确加载着色器并且源代码字符串是空的。

以上是关于OpenGL 忽略四边形并将它们变成三角形的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL入门02.使用OpenGL绘制三角形多边形

opengl绘图,画一个旋转的四边形和一个旋转的三角形,平滑着色和单一着色

如何在 OpenGL 中加载和渲染可能包含三角形、四边形或 N-Gons 的 OBJ 文件?

OpenGL c++ - 出现不需要的黑色三角形

如何纹理 Opengl glut 对象(C++)

Android OpenGL - ES 纹理出血