简体   繁体   中英

OpenGL alpha blending issue with back face visible

I'm trying to display "transparent" surfaces (not closed volumes) with both the front face and back face are visible (not culled).

For example displaying a cone or cylinder where the transparency is applied on both sides. There are some visible artifacts where some part of the surface does not seems to be handling the alpha values correctly.

The issue it seems is when I (opengl) is trying to apply the alpha from the front side of the surface to the backside of the surface. (when both the inside/outside of the surface is visible).

void init()
{
    glMatrixMode(GL_PROJECTION);
    gluPerspective( /* field of view in degree */ 40.0,
        /* aspect ratio */ 1.0,
        /* Z near */ 1.0, /* Z far */ 10.0);
    glMatrixMode(GL_MODELVIEW);
    gluLookAt(0.0, 0.0, 5.0,  /* eye is at (0,0,5) */
        0.0, 0.0, 0.0,      /* center is at (0,0,0) */
        0.0, 1.0, 0.);      /* up is in positive Y direction */
    glTranslatef(0.0, 0.6, -1.0);

    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
    glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_diffuse);
    glLightfv(GL_LIGHT1, GL_POSITION, light1_position);
    glLightfv(GL_LIGHT2, GL_DIFFUSE, light2_diffuse);
    glLightfv(GL_LIGHT2, GL_POSITION, light2_position);

    glClearDepth(1.0f);
    glEnable(GL_DEPTH_TEST);
    //glEnable(GL_CULL_FACE);
    glFrontFace( GL_CW );

    glShadeModel(GL_SMOOTH);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

}
void draw ()
{
    static GLfloat amb[] = {0.4f, 0.4f, 0.4f, 0.0f};
    static GLfloat dif[] = {1.0f, 1.0f, 1.0f, 0.0f};
    static GLfloat back_amb[] = {0.4f, 0.4f, 0.4f, 1.0f};
    static GLfloat back_dif[] = {1.0f, 1.0f, 1.0f, 1.0f};

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_LIGHT1);
    glDisable(GL_LIGHT2);
    amb[3] = dif[3] = 0.5f;// cos(s) / 2.0f + 0.5f;
    glMaterialfv(GL_FRONT, GL_AMBIENT, amb);
    glMaterialfv(GL_FRONT, GL_DIFFUSE, dif);
    glMaterialfv(GL_BACK, GL_AMBIENT, back_amb);
    glMaterialfv(GL_BACK, GL_DIFFUSE, back_dif);
    glPushMatrix();
    glTranslatef(-0.3f, -0.3f, 0.0f);
    glRotatef(angle1, 1.0f, 5.0f, 0.0f);
    glutSolidCone(1.0, 1.0, 50, 2 ); 
    glPopMatrix();

    ///...
    SwapBuffers(wglGetCurrentDC()); // glutSwapBuffers();

}

The code is based on : http://www.sgi.com/products/software/opengl/examples/glut/examples/source/blender.c

tinyurled links to 2 images on flickr showing the issue (but from out production code, not the above code, but both have the same kind of problems): http://flic.kr/p/99soxy and http://flic.kr/p/99pg18

Thanks. Max.

Your problem is probably a mix of two problems.

  • as your depth test is enabled, and all polygons write to depth buffer, the polygons that are further away cannot contribute to the pixel color if they are drawn after the nearest polygons. You should try to disable your depth test.

  • alphablending is a non-commutative operation, so the order is which the triangles are drawn is important and changes the result. To have a consistent result, you'd have to draw the triangles in consistent order. In your code, this order may vary, depending on the viewpoint for instance. As your objects are convex, you could draw your object in two passes, both with culling enabled, the first pass drawing the backfacing triangles (that are the most distant to the camera), then the frontfacing triangles (that are nearest)

More generally, correct blending for arbitrary geometry is a hard problem, you may want to look at Order Independent Transparency algorithms (depth peeling, ...) if you want to go further.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM