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_SHADERGL_FRAGMENT_SHADERまたは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 は空です。ターミナルから実行すると、コンパイルとリンクのステータスが成功し、検証も成功し、シェーダーが機能します。また、ターミナルから実行すると、警告などで情報ログがいっぱいになります。

この質問は、ここから来る問題を調査した後に形成されました: Linux での GLSL シェーダーのコンパイル

シェーダー クラスのソースは次のとおりです。

#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