Skip to content

Commit

Permalink
GL: improve Framebuffer usage docs.
Browse files Browse the repository at this point in the history
  • Loading branch information
mosra committed Oct 7, 2019
1 parent 3f9c541 commit dbb4cb3
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 29 deletions.
80 changes: 70 additions & 10 deletions doc/snippets/MagnumGL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
#include "Magnum/GL/PixelFormat.h"
#include "Magnum/GL/Renderer.h"
#include "Magnum/GL/Renderbuffer.h"
#include "Magnum/GL/RenderbufferFormat.h"
#include "Magnum/GL/Shader.h"
#include "Magnum/GL/Texture.h"
#include "Magnum/GL/TextureFormat.h"
Expand Down Expand Up @@ -893,41 +894,100 @@ GL::defaultFramebuffer.mapForDraw({

#ifndef MAGNUM_TARGET_GLES2
{
/* [Framebuffer-usage-attach] */
GL::Framebuffer framebuffer{GL::defaultFramebuffer.viewport()};
GL::Texture2D color, normal;
struct MyShader {
void bindTexture(GL::Texture2D&) {}
} myShader;
Vector2i size;
/* [Framebuffer-usage] */
GL::Texture2D color;
GL::Renderbuffer depthStencil;
color.setStorage(1, GL::TextureFormat::RGBA8, size);
depthStencil.setStorage(GL::RenderbufferFormat::Depth24Stencil8, size);

// configure the textures and allocate texture memory...

GL::Framebuffer framebuffer{{{}, size}};
framebuffer.attachTexture(GL::Framebuffer::ColorAttachment{0}, color, 0);
framebuffer.attachTexture(GL::Framebuffer::ColorAttachment{1}, normal, 0);
framebuffer.attachRenderbuffer(
GL::Framebuffer::BufferAttachment::DepthStencil, depthStencil);
/* [Framebuffer-usage-attach] */
/* [Framebuffer-usage] */

/* [Framebuffer-usage-rendering] */
framebuffer
.clear(GL::FramebufferClear::Color|GL::FramebufferClear::Depth)
.bind();

// draw to this framebuffer ...

/* Switch back to the default framebuffer */
GL::defaultFramebuffer
.clear(GL::FramebufferClear::Color|GL::FramebufferClear::Depth)
.bind();

// use the rendered texture in a shader ...
myShader.bindTexture(color);
/* [Framebuffer-usage-rendering] */
}
#endif

#ifndef MAGNUM_TARGET_GLES2
{
/* [Framebuffer-usage-multisample] */
Vector2i size = GL::defaultFramebuffer.viewport().size();

/* 8x MSAA */
GL::Renderbuffer color, depthStencil;
color.setStorageMultisample(8, GL::RenderbufferFormat::RGBA8, size);
depthStencil.setStorageMultisample(8,
GL::RenderbufferFormat::Depth24Stencil8, size);

GL::Framebuffer framebuffer{{{}, size}};
framebuffer.attachRenderbuffer(GL::Framebuffer::ColorAttachment{0}, color);
framebuffer.attachRenderbuffer(
GL::Framebuffer::BufferAttachment::DepthStencil, depthStencil);

framebuffer.clear(GL::FramebufferClear::Color|GL::FramebufferClear::Depth)
.bind();

// draw to the multisampled framebuffer ...

/* Resolve the color output to a single-sampled default framebuffer */
GL::defaultFramebuffer.clear(GL::FramebufferClear::Color)
.bind();
GL::Framebuffer::blit(framebuffer, GL::defaultFramebuffer,
{{}, size}, GL::FramebufferBlit::Color);
/* [Framebuffer-usage-multisample] */
}
#endif

#ifndef MAGNUM_TARGET_GLES2
{
struct MyShader {
enum: UnsignedInt {
ColorOutput = 0,
NormalOutput = 1
};
};
GL::Framebuffer framebuffer{{}};
/* [Framebuffer-usage-map] */
/* [Framebuffer-usage-deferred] */
GL::Framebuffer framebuffer{GL::defaultFramebuffer.viewport()};
GL::Texture2D color, normal;
GL::Renderbuffer depthStencil;
// setStorage() ...

framebuffer.attachTexture(GL::Framebuffer::ColorAttachment{0}, color, 0);
framebuffer.attachTexture(GL::Framebuffer::ColorAttachment{1}, normal, 0);
framebuffer.attachRenderbuffer(
GL::Framebuffer::BufferAttachment::DepthStencil, depthStencil);
framebuffer.mapForDraw({
{MyShader::ColorOutput, GL::Framebuffer::ColorAttachment(0)},
{MyShader::NormalOutput, GL::Framebuffer::ColorAttachment(1)}});
/* [Framebuffer-usage-map] */
/* [Framebuffer-usage-deferred] */

/* [Framebuffer-mapForDraw] */
framebuffer.mapForDraw({
{MyShader::ColorOutput, GL::Framebuffer::ColorAttachment(0)},
{MyShader::NormalOutput, GL::Framebuffer::DrawAttachment::None}});
/* [Framebuffer-mapForDraw] */
}
#endif

{
/* [Mesh-nonindexed] */
Expand Down
55 changes: 38 additions & 17 deletions src/Magnum/GL/Framebuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,30 +44,51 @@ namespace Magnum { namespace GL {
@brief Framebuffer
Unlike @ref DefaultFramebuffer, which is used for on-screen rendering, this
class is used for off-screen rendering, usable either in windowless
applications, texture generation or for various post-processing effects.
class is used for off-screen rendering, usable in windowless applications, for
texture generation or for various post-processing effects.
@section GL-Framebuffer-usage Example usage
@section GL-Framebuffer-usage Basic usage
See @ref GL-DefaultFramebuffer-usage "DefaultFramebuffer documentation" for
introduction. Imagine you have shader with multiple outputs (e.g. for deferred
rendering). You want to render them off-screen to textures and then use the
textures for actual on-screen rendering. First you need to create the
framebuffer with the same viewport as default framebuffer and attach textures
and renderbuffers to desired outputs:
A basic setup for rendering to a texture of a desired `size` might look like
below. Apart from a color attachment, there's also a depth/stencil attachment
in order to make depth test work properly. If you render 2D or don't need to
use a depth/stencil test, you can have just a color attachment. It's possible
to attach either a @ref Texture or a @ref Renderbuffer --- a texture allows
you to read the rendered output later from a shader, while a renderbuffer
allows you to only @ref read() or @ref blit() from it. In modern desktop OpenGL
there's not much reason to use @ref Renderbuffer anymore, however in OpenGL ES
and WebGL due to various texture format restrictions, renderbuffers are still
the more flexible option if you don't need to use the result in a shader.
@snippet MagnumGL.cpp Framebuffer-usage-attach
@snippet MagnumGL.cpp Framebuffer-usage
Then you need to map outputs of your shader to color attachments in the
framebuffer:
Rendering then usually consists of switching between different framebuffers
using @ref bind() and reusing the rendered texture in subsequent draws:
@snippet MagnumGL.cpp Framebuffer-usage-map
@snippet MagnumGL.cpp Framebuffer-usage-rendering
The actual @ref Platform::Sdl2Application::drawEvent() "drawEvent()" might look
like this. First you clear all buffers you need, perform drawing to off-screen
framebuffer, then bind the default and render the textures on screen:
@section GL-Framebuffer-usage-multisample Multisampled rendering
@snippet MagnumGL-framebuffer.cpp Framebuffer-usage-draw
Another use case for custom framebuffers is multisampled rendering --- as
you're not always allowed to control the MSAA setting on a default framebuffer,
or you might want your rendered texture to be multisampled as well:
@snippet MagnumGL.cpp Framebuffer-usage-multisample
Here @ref Renderbuffer gets used for the color attachment as well. While it's
possible to achieve the same with a @ref MultisampleTexture2D, support for it
is rather sparse on OpenGL ES and completely nonexistent on WebGL or
macOS / iOS.
@section GL-Framebuffer-usage-multiple-output Multiple fragment shader outputs
In a deferred rendering setup for example, a shader usually has more than one
output. That's finally where non-zero @ref ColorAttachment and @ref mapForDraw()
gets used. In builtin shaders this is also how the
@ref Shaders::Flat::ColorOutput / @ref Shaders::Flat::ObjectIdOutput etc. get
used:
@snippet MagnumGL.cpp Framebuffer-usage-deferred
@section GL-Framebuffer-performance-optimizations Performance optimizations
Expand Down
4 changes: 2 additions & 2 deletions src/Magnum/GL/Renderbuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ namespace Implementation { struct FramebufferState; }
/**
@brief Renderbuffer
Attachable to framebuffer as render target, see @ref Framebuffer documentation
for more information.
Attachable to a framebuffer as render target, see the @ref Framebuffer class
for a detailed usage example.
@section GL-Renderbuffer-performance-optimizations Performance optimizations
Expand Down

0 comments on commit dbb4cb3

Please sign in to comment.