2009-06-21 12 views
32

Tôi đã gặp khó khăn trong việc tìm mã đơn giản để hiển thị cảnh cho kết cấu trong OpenGL ES (đặc biệt dành cho iPhone, nếu có vấn đề). Tôi quan tâm đến việc biết những điều sau đây:OpenGL ES Render to Texture

  1. Làm cách nào để hiển thị một cảnh cho kết cấu trong OpenGL ES?
  2. Bạn phải sử dụng thông số nào để tạo họa tiết có khả năng trở thành mục tiêu hiển thị trong OpenGL ES?
  3. Có bất kỳ tác động nào khi áp dụng texture này cho các nguyên thủy khác không?

Trả lời

43

Đây là cách tôi đang thực hiện.

tôi định nghĩa một biến kết cấu (tôi sử dụng lớp Texture2D của Apple, nhưng bạn có thể sử dụng một id kết cấu OpenGL nếu bạn muốn), và một bộ đệm khung:

Texture2d * texture; 
GLuint textureFrameBuffer; 

Sau đó, tại một số điểm, tôi có thể tạo các kết cấu , bộ đệm khung và đính kèm bộ dựng hình. Này, bạn chỉ cần làm điều đó một lần:

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

Mỗi lần tôi muốn trả cho các kết cấu, tôi làm:

glBindFramebufferOES(GL_FRAMEBUFFER_OES, textureFrameBuffer); 

... 
// GL commands 
... 

glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0); 

Về câu hỏi của bạn 3, đó là nó, bạn có thể sử dụng các kết cấu như nếu nó là bất kỳ kết cấu khác.

+0

Marco, bạn có biết bao nhiêu chi phí liên quan đến việc giữ bộ đệm khung và biểu tượng kết xuất cho mỗi kết cấu bạn cần hiển thị không? Tôi có một số kết cấu lớn mà ứng dụng của tôi cần phải đưa vào và tôi sắp xếp các kết cấu khác nhau vào một bộ đệm khung "phụ" duy nhất bằng cách sử dụng glFramebufferTexture2DOES. Sẽ giữ một framebuffer riêng biệt cho mỗi được tốt hơn? –

+0

Bạn có thể chỉnh sửa mã của mình để initWithData: ... cuộc gọi vừa khớp mà không cần cuộn? – nornagon

+0

Ok, đã chỉnh sửa, trông đẹp hơn ngay bây giờ. –

9

Để hiển thị cảnh thành kết cấu, bạn phải sử dụng bộ đệm khung được liên kết với họa tiết. Dưới đây là một phương pháp mà tôi tạo ra để đơn giản hóa nó:

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

Bạn có thể tạo bộ đệm khung và kết cấu một cách dễ dàng:

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

Bạn sau đó có thể sử dụng _framebuffer để render cảnh vào _texture trong bốc thăm của bạn phương pháp:

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 

Bây giờ bạn có thể làm những gì bạn muốn với kết cấu. Nếu bạn muốn làm một số xử lý bài (mờ, nở, bóng, vv ...) bạn có thể!

+0

Xin chào, bạn đã nhận được '_renderToTextureBuffer' từ đâu? –

+0

_renderToTextureBuffer là _framebuffer tôi sửa nó, sry – Anthony

+0

Thật tuyệt, đó là những gì tôi đang nghĩ. Bạn có điều này trong một ví dụ làm việc? Tôi sẽ cố gắng thêm mã này vào mã của tôi (một lần nữa), nhưng không chắc chắn về cách vẽ vào kết cấu '// vẽ ở đây nội dung bạn muốn trong texture' Tôi có thể làm điều đó với VBO và' glDrawArrays() 'không ? –