片段着色器中设置的颜色未显示 GLSL 1.30

Posted

技术标签:

【中文标题】片段着色器中设置的颜色未显示 GLSL 1.30【英文标题】:Colors set in fragment shader not showing GLSL 1.30 【发布时间】:2019-03-20 15:35:06 【问题描述】:

我正在学习 OpenGL,我刚刚看到了如何编写着色器。但第一个问题是,在课程中,支持 GLSL 3.30+(OpenGL 4),但我的驱动程序(台面)不允许我使用 GLSL 1.30 或 ES 3.20 以上的版本。所以我更改了着色器中的#version 预处理器,然后我继续。但是,不幸的是,当我尝试使用颜色时,它不起作用。

这是我的代码:

#include "colors.h"
#include <iostream>
#include <fstream>
#include <regex>
#include <GL/glew.h>
#include <GLFW/glfw3.h>

unsigned int CompileShader(unsigned int type, std::string& source);
unsigned int CreateShader(std::string& vertexShader, std::string& fragmentShader);

int main(int argc, char* argv[]) 
    GLFWwindow* window;

    /* Initialize the library */
    if (!glfwInit()) 
        std::cerr << "Couldn't initialize GLFW" << std::endl;
        exit(1);
    

    /* Create a windowed mode window and its OpenGL context */
    window = glfwCreateWindow(640, 480, "Hello World", nullptr, nullptr);
    if (!window)
    
        glfwTerminate();
        return -1;
    

    /* Make the window's context current */
    glfwMakeContextCurrent(window);

    if(glewInit() != GLEW_OK) 
        std::cerr << "Couldn't initialize GLEW" << std::endl;
        exit(1);
    

    float positions[6] = 
        -0.5f, -0.5f,
        0.0f, 0.5f,
        0.5f, -0.5f
    ;
    unsigned int buffer;

    glGenBuffers(1, &buffer);
    glBindBuffer(GL_ARRAY_BUFFER, buffer);
    glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(float), positions, GL_STATIC_DRAW);

    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), 0);

    // Compiling Shader
    std::string vertexShader = "#version 130\n"
                               "\n"
                               "in vec4 position;\n"
                               "\n"
                               "void main () \n"
                               "    gl_Position = position;\n"
                               "";
    std::string fragmentShader = "#version 130\n"
                                 "\n"
                                 "uniform vec4 color = vec4(1.0, 0.0, 0.0, 1.0);\n"
                                 "\n"
                                 "out vec4 outputF;\n"
                                 "\n"
                                 "void main () \n"
                                 "    outputF = color;\n"
                                 "";

    unsigned int shader = CreateShader(vertexShader, fragmentShader);

    glUseProgram(shader);

    /* Loop until the user closes the window */
    while (!glfwWindowShouldClose(window))
    
        /* Render here */
        glClear(GL_COLOR_BUFFER_BIT);

        glDrawArrays(GL_TRIANGLES, 0, 3);

        /* Swap front and back buffers */
        glfwSwapBuffers(window);

        /* Poll for and process events */
        glfwPollEvents();
    

    glfwTerminate();
    return 0;


unsigned int CompileShader(unsigned int type, std::string& source) 
    unsigned int id = glCreateShader(type);
    const char* src = source.c_str();

    glShaderSource(id, 1, &src, nullptr);
    glCompileShader(id);

    int result;
    glGetShaderiv(id, GL_COMPILE_STATUS, &result);

    if (result == GL_FALSE) 
        int length;
        glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);

        char* message = (char*)alloca(length * sizeof(char));
        glGetShaderInfoLog(id, length, &length, message);

        std::cerr << "Failed to compile "
                  << (type == GL_VERTEX_SHADER ? "vertex" : "fragment")
                  << " shader. Error message:" << std::endl;

        std::cerr << "\t" << FG_ERROR << message << std::endl;
    

    return id;


unsigned int CreateShader(std::string& vertexShader, std::string& fragmentShader) 
    unsigned int program = glCreateProgram();
    unsigned int vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
    unsigned int fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);

    glAttachShader(program, vs);
    glAttachShader(program, vs);

    glLinkProgram(program);
    glValidateProgram(program);

    glDeleteShader(vs);
    glDeleteShader(fs);

    return program;

