82 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			82 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include "texture.h"
 | |
| 
 | |
| #include <algorithm>
 | |
| 
 | |
| #include "../lib/glew/GL/glew.h"
 | |
| #include "../lib/glfw/glfw3.h"
 | |
| #include "../lib/stb_image.h"
 | |
| 
 | |
| #include "logger.h"
 | |
| 
 | |
| Texture::Texture(uint32_t id, const glm::ivec2& size)
 | |
|     : id_(id), size_(size)
 | |
| {
 | |
| }
 | |
| 
 | |
| Texture::~Texture()
 | |
| {
 | |
| 	if (id_ != 0) {
 | |
| 		glDeleteTextures(1, &id_);
 | |
| 		Logger::info(sstr("Texture ", id_, " destroyed"));
 | |
| 	}
 | |
| }
 | |
| 
 | |
| std::shared_ptr<Texture> Texture::load(const char* filename)
 | |
| {
 | |
| 	Logger::info(sstr("Loading texture: ", filename));
 | |
| 
 | |
| 	// Load image
 | |
| 	int	 width, height, channels;
 | |
| 	stbi_uc* pixels =
 | |
| 	    stbi_load(filename, &width, &height, &channels, STBI_rgb_alpha);
 | |
| 
 | |
| 	if (!pixels) {
 | |
| 		Logger::error(sstr("Failed to load texture: ", filename, " - ",
 | |
| 				   stbi_failure_reason()));
 | |
| 		return nullptr;
 | |
| 	}
 | |
| 
 | |
| 	// Flip image vertically (OpenGL expects bottom row first)
 | |
| 	const int row_size   = width * 4; // 4 channels (RGBA)
 | |
| 	auto*	  row_buffer = new stbi_uc[row_size];
 | |
| 	for (int y = 0; y < height / 2; ++y) {
 | |
| 		stbi_uc* row1 = pixels + y * row_size;
 | |
| 		stbi_uc* row2 = pixels + (height - 1 - y) * row_size;
 | |
| 		std::copy(row1, row1 + row_size, row_buffer);
 | |
| 		std::copy(row2, row2 + row_size, row1);
 | |
| 		std::copy(row_buffer, row_buffer + row_size, row2);
 | |
| 	}
 | |
| 	delete[] row_buffer;
 | |
| 
 | |
| 	// Generate OpenGL texture
 | |
| 	GLuint texture_id;
 | |
| 	glGenTextures(1, &texture_id);
 | |
| 	glBindTexture(GL_TEXTURE_2D, texture_id);
 | |
| 
 | |
| 	// Upload texture data
 | |
| 	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
 | |
| 		     GL_UNSIGNED_BYTE, pixels);
 | |
| 
 | |
| 	// Set trilinear filtering
 | |
| 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
 | |
| 			GL_LINEAR_MIPMAP_LINEAR);
 | |
| 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 | |
| 
 | |
| 	// Generate mipmaps
 | |
| 	glGenerateMipmap(GL_TEXTURE_2D);
 | |
| 
 | |
| 	// Free image data
 | |
| 	stbi_image_free(pixels);
 | |
| 
 | |
| 	Logger::info(sstr("Texture loaded successfully: ", filename, " (",
 | |
| 			  width, "x", height, ", ", channels, " channels)"));
 | |
| 
 | |
| 	return std::shared_ptr<Texture>(
 | |
| 	    new Texture(texture_id, glm::ivec2(width, height)));
 | |
| }
 | |
| 
 | |
| void Texture::bind() const
 | |
| {
 | |
| 	glBindTexture(GL_TEXTURE_2D, id_);
 | |
| }
 |