2015-11-28 71 views
9

所以我一直試圖用OpenGL ES 2.0創建尾隨粒子效果(seen here)。不幸的是,OpenGL es中沒有提供這種可能的OpenGL命令(累積緩衝區)。這意味着有必要採用LONG方式。如何在OpenGL ES 2.0中模擬累積緩衝區(Trailing Particles Effect)

This話題描述了一個可能的方法來做這樣的事情。然而,我很困惑如何將內容存儲在緩衝區中併合並緩衝區。所以我的想法是要做到以下幾點。

  1. 使用寫入到紋理
  2. 緩衝器繪製當前幀到紋理繪製先前幀(但褪色)到另一個緩衝器。
  3. 把步驟1放在步驟2的頂部並顯示出來。
  4. 保存顯示下一幀的內容。

我的理解到目前爲止,緩衝存儲像素數據的方式與紋理相同,只是緩衝區可以更容易地使用着色器。

所以這個想法可能是渲染到緩衝區,然後將其移動到紋理中。這樣做,我發現

有一種說法是這個

回想起來,你應該創建兩個的FBO(每個都有自己的紋理);使用默認幀緩衝區的 不可靠(內容不保證在幀之間保留 )。

綁定第一個FBO後,清除它然後正常渲染場景。 場景渲染完成後,使用紋理作爲源,並使用混合渲染到第二個FBO(第二個FBO從未清除過 )。這將導致第二個FBO包含 新場景以及之前的內容。最後,第二個FBO應該是直接渲染到窗口的 (這可以通過渲染 紋理四元組來完成,與前面的操作類似,或者通過使用glBlitFramebuffer使用 )。

本質上,第一個FBO取代了默認幀緩衝區 ,而第二個FBO取代了累積緩衝區。

總結:

初始化:

對於每個FBO: - glGenTextures - glBindTexture - glTexImage2D - glBindFrameBuffer - glFramebufferTexture2D

每個幀:

glBindFrameBuffer(GL_DRAW_FRAMEBUFFER ,fbo1)glClear glDraw * //場景

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

我不明白爲什麼粒子軌跡需要完整的實體。只是一個位置,方向(可能)和時間。我的觀點是,積累緩衝區方法需要很多工作,包括切換渲染目標(通常是移動硬件上的大性能禁止)。雖然自己淡出的粒子只需要一個體面的粒子系統。 –

回答

1

您可以用相同的變量tex1調用glGenTextures(1, &tex1)兩次。這會覆蓋變量。當您稍後調用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紋理不起作用,因爲沒有生成mipmap。將這些設置爲任何你喜歡的。

此外,還要確保您有

glEnable(GL_TEXTURE_2D) 

啓用紋理我希望這將有助於。