Alexandru
Alexandru

Reputation: 25840

render transparent textures

I have one texture that has some portions which are transparent transparent I want to apply over an object whose faces are some opaque material (or colour if it's simpler) but the final object gets transparent. I want the final object to be totally opaque.

Here is my code:

First I set the material:

   glDisable(GL_COLOR_MATERIAL);
   glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
   glColor4f(0.00, 0.00, 0.00, 1.00);
   glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
   glColor4f(0.80, 0.80, 0.80, 1.00);
   glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
   glColor4f(0.01, 0.01, 0.01, 1.00);
   glEnable(GL_COLOR_MATERIAL);

Then I setup the VBOs

   glBindTexture(GL_TEXTURE_2D, object->texture);
   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

   glBindBuffer(GL_ARRAY_BUFFER, object->object);
   glVertexPointer(3, GL_FLOAT, sizeof(Vertex), ver_offset);
   glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), tex_offset);
   glNormalPointer(GL_FLOAT, sizeof(Vertex), nor_offset);

And finally I draw the object

   glEnable(GL_BLEND);
   glDisable(GL_DEPTH_TEST);

   glDisable(GL_TEXTURE_2D);
   glBlendFunc(GL_ONE, GL_ZERO);
   glDrawArrays(GL_TRIANGLES, 0, object->num_faces);

   glEnable(GL_TEXTURE_2D);
   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
   glDrawArrays(GL_TRIANGLES, 0, object->num_faces);

   glDisableClientState(GL_VERTEX_ARRAY);
   glDisableClientState(GL_TEXTURE_COORD_ARRAY);

   glDisable(GL_BLEND); 
   glEnable(GL_DEPTH_TEST);

I tried passing different arguments to glBlendFunc() with no prevail. I've uploaded the source here: http://dpaste.com/83559/

UPDATE I get this, but I want this (or without texture this).

The 2nd and the 3rd picture are produces with glm. I studied the sources, but since my knowledge of OpenGL is limited I didn't understand much.

Upvotes: 2

Views: 2504

Answers (5)

Pivot
Pivot

Reputation: 3446

Try disabling blending and drawing a single pass with your texture function set to GL_DECAL instead of GL_MODULATE. This will blend between the vertex color and the texture color based on the texture’s alpha channel, but leave the alpha channel set to the vertex color.

Note that this will ignore any lighting applied to the vertex color anywhere the texture was opaque, but this sounds like the intended effect, based on your description.

Upvotes: 0

Goz
Goz

Reputation: 62333

This is just a wild guess, as you have failed to provide any screenshots of what the actual problem is, but why do you disable the depth test? Surely you want to enable depth testing on the first pass with a standard GL_LESS and then do the second pass with GL_EQUAL?

Edit:

ie

glEnable(GL_BLEND);
glEnable(GL_DEPTH_TEST);  // ie do not disable
glDepthFunc( GL_LESS );   // only pass polys have a z value less than ones already in the z-buffer (ie are in front of any previous pixels)

glDisable(GL_TEXTURE_2D);
glBlendFunc(GL_ONE, GL_ZERO);
glDrawArrays(GL_TRIANGLES, 0, object->num_faces);

// for the second pass we only want to blend pixels where they occupy the same position 
// as in the previous pass.  Therefore set to equal and only pixels that match the
// previous pass will be blended together.
glDepthFunc( GL_EQUAL );

glEnable(GL_TEXTURE_2D);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDrawArrays(GL_TRIANGLES, 0, object->num_faces);

glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);

glDisable(GL_BLEND); 

Upvotes: 0

Peter Parker
Peter Parker

Reputation: 29735

It will be much simpler with pixel shaders. otherwise I think you need multi-passes rendering or more than one texture. You can find comprehensive details here :http://www.opengl.org/resources/faq/technical/transparency.htm

Upvotes: -1

Gunther Piez
Gunther Piez

Reputation: 30449

AFAIK the blend function takes fragment colors (opposed to texture colors). So if you draw the object a second time with blending, the triangles become transparent.

What you want to accomplish could be done using multitexturing.

Upvotes: 1

Ron Warholic
Ron Warholic

Reputation: 10074

If you're trying to apply two textures to your object you really want to set two textures and use multitexturing to achieve this look. Your method is drawing the geometry twice which is a huge waste of performance.

Multitexturing will just sample from two texture units while only drawing the geometry once. You can do this with shaders (the way things really should be done) or you can still used the fixed function pipeline (see: http://bluevoid.com/opengl/sig00/advanced00/notes/node62.html)

Upvotes: 3

Related Questions