ios - Cómo emular un búfer de acumulación en OpenGL es 2.0(Efecto de partículas finales)
swift opengl-es (1)
Llama a glGenTextures(1, &tex1)
dos veces con la misma variable tex1. Esto sobrescribe la variable. Cuando más tarde llama a glBindTexture(GLenum(GL_TEXTURE_2D), tex1)
, no vincula la textura correspondiente a fbo1, sino la de fbo2. Necesitas una textura diferente para cada fbo.
En cuanto a una referencia, a continuación se muestra una muestra de un programa de trabajo mío que usa múltiples FBO y representa la textura.
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;
}
Algunas notas Para que funcione, tuve que agregar los parámetros de textura.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
Esto se debe a que en mi sistema se establecieron por defecto en GL_NEAREST_MIPMAP_LINEAR. Esto no funcionó para la textura FBO, ya que no se generó mipmap. Ponlos en todo lo que quieras.
Además, asegúrese de tener habilitadas las texturas con
glEnable(GL_TEXTURE_2D)
Espero que esto sea de ayuda.
Así que he estado tratando de crear un efecto de partícula final ( visto aquí ) con OpenGL ES 2.0. Desafortunadamente, parece que el comando OpenGL (buffer de acumulación) que hace esto posible no está disponible en OpenGL. Esto significa que será necesario seguir el camino LARGO.
Este tema describió un posible método para hacer tal cosa. Sin embargo, estoy bastante confundido acerca de cómo almacenar cosas dentro de un búfer y combinar búferes. Entonces mi pensamiento era hacer lo siguiente.
- Dibuja el marco actual en una textura usando un buffer que escribe en una textura
- Dibuja los cuadros anteriores (pero desvanecidos) en otro buffer.
- Pon el paso 1 en la parte superior del paso 2. Y muestra eso.
- Guarde lo que se muestra para el siguiente cuadro.
Lo que entiendo hasta ahora es que los almacenamientos intermedios almacenan datos de píxeles de la misma manera que las texturas, solo que los almacenamientos intermedios se pueden dibujar más fácilmente usando sombreadores.
Entonces la idea probablemente sería renderizar en un búfer ENTONCES moverlo a una textura.
Una teoría para hacer esto que encontré es esta
En retrospectiva, debe crear dos FBO (cada uno con su propia textura); utilizar el framebuffer predeterminado no es confiable (no se garantiza que los contenidos se conserven entre fotogramas).
Después de unir el primer FBO, límpielo y renderice la escena normalmente. Una vez que la escena ha sido renderizada, usa la textura como fuente y renderízalo en el segundo FBO con mezcla (el segundo FBO nunca se borra). Esto dará como resultado el segundo FBO que contiene una mezcla de la nueva escena y lo que estaba allí antes. Finalmente, el segundo FBO se debe representar directamente en la ventana (esto se puede hacer representando un cuadrante texturizado, de forma similar a la operación anterior, o usando glBlitFramebuffer).
Esencialmente, el primer FBO toma el lugar del framebuffer predeterminado mientras que el segundo FBO toma el lugar del buffer de acumulación.
En resumen:
Inicialización:
Para cada FBO: - glGenTextures - glBindTexture - glTexImage2D - glBindFrameBuffer - glFramebufferTexture2D
Cada cuadro:
glBindFrameBuffer (GL_DRAW_FRAMEBUFFER, fbo1) glClear glDraw * // escena
glBindFrameBuffer (GL_DRAW_FRAMEBUFFER, fbo2) glBindTexture (tex1) glEnable (GL_BLEND) glBlendFunc glDraw * // quad de pantalla completa
glBindFrameBuffer (GL_DRAW_FRAMEBUFFER, 0) glBindFrameBuffer (GL_READ_FRAMEBUFFER, fbo2) glBlitFramebuffer
desafortunadamente no tenía suficiente código (especialmente para la inicialización para comenzar).
Pero lo he intentado, y hasta ahora todo lo que obtuve es una pantalla en blanco decepcionante. Realmente no sé lo que estoy haciendo, por lo que probablemente este código sea bastante incorrecto.
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))
}
Por cierto, aquí hay algunas fuentes que encontré útiles.
Mi pregunta principal es: ¿podría alguien escribir el código para esto? Creo que entiendo la teoría involucrada, pero he pasado tanto tiempo intentando en vano aplicarla.
Si quiere un lugar para comenzar, tengo el proyecto Xcode que dibuja puntos, y tiene uno azul que se mueve por la pantalla periódicamente aquí, también el código que no está funcionando está en su también.
Nota: Si va a escribir código, puede usar cualquier lenguaje c ++, java, swift, objective-c, estará perfectamente bien. Siempre y cuando sea para OpenGL-ES