Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OpenGL translucent texture over other texture

I got a 2 png images, being used as textures in a Qt/C++ 2D OpenGL application. The first is used as some kind of "middle" ground and the second is used as an "object" being rendered "ontop" (Note: they all have the same z-value atm, I get the desired behaviour be rendering it in a defined order). The "object"-texture is partly translucent. The "middleground" texture is mostly solid. The problem is that, the translucent part of my "object" texture does the solid background color and not the "middleground" texture.

Any tips how to achieve this?

Following OpenGL falgs are used for my textures rendering

glEnable (GL_TEXTURE_2D);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glEnable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

Thanks for any help.

Edit:

More code:

glColor4f(1.0f, 1.0f, 1.0f, 1.0f);

glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);

glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.1f);

glEnable(GL_TEXTURE_2D);
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glBindTexture(GL_TEXTURE_2D, c->_texture);

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

glBegin(GL_QUADS);
{
    glTexCoord2i(0,0);
    glVertex2i(-128,-128);

    glTexCoord2i(0,1);
    glVertex2i(-128,128);

    glTexCoord2i(1,1);
    glVertex2i(128,128);

    glTexCoord2i(1,0);
    glVertex2i(128,-128);

}
glEnd();

glDisable(GL_TEXTURE_2D);

glDisable(GL_ALPHA_TEST);
glDisable(GL_DEPTH_TEST);

Edit: How I load my texture and as far as I can say it loads it with alpha channel

QImage img("./images/dummycar.png","PNG");
QImage t(QGLWidget::convertToGLFormat(img));
glGenTextures(1, &_texture);
glBindTexture(GL_TEXTURE_2D, _texture);
glTexImage2D( GL_TEXTURE_2D, 0, 3, t.width(), t.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, t.bits() );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

Screenshot: http://img824.imageshack.us/img824/1912/blackbox.png

The Skyimage is the "middleground" the background is solid black.

like image 801
drahnr Avatar asked Jul 02 '10 07:07

drahnr


3 Answers

glTexImage2D( GL_TEXTURE_2D, 0, 3, t.width(), t.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, t.bits() );

You're specifying 3 channels for the internalFormat, so that's RGB, not RGBA. Try using GL_RGBA in that position instead.

like image 170
Thomas Avatar answered Nov 10 '22 09:11

Thomas


Have you tried fiddling with glAlphaFunc? You can use it to discard drawing translucent parts of your object texture based on alpha value.

What about either

glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND)

or

glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE)?

I hope that helps.

like image 39
Greg S Avatar answered Nov 10 '22 08:11

Greg S


If you're rendering one texture per object, then you need to use glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE).

If texture still has "box" around it even after that, then it was loaded without alpha channel.

This perfectly works for me:

    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glBindTexture(GL_TEXTURE_2D, texture2->tex);
    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    glColor4f(0.5f, 1.0f, 0.5f, 0.5f);
    glBegin(GL_TRIANGLE_FAN);
    glTexCoord2f(0, 0);
    glVertex2f(x, y);
    glTexCoord2f(1, 0);
    glVertex2f(x + texture2->width, y);
    glTexCoord2f(1, 1);
    glVertex2f(x + texture2->width, y+ texture2->height);
    glTexCoord2f(0, 1);
    glVertex2f(x, y + texture2->height);
    glEnd();
    glDisable(GL_BLEND);

Semi-transparent texture, tinted by last color.

If "having a box around texture" does not describe your problem, then you need to post screenshots.

--EDIT--

Updated data based on your screenshot.

You need to FIRST render background, and then render the car. You see background color because even if surface is transparent, it fills z-buffer with values, and since background is below car, it becomes invisible.

When you're rendering semi-transparent objects, you need to follow those rules.

  1. All non-transparent objects should be rendered before semi-transparent objects. Always.

  2. All transparent objects should be rendered in back to front object. Furthest objects should be rendered first, closest objects should be rendered second.

  3. If rendering in back-to-front order is not possible (unsorted particles with GL_ADD blend), writing into depth buffer should be disabled using glDepthMask(GL_FALSE). If you don't do it, you'll get ugly artifacts. (like the one on your screenshot).

like image 3
SigTerm Avatar answered Nov 10 '22 08:11

SigTerm