Files
openglplayground/texture.hh

205 lines
4.8 KiB
C++

#ifndef __OPENGLPLAYGROUND_TEXTURE_HH__
#define __OPENGLPLAYGROUND_TEXTURE_HH__
#include <string>
#include <cstdio>
#include <cassert>
#include <algorithm>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <glbinding/gl/gl.h>
#include "common.hh"
using namespace gl;
static unsigned ilog2(unsigned in)
{
unsigned ret = 0u;
while (in >>= 1) ++ret;
return ret;
}
class Framebuffer {
public:
Framebuffer() {
glGenFramebuffers(1, &_fbID);
}
~Framebuffer() {
glDeleteFramebuffers(1, &_fbID);
}
Framebuffer(Framebuffer const& copy) = delete;
Framebuffer& operator=(Framebuffer const& copy) = delete;
Framebuffer(Framebuffer && move) : _fbID(move._fbID) {
move._fbID = 0;
}
Framebuffer& operator=(Framebuffer && move) {
glDeleteFramebuffers(1, &_fbID);
_fbID = move._fbID;
move._fbID = 0;
return *this;
}
void bind() const {
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _fbID);
}
GLuint getID() const {
return _fbID;
}
void attachTexture(GLenum textarget, GLuint texID) {
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
textarget, texID, 0);
}
private:
GLuint _fbID;
};
class TextureCubeMap {
public:
TextureCubeMap(unsigned size) {
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<GLint>(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<GLint>(GL_LINEAR));
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, static_cast<GLint>(GL_LINEAR));
}
~TextureCubeMap() {
glDeleteTextures(1, &_texID);
}
TextureCubeMap(TextureCubeMap const& copy) = delete;
TextureCubeMap& operator=(TextureCubeMap const& copy) = delete;
TextureCubeMap(TextureCubeMap && move) : _texID(move._texID) {
move._texID = 0;
}
TextureCubeMap& operator=(TextureCubeMap && move) {
glDeleteTextures(1, &_texID);
_texID = move._texID;
move._texID = 0;
return *this;
}
void bind() const {
glBindTexture(GL_TEXTURE_CUBE_MAP, _texID);
}
GLuint getID() const {
return _texID;
}
private:
GLuint _texID;
};
class Texture2D {
public:
Texture2D(unsigned width, unsigned height) {
_glCreate(width, height);
}
Texture2D(std::string const& file) {
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() {
glDeleteTextures(1, &_texID);
}
Texture2D(Texture2D const& copy) = delete;
Texture2D& operator=(Texture2D const& copy) = delete;
Texture2D(Texture2D && move) : _texID(move._texID) {
move._texID = 0;
}
Texture2D& operator=(Texture2D && move) {
glDeleteTextures(1, &_texID);
_texID = move._texID;
move._texID = 0;
return *this;
}
void bind() {
glBindTexture(GL_TEXTURE_2D, _texID);
}
private:
void _glCreate(unsigned width, unsigned height) {
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, 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<const int>(GL_RGB8), width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
width = std::max(1u, (width / 2u));
height = std::max(1u, (height / 2u));
}
}
} catch(...) {
glDeleteTextures(1, &_texID);
}
}
GLuint _texID;
};
#endif