views:

398

answers:

5

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.

A: 

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

Peter Parker
Pixelshaders are simpler than multitexturing?
drhirsch
of course! it depends on your target platform and engine, but if you want to achieve a descent transparency effect like glass or cut out it is much easier with a simple pixel shader than with fixed function pipeline
Peter Parker
+2  A: 

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)

Ron Warholic
I disagree that everything should be done using shaders. But you have beaten me by 19 secs ;-)
drhirsch
OpenGL 3.X has completely phased out parts of the FFP, shaders are the future.
Ron Warholic
I don't want to textures. I want one material and one texture (like painting (texture) on grey metal (material)). I agree that drawing the geometry twice is a waste of time, and possible the problem so I'm looking for an alternative.
Alexandru
You probably still want to use two textures here - set your first texture as a very small texture that is appropriately colored for your gray material and set your second texture as your detail texture. It might seem awkward but reading from two textures is very very fast on modern hardware whereas rendering geometry and switching rendering states is much much slower. If you need dynamic coloring filling a 2x2 texture with a color is very fast and will give you the same net effect.
Ron Warholic
+1  A: 

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.

drhirsch
A: 

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);
Goz
A: 

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.

Pivot