2

多くのパーティクルのすべての頂点データを1つの配列に結合しました。独自の翻訳を維持する方法で、これらすべてのパーティクルをバッチ描画するにはどうすればよいですか?

私はこれを行う方法についてとても混乱しています。この問題についてはすでに2つの投稿を作成しましたが、まだ混乱しています。現在OpenGLES1.1を使用していますが、独自の平行移動や回転などを使用してパーティクルのバッチレンダリングを実際に実行できる場合は、2.0にアップグレードする予定です。

2つの投稿は次のとおりです。

どちらも高レベルのアプローチを説明していますが、各パーティクルの平行移動、回転、スケールがフレームごとに変わるこのパーティクルのバッチをレンダリングする方法を知る必要があります。あなたの答えがCPUでの変換を計算することである場合は、この例を示してください。

現在、実装で頂点配列オブジェクトを使用しています。最高のパフォーマンスを得るには、VBOを使用する必要があることを理解しています。VBOを実装しますが、最初にバッチ処理を実装したいと思います。バッチ処理が正常に完了したら、VAOをVBOに変更します。したがって、この質問の焦点は、VAOを使用してこれをどのように達成するかです。

バッチ処理前のコードは次のとおりです。モデルビューマトリックスに新しいマトリックスをプッシュし、レンダリングされている現在のアクターに応じて変換、回転、スケーリング、アルファ化し、レンダリングされている現在のアクターの頂点とテクスチャコードを描画します。

    glPushMatrix();

    glTranslatef(translation.x, translation.y, translation.z);

    // rotation
    glRotatef(rotation.x, 1, 0, 0);
    glRotatef(rotation.y, 0, 1, 0);
    glRotatef(rotation.z, 0, 0, 1);

    // scale
    glScalef(scale.x, scale.y, scale.z);

    // color and alpha
    glColor4f(1.0, 1.0, 1.0, alpha);

    glVertexPointer(2, GL_FLOAT, 0, aSprite.vertices);
    glEnableClientState(GL_VERTEX_ARRAY);


    glTexCoordPointer(2, GL_FLOAT, 0, texturedQuad.textureCoords);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);

    glDrawArrays(GL_TRIANGLES, 0, 6);

    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glPopMatrix();

ここで、すべてのパーティクルアクターの頂点とtextureCoordsをバッチ配列に結合したので、modelviewマトリックスに新しいマトリックスをプッシュし、それらのアクターの頂点とtextureCoordsを適切な変換、回転、スケールで描画したいと思います。 、アルファなど。

だから私の推測では、それは次のように見えるでしょう:

    static GLFloat verticesBatched[appropriate_length] = ...; // I have a method to populate this array based on the Actors to render

    static GLFloat textureCoordsBatched[appropriate_length] = ...; // I have a method to populate this array based on the Actors to render

    glPushMatrix();

    // perform CPU matrix manipulation to manually translate, rotate, and scale all vertices         

    glVertexPointer(2, GL_FLOAT, 0, verticesBatched);
    glEnableClientState(GL_VERTEX_ARRAY);


    glTexCoordPointer(2, GL_FLOAT, 0, textureCoordsBatched);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);

    glDrawArrays(GL_TRIANGLES, 0, 6);

    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glPopMatrix();

有効な答えは、この質問の解決策を明確に示すコード例を含むものです。

4

1 に答える 1

0

すべてのパーティクルが同じテクスチャを持っているので、これでうまくいきます:

float squarevData[12]={
    -1,1,
    1,1,
    -1,-1,
    1,1,
    1,-1,
    -1,-1,
};
float squarevDataSteady[12]={
    -1,1,
    1,1,
    -1,-1,
    1,1,
    1,-1,
    -1,-1,
};

