Così ho cercato di creare un effetto particella finale (seen here) con OpenGL ES 2.0. Sfortunatamente sembra che il comando OpenGL (accumulation buffer) che rende ciò possibile non sia disponibile in OpenGL es. Ciò significa che sarà necessario percorrere la strada LUNGO.Come emulare un buffer di accumulo in OpenGL es 2.0 (Trailing Particles Effect)
This argomento descritto un possibile metodo per fare una cosa del genere. Comunque sono abbastanza confuso su come immagazzinare cose all'interno di un buffer e combinare buffer. Quindi il mio pensiero era di fare quanto segue.
- Disegnare il frame corrente in una texture utilizzando un buffer che scrive una texture
- Disegnare i fotogrammi precedenti (ma sbiadito) in un altro buffer.
- Inserire il passaggio 1 in cima al passaggio 2. E visualizzarlo.
- Salva tutto ciò che viene visualizzato per l'utilizzo del fotogramma successivo.
La mia comprensione finora è che i buffer memorizzano i dati dei pixel nello stesso modo delle texture, solo che i buffer possono essere disegnati più facilmente utilizzando gli shader.
Quindi l'idea sarebbe probabilmente quella di eseguire il rendering su un buffer ALLORA spostarlo in una trama.
Una teoria per fare questo che ho trovato è questo
Col senno di poi, è necessario creare due OSA (ciascuno con la propria consistenza); utilizzando il framebuffer predefinito non è affidabile (i contenuti non sono garantiti da tra i frame).
Dopo aver vincolato il primo FBO, cancellarlo e renderizzare la scena normalmente. Una volta che la scena è stata renderizzata, utilizzare la trama come origine e renderla al secondo FBO con fusione (il secondo FBO non è mai eliminato). Ciò comporterà il secondo FBO contenente un mix della nuova scena e quello che c'era prima. Infine, il secondo FBO dovrebbe essere visualizzato direttamente nella finestra (questo può essere eseguito rendendo un quad strutturato similmente all'operazione precedente o usando glBlitFramebuffer).
In sostanza, il primo FBO prende il posto del framebuffer predefinito mentre il secondo FBO prende il posto del buffer di accumulo.
In sintesi:
inizializzazione:
Per ogni FBO: - glGenTextures - glBindTexture - glTexImage2D - glBindFrameBuffer - glFramebufferTexture2D
Ogni frame:
glBindFrameBuffer (GL_DRAW_FRAMEBUFFER , fbo1) glClear glDraw * // scena
glBindFrameBuffer (GL_DRAW_FRAMEBUFFER, fbo2) glBindTexture (tex1) glEnable (GL_BLEND) glBlendFunc glDraw * // intero schermo quad
glBindFrameBuffer (GL_DRAW_FRAMEBUFFER, 0) glBindFrameBuffer (GL_READ_FRAMEBUFFER, fbo2) glBlitFramebuffer
sfortunatamente non ha abbastanza codice (specialmente per l'inizializzazione per farmi iniziare).
Ma ho provato, e finora tutto quello che ho ottenuto è uno schermo vuoto deludente. Non so davvero cosa sto facendo, quindi probabilmente questo codice è abbastanza sbagliato.
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))
}
BTW Ecco alcune fonti che ho trovato utili.
mia domanda principale è: Qualcuno potrebbe scrivere il codice per questo. Penso di capire la teoria in questione, ma ho passato così tanto tempo a cercare invano di applicarlo.
Se si desidera che un punto di partenza, ho il Xcode project che disegna punti e ha uno blu che si sposta sullo schermo periodicamente qui, anche il codice che non funziona è nel loro pure.
Nota: se si intende scrivere codice, è possibile utilizzare qualsiasi linguaggio C++, java, swift, objective-c e sarà perfettamente soddisfacente. Finché è per OpenGL-ES
Perché si desidera utilizzare un buffer di accumulo di tutte le cose per far scomparire le particelle? –
Ho bisogno di un modo per farli avere tracce. Guarda il video sul primo link. Ho bisogno di tracce di particelle. Comunque non voglio usare tonnellate di entità per le tracce di particelle. –
Non vedo perché le scie di particelle richiederebbero entità a pieno titolo. Solo una posizione, orientamento (possibilmente) e tempo. Il mio punto è che il metodo del buffer di accumulo richiede molto lavoro, compreso il cambio degli obiettivi di rendering (di solito un grosso ostacolo alle prestazioni sull'hardware mobile). Mentre le particelle che svaniscono da sole richiedono semplicemente un sistema di particelle decente. –