OpenGL无法将变量从顶点着色器发送到片段着色器

omtl5h9j  于 2022-09-26  发布在  其他
关注(0)|答案(1)|浏览(182)

我对OpenGL非常陌生,刚刚开始使用一个具有顶点着色器和片段着色器的基本程序。在我尝试将数据从顶点着色器发送到碎片着色器之前,一切都正常工作。我在顶点着色器中使用out,在碎片着色器中使用in

以下是着色器。

顶点:


# version 120

varying vec4 ourColor;
attribute vec3 position;

void main()
{
gl_Position = vec4(position, 1.0);
ourColor = vec4(1.0,0.1,0.2,0.5);
}

而片断:


# version 120

varying vec4 ourColor;

void main()
{
gl_FragColor = ourColor;
}

错误是:

片段着色器包含一个用户变量,但链接时没有顶点着色器。

我尝试使用关键字flat和关键字varying,结果相同。此外,我还尝试更改版本,然后使用inout,相同的错误。

以下是Shader代码(它在着色器类中,这是Shader.cpp):

Shader::Shader(const std::string & fileName)
    {
    m_program = glCreateProgram();
    //vertex shader
    m_shaders[0] = CreateShader(LoadShader(fileName + ".vs"), GL_VERTEX_SHADER); 
    m_shaders[0] = CreateShader(LoadShader(fileName + ".fs"),       
            GL_FRAGMENT_SHADER); 

    for(unsigned int i = 0; i < NUM_SHADERS; i++)
        glAttachShader(m_program, m_shaders[i]);

    glBindAttribLocation(m_program, 0, "position");

    glLinkProgram(m_program);
    CheckShaderError(m_program, GL_LINK_STATUS, true, "Error: Program linking failed. ");

    glValidateProgram(m_program);
    CheckShaderError(m_program, GL_VALIDATE_STATUS, true, "Error: Program is invalid. ");
}
//-----------
Shader::~Shader(void)
{
    for(unsigned int i = 0; i < NUM_SHADERS; i++)
    {
        glDetachShader(m_program, m_shaders[i]);
        glDeleteShader(m_shaders[i]);
    }

    glDeleteProgram(m_program);

}
//----------
void Shader::Bind()
{
    glUseProgram(m_program);
}
static GLuint CreateShader(const std::string & text, GLenum shaderType)
{
    GLuint shader = glCreateShader(shaderType);
    if(shader == 0)
    {
        std::cerr << "Error: Shader creation failed! " << std::endl;
    }
    const GLchar* ShaderSourceStrings[1];
    GLint ShaderSourceStringsLengths[1];
    ShaderSourceStrings[0] = text.c_str();
    ShaderSourceStringsLengths[0] = text.length();
    glShaderSource(shader, 1, ShaderSourceStrings, ShaderSourceStringsLengths);
    glCompileShader(shader);
    CheckShaderError(shader, GL_COMPILE_STATUS, false, "Error: Shader compilation failed");
    return shader;
}
//-----------
static std::string LoadShader(const std::string & fileName)
{
    std::ifstream file;
    file.open((fileName).c_str());
    std::string output;
    std::string line;
    if(file.is_open())
    {
        while(file.good())
        {
            getline(file, line);
            output.append(line + "n");
        }
    }
    else
    {
        std::cerr << "unable to load shader file: " << fileName << std::endl;
    }
    return output;
}
//-----------
static void CheckShaderError(GLuint shader, GLuint flag, bool isProgram, const std::string & errorMessage)
{
    GLint success = 0;
    GLchar error[1024] = {0};
    if(isProgram)
        glGetProgramiv(shader, flag, &success);
    else
        glGetShaderiv(shader, flag, &success);
    if(success == GL_FALSE)
    {
        if(isProgram){
            glGetProgramInfoLog(shader, sizeof(error), NULL, error);
        std::cout << "error from program" << std::endl;
        }
        else{
            glGetShaderInfoLog(shader, sizeof(error), NULL, error);
            std::cout << "error from shader" << std::endl;
        }
            std::cerr << errorMessage << ": '"  << error << "'" << std::endl;
        }
    }
knsnq2tg

knsnq2tg1#

以下是错误所在。

m_shaders[0] = 
m_shaders[0] =

片段着色器包含一个用户变量,但链接时没有顶点着色器。

在没有顶点着色器的情况下链接?这肯定会带来问题。代码应该“模糊地”看起来像这样:

GLuint load_shader(GLenum shader_type, ...) {
    GLuint shader = glCreateShader(shader_type);
    ... load shader source code ...
    glCompileShader(shader);
    GLint success;
    glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
    if (!success) {
        // boom
    }
    ... glGetShaderInfoLog ...
    return shader;
}

GLuint load_program(...) {
    GLuint prog = glCreateProgram();
    // Attach both fragment and vertex shader
    glAttachShader(prog, load_shader(GL_VERTEX_SHADER, ...));
    glAttachShader(prog, load_shader(GL_FRAGMENT_SHADER, ...));
    // Then link them together
    glLinkProgram(prog);
    GLint success;
    glGetProgramiv(program, GL_LINK_STATUS, &success);
    if (!success) {
        // boom
    }
    ... glGetProgramInfoLog ...
}

这是一个相当多的样板代码,并且代码有很多机会包含错误,所以出现错误是很常见的,特别是因为OpenGL中的几乎所有东西都是typedef int GLxxx;或类似的东西。

在GLSL 120中,inout不是存储限定符。请改用varying

// Same in vertex and fragment shader.
varying vec4 ourColor;

或者,使用较新的GLSL版本。


# version 330

out vec4 ourColor;
in vec3 position;

# version 330

in vec4 ourColor;
out vec4 fragColor;

相关问题