Проблема альфа-смешения OpenGL с видимой задней стороной - PullRequest
1 голос
/ 12 января 2011

Я пытаюсь отобразить «прозрачные» поверхности (не закрытые объемы), при этом видны как передняя, ​​так и задняя поверхность (не выбрано).

Например, отображение конуса или цилиндра, где прозрачность применяется с обеих сторон. Есть некоторые видимые артефакты, где некоторая часть поверхности, кажется, не обрабатывает альфа-значения правильно.

Проблема, по-видимому, заключается в том, что я (opengl) пытается применить альфу от передней стороны поверхности к задней стороне поверхности. (когда видна внутренняя / внешняя поверхность).

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();

}

Код основан на: http://www.sgi.com/products/software/opengl/examples/glut/examples/source/blender.c

крошечные ссылки на 2 изображения на flickr, показывающие проблему (но из производственного кода, а не из приведенного выше кода, но у обоих одинаковые проблемы): http://flic.kr/p/99soxy и http://flic.kr/p/99pg18

Спасибо. Макс.

1 Ответ

5 голосов
/ 13 января 2011

Ваша проблема, вероятно, является смесью двух проблем.

  • , так как ваш тест глубины включен, и все полигоны записывают в буфер глубины, полигоны, которые находятся дальше, не могут вносить вклад в цвет пикселя, если они нарисованы после ближайших полигонов. Вы должны попытаться отключить тест глубины.

  • alphablending - это некоммутативная операция, поэтому порядок, в котором нарисованы треугольники, важен и меняет результат. Чтобы получить последовательный результат, вы должны нарисовать треугольники в последовательном порядке. В вашем коде этот порядок может отличаться, например, в зависимости от точки зрения. Поскольку ваши объекты являются выпуклыми, вы можете нарисовать ваш объект в два прохода, оба с включенным отбраковкой, первый проход нарисовать треугольники обратного хода (которые наиболее отдалены от камеры), затем треугольники переднего плана (которые находятся ближе всего)

В целом, правильное смешивание для произвольной геометрии является сложной проблемой, вы можете обратиться к алгоритмам независимой прозрачности заказа (очистка по глубине, ...), если хотите пойти дальше.

...