2

I am trying to use a GLSL shader I wrote from LWJGL. It is just a simple fragment-based phong shader. The shader has worked fine in the past, even on this computer. The other day, all of a sudden, it simply stopped compiling for no apparent reason. When I try to compile it and check the info log, I get this message:

Exception in thread "Thread-1" org.lwjgl.opengl.OpenGLException: Invalid value (1281)
    at org.lwjgl.opengl.Util.checkGLError(Util.java:59)
    at org.lwjgl.opengl.GL20.glGetShaderi(GL20.java:542)
    at aspect.render.shader.ShaderProgram.getLogInfo(ShaderProgram.java:161)
    at aspect.render.shader.ShaderProgram.<init>(ShaderProgram.java:69)
    at aspect.render.shader.ShaderProgram.loadPrebuilt(ShaderProgram.java:168)
    at aspect.core.AspectLauncher$1.run(AspectLauncher.java:143)

My OpenGL info:

GL VENDOR: Intel
GL RENDERER: Intel(R) HD Graphics 3000
GL VERSION: 3.1.0 - Build 9.17.10.3347
GLSL VERSION: 1.40 - Intel Build 9.17.10.3347

Here is the shader itself:

Vertex:

#version 140

uniform int numLights;
uniform bool useLighting;

varying vec3 normal;
varying vec3 ambient;
varying vec3 color;

varying vec3 diffuse[8];
varying vec3 lightDir[8];
varying vec3 dist[8];

varying vec2 texCoord;

void main() { 
    vec4 position = gl_ModelViewMatrix * gl_Vertex;
    gl_Position = gl_ProjectionMatrix * position;
    normal = normalize(gl_NormalMatrix * gl_Normal);
    texCoord = gl_MultiTexCoord0.st;
    color = gl_Color.rgb;

    ambient = gl_FrontMaterial.emission.rgb + gl_LightModel.ambient.rgb * gl_FrontMaterial.ambient.rgb;

    if (useLighting) {
        for (int i = 0; i < numLights; i++) {

            float diffuseIntensity;

            if (gl_LightSource[i].position.w != 0.0) {
                vec3 toLight = (gl_LightSource[i].position - position).xyz;

                dist[i] = toLight;
                lightDir[i] = normalize(toLight);

                diffuseIntensity = dot(normalize(toLight), normal);
            } else {
                lightDir[i] = normalize(gl_LightSource[i].position.xyz);

                diffuseIntensity = dot(normalize(gl_LightSource[i].position.xyz), normal);
            }

            diffuseIntensity = max(diffuseIntensity, 0.0);

            diffuse[i] = gl_FrontMaterial.diffuse.rgb * gl_LightSource[i].diffuse.rgb * diffuseIntensity;

        }
    }
}

Fragment:

#version 140

uniform bool useTexture;
uniform bool useLighting;
uniform sampler2D tex;
uniform int numLights;

varying vec3 normal;
varying vec3 ambient;
varying vec3 color;

varying vec3 diffuse[8];
varying vec3 lightDir[8];
varying vec3 dist[8];

varying vec2 texCoord;

void main() {


    vec4 texColor;

    if (useTexture) {
        texColor = texture2D(tex, texCoord);
    } else {
        texColor = vec4(1.0);
    }

    if (texColor.a == 0.0) {
        discard;
    } else {
        texColor.a = 1.0;
    }

    vec3 lightColor;

    if (useLighting) {
        lightColor = ambient;

        for (int i = 0; i < numLights; i++) {
            float specularIntensity;

            float att = 1.0;

            if (gl_LightSource[i].position.w != 0.0) {

                float dist = length(dist[i]);

                att = 1.0 / (gl_LightSource[i].constantAttenuation +
                             gl_LightSource[i].linearAttenuation * dist +
                             gl_LightSource[i].quadraticAttenuation * dist * dist);

                vec3 halfVector = normalize(lightDir[i]) + vec3(0.0, 0.0, 1.0);

                specularIntensity = dot(normalize(halfVector), normalize(normal));
            } else {
                vec3 halfVector = normalize(lightDir[i]) + vec3(0.0, 0.0, 1.0);

                specularIntensity = dot(normalize(halfVector), normalize(normal));
            }

            specularIntensity = max(specularIntensity, 0.0);

            lightColor += diffuse[i] * att;
            lightColor += gl_FrontMaterial.specular.rgb * gl_LightSource[i].specular.rgb * pow(specularIntensity, gl_FrontMaterial.shininess) * att;
        }
    } else {
        lightColor = color;
    }

    gl_FragColor = texColor * vec4(lightColor, 1.0);
}

And finally, my code for loading a shader:

public class ShaderProgram {

    private final int programID;

    public ShaderProgram(int programID) {
        this.programID = programID;
    }

