J'avais espéré au moins une réponse...
enfin bon, un peu de Google et j'ai trouvé plus ou moins ce qu'il me fallait.
http://www.gamedev.net/reference/pro...features/fbo2/
http://www.opengl.org/discussion_boa...&Number=238733
'fin bref, avant de marquer ce thread comme résolu, voici la réponse à mes questions:
du côté API, il faut créer le FBO:
1 2
| GLuint fbo;
glGenFramebuffersEXT(1, &fbo); |
et les textures: (considérons que nous avons défini un enum, dont les valeurs de 0 à N-1 représentent nos Render targets, et N est définie comme RenderTargetCount).
(notez que RenderTargetCount doit être <= GLuint maxbuffers;
glGetIntergeri(GL_MAX_COLOR_ATTACHMENTS, &maxbuffers)
1 2 3 4 5 6 7
| GLuint rendertargets[RenderTargetCount];
glGenTextures(RenderTargetCount, rendertargets);
for(u32 i = 0; i < RenderTargetCount; i++)
{
glBindTexture(GL_TEXTURE_2D, rendertargets[i]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
} |
(nota: je laisse le format de texture en RGBA8 par défaut, mais en fait, il faudrait le définir en rapport au format optimal de ce target).
ensuite, nous définissons nos textures comme
RenderBuffer (eTargetColor) du FBO:
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, rendertargets[eTargetColor], 0);
Depthbuffer (eTargetDepth) du FBO:
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, rendertargets[eTargetDepth], 0);
puis d'autres buffers (genre les normales, la lumière ambiente, diffuse, speculaire, les ombres, etc)
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENTn_EXT, GL_TEXTURE_2D, rendertargets[eBufferID], 0);
puis tester si tout a foncmtionné:
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
ne pas oublier d'activer (lier) les objets ainsi créés avant leur utilisation
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
avant de passer au rendu (tout à fait classique), il faudra faire comprendre à OpenGL dans quel ordre viennent nos targets.
par exemple
glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT);
si nous ne voulons qu'utiliser par exemple notre eTargetNormal
ou alors comme ceci pour plus d'un render target
1 2
| GLenum buffers[] = { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT };
glDrawBuffers(2, buffers); |
dans notre cas, ca devrait donner ceci:
1 2 3 4 5 6 7 8
| GLenum buffers[RenderTargetCount];
buffers[eTargetColor] = GL_COLOR_ATTACHMENT0_EXT;
//buffers[eTargetDepth] = GL_DEPTH_ATTACHMENT_EXT;
for(u32 i = eTargetNormal; i < RenderTargetCount; i++)
{
buffers[i] = GL_COLOR_ATTACHMENT0_EXT + i;
}
glDrawBuffers(RenderTargetCount, buffers); |
pour reutiliser les textures, il faudra les activer et par exemple les rendre sur un simple quad la taille de votre fenêtre.
glBindTexture(GL_TEXTURE_2D, rendertarget[x]);
(ne pas oublier aussi de détruire ce que vous créez)
1 2
| glDeleteFramebuffersEXT(1, &fbo);
glDeleteTexture(RenderTargetCount, rendertarget); |
du côté GLSL, ou plus précisement dans le fragment shader, nous adressons les registres des différents targets comme avec gl_FragData[n], où n représente l'index dans les buffers définis ci-dessus et passés à l'API via glDrawBuffers(RenderTargetCount, buffers).
donc par exemple:
1 2 3 4 5
| gl_FragData[0] = color;
gl_FragData[1] = normal;
gl_FragData[2] = litDiff;
gl_FragData[3] = litAmb;
gl_FragData[4] = litSpec; |
voilà, en fait, c'est assez simple comme procédure. Bien sûr, il faudra ajouter du post-processing aux textures ainsi obtenues, mais l'essentiel y est.
(Ah oui, mon code est écrit comme ca, j'ai rien testé chez moi, donc ne comptez pas sur sa validité, il se peut qu'il y ait des erreurs. C'est une compilation de plusieurs autres tutoriaux sur ce sujet).
Ce qui m'étonne tout de même après coup, ce qu'il semble y avoir peu de monde ici à utiliser les render targets. M'enfin, en espérant que ce petit tuto vous aide, vous ici.
Partager