在OpenGL中使用粒子效果的Alpha透明度

3

我在OpenGL中使用GL_POINTS实现了一个简单的粒子效果。下面的代码被调用,按照从相机最远的粒子到相机最近的粒子的顺序传递粒子:

void draw_particle(particle* part) {
    /* The following is how the distance is calculated when ordering.
     * GLfloat distance = sqrt(pow(get_camera_pos_x() - part->pos_x, 2) + pow(get_camera_pos_y() - part->pos_y, 2) + pow(get_camera_pos_z() - part->pos_z, 2));
     */

    static GLfloat quadratic[] = {0.005, 0.01, 1/600.0};
    glPointParameterfvARB(GL_POINT_DISTANCE_ATTENUATION_ARB, quadratic);
    glPointSize(part->size);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_POINT_SPRITE_ARB);
    glEnable(GL_TEXTURE_2D);

    glBegin(GL_POINTS);
        glColor4f(part->r, part->g, part->b, part->a);
        glVertex3f(part->pos_x, part->pos_y, part->pos_z);
    glEnd();

    glDisable(GL_BLEND);
    glDisable(GL_POINT_SPRITE_ARB);
}

然而,在渲染时存在一些伪影问题,如下图所示:伪影图像 http://img199.imageshack.us/img199/9574/particleeffect.png 如果我禁用深度测试,则问题会消失,但我需要效果能够与场景中的其他元素交互,根据深度在相同的GL_TRIANGLE_STRIP元素前后出现。

1
关于你的代码,我有一个评论。我认为你应该从draw_particle()函数中提取所有非“particle*”相关的代码:
  1. 启用你想要使用的东西,设置混合函数,调用glPointParameterfvARB等。
  2. 调用draw_particles(const std::vector<particle*>& v)。
  3. 禁用混合等。
- ralphtheninja
2个回答

3
如果你的颗粒已经排序好了,可以这样渲染:
  • 使用GL WRITE DEPTH来渲染颗粒,但不进行深度测试(我不记得具体的常量)
  • 使用深度测试来渲染场景的其余部分。
这样做可以确保在看起来很漂亮的颗粒中获得场景交互。

在同一时间内找到了答案。解决方法是使用: glDepthMask(GL_FALSE); [渲染粒子] glDepthMask(GL_TRUE); - ICR
反过来说,您想根据深度丢弃某些内容,但是又不希望由于编写新的深度而影响混合原语之间的关系。因此,实际的深度缓冲区内容只能来自glClear或者不透明物体。 - Mads Elvheim

2
注意:在您发布问题时,请指定使用的OpenGL版本。这适用于任何API。 当您想要使用alpha混合渲染基元时,不能启用深度写入。您需要按照从后往前排序的顺序绘制混合基元。如果场景中有不透明物体,请首先将它们渲染出来,然后以启用深度测试和禁用深度写入的方式以从后往前排序的方式绘制透明基元。
glEnable(GL_DEPTH_TEST);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_POINT_SPRITE);
glEnable(GL_CULL_FACE);

while(1)
{
    ...
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glDisable(GL_BLEND);
    glDepthMask(1);
    RenderOpaque();
    SortSprites();
    glEnable(GL_BLEND);
    glDepthMask(0);
    DrawSprites();
    ...
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接