Renderbuffer object attachments
Renderbuffer objects were introduced to OpenGL after textures as a possible type of framebuffer attachments, so textures were the only attachments used in the good old days. Just like a texture image, a renderbuffer object is an actual buffer e.g. an array of bytes, integers, pixels or whatever. A renderbuffer object has the added advantage though that it stores its data in OpenGL's native rendering format making it optimized for off-screen rendering to a framebuffer.
Renderbuffer objects store all the render data directly into their buffer without any conversions to texture-specific formats, thus making them faster as a writeable storage medium. However, renderbuffer objects are generally write-only, thus you cannot read from them (like with texture-access). It is possible to read from them via glReadPixels() though that returns a specified area of pixels from the currently bound framebuffer, but not directly from the attachment itself.
Because their data is already in its native format they are quite fast when writing data or simply copying their data to other buffers. Operations like switching buffers are thus quite fast when using renderbuffer objects. The glfwSwapBuffersfunction we've been using at the end of each render iteration might as well be implemented with renderbuffer objects: we simply write to a renderbuffer image, and swap to the other one at the end. Renderbuffer objects are perfect for these kind of operations.
Creating a renderbuffer object looks similar to the framebuffer's code:
- GLuint rbo;
- glGenRenderbuffers(1, &rbo);
And similarly we want to bind the renderbuffer object so all subsequent renderbuffer operations affect the current rbo:
- glBindRenderbuffer(GL_RENDERBUFFER, rbo);
Since renderbuffer objects are generally write-only they are often used as depth and stencil attachments, since most of the time we don't really need to read values from the depth and stencil buffers but still care about depth and stencil testing. We need the depth and stencil values for testing, but don't need to sample these values so a renderbuffer object suits this perfectly. When we're not sampling from these buffers, a renderbuffer object is generally preferred since it's more optimized.
Creating a depth and stencil renderbuffer object is done by calling the glRenderbufferStorage function:
- glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 800, 600);
Creating a renderbuffer object is similar to texture objects, the difference being that this object is specifically designed to be used as an image, instead of a general purpose data buffer like a texture. Here we've chosen the GL_DEPTH24_STENCIL8as the internal format, which holds both the depth and stencil buffer with 24 and 8 bits respectively.
Last thing left to do is actually attach the renderbuffer object:
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);
Renderbuffer objects could provide some optimizations in your framebuffer projects, but it is important to realize when to use renderbuffer objects and when to use textures. The general rule is that if you never need to sample data from a specific buffer, it is wise to use a renderbuffer object for that specific buffer. If you need to someday sample data from a specific buffer like colors or depth values, you should use a texture attachment instead. Performance-wise it doesn't have an enormous impact though.
No comments:
Post a Comment