From 70153a4e27eeebc7e0a91de122f45eff6296cb71 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Thu, 9 Aug 2012 21:07:43 +0300 Subject: [PATCH] Add support for cube map textures --- source/framebuffer.cpp | 26 ++++++++++++-- source/framebuffer.h | 5 ++- source/texturecube.cpp | 82 ++++++++++++++++++++++++++++++++++++++++++ source/texturecube.h | 70 ++++++++++++++++++++++++++++++++++++ 4 files changed, 180 insertions(+), 3 deletions(-) create mode 100644 source/texturecube.cpp create mode 100644 source/texturecube.h diff --git a/source/framebuffer.cpp b/source/framebuffer.cpp index 6877f480..8806ea6c 100644 --- a/source/framebuffer.cpp +++ b/source/framebuffer.cpp @@ -60,6 +60,11 @@ void Framebuffer::update_attachment(unsigned mask) const static_cast(attch.tex)->allocate(attch.level); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attch.attachment, attch.type, attch.tex->get_id(), attch.level); } + else if(attch.type==GL_TEXTURE_CUBE_MAP) + { + static_cast(attch.tex)->allocate(attch.level); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attch.attachment, attch.cube_face, attch.tex->get_id(), attch.level); + } else glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, attch.attachment, 0, 0); } @@ -90,6 +95,11 @@ void Framebuffer::check_size() width = tex->get_width(); height = tex->get_height(); } + else if(i->type==GL_TEXTURE_CUBE_MAP) + { + width = static_cast(i->tex)->get_size(); + height = width; + } if(current()==this) glViewport(0, 0, width, height); break; @@ -113,7 +123,18 @@ void Framebuffer::attach(FramebufferAttachment attch, Texture2D &tex, unsigned l throw invalid_operation("Framebuffer::attach"); unsigned i = get_attachment_index(attch); - attachments[i].set(tex, level); + attachments[i].set(tex, 0, level); + update_attachment(1< #include "bindable.h" #include "gl.h" +#include "texturecube.h" namespace Msp { namespace GL { @@ -80,10 +81,11 @@ private: Texture *tex; }; unsigned level; + GLenum cube_face; Attachment(FramebufferAttachment); void set(Renderbuffer &); - void set(Texture &, unsigned); + void set(Texture &, GLenum, unsigned); void clear(); }; @@ -107,6 +109,7 @@ private: public: void attach(FramebufferAttachment attch, Renderbuffer &rbuf); void attach(FramebufferAttachment attch, Texture2D &tex, unsigned level = 0); + void attach(FramebufferAttachment attch, TextureCube &tex, TextureCubeFace face, unsigned level = 0); void detach(FramebufferAttachment attch); /** diff --git a/source/texturecube.cpp b/source/texturecube.cpp new file mode 100644 index 00000000..4a613a37 --- /dev/null +++ b/source/texturecube.cpp @@ -0,0 +1,82 @@ +#include "bindable.h" +#include "error.h" +#include "extension.h" +#include "texturecube.h" + +using namespace std; + +namespace { + +// An array to facilitate looping through the cube faces +Msp::GL::TextureCubeFace faces[6] = +{ + Msp::GL::POSITIVE_X, + Msp::GL::NEGATIVE_X, + Msp::GL::POSITIVE_Y, + Msp::GL::NEGATIVE_Y, + Msp::GL::POSITIVE_Z, + Msp::GL::NEGATIVE_Z +}; + +} + + +namespace Msp { +namespace GL { + +TextureCube::TextureCube(): + Texture(GL_TEXTURE_CUBE_MAP), + size(0), + allocated(0) +{ + static RequireVersion _ver(1, 3); +} + +void TextureCube::storage(PixelFormat fmt, unsigned sz) +{ + if(size>0) + throw invalid_operation("TextureCube::storage"); + if(sz==0) + throw invalid_argument("TextureCube::storage"); + + ifmt = fmt; + size = sz; +} + +void TextureCube::allocate(unsigned level) +{ + if(allocated&(1<>=1, ++level) ; + allocated |= (1<>level; +} + +} // namespace GL +} // namespace Msp diff --git a/source/texturecube.h b/source/texturecube.h new file mode 100644 index 00000000..c8e18a11 --- /dev/null +++ b/source/texturecube.h @@ -0,0 +1,70 @@ +#ifndef MSP_GL_TEXTURECUBE_H_ +#define MSP_GL_TEXTURECUBE_H_ + +#include "datatype.h" +#include "pixelformat.h" +#include "texture.h" + +namespace Msp { +namespace GL { + +enum TextureCubeFace +{ + POSITIVE_X = GL_TEXTURE_CUBE_MAP_POSITIVE_X, + NEGATIVE_X = GL_TEXTURE_CUBE_MAP_NEGATIVE_X, + POSITIVE_Y = GL_TEXTURE_CUBE_MAP_POSITIVE_Y, + NEGATIVE_Y = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, + POSITIVE_Z = GL_TEXTURE_CUBE_MAP_POSITIVE_Z, + NEGATIVE_Z = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z +}; + +/** +Cube map texture, consisting of six square faces. All of the faces must be of +the same size. A cube map texture is addressed by three-dimensional texture +coordinates. The face is first selected according to the largest coordinate, +and the remaining two coordinates are used to sample the face image. + +All faces of a cube map texture must be allocated for it to be usable. + +Requires OpenGL version 1.3. +*/ +class TextureCube: public Texture +{ +private: + PixelFormat ifmt; + unsigned size; + unsigned allocated; + +public: + TextureCube(); + + /** Defines storage structure for the texture. Must be called before an + image can be uploaded. Once storage is defined, it can't be changed. */ + void storage(PixelFormat fmt, unsigned size); + + /** Allocates storage for the cube faces. The contents are initially + undefined. If storage has already been allocated, does nothing. */ + void allocate(unsigned level); + + /** Uploads image data to a face. Storage must be defined beforehand. The + image data must have dimensions and format compatible with the defined + storage. */ + void image(TextureCubeFace face, unsigned level, + PixelFormat fmt, DataType type, const void *data); + + /** Updates a rectangular region of a face. Storage must be defined and + allocated beforehand. The update region must be fully inside the texture. + The data format must be compatible with the defined storage. */ + void sub_image(TextureCubeFace face, unsigned level, + int x, int y, unsigned w, unsigned h, + PixelFormat fmt, DataType type, const void *data); + + unsigned get_size() const { return size; } +private: + unsigned get_level_size(unsigned); +}; + +} // namespace GL +} // namespace Msp + +#endif -- 2.45.2