1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
use crate::context::consts;
use crate::core::texture::*;
pub struct TextureCubeMap {
context: Context,
id: crate::context::Texture,
width: u32,
height: u32,
format: Format,
number_of_mip_maps: u32,
}
impl TextureCubeMap {
pub fn new<T: TextureDataType>(
context: &Context,
cpu_texture: &CPUTexture<T>,
) -> ThreeDResult<TextureCubeMap> {
let id = generate(context)?;
let number_of_mip_maps = calculate_number_of_mip_maps(
cpu_texture.mip_map_filter,
cpu_texture.width,
cpu_texture.height,
1,
);
set_parameters(
context,
&id,
consts::TEXTURE_CUBE_MAP,
cpu_texture.min_filter,
cpu_texture.mag_filter,
if number_of_mip_maps == 1 {
None
} else {
cpu_texture.mip_map_filter
},
cpu_texture.wrap_s,
cpu_texture.wrap_t,
Some(cpu_texture.wrap_r),
);
context.bind_texture(consts::TEXTURE_CUBE_MAP, &id);
context.tex_storage_2d(
consts::TEXTURE_CUBE_MAP,
number_of_mip_maps,
T::internal_format(cpu_texture.format)?,
cpu_texture.width,
cpu_texture.height,
);
let mut texture = Self {
context: context.clone(),
id,
width: cpu_texture.width,
height: cpu_texture.height,
format: cpu_texture.format,
number_of_mip_maps,
};
texture.fill(&cpu_texture.data)?;
Ok(texture)
}
pub fn fill<T: TextureDataType>(&mut self, data: &[T]) -> ThreeDResult<()> {
let offset = data.len() / 6;
check_data_length(self.width, self.height, 1, self.format, offset)?;
self.context
.bind_texture(consts::TEXTURE_CUBE_MAP, &self.id);
for i in 0..6 {
T::fill(
&self.context,
consts::TEXTURE_CUBE_MAP_POSITIVE_X + i as u32,
self.width,
self.height,
self.format,
&data[i * offset..(i + 1) * offset],
);
}
self.generate_mip_maps();
Ok(())
}
pub(in crate::core) fn generate_mip_maps(&self) {
if self.number_of_mip_maps > 1 {
self.context
.bind_texture(consts::TEXTURE_CUBE_MAP, &self.id);
self.context.generate_mipmap(consts::TEXTURE_CUBE_MAP);
}
}
}
impl TextureCube for TextureCubeMap {
fn bind(&self, location: u32) {
bind_at(&self.context, &self.id, consts::TEXTURE_CUBE_MAP, location);
}
fn width(&self) -> u32 {
self.width
}
fn height(&self) -> u32 {
self.height
}
fn format(&self) -> Format {
self.format
}
}
impl Drop for TextureCubeMap {
fn drop(&mut self) {
self.context.delete_texture(&self.id);
}
}