PDA

View Full Version : gBlendFunc behavior



rpenland
12-08-2003, 11:36 AM
I am new to OpenGL and have been going through some of the various book tutorials. Following the sample code for a simple blend, I wanted to take to RGBA bitmaps and combine them such that the left half would be from the one image and the right half would be from the other image. The code I am using is as follows:

#define checkImageWidth 256
#define checkImageHeight 256
GLubyte checkImage[checkImageHeight][checkImageWidth][4];
GLubyte checkImage2[checkImageHeight][checkImageWidth][4];
int gMainWindow = 0;

void makeCheckImage(void)
{
int i,j,c;

for(i = 0; i < checkImageHeight;i++)
{
for(j = 0; j < checkImageWidth; j++)
{
c = ((((i&0x8)==0)^((j&0x8))==0))*255;
checkImage[i][j][0] = (GLubyte) c;
checkImage[i][j][1] = (GLubyte) c;
checkImage[i][j][2] = (GLubyte) c;
if(j < checkImageWidth/2)
checkImage[i][j][4] = (GLubyte) 0x00;
else
checkImage[i][j][4] = (GLubyte) 0x255;
}
}
}
void makeCheckImage2(void)
{
int i,j,c;

for(i = 0; i < checkImageHeight;i++)
{
for(j = 0; j < checkImageWidth; j++)
{
c = ((((i&0x10)==0)^((j&0x10))==0))*255;
checkImage2[i][j][0] = (GLubyte) c;
checkImage2[i][j][1] = (GLubyte) c;
checkImage2[i][j][2] = (GLubyte) c;
if(j < checkImageWidth/2)
checkImage2[i][j][4] = (GLubyte) 0x255;
else
checkImage2[i][j][4] = (GLubyte) 0x00;
}
}
}
#pragma mark ---- GLUT callbacks ----

static void init (void)
{
glClearColor(0.0,0.0,0.0,0.0); /* Background recColor */
glShadeModel(GL_FLAT);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
makeCheckImage();
makeCheckImage2();
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
}


void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glRasterPos2i(0,0);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE,GL_ZERO);
glDrawPixels(checkImageWidth,checkImageHeight,GL_R GBA,GL_UNSIGNED_BYTE,checkImage);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glDrawPixels(checkImageWidth,checkImageHeight,GL_R GBA,GL_UNSIGNED_BYTE,checkImage2);
glFlush();
}
void reshape(int w, int h)
{
glViewport(0,0,(GLsizei)w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if(w <= h)
gluOrtho2D(0.0,1.0,0.0,1.0*(GLfloat)h/(GLfloat)w);
else
gluOrtho2D(0.0,1.0*(GLfloat)h/(GLfloat)w,0.0,1.0);
}
void keyboard(unsigned char key, int x, int y)
{
switch(key)
{
case '27': // help
exit(0);
break;
default:
break;
}
}

#pragma mark ---- main ----

int main (int argc, const char * argv[])
{
glutInit(&argc, (char **)argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA); // non-stereo for main window
glutInitWindowPosition (300, 50);
glutInitWindowSize (checkImageWidth, checkImageHeight);
gMainWindow = glutCreateWindow("GLUT Basics");

init(); // standard GL init

glutReshapeFunc (reshape);
// glutKeyboardFunc (keyboard);
glutDisplayFunc (display);

glutMainLoop();
return 0;
}


All I see when I run this is a window filled entirely with the first image. Am I totally missing the boat here as to how to use this function?

Thanks,
Rob

dorbie
12-09-2003, 01:09 AM
The code looks good and as far as I can tell should work. I may have missed something though. I have not compiled and tested. Try this using Mesa instead of your card's drivers and see what you get. That's always handy for figuring if it's your problem or not.

sh
12-09-2003, 04:00 AM
glBlendFunc (GL_ONE, GL_ZERO);nullifies the effects of blending, so you might as well just call

glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); in your startup routine and use

glEnable (GL_BLEND); and

glDisable (GL_BLEND); as necessary.

The best way to do what you want is to render two textured quads with an orthographic projection matrix. The first is your first image with GL_BLEND disabled, and the second is the second image drawn overtop with GL_BLEND enabled, with alpha values set for one or more of its vertices.

dorbie
12-10-2003, 08:59 AM
None of these are errors in his algorithm.

They're reasonable suggestions for improving performance / tidying the code but his code should work as posted.

I'd add the following corrections to your advice though:

There's no point in enabling blend then disabling it if you don't draw anything, looks like legacy initializations and the correct thing to do would be to remove the enable from the initialization not add a disable.

AFAIK the blendfunc one, zero in the draw routine is intentional, to ensure drawing the background image, it would be far better to disable GL_BLEND for that image then enable GL_BLEND for the sectond image and leave srcalpha 1-srcalpha as that blendfunc state all the time even if alpha is 1.0 on the whole first image. I see that the images have complimentary masks, but either way it works, there are several combinations of blend func that would work to produce identical results because of this.

Again, his code as written seems functional and should work without these suggestions.

Final advice would be to change the color as well as the pattern in the check to ensure you're seeing the expected results from your bitwise and xor and computation.