class BatchRenderer
{
public:
    float* partVdata;
    float* partCdata;
    float* partTdata;
    bool isanydrawed;
    int counter1,counter2,counter3;
    int count;
    bool isz;
    bool textured;
    void Innit(int maxTextures,bool iszi)
    {
        isz=iszi;
        if(isz)partVdata=(float*)malloc(maxTextures*18*4);
        else partVdata=(float*)malloc(maxTextures*12*4);

        partCdata=(float*)malloc(maxTextures*24*4);
        partTdata=(float*)malloc(maxTextures*12*4);

        isanydrawed=false;
    }
    void Draw(float x,float y,float z,float scalex,float scaley,float angle,float r,float g,float b,float a)
    {
        isanydrawed=true;

        angle*=0.017453f;
        for(int c2=0;c2<12;c2+=2)
        {
            float x=squarevData[c2]*scalex;
            float y=squarevData[c2+1]*scaley;
            float cos1=cos(angle);
            float sin1=sin(angle);
            squarevDataSteady[c2] = (cos1*x) - ( sin1*y);
            squarevDataSteady[c2+1] = (sin1*x) + ( cos1*y);
        }

        partVdata[counter1++]=x+squarevDataSteady[0];
        partVdata[counter1++]=y+squarevDataSteady[1];
        if(isz)partVdata[counter1++]=z;
        partCdata[counter2++]=r;
        partCdata[counter2++]=g;
        partCdata[counter2++]=b;
        partCdata[counter2++]=a;
        partTdata[counter3++]=0;
        partTdata[counter3++]=1;


        partVdata[counter1++]=x+squarevDataSteady[2];
        partVdata[counter1++]=y+squarevDataSteady[3];
        if(isz)partVdata[counter1++]=z;
        partCdata[counter2++]=r;
        partCdata[counter2++]=g;
        partCdata[counter2++]=b;
        partCdata[counter2++]=a;
        partTdata[counter3++]=1;
        partTdata[counter3++]=1;

        partVdata[counter1++]=x+squarevDataSteady[4];
        partVdata[counter1++]=y+squarevDataSteady[5];
        if(isz)partVdata[counter1++]=z;
        partCdata[counter2++]=r;
        partCdata[counter2++]=g;
        partCdata[counter2++]=b;
        partCdata[counter2++]=a;
        partTdata[counter3++]=0;
        partTdata[counter3++]=0;

        partVdata[counter1++]=x+squarevDataSteady[6];
        partVdata[counter1++]=y+squarevDataSteady[7];
        if(isz)partVdata[counter1++]=z;
        partCdata[counter2++]=r;
        partCdata[counter2++]=g;
        partCdata[counter2++]=b;
        partCdata[counter2++]=a;
        partTdata[counter3++]=1;
        partTdata[counter3++]=1;

        partVdata[counter1++]=x+squarevDataSteady[8];
        partVdata[counter1++]=y+squarevDataSteady[9];
        if(isz)partVdata[counter1++]=z;
        partCdata[counter2++]=r;
        partCdata[counter2++]=g;
        partCdata[counter2++]=b;
        partCdata[counter2++]=a;
        partTdata[counter3++]=1;
        partTdata[counter3++]=0;

        partVdata[counter1++]=x+squarevDataSteady[10];
        partVdata[counter1++]=y+squarevDataSteady[11];
        if(isz)partVdata[counter1++]=z;
        partCdata[counter2++]=r;
        partCdata[counter2++]=g;
        partCdata[counter2++]=b;
        partCdata[counter2++]=a;
        partTdata[counter3++]=0;
        partTdata[counter3++]=0;

        count++;

    }
    void RenderStart()
    {
        counter1=counter2=count=counter3=0;
    }
    void RenderStop(int textureid)
    {
        if(!isanydrawed)return;

            glEnable(GL_TEXTURE_2D);
            glEnableClientState(GL_COLOR_ARRAY);
            glEnableClientState(GL_TEXTURE_COORD_ARRAY);
            glEnableClientState(GL_VERTEX_ARRAY);
            glBindTexture(GL_TEXTURE_2D, textureid);
            glTexCoordPointer(2, GL_FLOAT, 0, partTdata);
        glColorPointer(4, GL_FLOAT, 0,partCdata );
        if(isz)glVertexPointer(3, GL_FLOAT, 0, partVdata);
        else glVertexPointer(2, GL_FLOAT, 0, partVdata);
        glDrawArrays(GL_TRIANGLES, 0, count*6);
        glDisableClientState(GL_COLOR_ARRAY);
        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
        glDisableClientState(GL_VERTEX_ARRAY);

        isanydrawed=false;
    }
};

あなたのコード:

BatchRenderer* br=new BatchRenderer(MAX_TEXTURES_NUM,true);//true since you are drawing 3d
void onParticlesRender()
{
      br->RenderStart();
      for(int c=0;c<PARTICLES_SIZE;c++)
      {
            br->Draw(p[c].pos.x,p[c].pos.y,p[c].pos.z,p[c].scale.x,p[c].scale.y,p[c].angle,p[c].r,p[c].g,p[c].b,p[c].a);
      }
      br->RenderStop(yourTextureID);
}

今はコードをテストできないので、問題なく動作する場合はお知らせください

VBO は、すべてのフレームで新しい頂点データを GPU にアップロードしているため、バッチ レンダーでは役に立ちません。

于 2012-12-30T12:14:48.640 に答える