#include #include #include #include "texture.hh" using namespace gl; static unsigned ilog2(unsigned in) { unsigned ret = 0u; while (in >>= 1) ++ret; return ret; } Framebuffer::Framebuffer() : _fbID(0) { glGenFramebuffers(1, &_fbID); } Framebuffer::~Framebuffer() { glDeleteFramebuffers(1, &_fbID); } Framebuffer::Framebuffer(Framebuffer && move) : _fbID(move._fbID) { move._fbID = 0; } Framebuffer& Framebuffer::operator=(Framebuffer && move) { glDeleteFramebuffers(1, &_fbID); _fbID = move._fbID; move._fbID = 0; return *this; } void Framebuffer::bind() const { glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _fbID); } void Framebuffer::attachTexture(GLenum textarget, GLuint texID) { glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, textarget, texID, 0); } TextureCubeMap::TextureCubeMap(unsigned size) : _texID(0) { glGenTextures(1, &_texID); glBindTexture(GL_TEXTURE_CUBE_MAP, _texID); if(SDL_GL_ExtensionSupported("GL_ARB_texture_storage")) glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_DEPTH_COMPONENT24, size, size); else { std::printf("Warning: extension GL_ARB_texture_storage not supported!\n"); for (unsigned i = 0;i < 6;++i) { GLenum const face[6] = {GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z}; glTexImage2D(face[i], 0, static_cast(GL_DEPTH_COMPONENT16), size, size, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, NULL); } } glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, 0); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, static_cast(GL_LINEAR)); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, static_cast(GL_LINEAR)); } TextureCubeMap::~TextureCubeMap() { glDeleteTextures(1, &_texID); } TextureCubeMap::TextureCubeMap(TextureCubeMap && move) : _texID(move._texID) { move._texID = 0; } TextureCubeMap& TextureCubeMap::operator=(TextureCubeMap && move) { glDeleteTextures(1, &_texID); _texID = move._texID; move._texID = 0; return *this; } void TextureCubeMap::bind() const { glBindTexture(GL_TEXTURE_CUBE_MAP, _texID); } Texture2D::Texture2D(unsigned width, unsigned height) : _texID(0) { _glCreate(width, height); } Texture2D::Texture2D(std::string const& file) : _texID(0) { SDL_Surface *surf = IMG_Load(file.c_str()); if (!surf) throw SDLException(); try { _glCreate(surf->w, surf->h); try { assert(surf->format->format == SDL_PIXELFORMAT_RGB24); // TODO: Proper support of many formats if (SDL_MUSTLOCK(surf)) SDL_LockSurface(surf); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, surf->w, surf->h, GL_RGB, GL_UNSIGNED_BYTE, surf->pixels); glGenerateMipmap(GL_TEXTURE_2D); } catch(...) { glDeleteTextures(1, &_texID); throw; } } catch(...) { SDL_FreeSurface(surf); throw; } SDL_FreeSurface(surf); } Texture2D::Texture2D(SDL_Surface *surface) : _texID(0) { if(surface->format->Amask == 0) _glCreate(surface->w, surface->h); else _glCreate(surface->w, surface->h, true); try { SDL_Surface *surf; if((surface->format->format != SDL_PIXELFORMAT_RGB24) && (surface->format->format != SDL_PIXELFORMAT_RGBA8888)) { if(surface->format->Amask == 0) { surf = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_RGB24, 0); } else { surf = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_ABGR8888, 0); } if(!surf) throw SDLException{}; } else { surf = surface; } if (SDL_MUSTLOCK(surf)) SDL_LockSurface(surf); try { if(surface->format->Amask == 0) glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, surf->w, surf->h, GL_RGB, GL_UNSIGNED_BYTE, surf->pixels); else glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, surf->w, surf->h, GL_RGBA, GL_UNSIGNED_BYTE, surf->pixels); glGenerateMipmap(GL_TEXTURE_2D); } catch(...) { if (surf != surface) SDL_FreeSurface(surf); throw; } SDL_FreeSurface(surf); } catch(...) { glDeleteTextures(1, &_texID); throw; } } Texture2D::Texture2D(Texture2D&& move) : _texID(move._texID) { move._texID = 0; } Texture2D& Texture2D::operator=(Texture2D&& move) { glDeleteTextures(1, &_texID); _texID = move._texID; move._texID = 0; return *this; } Texture2D::~Texture2D() { glDeleteTextures(1, &_texID); } void Texture2D::bind() const { glBindTexture(GL_TEXTURE_2D, _texID); } void Texture2D::_glCreate(unsigned width, unsigned height, bool alpha) { glGenTextures(1, &_texID); try { glBindTexture(GL_TEXTURE_2D, _texID); unsigned logWidth = ilog2(width), logHeight = ilog2(height); unsigned levels = std::max(logWidth,logHeight)+1u; if(SDL_GL_ExtensionSupported("GL_ARB_texture_storage")) glTexStorage2D(GL_TEXTURE_2D, levels, alpha?GL_RGBA8:GL_RGB8, width, height); else { std::printf("Warning: extension GL_ARB_texture_storage not supported!\n"); for (unsigned i = 0u; i < levels; ++i) { glTexImage2D(GL_TEXTURE_2D, i, static_cast(alpha?GL_RGBA8:GL_RGB8), width, height, 0, alpha?GL_RGBA8:GL_RGB8, GL_UNSIGNED_BYTE, NULL); width = std::max(1u, (width / 2u)); height = std::max(1u, (height / 2u)); } } } catch(...) { glDeleteTextures(1, &_texID); } }