107 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			C++
		
	
	
			
		
		
	
	
			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;
 | |
| }
 |