2015-11-28 12 views
9

OpenGL ES 2.0で末尾のパーティクルエフェクト(seen here)を作成しようとしています。残念ながら、これを可能にするOpenGLコマンド(累積バッファ)はOpenGL esでは使用できません。これは、LONGの道を行く必要があることを意味します。OpenGL ES 2.0で累積バッファをエミュレートする方法(末尾パーティクルエフェクト)

Thisトピックは、このようなことを行う可能な方法について説明しました。しかし、バッファ内に物を格納してバッファを結合する方法については、私はかなり混乱しています。だから私の考えは次のことをすることでした。

  1. 別のバッファに前のフレーム(ただし、フェード)を描画テクスチャ
  2. に書き込みバッファを使用してテクスチャに現在のフレームを描きます。
  3. 手順2のステップ1の上に置き、それを表示します。
  4. 次のフレームで使用するために表示される内容を保存します。

これまでのところ、バッファにはテクスチャと同じ方法でピクセルデータが格納されていましたが、バッファはシェーダを使用して簡単に描画できます。

だから、おそらくバッファにレンダリングしてテクスチャに移動させるという考えがあります。私は振り返ってみると、この

である、あなたは2 FBOs(独自の風合いを持つ各)を作成する必要が見つけ、これを行うための

一説。 デフォルトフレームバッファを使用すると信頼性がありません(内容は がフレーム間で保証されていません)。

最初のFBOをバインドした後、クリアしてシーンを正常にレンダリングします。 シーンがレンダリングされたら、テクスチャをソースとして使用し、ブレンディングを使用して を2番目のFBOにレンダリングします(2番目のFBOは決して がクリアされません)。これにより、新しいシーン とそれ以前のものが混在した2番目のFBOが作成されます。最後に、第2のFBOはウィンドウに直接レンダリングされた でなければなりません(これは、以前の操作と同様に テクスチャ付きクワッドをレンダリングするか、 glBlitFramebufferを使用して行うことができます)。

基本的に、最初のFBOはデフォルトのフレームバッファ の代わりに使用され、2番目のFBOは累積バッファの代わりに使用されます。要約する

初期化:各FBOについて

: - glGenTextures - glBindTexture - glTexImage2D - glBindFrameBuffer - glFramebufferTexture2D

各フレーム:

glBindFrameBuffer(GL_DRAW_FRAMEBUFFER 、fbo1)glClear glDraw * // scene

glBindFrameBuffer(GL_DRAW_FRAMEBUFFER、fbo2)glBindTexture(TEX1) glEnableです(GL_BLEND)glBlendFunc glDraw * //フルスクリーンクワッド

glBindFrameBuffer(GL_DRAW_FRAMEBUFFER、0) glBindFrameBuffer(GL_READ_FRAMEBUFFER、fbo2)glBlitFramebuffer

残念ながら、それはかなりのコードを持っていませんでした(特に初期化を開始するには)。

しかし私は試してみたところ、私が得たのは残念ながら空白の画面でした。私は何をしているのか本当に分かっていないので、おそらくこのコードはかなり間違っています。

var fbo1:GLuint = 0 
var fbo2:GLuint = 0 
var tex1:GLuint = 0 

Init() 
{ 
    //...Loading shaders OpenGL etc. 
    //FBO 1 
     glGenFramebuffers(1, &fbo1) 
     glBindFramebuffer(GLenum(GL_FRAMEBUFFER), fbo1) 

     //Create texture for shader output 
     glGenTextures(1, &tex1) 
     glBindTexture(GLenum(GL_TEXTURE_2D), tex1) 
     glTexImage2D(GLenum(GL_TEXTURE_2D), 0, GL_RGB, width, height, 0, GLenum(GL_RGB), GLenum(GL_UNSIGNED_BYTE), nil) 

     glFramebufferTexture2D(GLenum(GL_FRAMEBUFFER), GLenum(GL_COLOR_ATTACHMENT0), GLenum(GL_TEXTURE_2D), tex1, 0) 
     //FBO 2 
     glGenFramebuffers(1, &fbo2) 
     glBindFramebuffer(GLenum(GL_FRAMEBUFFER), fbo2) 

     //Create texture for shader output 
     glGenTextures(1, &tex1) 
     glBindTexture(GLenum(GL_TEXTURE_2D), tex1) 
     glTexImage2D(GLenum(GL_TEXTURE_2D), 0, GL_RGB, width, height, 0, GLenum(GL_RGB), GLenum(GL_UNSIGNED_BYTE), nil) 

     glFramebufferTexture2D(GLenum(GL_FRAMEBUFFER), GLenum(GL_COLOR_ATTACHMENT0), GLenum(GL_TEXTURE_2D), tex1, 0) 
} 