    public ShaderProgram(Shader... shaders) {

        int id;

        try {
            id = glCreateProgram();
        } catch (Exception ex) {
            Logger.getLogger(ShaderProgram.class.getName()).log(Level.SEVERE, null, ex);
            programID = 0;
            return;
        }

        for (Shader shader : shaders) {
            glAttachShader(id, shader.id);
        }

        glLinkProgram(id); 
        if (glGetProgrami(id, GL_LINK_STATUS) == GL_FALSE) {
            System.err.println(getLogInfo(id)); // This is the line that causes the error. It actually throws an exception (doesn't just print error info)
            programID = 0;
            return;
        }

        glValidateProgram(id);
        if (glGetProgrami(id, GL_VALIDATE_STATUS) == GL_FALSE) {
            System.err.println(getLogInfo(id));
            programID = 0;
            return;
        }

        programID = id;
    }

    public static String getLogInfo(int obj) {
        return glGetShaderInfoLog(obj, glGetShaderi(obj, GL_INFO_LOG_LENGTH));
    }

    public static ShaderProgram loadPrebuilt(String name) {
        Shader vert = Shader.loadPrebuilt(name + ".vert", Shader.Type.VERTEX);
        Shader frag = Shader.loadPrebuilt(name + ".frag", Shader.Type.FRAGMENT);

        return new ShaderProgram(vert, frag);
    }
}

This is the class for a single shader file (either fragment or vertex)

public class Shader {

    public final int id;

    public Shader(int id) {
        this.id = id;
    }

    public Shader(File file, Shader.Type type) {
        int shader = 0;
        try {
            shader = create(readIntoString(new FileInputStream(file)), type);
        } catch (IOException ex) {
            Logger.getLogger(Shader.class.getName()).log(Level.SEVERE, null, ex);
        }
        id = shader;
    }

    public Shader (String program, Shader.Type type) {
        id = create(program, type);
    }


    public static Shader loadPrebuilt(String name, Shader.Type type) {
        try {
            return new Shader(readIntoString(name), type);
        } catch (IOException | URISyntaxException ex) {
            Logger.getLogger(ShaderProgram.class.getName()).log(Level.SEVERE, null, ex);
            return new Shader(0);
        }
    }

    private int create(String program, Type type) {
        int shader = 0;
        try {
            shader = glCreateShader(type.glType);

            glShaderSource(shader, program);

            glCompileShader(shader);

            if (glGetShaderi(shader, GL_COMPILE_STATUS) == GL_FALSE) {
                System.err.println("Error creating shader (" + type.name() + "): " + getLogInfo(shader));
            }

        } catch (Exception ex) {
            glDeleteShader(shader);
            Logger.getLogger(ShaderProgram.class.getName()).log(Level.SEVERE, null, ex);
            shader = 0;
        }

        return shader;
    }

    private static String readIntoString(String filename) throws IOException, URISyntaxException {
        InputStream stream = Shader.class.getResourceAsStream(filename);

        return readIntoString(stream);
    }

    private static String readIntoString(InputStream stream) throws IOException {

        String version = glGetString(GL_SHADING_LANGUAGE_VERSION);
        version = version.substring(0, version.indexOf(" ")).replaceFirst("\\.", "");

        return "#version " + version + "\n\n" + loadTextFile(stream);
    }
}

The line that fails is this:

ShaderProgram.loadPrebuilt("phong");

The files loads just fine. If I print it it prints exactly what I want, and it doesn't fail until I try to get the log info in ShaderProgram.java

2
  • I bet the problem isn't with your shader, but that just happens to be the next time you check for GL errors. Commented Feb 11, 2015 at 22:45
  • @immibis If I try to get the log info earlier then it fails no matter what. My other shaders are compiling just fine, it's just this one that doesn't. This line is only run if glGetProgrami(id, GL_LINK_STATUS) == GL_FALSE, so the program has already failed to compile when the exception occurs. The exception itself does appear to be caused by getting the log from an invalid shader program, since for some reason glLinkProgram(id) did not work properly. Commented Feb 11, 2015 at 23:57

1 Answer 1

2

In this code sequence in the ShaderProgram constructor:

if (glGetProgrami(id, GL_LINK_STATUS) == GL_FALSE) {
    System.err.println(getLogInfo(id));

id is a program id. You pass it to the getLogInfo() method:

public static String getLogInfo(int obj) {
    return glGetShaderInfoLog(obj, glGetShaderi(obj, GL_INFO_LOG_LENGTH));
}

Both glGetShaderInfoLog() and glGetShaderi() expect a shader id as the first argument. To get information about programs, you need to use the corresponding calls for programs instead:

public static String getLogInfo(int obj) {
    return glGetProgramInfoLog(obj, glGetProgrami(obj, GL_INFO_LOG_LENGTH));
}
Sign up to request clarification or add additional context in comments.

1 Comment

Wow, OK that makes sense. I changed my getLogInfo method in the ShaderProgram class like you said (and made a new one for Shader). Now I can actually see what's wrong with my shader (it says not enough space for defined varyings) so I guess I'll look that up now.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.