chaos_framework/graphics/
texture.rs

1use std::{collections::HashMap, ops::{Index, IndexMut}};
2
3use gl::types::{GLint, GLsizei, GLuint, GLvoid};
4
5use crate::Renderer;
6
7#[derive(PartialEq, Eq, Hash, Debug, Copy, Clone)]
8pub struct TextureHandle {
9    pub id: usize,
10}
11
12impl<'a> Index<TextureHandle> for HashMap<TextureHandle, Texture<'a>> {
13    type Output = Texture<'a>;
14
15    fn index(&self, handle: TextureHandle) -> &Self::Output {
16        self.get(&handle).expect("No entry found for key")
17    }
18}
19
20impl<'a> IndexMut<TextureHandle> for HashMap<TextureHandle, Texture<'a>> {
21    fn index_mut(&mut self, handle: TextureHandle) -> &mut Self::Output {
22        self.get_mut(&handle).expect("No entry found for key")
23    }
24}
25
26#[derive(PartialEq, Debug, Clone)]
27pub enum Texture<'a> {
28    Path(&'a str),
29    Loaded(GLuint),
30    None,
31}
32
33pub unsafe fn load_texture(path: &str) -> GLuint { 
34    let img = image::open(path).expect("Failed to load image");
35    
36    let img = img.flipv();
37    let width = img.width();
38    let height = img.height();
39    let raw_pixels = img.to_rgba8().into_raw();
40    
41    let mut texture: GLuint = 0;
42    gl::GenTextures(1, &mut texture);
43    gl::BindTexture(gl::TEXTURE_2D, texture);
44
45    gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::REPEAT as GLint);
46    gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::REPEAT as GLint);
47    gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR as GLint);
48    gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as GLint);
49
50    gl::TexImage2D(
51        gl::TEXTURE_2D,
52        0,
53        gl::RGBA as GLint,
54        width as GLsizei,
55        height as GLsizei,
56        0,
57        gl::RGBA,
58        gl::UNSIGNED_BYTE,
59        raw_pixels.as_ptr() as *const GLvoid,
60    );
61
62    gl::GenerateMipmap(gl::TEXTURE_2D);
63
64    texture
65}
66
67impl Renderer {
68    pub fn add_texture(&mut self, path: &str) -> Option<TextureHandle> {
69        let handle = TextureHandle {id: self.textures.len()};
70
71        if self.textures.contains_key(&handle) {
72            println!("Texture with handle {:?} already exists", handle);
73            return None;
74        }
75
76        self.textures.insert(handle, unsafe {load_texture(path)});
77        Some(handle)
78    }
79
80    pub fn destroy_texture(&mut self, handle: TextureHandle) {
81        if self.textures.remove(&handle).is_some() {
82
83        } else {
84            println!("Failed to remove texture");
85        }
86    }
87}
88
89impl Drop for Texture<'_> {
90    fn drop(&mut self) {
91        unsafe {
92            if let Texture::Loaded(id) = self {
93                gl::DeleteTextures(1, id);
94            }
95        }
96    }
97}