Browse Source

More intuitive framebuffer attachment mapping.

pull/7/head
Vladimír Vondruš 14 years ago
parent
commit
72d48ac3e7
  1. 22
      src/DefaultFramebuffer.cpp
  2. 29
      src/DefaultFramebuffer.h
  3. 28
      src/Framebuffer.cpp
  4. 31
      src/Framebuffer.h

22
src/DefaultFramebuffer.cpp

@ -27,15 +27,27 @@ DefaultFramebuffer defaultFramebuffer;
DefaultFramebuffer::DefaultFramebuffer() { _id = 0; } DefaultFramebuffer::DefaultFramebuffer() { _id = 0; }
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void DefaultFramebuffer::mapForDraw(std::initializer_list<DrawAttachment> attachments) { void DefaultFramebuffer::mapForDraw(std::initializer_list<std::pair<GLuint, DrawAttachment>> attachments) {
GLenum* _attachments = new GLenum[attachments.size()]; /* Max attachment location */
for(auto it = attachments.begin(); it != attachments.end(); ++it) std::size_t max = 0;
_attachments[it-attachments.begin()] = static_cast<GLenum>(*it); for(const auto& attachment: attachments)
if(attachment.first > max) max = attachment.first;
/* Create linear array from associative */
GLenum* _attachments = new GLenum[max+1];
std::fill_n(_attachments, max, GL_NONE);
for(const auto& attachment: attachments)
_attachments[attachment.first] = static_cast<GLenum>(attachment.second);
bindInternal(drawTarget); bindInternal(drawTarget);
glDrawBuffers(attachments.size(), _attachments); glDrawBuffers(max+1, _attachments);
delete[] _attachments; delete[] _attachments;
} }
void DefaultFramebuffer::mapForDraw(DrawAttachment attachment) {
bindInternal(drawTarget);
glDrawBuffer(static_cast<GLenum>(attachment));
}
#endif #endif
void DefaultFramebuffer::mapForRead(ReadAttachment attachment) { void DefaultFramebuffer::mapForRead(ReadAttachment attachment) {

29
src/DefaultFramebuffer.h

@ -168,21 +168,38 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
/** /**
* @brief Map given attachments for drawing * @brief Map shader outputs to buffer attachment
* @param attachments Attachments. If any value is
* @ref DrawAttachment "Attachment::None", given output is not
* used.
* *
* @p attachments is list of shader outputs mapped to framebuffer
* buffer attachments. Shader outputs which are not listed are not
* used, you can achieve the same by passing @ref DrawAttachment "DrawAttachment::None"
* as attachment. Example usage:
* @code
* framebuffer.mapForDraw({{MyShader::ColorOutput, DefaultFramebuffer::DrawAttachment::BackLeft},
* {MyShader::NormalOutput, DefaultFramebuffer::DrawAttachment::None}});
* @endcode
* @see mapForRead(), @fn_gl{BindFramebuffer}, @fn_gl{DrawBuffers} * @see mapForRead(), @fn_gl{BindFramebuffer}, @fn_gl{DrawBuffers}
* @requires_gles30 Draw attachments for default framebuffer are * @requires_gles30 Draw attachments for default framebuffer are
* available only in OpenGL ES 3.0. * available only in OpenGL ES 3.0.
*/ */
void mapForDraw(std::initializer_list<DrawAttachment> attachments); void mapForDraw(std::initializer_list<std::pair<GLuint, DrawAttachment>> attachments);
/**
* @brief Map shader output to buffer attachment
* @param attachment Buffer attachment
*
* Similar to above function, can be used in cases when shader has
* only one (unnamed) output.
* @see mapForRead(), @fn_gl{BindFramebuffer}, @fn_gl{DrawBuffer}
* @requires_gles30 Draw attachments for default framebuffer are
* available only in OpenGL ES 3.0.
*/
void mapForDraw(DrawAttachment attachment);
#endif #endif
/** /**
* @brief Map given attachment for reading * @brief Map given attachment for reading
* @param attachment Attachment * @param attachment Buffer attachment
* *
* @see mapForDraw(), @fn_gl{BindFramebuffer}, @fn_gl{ReadBuffer} * @see mapForDraw(), @fn_gl{BindFramebuffer}, @fn_gl{ReadBuffer}
* @requires_gles30 %Extension @es_extension2{NV,read_buffer,GL_NV_read_buffer} * @requires_gles30 %Extension @es_extension2{NV,read_buffer,GL_NV_read_buffer}

28
src/Framebuffer.cpp

@ -42,17 +42,29 @@ Framebuffer::~Framebuffer() {
glDeleteFramebuffers(1, &_id); glDeleteFramebuffers(1, &_id);
} }
void Framebuffer::mapForDraw(std::initializer_list<std::int8_t> colorAttachments) { void Framebuffer::mapForDraw(std::initializer_list<std::pair<GLuint, std::int8_t>> attachments) {
GLenum* attachments = new GLenum[colorAttachments.size()]; /* Max attachment location */
for(auto it = colorAttachments.begin(); it != colorAttachments.end(); ++it) std::size_t max = 0;
attachments[it-colorAttachments.begin()] = *it + GL_COLOR_ATTACHMENT0; for(const auto& attachment: attachments)
if(attachment.first > max) max = attachment.first;
bindInternal(Target::Draw);
/* Create linear array from associative */
GLenum* _attachments = new GLenum[max+1];
std::fill_n(_attachments, max, GL_NONE);
for(const auto& attachment: attachments)
_attachments[attachment.first] = attachment.second < 0 ? GL_NONE : GL_COLOR_ATTACHMENT0 + attachment.second;
bindInternal(drawTarget);
/** @todo Re-enable when extension wrangler is available for ES2 */ /** @todo Re-enable when extension wrangler is available for ES2 */
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
glDrawBuffers(colorAttachments.size(), attachments); glDrawBuffers(max+1, _attachments);
#endif #endif
delete[] attachments; delete[] _attachments;
}
void Framebuffer::mapForDraw(std::int8_t attachment) {
bindInternal(drawTarget);
glDrawBuffer(static_cast<GLenum>(attachment));
} }
void Framebuffer::mapForRead(std::uint8_t colorAttachment) { void Framebuffer::mapForRead(std::uint8_t colorAttachment) {

31
src/Framebuffer.h

@ -49,23 +49,40 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer {
~Framebuffer(); ~Framebuffer();
/** /**
* @brief Map given color attachments of current framebuffer for drawing * @brief Map shader output to color attachment
* @param colorAttachments Color attachment IDs. If any value is -1,
* given output is not used.
* *
* @p attachments is list of shader outputs mapped to framebuffer
* color attachment IDs. Shader outputs which are not listed are not
* used, you can achieve the same by passing `-1` as color attachment
* ID. Example usage:
* @code
* framebuffer.mapForDraw({{MyShader::ColorOutput, 0},
* {MyShader::NormalOutput, 1}});
* @endcode
* @see mapForRead(), @fn_gl{BindFramebuffer}, @fn_gl{DrawBuffers} * @see mapForRead(), @fn_gl{BindFramebuffer}, @fn_gl{DrawBuffers}
* @requires_gles30 %Extension @es_extension2{NV,draw_buffers,GL_NV_draw_buffers} * @requires_gles30 %Extension @es_extension2{NV,draw_buffers,GL_NV_draw_buffers}
*/ */
void mapForDraw(std::initializer_list<std::int8_t> colorAttachments); void mapForDraw(std::initializer_list<std::pair<GLuint, std::int8_t>> attachments);
/** /**
* @brief Map given color attachment of current framebuffer for reading * @brief Map shader output to color attachment
* @param colorAttachment Color attachment ID * @param attachment Color attachment ID
*
* Similar to above function, can be used in cases when shader has
* only one (unnamed) output.
* @see mapForRead(), @fn_gl{BindFramebuffer}, @fn_gl{DrawBuffer}
* @requires_gles30 %Extension @es_extension2{NV,draw_buffers,GL_NV_draw_buffers}
*/
void mapForDraw(std::int8_t attachment);
/**
* @brief Map given color attachment for reading
* @param attachment Color attachment ID
* *
* @see mapForDraw(), @fn_gl{BindFramebuffer}, @fn_gl{ReadBuffer} * @see mapForDraw(), @fn_gl{BindFramebuffer}, @fn_gl{ReadBuffer}
* @requires_gles30 %Extension @es_extension2{NV,read_buffer,GL_NV_read_buffer} * @requires_gles30 %Extension @es_extension2{NV,read_buffer,GL_NV_read_buffer}
*/ */
void mapForRead(std::uint8_t colorAttachment); void mapForRead(std::uint8_t attachment);
/** /**
* @brief Attachment for depth/stencil part of fragment shader output * @brief Attachment for depth/stencil part of fragment shader output

Loading…
Cancel
Save