Atrus
Atrus

Reputation: 798

Implementing a fragment shader that uses a uniform Sampler2D (lwjgl)

I am unable to successfully run a shader, and I seem to be missing some step to make it all work. I end up with the error of:

Exception in thread "main" org.lwjgl.opengl.OpenGLException: Invalid operation (1282)
    at org.lwjgl.opengl.Util.checkGLError(Util.java:59)
    at org.lwjgl.opengl.GL20.glUniform1i(GL20.java:374)
    at sprites.Sprite.draw(Sprite.java:256)
    at gui.Game.drawFrame(Game.java:238)
    at gui.Game.gameLoop(Game.java:205)
    at gui.Game.startGame(Game.java:244)
    at tests.simple.SimpleShader.main(SimpleShader.java:36)

My initialization begins with:

int frag = FilterLoader.createShader("/tests/resources/shaders/grayscale.frag", GL20.GL_FRAGMENT_SHADER);

and the createShader method looks like the following:

int shader = GL20.glCreateShader(type);

if(shader == 0)
    return 0;

StringBuilder code = new StringBuilder("");
String line;

try
{
    String path = FilterLoader.class.getResource(filename).getPath();
    BufferedReader reader = new BufferedReader(new FileReader(path));

    while((line = reader.readLine()) != null)
    {
        code.append(line + "\n");
    }
}
catch(Exception e)
{
    e.printStackTrace();
    System.err.println("Error reading in " + type + " shader");
    return 0;
}

GL20.glShaderSource(shader, code);
GL20.glCompileShader(shader);

return shader;

I then attach the shader to the specific Sprite with:

two.addFragmentShader(frag); //two is a Sprite

which is just simply:

fragmentShader = fragment_shader;
GL20.glAttachShader(shader, fragment_shader);
GL20.glLinkProgram(shader);

The int shader has been previously initialized in the Sprites constructor with:

shader = GL20.glCreateProgram();

This was a previous problem, but no longer obviously. Now I get to where the actual error occured, in the Sprites (two in this case) draw method, which looks like so:

if(true)
{
    GL20.glUseProgram(shader);
}

glPushMatrix();

glActiveTexture(GL13.GL_TEXTURE0);
imageData.getTexture().bind();

//The line below is where the error occurs.
GL20.glUniform1i(fragmentShader, GL13.GL_TEXTURE0);

int tx = (int)location.x;
int ty = (int)location.y;
glTranslatef(tx, ty, location.layer);


float texture_X = ((float)which_column/(float)columns);
float texture_Y = ((float)which_row/(float)rows);
float texture_XplusWidth = ((float)(which_column+wide)/(float)columns);
float texture_YplusHeight = ((float)(which_row+tall)/(float)rows);

glBegin(GL_QUADS);
{
    GL11.glTexCoord2f(texture_X, texture_Y);
    glVertex2f(0, 0);

    GL11.glTexCoord2f(texture_X, texture_YplusHeight);
    glVertex2f(0, getHeight());

    GL11.glTexCoord2f(texture_XplusWidth, texture_YplusHeight);
    glVertex2f(getWidth(), getHeight());

    GL11.glTexCoord2f(texture_XplusWidth, texture_Y);
    glVertex2f(getWidth(), 0);
}
glEnd();
GL20.glUseProgram(0);
glPopMatrix();

And the error occurs at this line:

GL20.glUniform1i(fragmentShader, GL13.GL_TEXTURE0);

And for reference my shader:

// simple fragment shader

uniform sampler2D texture;

void main()
{
    vec4 color, texel;
    color = gl_Color;
    texel = texture2DRect(texture, gl_TexCoord[0].xy);
    color *= texel;

    float gray = dot(color.rgb, vec3(0.299, 0.587, 0.144));

    gl_FragColor = vec4(gray, gray, gray, color.a);
}

I've gone through the tutorials, read about the error, and I can't figure out what step I have missed.

Upvotes: 2

Views: 7949

Answers (1)

Dr. Snoopy
Dr. Snoopy

Reputation: 56417

GL20.glUniform1i(fragmentShader, GL13.GL_TEXTURE0);

This is wrong. The first parameter of glUniform1i is the uniform location, which you can get with glGetUniformLocation.

The second parameter is an integer, but for texture sampler, you need to pass the texture unit number (0, 1, 2, etc), and bind the texture to that texture unit, for example:

glUseProgram(program);
int loc = glGetUniformLocation(program, "texture");
glUniform1i(loc, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texId);

Then it should work.

Upvotes: 7

Related Questions