use crate::custom_errors::Errors;
use gl::types::*;
use image::ImageError;
use std::path::Path;
pub struct Texture {
id: GLuint,
}
impl Texture {
pub fn new() -> Self {
let mut id = 0;
unsafe {
gl::GenTextures(1, &mut id);
}
Self { id }
}
pub fn bind(&self, unit: GLenum) {
unsafe {
gl::ActiveTexture(unit);
gl::BindTexture(gl::TEXTURE_2D, self.id);
}
}
pub fn set_parameteri(&self, param: GLenum, value: GLint) {
unsafe {
gl::TexParameteri(gl::TEXTURE_2D, param, value);
}
}
pub fn set_parameterf(&self, param: GLenum, value: GLfloat) {
unsafe {
gl::TexParameterf(gl::TEXTURE_2D, param, value);
}
}
pub fn load_from_file<P: AsRef<Path>>(&self, path: P) -> Result<(), Errors> {
let img = image::open(path).map_err(|e: ImageError| {
Errors::TextureLoadError(format!("Failed to load texture: {}", e))
})?;
let img = img.to_rgba8();
let (width, height) = img.dimensions();
unsafe {
gl::BindTexture(gl::TEXTURE_2D, self.id);
gl::TexImage2D(
gl::TEXTURE_2D,
0,
gl::RGBA as i32,
width as i32,
height as i32,
0,
gl::RGBA,
gl::UNSIGNED_BYTE,
img.as_ptr() as *const _,
);
gl::GenerateMipmap(gl::TEXTURE_2D);
}
Ok(())
}
pub fn load_from_data(&self, width: u32, height: u32, data: &[u8]) -> Result<(), Errors> {
if data.len() != (width * height * 4) as usize {
return Err(Errors::TextureLoadError(
"Invalid data size for texture".to_string(),
));
}
unsafe {
gl::BindTexture(gl::TEXTURE_2D, self.id);
gl::TexImage2D(
gl::TEXTURE_2D,
0,
gl::RGBA as i32,
width as i32,
height as i32,
0,
gl::RGBA,
gl::UNSIGNED_BYTE,
data.as_ptr() as *const _,
);
gl::GenerateMipmap(gl::TEXTURE_2D);
}
Ok(())
}
}
impl Drop for Texture {
fn drop(&mut self) {
unsafe {
gl::DeleteTextures(1, &self.id);
}
}
}