OpenGL忽略四边形并将其转换为三角形。

3
这是我第二次制作游戏引擎,但现在遇到了一些困难,因为无论我发送什么对象,OpenGL只会在屏幕中央绘制一个白色三角形,就像这样。 我甚至从上一个引擎的渲染器和相机对象中复制了旧代码,但仍然表现相同,所以我猜测这与渲染脚本有关。
渲染器:
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);
}  

Resources.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;
}

1
@Patrick,我在标题上加了“四边形”是因为我正在尝试绘制四边形,但实际上我只是在画两个相邻的三角形,我刚刚更新了问题并添加了那段代码。 - Aether
你没有正确地渲染纹理,因为你不再将UV坐标发送到GPU。你的选择是发送一个vec4,其中xy为顶点坐标,zw为UV坐标,或者你可以为UV数据创建一个新的缓冲区。 - Patrick
我会尝试一下,但是位置和大小不正确怎么办?这是着色器的问题吗?它只采用了普通顶点的位置。 - Aether
原始大小为4应该与您的着色器配合使用。 - Patrick
那为什么它不能改变大小呢?是否与纹理错误有关? - Aether
显示剩余18条评论
1个回答

5

你的着色器甚至无法编译。当你声明矩阵统一变量时,你使用了名称 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。
- Aether
@MarceloColonia,你的代码中有一个错别字:mode2Dl应该是model2D - Rabbid76
抱歉,那个打字错误是因为我手动写了更新而不是复制它,原始代码是正确的。 - Aether
@MarceloColonia,您遇到了链接错误,可能是您交换了顶点和片段着色器,或者您没有正确地从文件中加载着色器,源代码字符串为空。 - Rabbid76
谢谢,我发现片段着色器上实际上有一个错误,我导出的是颜色而不是color2D,现在它可以工作了。 - Aether
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接