fyrox_graphics/gpu_texture.rs
1// Copyright (c) 2019-present Dmitry Stepanov and Fyrox Engine contributors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in all
11// copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19// SOFTWARE.
20
21//! Texture is an image that used to fill faces to add details to them. It could also be used as a
22//! generic and mostly unlimited capacity storage for arbitrary data.
23
24#![warn(missing_docs)]
25
26use crate::{
27 core::{color::Color, Downcast},
28 error::FrameworkError,
29};
30use bytemuck::Pod;
31
32/// A kind of GPU texture.
33#[derive(Copy, Clone)]
34pub enum GpuTextureKind {
35 /// 1D texture.
36 Line {
37 /// Length of the texture.
38 length: usize,
39 },
40 /// 2D texture.
41 Rectangle {
42 /// Width of the texture.
43 width: usize,
44 /// Height of the texture.
45 height: usize,
46 },
47 /// Six 2D textures forming a cube.
48 Cube {
49 /// Width of the texture.
50 width: usize,
51 /// Height of the texture.
52 height: usize,
53 },
54 /// Volumetric texture that consists of `depth` textures with `width x height` size.
55 Volume {
56 /// Width of the texture.
57 width: usize,
58 /// Height of the texture.
59 height: usize,
60 /// Depth of the texture.
61 depth: usize,
62 },
63}
64
65/// Pixel kind of GPU texture.
66#[derive(Copy, Clone, Debug, PartialEq)]
67pub enum PixelKind {
68 /// Floating point 32-bit pixel.
69 R32F,
70 /// Unsigned integer 32-bit pixel.
71 R32UI,
72 /// Floating point 16-bit pixel.
73 R16F,
74 /// Floating point 32-bit depth pixel.
75 D32F,
76 /// Integer 16-bit depth pixel.
77 D16,
78 /// Integer 24-bit depth pixel + 8-bit stencil.
79 D24S8,
80 /// Red, Green, Blue, Alpha; all by 8-bit.
81 RGBA8,
82 /// Red, Green, Blue, Alpha in sRGB color space; all by 8-bit.
83 SRGBA8,
84 /// Red, Green, Blue; all by 8-bit.
85 RGB8,
86 /// Red, Green, Blue in sRGB color space; all by 8-bit.
87 SRGB8,
88 /// Blue, Green, Red, Alpha; all by 8-bit.
89 BGRA8,
90 /// Blue, Green, Red; all by 8-bit.
91 BGR8,
92 /// Red, Green; all by 8-bit.
93 RG8,
94 /// Luminance, Alpha; all by 8-bit.
95 LA8,
96 /// Luminance, Alpha; all by 16-bit.
97 LA16,
98 /// Red, Green; all by 16-bit.
99 RG16,
100 /// Red, Green; 16-bit.
101 R8,
102 /// Luminance; 8-bit.
103 L8,
104 /// Luminance; 16-bit.
105 L16,
106 /// Red, unsigned integer; 8-bit.
107 R8UI,
108 /// Red, signed integer; 16-bit.
109 R16,
110 /// Red, Green, Blue; all by 16-bit.
111 RGB16,
112 /// Red, Green, Blue, Alpha; all by 8-bit.
113 RGBA16,
114 /// Compressed S3TC DXT1 RGB.
115 DXT1RGB,
116 /// Compressed S3TC DXT1 RGBA.
117 DXT1RGBA,
118 /// Compressed S3TC DXT3 RGBA.
119 DXT3RGBA,
120 /// Compressed S3TC DXT5 RGBA.
121 DXT5RGBA,
122 /// Floating-point RGB texture with 32-bit depth.
123 RGB32F,
124 /// Floating-point RGBA texture with 32-bit depth.
125 RGBA32F,
126 /// Floating-point RGB texture with 16-bit depth.
127 RGB16F,
128 /// Floating-point RGBA texture with 16-bit depth.
129 RGBA16F,
130 /// Compressed R8 texture (RGTC).
131 R8RGTC,
132 /// Compressed RG8 texture (RGTC).
133 RG8RGTC,
134 /// Floating-point RGB texture with 11-bit for Red and Green channels, 10-bit for Blue channel.
135 R11G11B10F,
136 /// Red, Green, Blue (8-bit) + Alpha (2-bit).
137 RGB10A2,
138}
139
140/// Element kind of pixel.
141pub enum PixelElementKind {
142 /// Floating-point pixel.
143 Float,
144 /// Normalized unsigned integer.
145 NormalizedUnsignedInteger,
146 /// Integer.
147 Integer,
148 /// Unsigned integer.
149 UnsignedInteger,
150}
151
152impl PixelKind {
153 pub(crate) fn unpack_alignment(self) -> Option<i32> {
154 match self {
155 Self::RGBA16
156 | Self::RGBA16F
157 | Self::RGB16
158 | Self::RGB16F
159 | Self::RGBA32F
160 | Self::RGB32F
161 | Self::RGBA8
162 | Self::SRGBA8
163 | Self::BGRA8
164 | Self::RG16
165 | Self::LA16
166 | Self::D24S8
167 | Self::D32F
168 | Self::R32F
169 | Self::R32UI
170 | Self::RGB10A2 => Some(4),
171 Self::RG8 | Self::LA8 | Self::D16 | Self::R16F | Self::L16 | Self::R16 => Some(2),
172 Self::R8
173 | Self::L8
174 | Self::R8UI
175 | Self::SRGB8
176 | Self::RGB8
177 | Self::BGR8
178 | Self::R11G11B10F => Some(1),
179 Self::DXT1RGB
180 | Self::DXT1RGBA
181 | Self::DXT3RGBA
182 | Self::DXT5RGBA
183 | Self::R8RGTC
184 | Self::RG8RGTC => None,
185 }
186 }
187
188 /// Returns `true` if the pixel kind is compressed, `false` - otherwise.
189 pub fn is_compressed(self) -> bool {
190 match self {
191 Self::DXT1RGB
192 | Self::DXT1RGBA
193 | Self::DXT3RGBA
194 | Self::DXT5RGBA
195 | Self::R8RGTC
196 | Self::RG8RGTC => true,
197 // Explicit match for rest of formats instead of _ will help to not forget
198 // to add new entry here.
199 Self::RGBA16
200 | Self::RGBA16F
201 | Self::RGB16
202 | Self::RGB16F
203 | Self::RGBA8
204 | Self::SRGBA8
205 | Self::RGB8
206 | Self::SRGB8
207 | Self::BGRA8
208 | Self::BGR8
209 | Self::RG16
210 | Self::R16
211 | Self::D24S8
212 | Self::D32F
213 | Self::R32F
214 | Self::R32UI
215 | Self::RG8
216 | Self::D16
217 | Self::R16F
218 | Self::R8
219 | Self::R8UI
220 | Self::RGB32F
221 | Self::RGBA32F
222 | Self::R11G11B10F
223 | Self::RGB10A2
224 | Self::L8
225 | Self::LA8
226 | Self::L16
227 | Self::LA16 => false,
228 }
229 }
230
231 /// Returns element kind of the pixel.
232 pub fn element_kind(self) -> PixelElementKind {
233 match self {
234 Self::R32F
235 | Self::R16F
236 | Self::RGB32F
237 | Self::RGBA32F
238 | Self::RGBA16F
239 | Self::RGB16F
240 | Self::D32F
241 | Self::R11G11B10F => PixelElementKind::Float,
242 Self::D16
243 | Self::D24S8
244 | Self::RGBA8
245 | Self::SRGBA8
246 | Self::RGB8
247 | Self::SRGB8
248 | Self::BGRA8
249 | Self::BGR8
250 | Self::RG8
251 | Self::RG16
252 | Self::R8
253 | Self::R16
254 | Self::RGB16
255 | Self::RGBA16
256 | Self::DXT1RGB
257 | Self::DXT1RGBA
258 | Self::DXT3RGBA
259 | Self::DXT5RGBA
260 | Self::R8RGTC
261 | Self::RG8RGTC
262 | Self::RGB10A2
263 | Self::LA8
264 | Self::L8
265 | Self::LA16
266 | Self::L16 => PixelElementKind::NormalizedUnsignedInteger,
267 Self::R8UI | Self::R32UI => PixelElementKind::UnsignedInteger,
268 }
269 }
270}
271
272fn ceil_div_4(x: usize) -> usize {
273 (x + 3) / 4
274}
275
276/// Calculates size in bytes of a volume texture using the given size of the texture and its pixel
277/// kind.
278pub fn image_3d_size_bytes(
279 pixel_kind: PixelKind,
280 width: usize,
281 height: usize,
282 depth: usize,
283) -> usize {
284 let pixel_count = width * height * depth;
285 match pixel_kind {
286 PixelKind::RGBA32F => 16 * pixel_count,
287 PixelKind::RGB32F => 12 * pixel_count,
288 PixelKind::RGBA16 | PixelKind::RGBA16F => 8 * pixel_count,
289 PixelKind::RGB16 | PixelKind::RGB16F => 6 * pixel_count,
290 PixelKind::RGBA8
291 | PixelKind::SRGBA8
292 | PixelKind::BGRA8
293 | PixelKind::RG16
294 | PixelKind::LA16
295 | PixelKind::D24S8
296 | PixelKind::D32F
297 | PixelKind::R32F
298 | PixelKind::R32UI
299 | PixelKind::R11G11B10F
300 | PixelKind::RGB10A2 => 4 * pixel_count,
301 PixelKind::RGB8 | PixelKind::SRGB8 | PixelKind::BGR8 => 3 * pixel_count,
302 PixelKind::RG8
303 | PixelKind::LA8
304 | PixelKind::R16
305 | PixelKind::L16
306 | PixelKind::D16
307 | PixelKind::R16F => 2 * pixel_count,
308 PixelKind::R8 | PixelKind::L8 | PixelKind::R8UI => pixel_count,
309 PixelKind::DXT1RGB | PixelKind::DXT1RGBA | PixelKind::R8RGTC => {
310 let block_size = 8;
311 ceil_div_4(width) * ceil_div_4(height) * ceil_div_4(depth) * block_size
312 }
313 PixelKind::DXT3RGBA | PixelKind::DXT5RGBA | PixelKind::RG8RGTC => {
314 let block_size = 16;
315 ceil_div_4(width) * ceil_div_4(height) * ceil_div_4(depth) * block_size
316 }
317 }
318}
319
320/// Calculates size in bytes of a rectangular texture using the given size of the texture and its pixel
321/// kind.
322pub fn image_2d_size_bytes(pixel_kind: PixelKind, width: usize, height: usize) -> usize {
323 let pixel_count = width * height;
324 match pixel_kind {
325 PixelKind::RGBA32F => 16 * pixel_count,
326 PixelKind::RGB32F => 12 * pixel_count,
327 PixelKind::RGBA16 | PixelKind::RGBA16F => 8 * pixel_count,
328 PixelKind::RGB16 | PixelKind::RGB16F => 6 * pixel_count,
329 PixelKind::RGBA8
330 | PixelKind::SRGBA8
331 | PixelKind::BGRA8
332 | PixelKind::RG16
333 | PixelKind::LA16
334 | PixelKind::D24S8
335 | PixelKind::D32F
336 | PixelKind::R32F
337 | PixelKind::R32UI
338 | PixelKind::R11G11B10F
339 | PixelKind::RGB10A2 => 4 * pixel_count,
340 PixelKind::RGB8 | PixelKind::SRGB8 | PixelKind::BGR8 => 3 * pixel_count,
341 PixelKind::RG8
342 | PixelKind::LA8
343 | PixelKind::R16
344 | PixelKind::L16
345 | PixelKind::D16
346 | PixelKind::R16F => 2 * pixel_count,
347 PixelKind::R8 | PixelKind::L8 | PixelKind::R8UI => pixel_count,
348 PixelKind::DXT1RGB | PixelKind::DXT1RGBA | PixelKind::R8RGTC => {
349 let block_size = 8;
350 ceil_div_4(width) * ceil_div_4(height) * block_size
351 }
352 PixelKind::DXT3RGBA | PixelKind::DXT5RGBA | PixelKind::RG8RGTC => {
353 let block_size = 16;
354 ceil_div_4(width) * ceil_div_4(height) * block_size
355 }
356 }
357}
358
359/// Calculates size in bytes of a linear texture using the given size of the texture and its pixel
360/// kind.
361pub fn image_1d_size_bytes(pixel_kind: PixelKind, length: usize) -> usize {
362 match pixel_kind {
363 PixelKind::RGBA32F => 16 * length,
364 PixelKind::RGB32F => 12 * length,
365 PixelKind::RGBA16 | PixelKind::RGBA16F => 8 * length,
366 PixelKind::RGB16 | PixelKind::RGB16F => 6 * length,
367 PixelKind::RGBA8
368 | PixelKind::SRGBA8
369 | PixelKind::BGRA8
370 | PixelKind::RG16
371 | PixelKind::LA16
372 | PixelKind::D24S8
373 | PixelKind::D32F
374 | PixelKind::R32F
375 | PixelKind::R32UI
376 | PixelKind::R11G11B10F
377 | PixelKind::RGB10A2 => 4 * length,
378 PixelKind::RGB8 | PixelKind::SRGB8 | PixelKind::BGR8 => 3 * length,
379 PixelKind::RG8
380 | PixelKind::LA8
381 | PixelKind::L16
382 | PixelKind::R16
383 | PixelKind::D16
384 | PixelKind::R16F => 2 * length,
385 PixelKind::R8 | PixelKind::L8 | PixelKind::R8UI => length,
386 PixelKind::DXT1RGB | PixelKind::DXT1RGBA | PixelKind::R8RGTC => {
387 let block_size = 8;
388 ceil_div_4(length) * block_size
389 }
390 PixelKind::DXT3RGBA | PixelKind::DXT5RGBA | PixelKind::RG8RGTC => {
391 let block_size = 16;
392 ceil_div_4(length) * block_size
393 }
394 }
395}
396
397/// The texture magnification function is used when the pixel being textured maps to an area
398/// less than or equal to one texture element.
399#[derive(Default, Copy, Clone, PartialOrd, PartialEq, Eq, Hash, Debug)]
400#[repr(u32)]
401pub enum MagnificationFilter {
402 /// Returns the value of the texture element that is nearest to the center of the pixel
403 /// being textured.
404 Nearest,
405 /// Returns the weighted average of the four texture elements that are closest to the
406 /// center of the pixel being textured.
407 #[default]
408 Linear,
409}
410
411/// The texture minifying function is used whenever the pixel being textured maps to an area
412/// greater than one texture element.
413#[derive(Default, Copy, Clone, PartialOrd, PartialEq, Eq, Hash, Debug)]
414pub enum MinificationFilter {
415 /// Returns the value of the texture element that is nearest to the center of the pixel
416 /// being textured.
417 Nearest,
418 /// Chooses the mipmap that most closely matches the size of the pixel being textured and
419 /// uses the Nearest criterion (the texture element nearest to the center of the pixel)
420 /// to produce a texture value.
421 NearestMipMapNearest,
422 /// Chooses the two mipmaps that most closely match the size of the pixel being textured
423 /// and uses the Nearest criterion (the texture element nearest to the center of the pixel)
424 /// to produce a texture value from each mipmap. The final texture value is a weighted average
425 /// of those two values.
426 NearestMipMapLinear,
427 /// Returns the weighted average of the four texture elements that are closest to the
428 /// center of the pixel being textured.
429 #[default]
430 Linear,
431 /// Chooses the mipmap that most closely matches the size of the pixel being textured and
432 /// uses the Linear criterion (a weighted average of the four texture elements that are
433 /// closest to the center of the pixel) to produce a texture value.
434 LinearMipMapNearest,
435 /// Chooses the two mipmaps that most closely match the size of the pixel being textured
436 /// and uses the Linear criterion (a weighted average of the four texture elements that
437 /// are closest to the center of the pixel) to produce a texture value from each mipmap.
438 /// The final texture value is a weighted average of those two values.
439 LinearMipMapLinear,
440}
441
442/// Defines a law of texture coordinate modification.
443#[derive(Default, Copy, Clone, Eq, PartialEq, Debug)]
444pub enum WrapMode {
445 /// Causes the integer part of a coordinate to be ignored; GPU uses only the fractional part,
446 /// thereby creating a repeating pattern.
447 #[default]
448 Repeat,
449 /// Causes a coordinates to be clamped to the range, where N is the size of the texture
450 /// in the direction of clamping
451 ClampToEdge,
452 /// Evaluates a coordinates in a similar manner to ClampToEdge. However, in cases where clamping
453 /// would have occurred in ClampToEdge mode, the fetched texel data is substituted with the values
454 /// specified by border color.
455 ClampToBorder,
456 /// Causes the coordinate to be set to the fractional part of the texture coordinate if the integer
457 /// part of coordinate is even; if the integer part of coordinate is odd, then the coordinate texture
458 /// coordinate is set to 1-frac, where frac represents the fractional part of coordinate.
459 MirroredRepeat,
460 /// Causes a coordinate to be repeated as for MirroredRepeat for one repetition of the texture, at
461 /// which point the coordinate to be clamped as in ClampToEdge.
462 MirrorClampToEdge,
463}
464
465/// Texture coordinate.
466#[derive(Copy, Clone, Eq, PartialEq, Debug)]
467pub enum Coordinate {
468 /// S coordinate, similar to X axis.
469 S,
470 /// T coordinate, similar to Y axis.
471 T,
472 /// R coordinate, similar to Z axis.
473 R,
474}
475
476/// Face of a cube map.
477#[derive(Copy, Clone, Eq, PartialEq, Debug)]
478pub enum CubeMapFace {
479 /// +X face.
480 PositiveX,
481 /// -X face.
482 NegativeX,
483 /// +Y face.
484 PositiveY,
485 /// -Y face.
486 NegativeY,
487 /// +Z face.
488 PositiveZ,
489 /// -Z face.
490 NegativeZ,
491}
492
493/// Descriptor of a texture that is used to request textures from a graphics server.
494pub struct GpuTextureDescriptor<'a> {
495 /// Kind of the texture. See [`GpuTextureKind`] docs for more info.
496 pub kind: GpuTextureKind,
497 /// Pixel kind of the texture. See [`PixelKind`] docs for more info.
498 pub pixel_kind: PixelKind,
499 /// Minification filter of the texture. See [`MinificationFilter`] docs for more info.
500 pub min_filter: MinificationFilter,
501 /// Magnification filter of the texture. See [`MagnificationFilter`] docs for more info.
502 pub mag_filter: MagnificationFilter,
503 /// Total number of mips in the texture. Texture data must contain at least this number of
504 /// mips.
505 pub mip_count: usize,
506 /// S coordinate wrap mode. See [`WrapMode`] docs for more info.
507 pub s_wrap_mode: WrapMode,
508 /// T coordinate wrap mode. See [`WrapMode`] docs for more info.
509 pub t_wrap_mode: WrapMode,
510 /// R coordinate wrap mode. See [`WrapMode`] docs for more info.
511 pub r_wrap_mode: WrapMode,
512 /// Anisotropy level of the texture. Default is 1.0. Max number is usually depends on the
513 /// GPU, but the cap is 16.0 on pretty much any platform. This number should be a power of two.
514 pub anisotropy: f32,
515 /// Optional data of the texture. If present, then the total number of bytes must match the
516 /// required number of bytes defined by the texture kind, pixel kind, mip count.
517 pub data: Option<&'a [u8]>,
518 /// Specifies the index of the lowest defined mipmap level. Keep in mind, that the texture data
519 /// should provide the actual mip map level defined by the provided value, otherwise the
520 /// rendering will be incorrect (probably just black on majority of implementations) and glitchy.
521 pub base_level: usize,
522 /// Sets the index of the highest defined mipmap level. Keep in mind, that the texture data
523 /// should provide the actual mip map level defined by the provided value, otherwise the
524 /// rendering will be incorrect (probably just black on majority of implementations) and glitchy.
525 pub max_level: usize,
526 /// Sets the minimum level-of-detail parameter. This floating-point value limits the selection
527 /// of highest resolution mipmap (lowest mipmap level). The initial value is -1000.0.
528 pub min_lod: f32,
529 /// Sets the maximum level-of-detail parameter. This floating-point value limits the selection
530 /// of the lowest resolution mipmap (highest mipmap level). The initial value is 1000.0.
531 pub max_lod: f32,
532 /// Specifies a fixed bias value that is to be added to the level-of-detail parameter for the
533 /// texture before texture sampling. The specified value is added to the shader-supplied bias
534 /// value (if any) and subsequently clamped into the implementation-defined range
535 /// `−bias_max..bias_max`, where `bias_max` is the value that can be fetched from the current
536 /// graphics server. The initial value is 0.0.
537 pub lod_bias: f32,
538}
539
540impl Default for GpuTextureDescriptor<'_> {
541 // WARNING: Do NOT change these default values. This will affect a lot of places in the engine
542 // and may potentially lead to weird behavior!
543 fn default() -> Self {
544 Self {
545 kind: GpuTextureKind::Rectangle {
546 width: 1,
547 height: 1,
548 },
549 pixel_kind: PixelKind::RGBA8,
550 min_filter: Default::default(),
551 mag_filter: Default::default(),
552 mip_count: 1,
553 s_wrap_mode: Default::default(),
554 t_wrap_mode: Default::default(),
555 r_wrap_mode: Default::default(),
556 anisotropy: 1.0,
557 data: None,
558 base_level: 0,
559 max_level: 1000,
560 min_lod: -1000.0,
561 max_lod: 1000.0,
562 lod_bias: 0.0,
563 }
564 }
565}
566
567/// Texture is an image that used to fill faces to add details to them. It could also be used as a
568/// generic and mostly unlimited capacity storage for arbitrary data.
569///
570/// In most cases textures are just 2D images, however there are some exclusions to that - for example
571/// cube maps, that may be used for environment mapping. Fyrox supports 1D, 2D, 3D and Cube textures.
572///
573/// ## Example
574///
575/// ```rust
576/// use fyrox_graphics::{
577/// error::FrameworkError,
578/// gpu_texture::{
579/// GpuTexture, GpuTextureDescriptor, GpuTextureKind, MagnificationFilter,
580/// MinificationFilter, PixelKind, WrapMode,
581/// },
582/// server::GraphicsServer,
583/// };
584/// use std::{cell::RefCell, rc::Rc};
585///
586/// fn create_texture(
587/// server: &dyn GraphicsServer,
588/// ) -> Result<Rc<RefCell<dyn GpuTexture>>, FrameworkError> {
589/// server.create_texture(GpuTextureDescriptor {
590/// kind: GpuTextureKind::Rectangle {
591/// width: 1,
592/// height: 1,
593/// },
594/// pixel_kind: PixelKind::RGBA8,
595/// min_filter: MinificationFilter::Nearest,
596/// mag_filter: MagnificationFilter::Nearest,
597/// mip_count: 1,
598/// s_wrap_mode: WrapMode::Repeat,
599/// t_wrap_mode: WrapMode::Repeat,
600/// r_wrap_mode: WrapMode::Repeat,
601/// anisotropy: 1.0,
602/// // Opaque red pixel.
603/// data: Some(&[255, 0, 0, 255]),
604/// // Take the defaults for the rest of parameters.
605/// ..Default::default()
606/// })
607/// }
608/// ```
609pub trait GpuTexture: Downcast {
610 /// Max samples for anisotropic filtering. Default value is 16.0 (max). However, real value passed
611 /// to GPU will be clamped to maximum supported by current GPU. To disable anisotropic filtering
612 /// set this to 1.0. Typical values are 2.0, 4.0, 8.0, 16.0.
613 fn set_anisotropy(&mut self, anisotropy: f32);
614
615 /// Returns current anisotropy level.
616 fn anisotropy(&self) -> f32;
617
618 /// Sets new minification filter. It is used when texture becomes smaller. See [`MinificationFilter`]
619 /// docs for more info.
620 fn set_minification_filter(&mut self, min_filter: MinificationFilter);
621
622 /// Returns current minification filter.
623 fn minification_filter(&self) -> MinificationFilter;
624
625 /// Sets new magnification filter. It is used when texture is "stretching". See [`MagnificationFilter`]
626 /// docs for more info.
627 fn set_magnification_filter(&mut self, mag_filter: MagnificationFilter);
628
629 /// Returns current magnification filter.
630 fn magnification_filter(&self) -> MagnificationFilter;
631
632 /// Sets new wrap mode for the given coordinate. See [`WrapMode`] for more info.
633 fn set_wrap(&mut self, coordinate: Coordinate, wrap: WrapMode);
634
635 /// Returns current wrap mode for the given coordinate.
636 fn wrap_mode(&self, coordinate: Coordinate) -> WrapMode;
637
638 /// Sets border color of the texture. Works together with [`WrapMode::ClampToBorder`] and
639 /// essentially forces the GPU to use the given color when it tries to read outside the texture
640 /// bounds.
641 fn set_border_color(&mut self, color: Color);
642
643 /// Sets the new data of the texture. This method is also able to change the kind of the texture
644 /// and its pixel kind.
645 fn set_data(
646 &mut self,
647 kind: GpuTextureKind,
648 pixel_kind: PixelKind,
649 mip_count: usize,
650 data: Option<&[u8]>,
651 ) -> Result<(), FrameworkError>;
652
653 /// Reads the texture data at the given mip level. This method could block current thread until
654 /// the data comes from GPU to CPU side.
655 fn get_image(&self, level: usize) -> Vec<u8>;
656
657 /// Reads texture pixels.
658 fn read_pixels(&self) -> Vec<u8>;
659
660 /// Returns kind of the texture.
661 fn kind(&self) -> GpuTextureKind;
662
663 /// Returns pixel kind of the texture.
664 fn pixel_kind(&self) -> PixelKind;
665
666 /// Specifies the index of the lowest defined mipmap level. Keep in mind, that the texture data
667 /// should provide the actual mip map level defined by the provided value, otherwise the
668 /// rendering will be incorrect (probably just black on majority of implementations) and glitchy.
669 fn set_base_level(&mut self, level: usize);
670
671 /// Returns the index of the lowest defined mipmap level.
672 fn base_level(&self) -> usize;
673
674 /// Sets the index of the highest defined mipmap level. Keep in mind, that the texture data
675 /// should provide the actual mip map level defined by the provided value, otherwise the
676 /// rendering will be incorrect (probably just black on majority of implementations) and glitchy.
677 fn set_max_level(&mut self, level: usize);
678
679 /// Returns the index of the highest defined mipmap level.
680 fn max_level(&self) -> usize;
681
682 /// Sets the minimum level-of-detail parameter. This floating-point value limits the selection
683 /// of highest resolution mipmap (lowest mipmap level). The initial value is -1000.0.
684 fn set_min_lod(&mut self, min_lod: f32);
685
686 /// Returns the minimum level-of-detail parameter. See [`Self::set_min_lod`] for more info.
687 fn min_lod(&self) -> f32;
688
689 /// Sets the maximum level-of-detail parameter. This floating-point value limits the selection
690 /// of the lowest resolution mipmap (highest mipmap level). The initial value is 1000.
691 fn set_max_lod(&mut self, max_lod: f32);
692
693 /// Returns the maximum level-of-detail parameter. See [`Self::set_max_lod`] for more info.
694 fn max_lod(&self) -> f32;
695
696 /// Specifies a fixed bias value that is to be added to the level-of-detail parameter for the
697 /// texture before texture sampling. The specified value is added to the shader-supplied bias
698 /// value (if any) and subsequently clamped into the implementation-defined range
699 /// `−bias_max..bias_max`, where `bias_max` is the value that can be fetched from the current
700 /// graphics server. The initial value is 0.0.
701 fn set_lod_bias(&mut self, bias: f32);
702
703 /// Returns a fixed bias value that is to be added to the level-of-detail parameter for the
704 /// texture before texture sampling. See [`Self::set_lod_bias`] for more info.
705 fn lod_bias(&self) -> f32;
706}
707
708impl dyn GpuTexture {
709 /// Reads the pixels at the given mip level and reinterprets them using the given type.
710 pub fn get_image_of_type<T: Pod>(&self, level: usize) -> Vec<T> {
711 let mut bytes = self.get_image(level);
712
713 let typed = unsafe {
714 Vec::<T>::from_raw_parts(
715 bytes.as_mut_ptr() as *mut T,
716 bytes.len() / size_of::<T>(),
717 bytes.capacity() / size_of::<T>(),
718 )
719 };
720
721 std::mem::forget(bytes);
722
723 typed
724 }
725
726 /// Reads the pixels and reinterprets them using the given type.
727 pub fn read_pixels_of_type<T>(&self) -> Vec<T>
728 where
729 T: Pod,
730 {
731 let mut bytes = self.read_pixels();
732 let typed = unsafe {
733 Vec::<T>::from_raw_parts(
734 bytes.as_mut_ptr() as *mut T,
735 bytes.len() / size_of::<T>(),
736 bytes.capacity() / size_of::<T>(),
737 )
738 };
739 std::mem::forget(bytes);
740 typed
741 }
742}