1use optic_core::{ImgFilter, ImgFormat, ImgWrap, Size2D};
2
3use crate::GL;
4
5#[derive(Clone, Debug)]
10pub struct Texture2D {
11 pub id: u32,
12 pub size: Size2D,
13 pub fmt: ImgFormat,
14 pub filter: ImgFilter,
15 pub wrap: ImgWrap,
16}
17
18impl Texture2D {
19 pub fn new(
21 id: u32,
22 size: Size2D,
23 fmt: ImgFormat,
24 filter: ImgFilter,
25 wrap: ImgWrap,
26 ) -> Self {
27 Self { id, size, fmt, filter, wrap }
28 }
29
30 pub fn size(&self) -> Size2D { self.size }
32 pub fn wrap(&self) -> ImgWrap { self.wrap }
34 pub fn set_wrap(&mut self, wrap: ImgWrap) { self.wrap = wrap; }
36 pub fn filter(&self) -> ImgFilter { self.filter }
38 pub fn set_filter(&mut self, filter: ImgFilter) { self.filter = filter; }
40
41 pub fn delete(self) { delete_texture(self.id); }
43}
44
45pub fn create_texture(
50 bytes: &[u8],
51 size: Size2D,
52 fmt: &ImgFormat,
53 filter: &ImgFilter,
54 wrap: &ImgWrap,
55) -> u32 {
56 let mut id = 0u32;
57 unsafe {
58 gl::GenTextures(1, &mut id);
59 GL::bind_texture_at(id, 0);
60
61 let wrap_gl = match wrap {
62 ImgWrap::Repeat => gl::REPEAT,
63 ImgWrap::Extend => gl::CLAMP_TO_EDGE,
64 ImgWrap::Clip => gl::CLAMP_TO_BORDER,
65 };
66 let (min_fil, mag_fil) = match filter {
67 ImgFilter::Closest => (gl::NEAREST_MIPMAP_NEAREST as i32, gl::NEAREST as i32),
68 ImgFilter::Linear => (gl::LINEAR_MIPMAP_LINEAR as i32, gl::LINEAR as i32),
69 };
70
71 gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, wrap_gl as i32);
72 gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, wrap_gl as i32);
73 gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, min_fil);
74 gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, mag_fil);
75
76 let (base, sized, pix_type) = match fmt {
77 ImgFormat::R(bd) => match bd {
78 32 => (gl::RED, gl::R32F, gl::FLOAT),
79 16 => (gl::RED, gl::R16, gl::UNSIGNED_SHORT),
80 _ => (gl::RED, gl::R8, gl::UNSIGNED_BYTE),
81 },
82 ImgFormat::RG(bd) => match bd {
83 32 => (gl::RG, gl::RG32F, gl::FLOAT),
84 16 => (gl::RG, gl::RG16, gl::UNSIGNED_SHORT),
85 _ => (gl::RG, gl::RG8, gl::UNSIGNED_BYTE),
86 },
87 ImgFormat::RGB(bd) => match bd {
88 32 => (gl::RGB, gl::RGB32F, gl::FLOAT),
89 16 => (gl::RGB, gl::RGB16, gl::UNSIGNED_SHORT),
90 _ => (gl::RGB, gl::RGB8, gl::UNSIGNED_BYTE),
91 },
92 ImgFormat::RGBA(bd) => match bd {
93 32 => (gl::RGBA, gl::RGBA32F, gl::FLOAT),
94 16 => (gl::RGBA, gl::RGBA16, gl::UNSIGNED_SHORT),
95 _ => (gl::RGBA, gl::RGBA8, gl::UNSIGNED_BYTE),
96 },
97 };
98
99 gl::TexImage2D(
100 gl::TEXTURE_2D,
101 0,
102 sized as i32,
103 size.w as i32,
104 size.h as i32,
105 0,
106 base,
107 pix_type,
108 bytes.as_ptr() as *const std::ffi::c_void,
109 );
110 gl::GenerateMipmap(gl::TEXTURE_2D);
111 GL::unbind_texture();
112 }
113 id
114}
115
116pub fn delete_texture(id: u32) {
118 unsafe { gl::DeleteTextures(1, &id); }
119}