3

GL_POINTS を使用して、OpenGL で簡単なパーティクル エフェクトを作成しました。以下が呼び出され、最初にカメラから最も遠い粒子から最後にカメラに最も近い粒子へと順番に粒子が渡されます。

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

ただし、次の効果で見られるように、レンダリング時にいくつかのアーティファクトがあります

深度テストを無効にすると問題は解決しますが、深さに応じて同じ GL_TRIANGLE_STRIP の要素の前後に表示される、シーンの他の要素と相互作用できる効果が必要です。

4

2 に答える 2

3

パーティクルが既にソートされている場合は、次のようにレンダリングできます。

  • パーティクルを GL WRITE DEPTH でレンダリングしますが、深度テストは行いません (定数を正確に覚えていません)
  • シーンの残りの部分を深度テストでレンダリングします。

このようにして、見栄えの良いパーティクルとのシーンの相互作用を確実に得ることができます。

于 2009-05-23T16:47:39.543 に答える
2

注: 質問を投稿する際は、使用している OpenGL のバージョンを指定してください。これは、どの API にも当てはまります。アルファ ブレンディングを使用してプリミティブをレンダリングする場合、深度書き込みを有効にすることはできません。ブレンドされたプリミティブを後ろから前に並べて描画する必要があります。シーンに不透明なオブジェクトがある場合は、まずそれらをレンダリングしてから、深度テストを有効にし、深度書き込みを無効にして、透明なプリミティブを後ろから前に並べ替えて描画します。

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();
    ...
}
于 2009-05-23T16:49:38.510 に答える