chaos_framework/graphics/
texture.rs1use 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}