4

So, I need to make a shader to replace the gray colors in the texture with a given color. The fragment shader works properly if I set the color to a given specific one, like

gl_FragColor = vec4(1, 1, 0, 1);

However, I'm getting an error when I try to retrieve the original color of the texture. It always return black, for some reason.

uniform sampler2D texture; //texture to change

void main() {
  vec2 coords = gl_TexCoord[0].xy;
  vec3 normalColor = texture2D(texture, coords).rgb; //original color

  gl_FragColor = vec4(normalColor.r, normalColor.g, normalColor.b, 1);
}

Theoretically, it should do nothing - the texture should be unchanged. But it gets entirely black instead. I think the problem is that I'm not sure how to pass the texture as a parameter (to the uniform variable). I'm currently using the ID (integer), but it seems to return always black. So I basically don't know how to set the value of the uniform texture (or to get it in any other way, without using the parameters). The code (in Java):

program.setUniform("texture", t.getTextureID());

I'm using the Program class, that I got from here, and also SlickUtils Texture class, but I believe that is irrelevant.

2 Answers 2

8
program.setUniform("texture", t.getTextureID());
                              ^^^^^^^^^^^^^^^^

Nope nope nope.

Texture object IDs never go in uniforms.

Pass in the index of the texture unit you want to sample from.

So if you want to sample from the nth texture unit (GL_TEXTURE0 + n) pass in n:

program.setUniform("texture", 0);
                              ^ or whatever texture unit you've bound `t` to
Sign up to request clarification or add additional context in comments.

3 Comments

I'm not sure what you mean with texture unit. I looked at google and found nothing very conclusive. I'm using, as I said, SlickUtil texture loader; I do like this: TextureLoader.getTexture("PNG", file), and it returns a Texture object. Then, I just do .bind(). I don't assign any number to the texture, but I assumed that the method getTextureID() would return the int that was assigned by OpenGL (that I believed to be the index). I'm not sure how to get this number, then (the 'n').
You can use the texture object returned by getTextureID() in glBindTexture(). As far as texture units go if you're just using one texture unit 0 should be fine.
You use glActiveTexture to set texture unit, then you bind the texture. The texture unit is what you send to the shader. It's a terrible system, but that's how it works!
0

In addition to what genpfault said, when you say "replace the gray colors in the texture with a given color", that had better be a shorthand for "write the color from one texture to another, except replacing gray with a different color". Because you are not allowed to simultaneously read from and write to the same image in the same texture.

2 Comments

Well, that is an inconvenient. I don't need to write in the image, just read and display - is that OK then? My problem is this: my game have several ships, and each one have a specific status set. According to the status set, I'd like to change the color of the ship, but only in the truly gray parts of the image (the other pixels are always the same). I believe it's not ok to create a texture every time I draw a ship. So, I'd have to maintain a map of textures and status set, so that I can re-use the already drawn ships' textures - is that right?
@LuanNico: You can do whatever you want (in this regard) provided that you're not reading from an image that you're writing to. Also, stop using grey for this; grey is too common a color. The standard color for color keying like this is (255, 0, 255); nobody ever uses that by accident.

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.