Browse Source

GL: improve Framebuffer usage docs.

findsdl-include-root
Vladimír Vondruš 7 years ago
parent
commit
dbb4cb39a1
  1. 80
      doc/snippets/MagnumGL.cpp
  2. 55
      src/Magnum/GL/Framebuffer.h
  3. 4
      src/Magnum/GL/Renderbuffer.h

80
doc/snippets/MagnumGL.cpp

@ -41,6 +41,7 @@
#include "Magnum/GL/PixelFormat.h" #include "Magnum/GL/PixelFormat.h"
#include "Magnum/GL/Renderer.h" #include "Magnum/GL/Renderer.h"
#include "Magnum/GL/Renderbuffer.h" #include "Magnum/GL/Renderbuffer.h"
#include "Magnum/GL/RenderbufferFormat.h"
#include "Magnum/GL/Shader.h" #include "Magnum/GL/Shader.h"
#include "Magnum/GL/Texture.h" #include "Magnum/GL/Texture.h"
#include "Magnum/GL/TextureFormat.h" #include "Magnum/GL/TextureFormat.h"
@ -893,21 +894,71 @@ GL::defaultFramebuffer.mapForDraw({
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
{ {
/* [Framebuffer-usage-attach] */ struct MyShader {
GL::Framebuffer framebuffer{GL::defaultFramebuffer.viewport()}; void bindTexture(GL::Texture2D&) {}
GL::Texture2D color, normal; } myShader;
Vector2i size;
/* [Framebuffer-usage] */
GL::Texture2D color;
GL::Renderbuffer depthStencil; 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{0}, color, 0);
framebuffer.attachTexture(GL::Framebuffer::ColorAttachment{1}, normal, 0);
framebuffer.attachRenderbuffer( framebuffer.attachRenderbuffer(
GL::Framebuffer::BufferAttachment::DepthStencil, depthStencil); 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 #endif
#ifndef MAGNUM_TARGET_GLES2
{ {
struct MyShader { struct MyShader {
enum: UnsignedInt { enum: UnsignedInt {
@ -915,12 +966,20 @@ struct MyShader {
NormalOutput = 1 NormalOutput = 1
}; };
}; };
GL::Framebuffer framebuffer{{}}; /* [Framebuffer-usage-deferred] */
/* [Framebuffer-usage-map] */ 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({ framebuffer.mapForDraw({
{MyShader::ColorOutput, GL::Framebuffer::ColorAttachment(0)}, {MyShader::ColorOutput, GL::Framebuffer::ColorAttachment(0)},
{MyShader::NormalOutput, GL::Framebuffer::ColorAttachment(1)}}); {MyShader::NormalOutput, GL::Framebuffer::ColorAttachment(1)}});
/* [Framebuffer-usage-map] */ /* [Framebuffer-usage-deferred] */
/* [Framebuffer-mapForDraw] */ /* [Framebuffer-mapForDraw] */
framebuffer.mapForDraw({ framebuffer.mapForDraw({
@ -928,6 +987,7 @@ framebuffer.mapForDraw({
{MyShader::NormalOutput, GL::Framebuffer::DrawAttachment::None}}); {MyShader::NormalOutput, GL::Framebuffer::DrawAttachment::None}});
/* [Framebuffer-mapForDraw] */ /* [Framebuffer-mapForDraw] */
} }
#endif
{ {
/* [Mesh-nonindexed] */ /* [Mesh-nonindexed] */

55
src/Magnum/GL/Framebuffer.h

@ -44,30 +44,51 @@ namespace Magnum { namespace GL {
@brief Framebuffer @brief Framebuffer
Unlike @ref DefaultFramebuffer, which is used for on-screen rendering, this Unlike @ref DefaultFramebuffer, which is used for on-screen rendering, this
class is used for off-screen rendering, usable either in windowless class is used for off-screen rendering, usable in windowless applications, for
applications, texture generation or for various post-processing effects. 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 A basic setup for rendering to a texture of a desired `size` might look like
introduction. Imagine you have shader with multiple outputs (e.g. for deferred below. Apart from a color attachment, there's also a depth/stencil attachment
rendering). You want to render them off-screen to textures and then use the in order to make depth test work properly. If you render 2D or don't need to
textures for actual on-screen rendering. First you need to create the use a depth/stencil test, you can have just a color attachment. It's possible
framebuffer with the same viewport as default framebuffer and attach textures to attach either a @ref Texture or a @ref Renderbuffer --- a texture allows
and renderbuffers to desired outputs: 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 Rendering then usually consists of switching between different framebuffers
framebuffer: 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 @section GL-Framebuffer-usage-multisample Multisampled rendering
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:
@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 @section GL-Framebuffer-performance-optimizations Performance optimizations

4
src/Magnum/GL/Renderbuffer.h

@ -42,8 +42,8 @@ namespace Implementation { struct FramebufferState; }
/** /**
@brief Renderbuffer @brief Renderbuffer
Attachable to framebuffer as render target, see @ref Framebuffer documentation Attachable to a framebuffer as render target, see the @ref Framebuffer class
for more information. for a detailed usage example.
@section GL-Renderbuffer-performance-optimizations Performance optimizations @section GL-Renderbuffer-performance-optimizations Performance optimizations

Loading…
Cancel
Save