func drawFullScreenTex() 
{ 
     glUseProgram(texShader) 
     let rect:[GLint] = [0, 0, GLint(width), GLint(height)] 
     glBindTexture(GLenum(GL_TEXTURE_2D), tex1) 
     //Texture is allready 
     glTexParameteriv(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_CROP_RECT_OES), rect) 
     glDrawTexiOES(0, 0, 0, width, height) 
} 

fun draw() 
{ 
    //Prep 
     glBindFramebuffer(GLenum(GL_DRAW_FRAMEBUFFER), fbo1) 
     glClearColor(0, 0.1, 0, 1.0) 
     glClear(GLbitfield(GL_COLOR_BUFFER_BIT)) 

     //1 
     glUseProgram(pointShader); 
     passTheStuff() //Just passes in uniforms 
     drawParticles(glGetUniformLocation(pointShader, "color"), size_loc: glGetUniformLocation(pointShader, "pointSize")) //Draws particles 


     //2 
     glBindFramebuffer(GLenum(GL_DRAW_FRAMEBUFFER), fbo2) 
     drawFullScreenTex() 


     //3 
     glBindFramebuffer(GLenum(GL_DRAW_FRAMEBUFFER), 0) 
     glBindFramebuffer(GLenum(GL_READ_FRAMEBUFFER), fbo2) 
     glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GLbitfield(GL_COLOR_BUFFER_BIT), GLenum(GL_NEAREST)) 

} 

ここに私が有用であると分かったいくつかの情報源があります。

  1. Site 1
  2. Site 2
  3. Site 3
  4. Site 4

私の主な質問は:誰かが、このためのコードを記述してもらえます。関係する理論を理解していると思いますが、私はそれを適用するのに無駄に努力しています。

場所を開始したい場合は、ドットを描画するXcode projectがあります。ここには定期的に画面上を移動する青色の矢印があります。また、動作していないコードも同様です。

注:コードを記述する場合は、任意の言語(C++、Java、Swift、Objective-C)を使用できます。 OpenGL-ES用であれば

+0

なぜ粒子をフェードアウトするためにすべてのものの累積バッファを使用したいのですか? –

+0

私は彼らに歩道を持たせる方法が必要です。最初のリンクのビデオを見てください。私はパーティクルの道が必要です。しかし、私はパーティクルの軌跡にたくさんのエンティティを使用したくありません。 –

+0

粒子軌跡に本格的なエンティティが必要な理由はわかりません。単なる位置、方向(おそらく)、および時間。私のポイントは、蓄積バッファーメソッドは、レンダリングターゲットの切り替え(通常、モバイルハードウェア上の大きなパフォーマンスno-no)を含む多くの作業を必要とするということです。独自にフェードアウトするパーティクルは、まともなパーティクルシステムを必要とするだけです。 –

答えて

1

glGenTextures(1, &tex1)を同じ変数tex1で2回呼び出します。これは変数を上書きします。後でglBindTexture(GLenum(GL_TEXTURE_2D), tex1)を呼び出すと、fbo1に対応するテクスチャはバインドされず、fbo2に対応するテクスチャはバインドされません。 fboごとに異なるテクスチャが必要です。

参考として、以下は、複数のFBOを使用してテクスチャにレンダリングする作業プログラムのサンプルです。

GLuint fbo[n]; 
GLuint tex[n]; 

init() { 
    glGenFramebuffers(n, fbo); 
    glGenTextures(n, tex); 

    for (int i = 0; i < n; ++i) { 
     glBindFramebuffer(GL_FRAMEBUFFER, fbo[i]); 

     glBindTexture(GL_TEXTURE_2D, tex[i]); 
     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); 

     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 

     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex[i], 0); 
    } 
} 

render() { 

    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo[0]); 
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 
    glClear(GL_COLOR_BUFFER_BIT); 

    // Draw scene into buffer 0 

    glBindFrameBuffer(GL_DRAW_FRAMEBUFFER, fbo[1]); 
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 
    glClear(GL_COLOR_BUFFER_BIT); 

    glBindTexture(cbo[0]); 

    //Draw full screen tex 


    ... 


    glBindFrameBuffer(GL_DRAW_FRAMEBUFFER, 0); 
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 
    glClear(GL_COLOR_BUFFER_BIT); 

    glBindTexture(cbo[n - 1]); 
    // Draw to screen 

    return; 
} 

いくつかのメモ。それを動作させるために、テクスチャパラメータを追加する必要がありました。

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 

私のシステムではGL_NEAREST_MIPMAP_LINEARにデフォルト設定されているからです。これは、ミップマップが生成されなかったため、FBOテクスチャでは機能しませんでした。これらをあなたが好きなものに設定してください。

また、あなたは私はこれが役立つことを願っています

glEnable(GL_TEXTURE_2D) 

で有効にテクスチャを持っていることを確認してください。