2

So I am developing a small Pong replica simply for some practice with LWJGL. Since there is no easy way to write customizable text in LWJGL, I am using textures for the start button, other buttons, and so on. However, when I drew the texture, it turned out to be discolored on my purple background. If I change the background to white, there is no discoloration. Help?

Also, my start button texture is something like 50x22, but I put it on a 64x64 image because Slick can only load resolutions that are an exponent of two. I adjusted the rectangle being drawn so that it is not warped, and the rest of the image is transparent, so it shouldn't be visible once I sort out the above problem. Are there any alternatives to my method?

This is where I initialize my OpenGL stuff:

public static void setCamera()
{
    glClear(GL_COLOR_BUFFER_BIT);
    glEnable(GL_TEXTURE_2D);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0,width,0,height,-1,1);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

And this is where I draw the texture:

public void draw()
{
    logic();
    glPushMatrix();
    glTranslated(x,y,0);
    texture.bind();
    glBegin(GL_QUADS);
    glTexCoord2d(0,1); glVertex2d(0,-196.875);
    glTexCoord2d(1,1); glVertex2d(width+18.75,-196.875);
    glTexCoord2d(1,0); glVertex2d(width+18.75,height);
    glTexCoord2d(0,0); glVertex2d(0,height);
    glEnd();
    glPopMatrix();
}

Thanks :)

Martijn Courteaux
  • 67,591
  • 47
  • 198
  • 287
Zach_1919
  • 107
  • 6
  • It would be helpful if you explained how you "set your background to white." Do you clear the color buffer, do you draw a fullscreen quad with `glColor3f (...)`, do you set the color in the texture? There are a number of possible causes ranging from the benign (forgetting to reset the current color) to something more complicated like the incorrect application of pre-multiplied alpha in your blend function. – Andon M. Coleman Feb 05 '14 at 00:51
  • It also does not make a whole lot of sense to clear the color buffer and enable `GL_TEXTURE_2D` in a function called `setCamera (...)`. To me, that name implies the only thing it should be doing is setting up your viewing volume (*e.g.* viewport, projection and modelview matrices). – Andon M. Coleman Feb 05 '14 at 00:54
  • @andon Well the name doesn't really matter right now. That setCamera() method runs in the game loop, and there is also another method called drawBackground(), which is where I draw the background color. When I said "set the background to white," I meant that I changed the color in drawBackground() using glColor3d(). – Zach_1919 Feb 05 '14 at 03:34
  • That is your problem then. You need to reset the current color before you draw your foreground, otherwise it will modulate your texture by the background color. Add a call to `glColor3f (1.0f, 1.0f, 1.0f)` after `texture.bind();` in `draw()`. And it was not the name of the function I was objecting to, but the function of the function. You are doing more things than you should be in that function, many of them are unrelated particularly enabling `GL_TEXTURE_2D` - you should only do that when you actually need to apply a texture. – Andon M. Coleman Feb 05 '14 at 03:36
  • @andon While we're on the topic of discoloration, when I display a texture with transparency, it shows up with the color set for that quad (in this case, white, to avoid discoloration), instead of the background color. For example, my background is purple, but the little texture with transparency is displayed on a white quad, so the transparent spots are showing up white instead of purple. – Zach_1919 Feb 05 '14 at 04:02

1 Answers1

1

As discussed in comments, your initial problem was that you had neglected to reset the "current color" before drawing your texture. GL is a glorified state machine, it will continue to use the color you set for every other draw operation... so setting glColor3d (...) when you drew your background also affects your foreground image.

Adding the following before drawing your textured quad will fix this problem:

glColor3f (1.0f, 1.0f, 1.0f);

However, you have brought up a new issue in your comments related to blending. This question boils down to a lack of a blending function. By default when you draw something in OpenGL it will merely overwrite anything else in the framebuffer.

What you need for transparency to work is enable blending and use this function:

glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

This effectively does the following:

NewColor = (NewColor.RGB * NewColor.A) + OldColor.RGB * (1.0 - NewColor.A)

With this, the parts of your texture that have an alpha value != 1.0 will be a mix of whatever was already in the framebuffer and what you just drew.

Remember to enable blending before you draw your transparent objects:

glEnable (GL_BLEND);

and disable it when you do not need it:

glDisable (GL_BLEND);

Lastly, you should be aware that the order you draw translucent objects in OpenGL is pretty important. Opaque objects (such as your background) need to be drawn first. In general, you need to draw things from back-to-front in order for alpha blending to function correctly. This is the opposite order you would ideally want for opaque geometry (since hardware can skip shading for obstructed objects if you draw objects in front of them first).

Andon M. Coleman
  • 42,359
  • 2
  • 81
  • 106