编译着色器并链接失败但是着色器的验证成功

时间:2012-07-25 11:55:29

标签: c++ opengl glsl codeblocks

我对着色器的作用感到困惑。 我有一个着色器类,它为我包装着色的opengl部分。我在code :: blocks中构建我的应用程序并运行它,编译fase失败,链接阶段失败但GL_VALIDATE_STATUS验证成功,着色器实际工作。

当我在codeblocks IDE之外运行它时,编译和链接阶段成功,验证也是如此。在IDE中运行时,ProgramLog和InfoLog为空甚至没有警告,但在编译和链接成功时在IDE外部运行时,InfoLog会显示警告。

我对此感到困惑,这是我的编译阶段:

GLuint handle = glCreateShader(a_Type);
glShaderSource(handle, 1, &a_Source, NULL); 
glCompileShader(handle); 

a_Type可以是GL_VERTEX_SHADERGL_FRAGMENT_SHADERGL_GEOMETRY_SHADERa_Sourceconst char*,我的着色器代码是从文件加载的。

然后我继续检查编译状态:

glGetShaderiv(handle, GL_COMPILE_STATUS, &success); OGLCHECK
if(success != GL_TRUE)
{

这是一个逻辑检查,从终端运行时为GL_TRUE,而从IDE运行时为GL_FALSE

链接检查如下

glGetProgramiv(m_ProgramHandle, GL_LINK_STATUS, &success); OGLCHECK
if(success != GL_TRUE)
{

验证

glValidateProgram(m_ProgramHandle); OGLCHECK
glGetProgramiv(m_ProgramHandle, GL_VALIDATE_STATUS, &success); OGLCHECK
if(success != GL_TRUE)
{

总结一下,从使用IDE开始,着色器编译和链接状态失败但验证通过且着色器工作但InfoLog为空。从终端运行时,编译和链接状态成功,验证和着色器也起作用。当从终端运行时,我也有一个填充的InfoLog,例如警告。

这个问题是在我对来自这里的问题进行调查后形成的: GLSL shader compilation on linux

以下是着色器类的来源

#include "Shader.h"

Shader::Shader():m_FragmentHandle(0),m_GeometryHandle(0),m_VertexHandle(0),m_ProgramHandle(0),m_CurrentTexture(0)
{

}

Shader::~Shader()
{
    if(m_GeometryHandle != 0)
    {
        glDeleteShader(m_GeometryHandle);
        m_GeometryHandle = 0;
    }

    if(m_VertexHandle != 0)
    {
        glDeleteShader(m_VertexHandle);
        m_VertexHandle = 0;
    }

    if(m_FragmentHandle != 0)
    {
        glDeleteShader(m_FragmentHandle);
        m_FragmentHandle = 0;
    }
}

bool Shader::Load(const char* a_FileName)
{
    printf( "Loading shader: %s\n", a_FileName );

    char* shaderFile = new char[strlen(a_FileName) + 6]; //(char*)calloc(custom::strlen(a_FileName) + 6, sizeof(char));
    char* source = NULL;

    strcpy(shaderFile, a_FileName);
    strcat(shaderFile, ".geom");

    source = GetShaderSource(shaderFile);
    if(source != NULL)
    {
        printf( "Compiling geometry shader...\n" );
        m_GeometryHandle = Compile(GL_GEOMETRY_SHADER, source);

        free(source);
        source = 0;

        if(m_GeometryHandle == 0)
        {
            printf( "Geometry shader compiling failed.\n" );
            delete[] shaderFile;
            shaderFile = 0;

            return false;
        }
    }

    strcpy(shaderFile, a_FileName);
    strcat(shaderFile, ".vert");

    source = GetShaderSource(shaderFile);
    if(source != NULL)
    {
        printf( "Compiling vertex shader...\n" );
        m_VertexHandle = Compile(GL_VERTEX_SHADER, source);

        free(source);
        source = 0;

        if(m_VertexHandle == 0)
        {
            printf( "Vertex shader compiling failed.\n" );
            delete[] shaderFile;
            shaderFile = 0;

            return false;
        }
    }
    else
    {
        printf("No vertex shader found. A vertex and fragment shader are required!\n");
    }

    strcpy(shaderFile, a_FileName);
    strcat(shaderFile, ".frag");

    source = GetShaderSource(shaderFile);
    if(source != NULL)
    {
        printf( "Compiling fragment shader...\n" );
        m_FragmentHandle = Compile(GL_FRAGMENT_SHADER, source);

        free(source);
        source = 0;

        if(m_FragmentHandle == 0)
        {
            printf( "Fragment shader compiling failed.\n" );
            delete[] shaderFile;
            shaderFile = 0;

            return false;
        }
    }
    else
    {
        printf("No fragment shader found. A vertex and fragment shader are required!\n");
    }

    delete[] shaderFile;
    shaderFile = 0;

    CreateProgram();

    if(!Link())
    {
        printf( "Linking of shader \"%s\" failed!\n", a_FileName );
        return false;
    }

    printf( "Shader build succesfully!\n" );
    return true;
}

// WARNING: YOU NEED TO FREE THE RETURNED SOURCE YOURSELF!! free(buffer);
char* Shader::GetShaderSource(const char* a_FileName)
{
    FILE* f;
    f = fopen(a_FileName, "rb");

    if(f != NULL)
    {
        // Shader is available

        char* buffer;
        long size;

        fseek(f, 0L, SEEK_END);
        size = ftell(f);
        rewind(f);

        buffer = (char*)calloc(1, size+1);
        if(!buffer)
        {
            fclose(f);
            return NULL;
        }

        if(fread(buffer, size, 1, f) != 1)
        {
            fclose(f);
            return NULL;
        }

        fclose(f);
        return buffer;
    }

    return NULL;
}

GLuint Shader::Compile(const GLuint a_Type, const char* a_Source)
{
    if(a_Source == NULL)
        return 0;

    GLuint handle = glCreateShader(a_Type); OGLCHECK
    glShaderSource(handle, 1, &a_Source, NULL); OGLCHECK
    glCompileShader(handle); OGLCHECK

    int bufflen = 0;
    GLint success = GL_FALSE;

    glGetShaderiv(handle, GL_INFO_LOG_LENGTH, &bufflen); OGLCHECK
    if(bufflen > 1)
    {
        GLchar* logString = new GLchar[bufflen + 1];
        glGetShaderInfoLog(handle, bufflen, 0, logString); OGLCHECK
        printf( "Shader compile output:\n%s\n", logString );

        delete logString;
        logString = 0;
    } else {
        glGetShaderiv(handle, GL_PROGRAM_LOG_LENGTH, &bufflen); OGLCHECK
    }

    glGetShaderiv(handle, GL_COMPILE_STATUS, &success); OGLCHECK
    if(success != GL_TRUE)
    {
        printf( "Failed to compile shader!\n" );

        glDeleteShader(handle); OGLCHECK
        //handle = 0;
    }

    return handle;
}

void Shader::CreateProgram()
{
    m_ProgramHandle = glCreateProgram(); OGLCHECK

    if(m_GeometryHandle != 0)
    {
        glAttachShader(m_ProgramHandle, m_GeometryHandle); OGLCHECK
        printf( "Attaching geometry shader...\n" );
    }
    if(m_VertexHandle != 0)
    {
        glAttachShader(m_ProgramHandle, m_VertexHandle); OGLCHECK
        printf( "Attaching vertex shader...\n" );
    }
    if(m_FragmentHandle != 0)
    {
        glAttachShader(m_ProgramHandle, m_FragmentHandle); OGLCHECK
        printf( "Attaching fragment shader...\n" );
    }
}

bool Shader::Link()
{
    glLinkProgram(m_ProgramHandle);

    GLint bufflen = 0;
    glGetProgramiv(m_ProgramHandle, GL_INFO_LOG_LENGTH, &bufflen); OGLCHECK
    if(bufflen > 1)
    {
        GLchar *logString = new GLchar[bufflen + 1];
        glGetProgramInfoLog(m_ProgramHandle, bufflen, 0, logString);

        printf( "Shader linking output:\n%s\n", logString );

        delete logString;
        logString = 0;
    }

    GLint success = GL_FALSE;
    glGetProgramiv(m_ProgramHandle, GL_LINK_STATUS, &success); OGLCHECK
    if(success != GL_TRUE)
    {
        printf( "Shader failed to link!\n" );
        return false;
    }

    glValidateProgram(m_ProgramHandle); OGLCHECK
    glGetProgramiv(m_ProgramHandle, GL_VALIDATE_STATUS, &success); OGLCHECK
    if(success != GL_TRUE)
    {
        printf( "Shader program was not validated.!\n" );
    }

    GLint activeCount = 0;
    GLint maxNameLength = 0;
    glGetProgramiv(m_ProgramHandle, GL_ACTIVE_UNIFORMS, &activeCount); OGLCHECK
    glGetProgramiv(m_ProgramHandle, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxNameLength); OGLCHECK

    GLchar* name = new GLchar[maxNameLength];
    GLsizei length = 100;
    GLenum type = GL_INVALID_ENUM;
    GLint size = 0;

    for(int i=0; i<activeCount; ++i)
    {
        glGetActiveUniform(m_ProgramHandle, i, maxNameLength, &length, &size, &type, name); OGLCHECK
        GLint handle = glGetUniformLocation(m_ProgramHandle, name); OGLCHECK

        m_Parameters.insert(ParameterPair(name, handle));
    }

    glGetProgramiv(m_ProgramHandle, GL_ACTIVE_ATTRIBUTES, &activeCount); OGLCHECK
    glGetProgramiv(m_ProgramHandle, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxNameLength); OGLCHECK

    delete name;
    name = new GLchar[maxNameLength];

    for(int i=0; i<activeCount; ++i)
    {
        glGetActiveAttrib(m_ProgramHandle, i, maxNameLength, &length, &size, &type, name); OGLCHECK
        GLint handle = glGetAttribLocation(m_ProgramHandle, name); OGLCHECK

        m_Attributes.insert(ParameterPair(name, handle));
    }

    delete name;
    name = 0;

    return true;
}

当我创建着色器时,我会这样做:

Shader gShader;
gShader.load("data/shaders/myshader");

加载器加载data / shaders / myshader.frag data / shaders / myshader.vert等。你可以在Load函数中看到这个。

更新1: 我发现虽然着色器似乎可以在IDE中工作但我无法绑定到属性位置。但我可以更改片段着色器中的颜色,这将显示。从终端,属性工作正常,我试图在2个统一的位置绑定2个纹理,并做了一些混合,工作正常。

0 个答案:

没有答案