2015-11-28 17 views
9

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.

  1. Disegnare il frame corrente in una texture utilizzando un buffer che scrive una texture
  2. Disegnare i fotogrammi precedenti (ma sbiadito) in un altro buffer.
  3. Inserire il passaggio 1 in cima al passaggio 2. E visualizzarlo.
  4. 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.

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

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

+0

Perché si desidera utilizzare un buffer di accumulo di tutte le cose per far scomparire le particelle? –

+0

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. –

+0

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. –

risposta

1

Si chiama glGenTextures(1, &tex1) due volte con la stessa variabile tex1. Questo sovrascrive la variabile. Quando in seguito chiamate glBindTexture(GLenum(GL_TEXTURE_2D), tex1), non associa la trama corrispondente a fbo1, ma piuttosto quella di fbo2. Hai bisogno di una trama diversa per ogni fbo.

Per quanto riguarda un riferimento, di seguito è un esempio da un mio programma di lavoro che utilizza più FBO e rendering per texture.

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; 
} 

Alcune note. Per farlo funzionare ho dovuto aggiungere i parametri della trama.

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

Questo perché sul mio sistema hanno impostato su GL_NEAREST_MIPMAP_LINEAR. Questo non ha funzionato per la trama dell'FBO, poiché non è stato generato alcun mipmap. Impostare questi a tutto ciò che ti piace.

Inoltre, assicurarsi di avere le texture abilitati con

glEnable(GL_TEXTURE_2D) 

Spero che questo vi aiuterà.