glBlend help

I am trying to invert the colors of items in a specific area of my screen that currently has a picture drawn on it using glDrawPixels using GL_BLEND using the following code:


glEnable(GL_BLEND);
glBlendFunc(GL_ONE_MINUS_DST_COLOR,GL_ZERO);
//draw rectangle
glDisable(GL_BLEND);

Later on in the same scene, I want to draw a transparent rectangle using the following code:


glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
//draw the rectangle
glDisable(GL_BLEND);

What I am finding is that the code works, but not together. Once I have created the semi-transparent rectangle, the inverted color rectangle ends up behind the scene and no longer inverts anything but the clear color.

I am drawing in the following order: glDrawPixels -> Invert Rectanlge -> semi-transparent rectangle

Can anyone help me figure out what I am doing wrong?

glDrawPixels do update the depth buffer, so the inverted rectangle may appear behind.

Try with :
glDisable(GL_DEPTH_TEST);

Read this post (and the whole discussion if you need more details) :
http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=234139#Post234139

Thanks for the reply.

I had already been doing that. I also have these other environment enablers/disablers

glDisable(GL_FOG);
glDisable(GL_LIGHTING);
glDisable(GL_LOGIC_OP);
glDisable(GL_STENCIL_TEST);
glDisable(GL_TEXTURE_1D);
glDisable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST);
glDisable(GL_ALPHA_TEST);

What seems to be happening is that once the second set of code is called, the entire screen changes color to that of the newly drawn quad. have double checked that I am calling glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) and I am redrawing the glDrawPixels each update.

I just recently switched the draw order to:


//Draw a quad to invert the color on the positive Z axis
glEnable(GL_BLEND);
glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
//Draw the Draw Pixels
glDisable(GL_BLEND);
//do other drawing that seems to have no effect on either of the issues I am seeing
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
//Draw semi-transparent quad
glDisable(GL_BLEND);

This still works individually and avoids the fact that not all gfx cards support DST. But it still has the same original problem of the first blend never working after the second one takes effect. (I can actually clear the screen and redraw without it and the blend still doesn’t produce the same result as before the quad (which is no longer there!) was drawn)

I am sure that this is something I am doing wrong, but I am can’t seem to figure it out.

Could anyone please offer any more suggestions?

Is it that my original concept only works in very specific conditions?

Is this the best way to get an inverted color to draw?

(glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR):wink:

I just can’t understand why it would work every time until the first time I add a new filled quad and then never work again.

Sorry, but I do not beleive that the following will invert colors
(glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR):wink:

Dc = 0 * Sc + (1-Sc)*Dc = Dc - Sc * Dc = 0 which is not the same as
Dc = 1 - Dc which would be color inversion.

You don’t say what colors, etc, you are using with your invert box. Also your original post suggests that you are expecting items drawn after you the inverted colors should also be inverted; or did you mean that after the original frame nothing works correctly anymore?



#include <stdio.h>
#include <assert.h>
#include <GL/glut.h>

void display()
{
    /* clear window */
    glClear(GL_COLOR_BUFFER_BIT);

    /* draw single triangle in center of window */
    glColor3f( 0.0f, 1.0f, 1.0f );
    glBegin(GL_TRIANGLES);
        glVertex2f( 0, 0.25 );
        glVertex2f( -0.25, -0.25 );
        glVertex2f(  0.25, -0.25 );
    glEnd();

    /* invert all colors */
    glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO);
    glColor3f( 1.0f, 1.0f, 1.0f );
    glEnable(GL_BLEND);
    glRectf( -1.0f, -1.0f, 1.0f, 1.0f );
    glDisable(GL_BLEND);

    /* draw points on triangle */
    glColor3f( 0.0f, 1.0f, 0.0f );
    glPointSize( 10.0f );
    glBegin(GL_POINTS);
        glVertex2f( 0, 0.25 );
        glVertex2f( -0.25, -0.25 );
        glVertex2f(  0.25, -0.25 );
    glEnd();

    /* draw translucent box */
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glColor4f( 0.0f, 0.0f, 1.0f, 0.5 );
    glEnable(GL_BLEND);
    glRectf( -0.5f, -0.5f, 0.5f, 0.5f );
    glDisable(GL_BLEND);

    /* assert no errors */
    assert( glGetError() == 0 );
    glutSwapBuffers();
}

int main(int ac, char **av)
{
    glutInit(&ac, av);
    glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGBA );
    glutInitWindowSize( 400,400);
    glutCreateWindow( "GL default settings");
    glutDisplayFunc(display);

    glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
    glutMainLoop();
}

Thanks for the reply.

It seems to give me the inverted pixels until I attempt to draw the other semi-transparent filled quad. What I am doing is:


//Draw a white quad
glEnable(GL_BLEND);
glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
//Draw image using glDrawPixels
//At this point the items in the glDrawPixels would be blended where they are at the same area as the white quad
glDisable(GL_BLEND);
//draw other things that do not affect the inversion
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
//draw a semi-transparent filled quad
glDisable(GL_BLEND);

I think this should work since I am drawing the white quad before drawing the glDrawPixels so the Quad is the DST and the glDrawPixels is the SRC. I don’t want any of the Quad, but I want 1-glDrawPixels.

Am I way off?

Sorry, I do not understand the problem. Are you expecting the other semi-transparent quads to be inverted?

I just need the glDrawPixels to be inverted.

The problem is that I get an inverted area where the white quad is drawn, but as soon as I enable the semi-transparent quad, the old quad turns black (or see-through to the black clear color) and I can no longer see my draw pixels. I am setting the color of the quads as I draw them each time to ensure they draw the same way, but the first quad seems to be permanently ruined by the second and never goes back to the correct color no matter how many times I redraw.

I think it is something else in the application. I modified the above example to render a white triangle then set up the blend mode and rendered a cyan triangle on top of it. Visually use see a red triangle. Rendering the semi-transparent quad has no ill effects.

Thank you for the feedback. I will double-check the rest of my application

The issue was elsewhere. I was setting the polygon mode in the code to fill the rectangle, but I was setting it to the wrong value back afterward.

//Wrong! (for what I was doing)
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
//Draw Semi-transparent Rectangle
glPolgonMode(GL_FRONT_AND_BACK,GL_LINE);

//Right!
int polygonMode[2];
glGetIntegerv(GL_POLYGON_MODE,polygonMode);
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
//Draw Semi-transparent Rectangle
glPolygonMode(polygonMode[0],polygonMode[1]);

Thanks to all for the help.