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

后端 未结 1 538
我寻月下人不归
我寻月下人不归 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
    • 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

    0 讨论(0)
提交回复
热议问题