Problem with Blending

Hi,

I am working on water surface simulation, as a newbie in openGL, with lots of help from this forum I have completed the dynamics and the refraction maps.

Now, next step is reflection of sky in to my water surface. I have read tutorials and topics related to blending. I understand that blending is done when two textured(or colored) primitives overlap and then we can make them translucent so that we can see through them.

        My problem is I have only one primitive i.e my triangular mesh. I have created the mesh using glDrawElements(),

and then Textured with the image of floor (pond). I have used the following code to blend the sky image with this image so as to give the effect of reflection, but there is some thing wrong with either my logic or code.

glBlendFunc(GL_ONE, GL_ONE);
glActiveTextureARB(GL_TEXTURE0_ARB);

  glBindTexture(GL_TEXTURE_2D, textureArray[0]); // first image

glActiveTextureARB(GL_TEXTURE1_ARB);
glBindTexture(GL_TEXTURE_2D, textureArray[1]); // second image
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE);

glPushMatrix();

glTranslatef(-(n/2),-(n/2),0);

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT, 0, normals);
glTexCoordPointer(2,GL_FLOAT,0,tex);
glVertexPointer(3,GL_FLOAT,0,vertices);
glDrawElements(GL_TRIANGLES,6*(n-1)*(n-1),GL_UNSIGNED_INT,indices);
glDisableClientState(GL_VERTEX_ARRAY);

glPopMatrix();

Also I am confused, in my case do I have to do Multitexturing or Blending?

Did you enable GL_BLEND?


glEnable( GL_BLEND );

The documentation of glBlendFunc says that GL_ONE set RGBA to (1,1,1,1). To mix things up I use the following configuration:


glBlendFunc(  GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );

More information can be found into documentation of glBlendFunc

You have a lot of calls missing after
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE);

Example:
http://www.opengl.org/wiki/Texture_Combiners

Hi McLeary,

Thankyou for your reply.

Yes, I have enabled GL_BLEND in the calling function.

I have not used

glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );

because I am using .png images which are photographs, so I don’t know or have control, over the alpha values of the images.

You have several problems with your code.

Blending is a multi-pass algorithum.
Multitexturing is a single-pass algorithum.

You are not clear which you are doing. I suggest the multitexturing is the approach you are after and can therefore disable GL_BLEND.

In you code you need to improve several areas:

  1. Initialisation
  2. Rendering
  3. Finalisation/cleanup

…so pretty much all of it!


glActiveTextureARB(GL_TEXTURE0_ARB);
glEnable (GL_TEXTURE_2D);			//should already be enabled - do we need this line?
glBindTexture(GL_TEXTURE_2D, textureArray[0]); // first image

Notice the need to enable the active texture unit for texturing.


glActiveTextureARB(GL_TEXTURE1_ARB);
glEnable (GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, textureArray[1]); // second image
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE);

You also need to setup the combiners. You have been given the link for this - very useful I can tell you. I wish I had that information 6 years ago!

The rendering now needs to enable the vertex arrays for each active texture:


glClientActiveTexture(GL_TEXTURE0); 
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2,GL_FLOAT,0,tex);

glClientActiveTexture(GL_TEXTURE1); 
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2,GL_FLOAT,0,tex);

and for clean up of the enabled client states…


//glClientActiveTexture(GL_TEXTURE1); 	//already active
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTexture(GL_TEXTURE0); 	
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);

and finally the clean up of the enabled textures…


//glActiveTextureARB(GL_TEXTURE1_ARB);	//already active
glDisable (GL_TEXTURE_2D);
glActiveTextureARB(GL_TEXTURE0_ARB);	//ensure we finish on texture unit #0

Notice we finish leaving GL_TEXTURE1_ARB disabled and GL_TEXTURE0_ARB as the current active (enabled) texture unit.

Hi BionicBytes,

Thank you for your guidance, I embedded your code along with the code from the link.

Now I am trying to blend the two images based upon the supplied blending factor alpha.

This alpha is supplied through the last(4th) element of array ‘mycolor[]’.

Now the problem I am getting is, irrespective of alpha value I supply the second texture is appearing without any blending or trace of first texture.

following is the code,

void drawFloor(int pass)
{

glActiveTextureARB(GL_TEXTURE0);

if (pass == PASS_NORMAL)
  glBindTexture(GL_TEXTURE_2D, textureArray[0]);

else
glCallList(100);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);

glActiveTextureARB(GL_TEXTURE1_ARB);
glEnable (GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, textureArray[1]); // second image
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE); //Interpolate RGB with RGB
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE);
//GL_CONSTANT refers to the call we make with glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, mycolor)
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_CONSTANT);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR);
//------------------------
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_INTERPOLATE); //Interpolate ALPHA with ALPHA
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_TEXTURE);
//GL_CONSTANT refers to the call we make with glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, mycolor)
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA, GL_CONSTANT);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA, GL_SRC_ALPHA);
//------------------------
float mycolor[4];
mycolor[0]=mycolor[1]=mycolor[2]=0.0;
mycolor[3]=0.0; //Set the blend factor with this

glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, mycolor);
glPushMatrix();
glTranslatef(-(n/2),-(n/2),0);

 glEnableClientState(GL_VERTEX_ARRAY);
 glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT, 0, normals);

glClientActiveTexture(GL_TEXTURE0);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2,GL_FLOAT,0,tex);

glClientActiveTexture(GL_TEXTURE1);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2,GL_FLOAT,0,tex);

glVertexPointer(3,GL_FLOAT,0,vertices);
glDrawElements(GL_TRIANGLES,6*(n-1)*(n-1),GL_UNSIGNED_INT,indices);
glDisableClientState(GL_VERTEX_ARRAY);

glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTexture(GL_TEXTURE0);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);

glDisable (GL_TEXTURE_2D);
glActiveTextureARB(GL_TEXTURE0_ARB); //ensure we finish on texture unit #0

glPopMatrix();

}

I am really grateful for your time.

Finally finished blending, thanks bionic bytes for code and V-man for the link

No problem. Glad I managed to help.