How to debug GLSL Fragment shader (Program Linking error after code change)

后端 未结 1 537
我寻月下人不归
我寻月下人不归 2021-01-26 10:43

(original Title) Please help me debug my glsl lighting shader so that it will compile! This is my first time debugging glsl

Hello I am VERY new to openg

相关标签:
1条回答
  • 2021-01-26 10:59

    Errors log of yours are not good

    • it is some linking log from the tool you are using
    • not the OpenGL compilation log !!!

    I put your fragment shader into OpenGL and this is the real compilation log (nVidia used):

    [Fragment]
    Compiler error
    0(94) : error C1009: "ambient" is not member of struct "DirLight"
    0(95) : error C1009: "diffuse" is not member of struct "DirLight"
    0(96) : error C1009: "specular" is not member of struct "DirLight"
    
    [Program]
    Linker error
    Fragment info
    -------------
    0(94) : error C1009: "ambient" is not member of struct "DirLight"
    0(95) : error C1009: "diffuse" is not member of struct "DirLight"
    0(96) : error C1009: "specular" is not member of struct "DirLight"
    
    • you should use glGetShaderInfoLog for every shader/program object you use in OpenGL
    • I use something like this

    It makes sense:

    vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir)
    {
        vec3 lightDir = normalize(-light.direction);
        // Diffuse shading
        float diff = max(dot(normal, lightDir), 0.0);
        // Specular shading
        vec3 reflectDir = reflect(-lightDir, normal);
        float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
        // Combine results
        vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords));
        vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));
        vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords));
        return (diffuse + specular);
    }
    

    After the // Combine results you are accessing struct fields that are not defined in:

    struct DirLight {
        vec3 direction;
        vec3 color;
        float strength;
    };
    

    [edit1] in C++ I use this class of mine for GLSL:

    //------------------------------------------------------------------------------
    //--- GLSL program class -------------------------------------------------------
    //------------------------------------------------------------------------------
    class GLSLprogram       // GLSL program class
        {
    public:
        AnsiString log;
        int prog_id,    // whole program
            tesc_id,    // tessellation control
            tese_id,    // tessellation evaluation
            geom_id,    // geometry
            vert_id,    // vertex
            frag_id;    // fragment
    
        GLSLprogram();
        GLSLprogram(GLSLprogram& a);
        ~GLSLprogram();
        GLSLprogram* operator = (const GLSLprogram *a);
        //GLSLprogram* operator = (const GLSLprogram &a);
        void bind();
        void unbind();
    
        void set_source_text(AnsiString tesc,AnsiString tese,AnsiString geom,AnsiString vert,AnsiString frag);  // set source texts
        void set_source_file(AnsiString tesc,AnsiString tese,AnsiString geom,AnsiString vert,AnsiString frag);  // load and set source files
    
        void set1f   (AnsiString name,GLfloat x);
        void set2f   (AnsiString name,GLfloat x, GLfloat y);
        void set3f   (AnsiString name,GLfloat x, GLfloat y, GLfloat z);
        void set4f   (AnsiString name,GLfloat x, GLfloat y, GLfloat z, GLfloat w);
        void set1i   (AnsiString name,GLint x);
        void set2i   (AnsiString name,GLint x, GLint y);
        void set3i   (AnsiString name,GLint x, GLint y, GLint z);
        void set4i   (AnsiString name,GLint x, GLint y, GLint z, GLint w);
        void set1fv  (AnsiString name,GLfloat *p);
        void set2fv  (AnsiString name,GLfloat *p);
        void set3fv  (AnsiString name,GLfloat *p);
        void set4fv  (AnsiString name,GLfloat *p);
        void set1iv  (AnsiString name,GLint *p);
        void set2iv  (AnsiString name,GLint *p);
        void set3iv  (AnsiString name,GLint *p);
        void set4iv  (AnsiString name,GLint *p);
        void set2x2fv(AnsiString name,GLfloat *p);
        void set3x3fv(AnsiString name,GLfloat *p);
        void set4x4fv(AnsiString name,GLfloat *p);
    
        void get1f   (AnsiString name,GLfloat &x);
        void get2f   (AnsiString name,GLfloat &x, GLfloat &y);
        void get3f   (AnsiString name,GLfloat &x, GLfloat &y, GLfloat &z);
        void get4f   (AnsiString name,GLfloat &x, GLfloat &y, GLfloat &z, GLfloat &w);
        void get1i   (AnsiString name,GLint &x);
        void get2i   (AnsiString name,GLint &x, GLint &y);
        void get3i   (AnsiString name,GLint &x, GLint &y, GLint &z);
        void get4i   (AnsiString name,GLint &x, GLint &y, GLint &z, GLint &w);
        void get1fv  (AnsiString name,GLfloat *p);
        void get2fv  (AnsiString name,GLfloat *p);
        void get3fv  (AnsiString name,GLfloat *p);
        void get4fv  (AnsiString name,GLfloat *p);
        void get1iv  (AnsiString name,GLint *p);
        void get2iv  (AnsiString name,GLint *p);
        void get3iv  (AnsiString name,GLint *p);
        void get4iv  (AnsiString name,GLint *p);
        void get2x2fv(AnsiString name,GLfloat *p);
        void get3x3fv(AnsiString name,GLfloat *p);
        void get4x4fv(AnsiString name,GLfloat *p);
        };
    //------------------------------------------------------------------------------
    GLSLprogram::GLSLprogram()
        {
        prog_id=0;
        tesc_id=0;
        tese_id=0;
        geom_id=0;
        vert_id=0;
        frag_id=0;
        }
    //------------------------------------------------------------------------------
    GLSLprogram::~GLSLprogram()
        {
        if (glDetachShader==NULL) return;
        if (glDeleteShader==NULL) return;
        unbind();
        if (tesc_id>0) { glDetachShader(prog_id,tesc_id); glDeleteShader(tesc_id); }
        if (tese_id>0) { glDetachShader(prog_id,tese_id); glDeleteShader(tese_id); }
        if (geom_id>0) { glDetachShader(prog_id,geom_id); glDeleteShader(geom_id); }
        if (vert_id>0) { glDetachShader(prog_id,vert_id); glDeleteShader(vert_id); }
        if (frag_id>0) { glDetachShader(prog_id,frag_id); glDeleteShader(frag_id); }
        if (prog_id>0) {                                  glDeleteShader(prog_id); }
        log="";
        }
    //------------------------------------------------------------------------------
    void GLSLprogram::bind()
        {
        if (glUseProgram==NULL) return;
        glUseProgram(prog_id);
        }
    //------------------------------------------------------------------------------
    void GLSLprogram::unbind()
        {
        if (glUseProgram==NULL) return;
        glUseProgram(0);
        }
    //------------------------------------------------------------------------------
    void GLSLprogram::set_source_text(AnsiString tesc,AnsiString tese,AnsiString geom,AnsiString vert,AnsiString frag)
        {
        if (glCreateProgram==NULL) return;
        if (glShaderSource==NULL) return;
        if (glCompileShader==NULL) return;
        if (glAttachShader==NULL) return;
        if (glGetShaderiv==NULL) return;
        if (glGetShaderInfoLog==NULL) return;
        if (glLinkProgram==NULL) return;
    
        if (glGetProgramiv==NULL) return;
        if (glGetProgramInfoLog==NULL) return;
        if (glReleaseShaderCompiler==NULL) return;
    
        const int _size=1024;
        char dat[_size];
        GLint status,siz=0,i;
        const char * TC = tesc.c_str();
        const char * TE = tese.c_str();
        const char * GS = geom.c_str();
        const char * VS = vert.c_str();
        const char * FS = frag.c_str();
        log="";
    
        if (prog_id<=0) prog_id=glCreateProgram();
    
        if (tesc_id<=0) tesc_id=glCreateShader(GL_TESS_CONTROL_SHADER);
        else glDetachShader(prog_id,tesc_id);
        if (tesc!="")
            {
            glShaderSource(tesc_id, 1, &TC,NULL);
            glCompileShader(tesc_id);
            glAttachShader(prog_id,tesc_id);
            glGetShaderiv(tesc_id,GL_COMPILE_STATUS,&status);
            log+="[Tessellation control]\n";
            if (status) log+="OK\n"; else log+="Compiler error\n";
            glGetShaderInfoLog(tesc_id,_size,&siz,dat);
            for (i=0;i<siz;i++) log+=dat[i];
    
            }
    
        if (tese_id<=0) tese_id=glCreateShader(GL_TESS_EVALUATION_SHADER);
        else glDetachShader(prog_id,tese_id);
        if (tese!="")
            {
            glShaderSource(tese_id, 1, &TE,NULL);
            glCompileShader(tese_id);
            glAttachShader(prog_id,tese_id);
            glGetShaderiv(tese_id,GL_COMPILE_STATUS,&status);
            log+="[Tessellation evaluation]\n";
            if (status) log+="OK\n"; else log+="Compiler error\n";
            glGetShaderInfoLog(tese_id,_size,&siz,dat);
            for (i=0;i<siz;i++) log+=dat[i];
    
            }
        if (geom_id<=0) geom_id=glCreateShader(GL_GEOMETRY_SHADER);
        else glDetachShader(prog_id,geom_id);
        if (geom!="")
            {
            glShaderSource(geom_id, 1, &GS,NULL);
            glCompileShader(geom_id);
            glAttachShader(prog_id,geom_id);
            glGetShaderiv(geom_id,GL_COMPILE_STATUS,&status);
            log+="[Geometry]\n";
            if (status) log+="OK\n"; else log+="Compiler error\n";
            glGetShaderInfoLog(geom_id,_size,&siz,dat);
            for (i=0;i<siz;i++) log+=dat[i];
    
            }
        if (vert_id<=0) vert_id=glCreateShader(GL_VERTEX_SHADER);
        else glDetachShader(prog_id,vert_id);
        if (vert!="")
            {
            glShaderSource(vert_id, 1, &VS,NULL);
            glCompileShader(vert_id);
            glAttachShader(prog_id,vert_id);
            glGetShaderiv(vert_id,GL_COMPILE_STATUS,&status);
            log+="[Vertex]\n";
            if (status) log+="OK\n"; else log+="Compiler error\n";
            glGetShaderInfoLog(vert_id,_size,&siz,dat);
            for (i=0;i<siz;i++) log+=dat[i];
            }
        if (frag_id<=0) frag_id=glCreateShader(GL_FRAGMENT_SHADER);
        else glDetachShader(prog_id,frag_id);
        if (frag!="")
            {
            glShaderSource(frag_id, 1, &FS,NULL);
            glCompileShader(frag_id);
            glAttachShader(prog_id,frag_id);
            glGetShaderiv(frag_id,GL_COMPILE_STATUS,&status);
            log+="\n[Fragment]\n";
            if (status) log+="OK\n"; else log+="Compiler error\n";
            glGetShaderInfoLog(frag_id,_size,&siz,dat);
            for (i=0;i<siz;i++) log+=dat[i];
            }
    
        glLinkProgram(prog_id);
        glGetProgramiv(prog_id,GL_LINK_STATUS,&status);
        log+="\n[Program]\n";
        if (status) log+="OK\n"; else log+="Linker error\n";
        glGetProgramInfoLog(prog_id,_size,&siz,dat);
        for (i=0;i<siz;i++) log+=dat[i];
    
        glReleaseShaderCompiler();
        }
    //------------------------------------------------------------------------------
    void GLSLprogram::set_source_file(AnsiString tesc,AnsiString tese,AnsiString geom,AnsiString vert,AnsiString frag)
        {
        set_source_text(load(tesc),load(tese),load(geom),load(vert),load(frag));
        }
    //------------------------------------------------------------------------------
    void GLSLprogram::set1f   (AnsiString name,GLfloat x)                                 { GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform1f  (id,x);       }
    void GLSLprogram::set2f   (AnsiString name,GLfloat x, GLfloat y)                      { GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform2f  (id,x,y);     }
    void GLSLprogram::set3f   (AnsiString name,GLfloat x, GLfloat y, GLfloat z)           { GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform3f  (id,x,y,z);   }
    void GLSLprogram::set4f   (AnsiString name,GLfloat x, GLfloat y, GLfloat z, GLfloat w){ GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform4f  (id,x,y,z,w); }
    void GLSLprogram::set1i   (AnsiString name,GLint x)                                   { GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform1i  (id,x);       }
    void GLSLprogram::set2i   (AnsiString name,GLint x, GLint y)                          { GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform2i  (id,x,y);     }
    void GLSLprogram::set3i   (AnsiString name,GLint x, GLint y, GLint z)                 { GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform3i  (id,x,y,z);   }
    void GLSLprogram::set4i   (AnsiString name,GLint x, GLint y, GLint z, GLint w)        { GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform4i  (id,x,y,z,w); }
    void GLSLprogram::set1fv  (AnsiString name,GLfloat *p)                                { GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform1fv (id,1,p);     }
    void GLSLprogram::set2fv  (AnsiString name,GLfloat *p)                                { GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform2fv (id,2,p);     }
    void GLSLprogram::set3fv  (AnsiString name,GLfloat *p)                                { GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform3fv (id,3,p);     }
    void GLSLprogram::set4fv  (AnsiString name,GLfloat *p)                                { GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform4fv (id,4,p);     }
    void GLSLprogram::set1iv  (AnsiString name,GLint *p)                                  { GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform1iv (id,1,p);     }
    void GLSLprogram::set2iv  (AnsiString name,GLint *p)                                  { GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform2iv (id,2,p);     }
    void GLSLprogram::set3iv  (AnsiString name,GLint *p)                                  { GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform3iv (id,3,p);     }
    void GLSLprogram::set4iv  (AnsiString name,GLint *p)                                  { GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniform4iv (id,4,p);     }
    void GLSLprogram::set2x2fv(AnsiString name,GLfloat *p)                                { GLboolean q=true; GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniformMatrix2fv(id, 4,q,p); }
    void GLSLprogram::set3x3fv(AnsiString name,GLfloat *p)                                { GLboolean q=true; GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniformMatrix3fv(id, 9,q,p); }
    void GLSLprogram::set4x4fv(AnsiString name,GLfloat *p)                                { GLboolean q=true; GLint id=glGetUniformLocation(prog_id,name.c_str()); glUniformMatrix4fv(id,16,q,p); }
    //------------------------------------------------------------------------------
    void GLSLprogram::get1f   (AnsiString name,GLfloat &x){ GLint id=glGetUniformLocation(prog_id,name.c_str()); glGetUniformfv(prog_id,id,&x); }
    void GLSLprogram::get1i   (AnsiString name,GLint &x)  { GLint id=glGetUniformLocation(prog_id,name.c_str()); glGetUniformiv(prog_id,id,&x); }
    void GLSLprogram::get1fv  (AnsiString name,GLfloat *p){ GLint id=glGetUniformLocation(prog_id,name.c_str()); glGetUniformfv(prog_id,id,p);  }
    void GLSLprogram::get2fv  (AnsiString name,GLfloat *p){ GLint id=glGetUniformLocation(prog_id,name.c_str()); glGetUniformfv(prog_id,id,p);  }
    void GLSLprogram::get3fv  (AnsiString name,GLfloat *p){ GLint id=glGetUniformLocation(prog_id,name.c_str()); glGetUniformfv(prog_id,id,p);  }
    void GLSLprogram::get4fv  (AnsiString name,GLfloat *p){ GLint id=glGetUniformLocation(prog_id,name.c_str()); glGetUniformfv(prog_id,id,p);  }
    void GLSLprogram::get1iv  (AnsiString name,GLint *p)  { GLint id=glGetUniformLocation(prog_id,name.c_str()); glGetUniformiv(prog_id,id,p);  }
    void GLSLprogram::get2iv  (AnsiString name,GLint *p)  { GLint id=glGetUniformLocation(prog_id,name.c_str()); glGetUniformiv(prog_id,id,p);  }
    void GLSLprogram::get3iv  (AnsiString name,GLint *p)  { GLint id=glGetUniformLocation(prog_id,name.c_str()); glGetUniformiv(prog_id,id,p);  }
    void GLSLprogram::get4iv  (AnsiString name,GLint *p)  { GLint id=glGetUniformLocation(prog_id,name.c_str()); glGetUniformiv(prog_id,id,p);  }
    void GLSLprogram::get2x2fv(AnsiString name,GLfloat *p){ GLint id=glGetUniformLocation(prog_id,name.c_str()); glGetUniformfv(prog_id,id,p);  }
    void GLSLprogram::get3x3fv(AnsiString name,GLfloat *p){ GLint id=glGetUniformLocation(prog_id,name.c_str()); glGetUniformfv(prog_id,id,p);  }
    void GLSLprogram::get4x4fv(AnsiString name,GLfloat *p){ GLint id=glGetUniformLocation(prog_id,name.c_str()); glGetUniformfv(prog_id,id,p);  }
    //------------------------------------------------------------------------------
    
    • AnsiString is just VCL string class (self relocable string class) can use anything else like char[] or char* instead but you need to handle operators of coarse...

    • AnsiString().c_str() returns char* compatible pointer to stored string

    usage:

    // [variables]
    GLSLprogram   shader;
    // [init]
    shader.set_source_text("","","","your vertex shader source text","your fragment shader source text");
    shader.log; // contains the compile/link log ...
    shader.prog_id; // contains the OpenGL id for your shader object
    
    
    // [render]
    shader.bind();
    // here render
    shader.unbind();
    

    [edit2] And also I forget to add:

    AnsiString load(AnsiString file)
        {
        int i,hnd,siz;
        char *dat=NULL;
        hnd=FileOpen(file,fmOpenRead);
        if (hnd<0) return "";
        siz=FileSeek(hnd,0,2);
            FileSeek(hnd,0,0);
        if (siz==0) { FileClose(hnd); return ""; }
        dat=new char[siz+1];
        if (dat==NULL) { FileClose(hnd); return ""; }
        FileRead(hnd,dat,siz);
        FileClose(hnd);
        AnsiString s=""; for (i=0;i<siz;i++) s+=dat[i];
        delete dat;
        return s;
        }
    
    0 讨论(0)
提交回复
热议问题