【问题标题】:Opengl 3.1 GLSL 140 Outputting White In Fragment Shader in C++ [closed]Opengl 3.1 GLSL 140 在 C++ 的片段着色器中输出白色 [关闭]
【发布时间】:2020-07-01 17:38:09
【问题描述】:

我无法使用不支持 OpenGL 3.3 或任何高于 3.1 的笔记本电脑。这是有问题的,因为我对这个版本并不完全熟悉,所以我正在学习如何再次使用这些东西。我的问题是,由于某种原因,我的片段着色器只输出白色。我不太确定出了什么问题,但我觉得这与我设置 VBO 数据的方式有关,因为这在我的代码中最近发生了变化。现在,我正在尝试将我的旧渲染引擎(用 OpenGL 3.3 编写)转换为 OpenGL 3.1。这是因为我的旧笔记本电脑设置的限制。这就是为什么我为 Vertex 使用结构,其中包括 BiTangentTangent 值。

我的代码:

struct Vertex {
    // Position
    glm::vec3 Position;
    // Normals
    glm::vec3 Normal;
    // Texture Coordinates
    glm::vec2 TexCoords;
    // BiTangent
    glm::vec3 BiTangent;
    // Tangent
    glm::vec3 Tangent;
};

struct Texture {
    unsigned int id;
    int number;
};

class Mesh {

    std::vector<Vertex> vertices;
    std::vector<unsigned int> indices;
    std::vector<Texture> textures;

    unsigned int VAO, VBO[5], EBO;

public:
    Mesh(std::vector<Vertex> vertices, std::vector<unsigned int> indices, std::vector<Texture> textures) {
        this->vertices = vertices;
        this->indices = indices;
        this->textures = textures;

        setupMesh();
    };

    void setupMesh() {
        glGenVertexArrays(1, &VAO);
        glGenBuffers(4, VBO);
        glGenBuffers(1, &EBO);

        glBindVertexArray(VAO);

        int stride = 14;

        // Position
        glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);
        glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), &vertices[0], GL_STATIC_DRAW);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride * sizeof(float), (void*)0);
        glEnableVertexAttribArray(0);

        // Normal
        glBindBuffer(GL_ARRAY_BUFFER, VBO[1]);
        glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), &vertices[0], GL_STATIC_DRAW);
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, stride * sizeof(float), (void*)3);
        glEnableVertexAttribArray(1);

        // Texture Coordinates
        glBindBuffer(GL_ARRAY_BUFFER, VBO[2]);
        glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), &vertices[0], GL_STATIC_DRAW);
        glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, stride * sizeof(float), (void*)6);
        glEnableVertexAttribArray(2);

        // BiTangent
        glBindBuffer(GL_ARRAY_BUFFER, VBO[3]);
        glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), &vertices[0], GL_STATIC_DRAW);
        glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, stride * sizeof(float), (void*)8);
        glEnableVertexAttribArray(3);

        // Tangent
        glBindBuffer(GL_ARRAY_BUFFER, VBO[4]);
        glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), &vertices[0], GL_STATIC_DRAW);
        glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, stride * sizeof(float), (void*)11);
        glEnableVertexAttribArray(4);

        // Element Buffer Object
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);

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

    };

    void Draw(ShaderProgram shader) {
        for (int i = 0; i < textures.size(); i++) {

            // Give textures the proper id and bind them
            glActiveTexture(GL_TEXTURE0 + textures[i].number);
            glBindTexture(GL_TEXTURE_2D, textures[i].id);
        }

        // Draw
        glBindVertexArray(VAO);
        glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);

        // Unbind
        glBindVertexArray(0);

    }

};

顶点着色器:

#version 140 core
in vec3 aPos;
in vec3 aColor;
in vec2 aTexCoords;
in vec3 aBiTangent;
in vec3 aTangent;

out vec3 Color;

void main(void){

    Color = vec3(aColor);

    gl_Position = vec4(aPos, 1.0);
}

片段着色器:

#version 140 core
out vec4 FragColor;

//precision highp float;

in  vec3 Color;

void main(void)
{
    FragColor = vec4(1.0, 0.8, 0.8, 1.0);
}

我尝试手动设置颜色以覆盖显示法线,但输出仍然是白色。

编辑:

如果我可以生成一个 VBO 而不是 4 个,那将很有用。我的问题是在使用一个 VBO 时我应该如何从着色器访问顶点数据。

【问题讨论】:

  • "[...] 我的问题是在使用一个 VBO 时我应该如何从着色器访问顶点数据。" - 没有区别在着色器代码中,只是顶点规范不同。
  • 这部分代码没有更明显的问题。如果它仍然不起作用,那么其他地方还有另一个错误。
  • 您确定要使用已编译的着色器程序调用 glUseProgram 以使其处于活动状态吗?您使用我们看不到的 ShaderProgram 对象调用 Draw,因此很难知道。以我的经验,白色输出通常是因为没有绑定任何程序。
  • 嘿!我不记得我是如何修复它的,但我很久以前就想通了。看着这个,我可能应该删除或存档或对这个问题做任何事情,因为它似乎非常没用。我确实记得解决方案是相当明显的,而且它位于代码的不同部分。我认为这可能是因为没有调用 glUseProgram(),但我不能肯定地说。无论如何,感谢您提供帮助:) 我会在 24 小时左右删除这个问题
  • 所以,没关系,因为我无法删除它

标签: c++ opengl glsl shader glm-math


【解决方案1】:

如果绑定了命名缓冲区对象,则 glVertexAttribPointer 的最后一个参数将被视为 字节偏移 进入缓冲区对象的数据存储区。
因此偏移量必须是sizeof(float)*number 而不是number

例如:

glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, stride * sizeof(float), (void*)3);

glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE,
    stride * sizeof(float), (void*)(sizeof(float) * 3));

glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, stride * sizeof(float), (void*)6);

glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 
    stride * sizeof(float), (void*)(sizeof(float) * 6));

...


此外,版本规范无效。没有 GLSL 1.40 核心版本。删除顶点和片段着色器中的标记core

#version 140 core

#version 140

coreOpenGL Shading Language 1.50中引入。

我建议检查着色器编译是否成功以及程序对象是否成功链接。见Shader Compilation
如果着色器编译成功,可以通过glGetShaderiv 和参数GL_COMPILE_STATUS 来检查。程序链接是否成功可以通过glGetProgramiv和参数GL_LINK_STATUS来检查。

【讨论】:

    猜你喜欢
    • 2013-07-30
    • 1970-01-01
    • 1970-01-01
    • 2017-05-16
    • 2021-10-18
    • 1970-01-01
    • 2013-07-30
    • 2017-04-12
    • 1970-01-01
    相关资源
    最近更新 更多