【问题讨论】:

“我的驱动程序(台面)不允许我使用 GLSL 1.30 或 ES 3.20 以上的版本。”他们很可能会这样做,但您必须请求版本化的 Core 上下文。 如果他们不这样做,您可能需要将结果分配给 gl_FragColor 而不是自定义的 out outputF 变量。 @NicoSchertler GLSL 1.3 文档说它为片段处理器添加了用户定义的输出,尽管我认为这可能会解决问题:khronos.org/registry/OpenGL/specs/gl/GLSLangSpec.1.30.pdf @dmoody256 啊,好的。我试图找出这是什么时候引入的。 @dmoody256 这是在哪个部分解释的?因为我不太明白你所说的 user defined outs... 是什么意思 【参考方案1】:

我有时间看这个,发现你有一个小的复制粘贴错误:

unsigned int CreateShader(std::string& vertexShader, std::string& fragmentShader) 
    unsigned int program = glCreateProgram();
    unsigned int vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
    unsigned int fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);

    glAttachShader(program, vs);
    glAttachShader(program, vs); //<--should be fs

您正在附加顶点着色器两次。这将设置一个 OpenGL 错误,实际上我发现它的方式是使用我通常使用的 OpenGL 调试方法。当我更深入地测试您的代码时,我用一个定义包围了所有 OpenGL 调用,如果 OpenGL 设置错误,它将停止执行。我把它放在源代码的顶部并建议使用它:

#include <cstdlib>
#include <iostream>
#include <iomanip>

void CheckOpenGLError(const char *stmt, const char *fname, int line);
#define GL_CHECK(stmt)                               \
    do                                               \
                                                    \
        stmt;                                        \
        CheckOpenGLError(#stmt, __FILE__, __LINE__); \
     while (0)

void CheckOpenGLError(const char *stmt, const char *fname, int line)

    GLenum err = glGetError();
    if (err != GL_NO_ERROR)
    
        std::cout << "OpenGL error 0x" << std::setfill('0') << std::setw(8) << std::hex << err << std::dec << ": " << gluErrorString(err) << ", at " << fname << ":" << line << " - for " << stmt << std::endl;
        abort();
    

如果您希望 OpenGL 错误以人类可读的形式打印出来,您将需要在 glu 库(Windows 上的 glu32.lib 或 linux 上的 libGLU.so)中额外链接 gluErrorString 函数,否则您需要去查找错误代码。在这种情况下,我像这样包围了你的电话:

unsigned int CreateShader(std::string& vertexShader, std::string& fragmentShader) 
    unsigned int program = glCreateProgram();
    unsigned int vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
    unsigned int fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);

    GL_CHECK(glAttachShader(program, vs));
    GL_CHECK(glAttachShader(program, vs)); //<--should be fs

然后当我运行代码时抛出此错误:

OpenGL error 0x00000502: invalid operation, at main.cpp:147 - for glAttachShader(program, vs)

还有一点需要注意的是,您可能应该在完成链接后分离着色器:

https://gamedev.stackexchange.com/a/47912

unsigned int CreateShader(std::string& vertexShader, std::string& fragmentShader) 
    unsigned int program = glCreateProgram();
    unsigned int vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
    unsigned int fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);

    glAttachShader(program, vs);
    glAttachShader(program, fs);

    glLinkProgram(program);
    glValidateProgram(program);

    glDetachShader(program, vs);
    glDetachShader(program, fs);

    glDeleteShader(vs);
    glDeleteShader(fs);

    return program;

【讨论】:

以上是关于片段着色器中设置的颜色未显示 GLSL 1.30的主要内容,如果未能解决你的问题,请参考以下文章

glsl片段着色器颜色添加逻辑

在顶点着色器中更改顶点的颜色

GLSL 着色器未编译,没有错误消息

OpenGL 片段着色器未写入 fbo 颜色缓冲区

如何在 C++ 中为 GLSL 片段着色器实现 iGlobalTime?

GLSL 问题:一个程序中有多个着色器