2

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

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

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

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

a_Type 可以是GL_VERTEX_SHADER,GL_FRAGMENT_SHADER或者是 a GL_GEOMETRY_SHADER,我的着色器代码是从文件加载的。a_Sourceconst char*

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

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

这是一个逻辑检查,将GL_TRUE在从终端GL_FALSE运行但从 IDE 运行时进行。

链接检查如下

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 个纹理并进行了一些混合,工作正常。

4

0 回答 0