所以我一直試圖用OpenGL ES 2.0創建尾隨粒子效果(seen here)。不幸的是,OpenGL es中沒有提供這種可能的OpenGL命令(累積緩衝區)。這意味着有必要採用LONG方式。如何在OpenGL ES 2.0中模擬累積緩衝區(Trailing Particles Effect)
This話題描述了一個可能的方法來做這樣的事情。然而,我很困惑如何將內容存儲在緩衝區中併合並緩衝區。所以我的想法是要做到以下幾點。
- 使用寫入到紋理
- 緩衝器繪製當前幀到紋理繪製先前幀(但褪色)到另一個緩衝器。
- 把步驟1放在步驟2的頂部並顯示出來。
- 保存顯示下一幀的內容。
我的理解到目前爲止,緩衝存儲像素數據的方式與紋理相同,只是緩衝區可以更容易地使用着色器。
所以這個想法可能是渲染到緩衝區,然後將其移動到紋理中。這樣做,我發現
有一種說法是這個
回想起來,你應該創建兩個的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))
}
順便說一句,這裏有一些我覺得有用的來源。
我的主要問題是:可能有人請寫出來的代碼這一點。我想我理解所涉及的理論,但我花了很多時間徒勞地嘗試應用它。
如果你想要一個地方開始我有Xcode project繪製點,並有一個藍色的在這裏定期在屏幕上移動,也是不工作的代碼也在其中。
注意:如果您要編寫代碼,您可以使用任何語言C++,java,swift,objective-c,那將會非常好。只要是用於OpenGL-ES
爲什麼要使用所有東西的累積緩衝區淡出粒子? –
我需要一種方法讓他們有足跡。看第一個鏈接上的視頻。我需要粒子軌跡。但是我不想使用大量的實體進行粒子追蹤。 –
我不明白爲什麼粒子軌跡需要完整的實體。只是一個位置,方向(可能)和時間。我的觀點是,積累緩衝區方法需要很多工作,包括切換渲染目標(通常是移動硬件上的大性能禁止)。雖然自己淡出的粒子只需要一個體面的粒子系統。 –