229 lines
5.4 KiB
C++
229 lines
5.4 KiB
C++
#include <glbinding/gl/gl.h>
|
|
#include <SDL2/SDL.h>
|
|
#include <SDL2/SDL_image.h>
|
|
|
|
#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<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::~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<const int>(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);
|
|
}
|
|
}
|