From 7d04b7d51145fd7d9389e7acafb19bcb179c0c0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 16 Dec 2012 23:26:36 +0100 Subject: [PATCH] Doc++ Basic framebuffer usage, mentioned framebuffer attachments in shader documentation. --- src/AbstractShaderProgram.h | 46 ++++++++++++++++++++-------------- src/DefaultFramebuffer.h | 32 +++++++++++++++++++++++- src/Framebuffer.h | 49 ++++++++++++++++++++++++++++++++++++- src/Mesh.h | 3 ++- src/Renderbuffer.h | 4 +-- 5 files changed, 111 insertions(+), 23 deletions(-) diff --git a/src/AbstractShaderProgram.h b/src/AbstractShaderProgram.h index 10d48afe0..ed646d079 100644 --- a/src/AbstractShaderProgram.h +++ b/src/AbstractShaderProgram.h @@ -57,22 +57,28 @@ typedef Attribute<0, Point3D> Position; typedef Attribute<1, Vector3> Normal; typedef Attribute<2, Vector2> TextureCoordinates; @endcode - @todoc Output attribute location (for bindFragmentDataLocationIndexed(), - referenced also from Framebuffer::mapDefaultForDraw() / Framebuffer::mapForDraw()) - + - **Output attribute locations**, if desired, for example: +@code +enum: GLuint { + ColorOutput = 0, + NormalOutput = 1 +}; +@endcode - **Layers for texture uniforms** to which the textures will be bound before rendering, for example: @code -static const GLint DiffuseTextureLayer = 0; -static const GLint SpecularTextureLayer = 1; +enum: GLint { + DiffuseTextureLayer = 0, + SpecularTextureLayer = 1 +}; @endcode - **Uniform locations** for setting uniform data (see below) (private - constants), for example: + variables), for example: @code -static const GLint TransformationUniform = 0; -static const GLint ProjectionUniform = 1; -static const GLint DiffuseTextureUniform = 2; -static const GLint SpecularTextureUniform = 3; +GLint TransformationUniform = 0, + ProjectionUniform = 1, + DiffuseTextureUniform = 2, + SpecularTextureUniform = 3; @endcode - **Constructor**, which attaches particular shaders, links the program and gets uniform locations, for example: @@ -112,12 +118,13 @@ layout(location = 0) in vec4 position; layout(location = 1) in vec3 normal; layout(location = 2) in vec2 textureCoordinates; @endcode + Similarly for ouput attributes, you can also specify blend equation color index for them (see Framebuffer::BlendFunction for more information about using color input index): @code layout(location = 0, index = 0) out vec4 color; -layout(location = 1, index = 1) out vec4 ambient; +layout(location = 1, index = 1) out vec3 normal; @endcode If you don't have the required extension, you can use functions @@ -131,8 +138,8 @@ bindAttributeLocation(Position::Location, "position"); bindAttributeLocation(Normal::Location, "normal"); bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates"); -bindFragmentDataLocationIndexed(0, 0, "color"); -bindFragmentDataLocationIndexed(1, 1, "ambient"); +bindFragmentDataLocationIndexed(ColorOutput, 0, "color"); +bindFragmentDataLocationIndexed(NormalOutput, 1, "normal"); // Link... @endcode @@ -198,11 +205,14 @@ setUniform(SpecularTextureUniform, SpecularTextureLayer); @section AbstractShaderProgram-rendering-workflow Rendering workflow -Basic workflow with %AbstractShaderProgram subclasses is to instance the class -and configuring attribute binding in meshes (see @ref Mesh-configuration "Mesh documentation" -for more information) at the beginning, then in draw event setting uniforms -and marking the shader for use, binding required textures to their respective -layers using AbstractTexture::bind(GLint) and calling Mesh::draw(). Example: +Basic workflow with %AbstractShaderProgram subclasses is: instance shader +class, configure attribute binding in meshes (see @ref Mesh-configuration "Mesh documentation" +for more information) and map shader outputs to framebuffer attachments if +needed (see @ref Framebuffer-usage "Framebuffer documentation" for more +information). In each draw event set uniforms, mark the shader for use, bind +specific framebuffer (if needed) and bind required textures to their +respective layers using AbstractTexture::bind(GLint). Then call Mesh::draw(). +Example: @code shader->setTransformation(transformation) ->setProjection(projection) diff --git a/src/DefaultFramebuffer.h b/src/DefaultFramebuffer.h index 7781b1e37..92a6486c7 100644 --- a/src/DefaultFramebuffer.h +++ b/src/DefaultFramebuffer.h @@ -26,7 +26,37 @@ namespace Magnum { /** @brief Default framebuffer -@see @ref defaultFramebuffer, Framebuffer +Default framebuffer, i.e. the actual screen surface. It is automatically +created when Context is created and it is available through global variable +@ref defaultFramebuffer. It is by default mapped to whole screen surface. + +@section DefaultFramebuffer-usage Usage + +When you are using only the default framebuffer, the usage is simple. You +must ensure that it is properly resized when application surface is resized, +i.e. you must pass the new size in your @ref Platform::GlutApplication::viewportEvent() "viewportEvent()" +implementation, for example: +@code +void viewportEvent(const Vector2i& size) { + defaultFramebuffer.setViewport({}, size); + + // ... +} +@endcode + +Next thing you probably want is to clear all used buffers before performing +any drawing in your @ref Platform::GlutApplication::drawEvent() "drawEvent()" +implementation, for example: +@code +void drawEvent() { + defaultFramebuffer.clear(AbstractFramebuffer::Clear::Color|AbstractFramebuffer::Clear::Depth); + + // ... +} +@endcode + +See Framebuffer documentation for more involved usage, usage of non-default or +multiple framebuffers. */ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer { friend class Context; diff --git a/src/Framebuffer.h b/src/Framebuffer.h index 062fed400..f755e9ef7 100644 --- a/src/Framebuffer.h +++ b/src/Framebuffer.h @@ -27,7 +27,54 @@ namespace Magnum { /** @brief %Framebuffer -@see DefaultFramebuffer +Unlike 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. + +@section Framebuffer-usage Example usage + +See @ref 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: +@code +Framebuffer framebuffer(defaultFramebuffer.viewportPosition(), defaultFramebuffer.viewportSize()); +Texture2D color, normal; +Renderbuffer depthStencil; + +// configure the textures and allocate texture memory... + +framebuffer.attachTexture2D(Framebuffer::Target::Draw, 0, &color); +framebuffer.attachTexture2D(Framebuffer::Target::Draw, 1, &normal); +framebuffer.attachRenderbuffer(Framebuffer::Target::Draw, Framebuffer::DepthStencilAttachment::DepthStencil, &depthStencil); +@endcode + +Then you need to map outputs of your shader to color attachments in the +framebuffer: +@code +framebuffer.mapForDraw({{MyShader::ColorOutput, 0}, + {MyShader::NormalOutput, 1}}); +@endcode + +The actual @ref Platform::GlutApplication::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: +@code +void drawEvent() { + defaultFramebuffer.clear(AbstractFramebuffer::Clear::Color) + framebuffer.clear(AbstractFramebuffer::Clear::Color|AbstractFramebuffer::Clear::Depth|AbstractFramebuffer::Clear::Stencil); + + framebuffer.bind(AbstractFramebuffer::Target::Draw); + // ... + + defaultFramebuffer.bind(AbstractFramebuffer::Target::Draw); + // ... +} +@endcode + @requires_gl30 %Extension @extension{EXT,framebuffer_object} */ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer { diff --git a/src/Mesh.h b/src/Mesh.h index 931e5140b..a7df32fe1 100644 --- a/src/Mesh.h +++ b/src/Mesh.h @@ -95,7 +95,8 @@ mesh->addVertexBuffer(buffer, MyShader::Color(Type::UsignedByte, MyShader::Color @section Mesh-drawing Rendering meshes -Basic workflow is to set up respective shader (see +Basic workflow is: bind specific framebuffer for drawing (if needed), set up +respective shader and bind required textures (see @ref AbstractShaderProgram-rendering-workflow "AbstractShaderProgram documentation" for more infromation) and call Mesh::draw(). diff --git a/src/Renderbuffer.h b/src/Renderbuffer.h index 7016db189..f96b1de2e 100644 --- a/src/Renderbuffer.h +++ b/src/Renderbuffer.h @@ -29,8 +29,8 @@ namespace Magnum { /** @brief %Renderbuffer -Attachable to Framebuffer as render target. - +Attachable to framebuffer as render target, see Framebuffer documentation +for more information. @requires_gl30 %Extension @extension{EXT,framebuffer_object} */ class Renderbuffer {