Skip to main content

geng_utils/
texture.rs

1use geng::prelude::*;
2
3use crate::conversions::Vec2RealConversions;
4
5/// Construct a new black texture of the given size.
6pub fn new_texture(ugli: &Ugli, size: vec2<usize>) -> ugli::Texture {
7    ugli::Texture::new_with(ugli, size, |_| Rgba::BLACK)
8}
9
10/// Ensure the texture's size is equal to `size`.
11/// If the size is the same, the texture doesn't change.
12pub fn update_texture_size(texture: &mut ugli::Texture, size: vec2<usize>, ugli: &Ugli) {
13    if texture.size() != size {
14        *texture = ugli::Texture::new_with(ugli, size, |_| Rgba::BLACK);
15        texture.set_filter(ugli::Filter::Nearest);
16    }
17}
18
19/// Attach a texture to a color-only framebuffer.
20pub fn attach_texture<'a>(texture: &'a mut ugli::Texture, ugli: &Ugli) -> ugli::Framebuffer<'a> {
21    ugli::Framebuffer::new_color(ugli, ugli::ColorAttachment::Texture(texture))
22}
23
24/// Helper for rendering textures.
25pub struct DrawTexture<'a> {
26    /// The texture to render.
27    pub texture: &'a ugli::Texture,
28    /// World position to render at.
29    pub target: Aabb2<f32>,
30    /// Color to render the texture with.
31    pub color: Rgba<f32>,
32    // TODO: DrawParameters
33}
34
35impl<'a> DrawTexture<'a> {
36    pub fn new(texture: &'a ugli::Texture) -> Self {
37        Self {
38            texture,
39            target: Aabb2::ZERO.extend_positive(texture.size().as_f32()),
40            color: Rgba::WHITE,
41        }
42    }
43
44    pub fn colored(self, color: Rgba<f32>) -> Self {
45        Self { color, ..self }
46    }
47
48    /// Fit into the target [Aabb2] in world space and align.
49    pub fn fit(self, target: Aabb2<f32>, align: vec2<f32>) -> Self {
50        let target = crate::layout::fit_aabb(self.texture.size().as_f32(), target, align);
51        Self { target, ..self }
52    }
53
54    /// Fit into the target [Aabb2] by width in world space and align vertically.
55    pub fn fit_width(self, target: Aabb2<f32>, align: f32) -> Self {
56        let target = crate::layout::fit_aabb_width(self.texture.size().as_f32(), target, align);
57        Self { target, ..self }
58    }
59
60    /// Fit into the target [Aabb2] by height in world space and align horizontally.
61    pub fn fit_height(self, target: Aabb2<f32>, align: f32) -> Self {
62        let target = crate::layout::fit_aabb_height(self.texture.size().as_f32(), target, align);
63        Self { target, ..self }
64    }
65
66    /// Fit to the whole framebuffer.
67    pub fn fit_screen(self, align: vec2<f32>, framebuffer: &ugli::Framebuffer) -> Self {
68        self.fit(
69            Aabb2::ZERO.extend_positive(framebuffer.size().as_f32()),
70            align,
71        )
72    }
73
74    /// Fit to the width of the framebuffer.
75    pub fn fit_screen_width(self, align: f32, framebuffer: &mut ugli::Framebuffer) -> Self {
76        self.fit_width(
77            Aabb2::ZERO.extend_positive(framebuffer.size().as_f32()),
78            align,
79        )
80    }
81
82    /// Fit to the height of the framebuffer.
83    pub fn fit_screen_height(self, align: f32, framebuffer: &mut ugli::Framebuffer) -> Self {
84        self.fit_height(
85            Aabb2::ZERO.extend_positive(framebuffer.size().as_f32()),
86            align,
87        )
88    }
89
90    /// Align to pixel-perfect: such that pixels of the texture align with the pixels of the framebuffer.
91    pub fn pixel_perfect(
92        self,
93        pos: vec2<f32>,
94        align: vec2<f32>,
95        camera: &impl geng::AbstractCamera2d,
96        framebuffer: &mut ugli::Framebuffer,
97    ) -> Self {
98        let target = crate::pixel::pixel_perfect_aabb(
99            pos,
100            align,
101            self.texture.size(),
102            camera,
103            framebuffer.size().as_f32(),
104        );
105        Self { target, ..self }
106    }
107
108    pub fn draw(
109        self,
110        camera: &impl geng::AbstractCamera2d,
111        geng: &Geng,
112        framebuffer: &mut ugli::Framebuffer,
113    ) {
114        geng.draw2d()
115            .textured_quad(framebuffer, camera, self.target, self.texture, self.color);
116    }
117}