OpenGL ES Render to Texture
У меня возникли проблемы с поиском простого кода для рендеринга сцены в текстуру в OpenGL ES (особенно для iPhone, если это имеет значение). Мне интересно знать следующее:
- Как вы визуализируете сцену текстуры в OpenGL ES?
- Какие параметры вы должны использовать для создания текстуры, которая может быть объектом рендеринга в OpenGL ES?
- Есть ли какие-либо последствия с применением этой текстурированной текстуры к другим примитивам?
Ответы
Ответ 1
Вот как я это делаю.
Я определяю переменную текстуры (я использую класс Apple Texture2D
, но вы можете использовать идентификатор текстуры OpenGL, если хотите) и буфер кадра:
Texture2d * texture;
GLuint textureFrameBuffer;
Затем в какой-то момент я создаю текстуру, буфер кадров и присоединяю renderbuffer. Это вам нужно сделать только один раз:
texture = [[Texture2D alloc] initWithData:0
pixelFormat:kTexture2DPixelFormat_RGB888
pixelsWide:32
pixelsHigh:32
contentSize:CGSizeMake(width, height)];
// create framebuffer
glGenFramebuffersOES(1, &textureFrameBuffer);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, textureFrameBuffer);
// attach renderbuffer
glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, texture.name, 0);
// unbind frame buffer
glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
Каждый раз, когда я хочу отображать текстуру, я делаю:
glBindFramebufferOES(GL_FRAMEBUFFER_OES, textureFrameBuffer);
...
// GL commands
...
glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
О вашем вопросе 3, что он, вы можете использовать текстуру, как будто это какая-либо другая текстура.
Ответ 2
Чтобы сделать сцену текстурой, вы должны использовать фреймбуфер, связанный с текстурой. Вот способ, который я создал для упрощения:
void glGenTextureFromFramebuffer(GLuint *t, GLuint *f, GLsizei w, GLsizei h)
{
glGenFramebuffers(1, f);
glGenTextures(1, t);
glBindFramebuffer(GL_FRAMEBUFFER, *f);
glBindTexture(GL_TEXTURE_2D, *t);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *t, 0);
GLuint depthbuffer;
glGenRenderbuffers(1, &depthbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, depthbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, w, h);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthbuffer);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if(status != GL_FRAMEBUFFER_COMPLETE)
NSLog(@"Framebuffer status: %x", (int)status);
}
Вы можете легко создать буфер кадра и текстуру:
GLuint _texture, _framebuffer;
GLsizei w,h;
float scale = [UIScreen mainScreen].scale;
w = self.view.bounds.size.width * scale;
h = self.view.bounds.size.height * scale;
glGenTextureFromFramebuffer(&_texture, &_framebuffer, w, h);
В дальнейшем вы можете использовать _framebuffer для рендеринга сцены в _texture в методе рисования:
glBindFramebuffer(GL_FRAMEBUFFER, _framebuffer);
//draw here the content you want in the texture
//_texture is now a texture with the drawn content
//bind the base framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, 0);
//or if you use GLKit
[view bindDrawable];
//draw normaly
Теперь вы можете делать то, что хотите, с текстурой. Если вы хотите сделать некоторую пост-обработку (размытие, цветение, тень и т.д.), Вы можете!