RtB/src/Texture.cpp

107 lines
3.4 KiB
C++

#include "Texture.hpp"
#include "Log.hpp"
#include "SDL_image.h"
/* ======== Constructors/Destructor ======== */
Texture::Texture(std::string name_, const char *buffer, size_t buffer_size) {
name.assign(name_);
texture = 0;
flags = 0;
w = h = 0;
image = NULL;
loadImg(buffer, buffer_size);
}
// NOTE: this is a special test constructor just so I can use RenderView(s) within the current system nicely
Texture::Texture(std::string name_, RenderView *view) {
name.assign(name_);
texture = view->getTex();
flags = 0;
w = view->getWidth();
h = view->getHeight();
}
Texture::~Texture() {
destroyTexture();
}
/* ======== Image/Surface loading/unloading ======== */
/* loadImg
This function takes in the given buffer that is composed of an SDL2_image compatible format, copies it to an SDL_RWops, loads it is an SDL_Surface, and then generates an OpenGL texture.
Yes, this is wasteful.
*/
int Texture::loadImg(const char *buffer, size_t buffer_size) {
if (flags & LOADED) {
LOG(LOG_WARNING) << FUNC_NAME << ": surface already loaded - unloading and replacing";
unloadImg();
}
if ((image = IMG_Load_RW(SDL_RWFromMem((char*)buffer, buffer_size), 1)) == NULL) {
LOG(LOG_ERROR) << FUNC_NAME << ": Could not load image from buffer: " << IMG_GetError();
return 1;
}
flags |= LOADED;
w = image->w;
h = image->h;
return 0;
}
/* unloadImg
This function effectively frees the SDL_Surface allocated by loadImg. It should be called after buildTexture()
*/
int Texture::unloadImg() {
if (flags & LOADED) {
SDL_FreeSurface(image);
flags &= ~LOADED;
return 0;
}
return 1;
}
/* ======== Texture generation/destruction ======== */
/* buildTexture
This function generates the OpenGL texture is an image is loaded. If the texture is already built, it is destroyed and recreated.
Returns 0 if no image is loaded, otherwise it returns the texture ID.
*/
GLuint Texture::buildTexture() {
if (!(flags & LOADED)) {
LOG(LOG_WARNING) << FUNC_NAME << ": image is not loaded!";
return 0;
}
if (flags & BUILT) {
LOG(LOG_WARNING) << FUNC_NAME << ": texture already built, destroying and recreating";
destroyTexture();
}
// Unbind any previous texture
glBindTexture(GL_TEXTURE_2D, 0);
// Create the texture
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
if (glIsTexture(texture) != 1) {
LOG(LOG_WARNING) << FUNC_NAME << ": failed to generate texture!";
return 0;
}
#ifdef __APPLE__
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image->w, image->h, 0, GL_BGRA, GL_UNSIGNED_BYTE, image->pixels);
#else
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image->w, image->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, image->pixels);
#endif
/*glGenerateMipmap(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);*/
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
flags |= BUILT;
LOG(LOG_DEBUG) << FUNC_NAME << ": " << name << " built as " << texture;
return texture;
}
/* destroyTexture
Deletes the given texture from OpenGL if it was already built via buildTexture.
*/
int Texture::destroyTexture() {
if (flags & BUILT) {
glDeleteTextures(1, &texture);
flags &= ~BUILT;
return 0;
}
return 1;
}