pub struct Texture2D { /* private fields */ }
Expand description
Texture, data stored in GPU memory
Implementations§
source§impl Texture2D
impl Texture2D
pub fn weak_clone(&self) -> Texture2D
sourcepub fn from_file_with_format<'a>(
bytes: &[u8],
format: Option<ImageFormat>
) -> Texture2D
pub fn from_file_with_format<'a>( bytes: &[u8], format: Option<ImageFormat> ) -> Texture2D
Creates a Texture2D from a slice of bytes that contains an encoded image.
If format
is None, it will make an educated guess on the
ImageFormat.
§Example
let texture = Texture2D::from_file_with_format(
include_bytes!("../examples/rust.png"),
None,
);
sourcepub fn from_image(image: &Image) -> Texture2D
pub fn from_image(image: &Image) -> Texture2D
Creates a Texture2D from an Image.
Examples found in repository?
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
fn color_picker_texture(w: usize, h: usize) -> (Texture2D, Image) {
let ratio = 1.0 / h as f32;
let mut image = Image::gen_image_color(w as u16, h as u16, WHITE);
let image_data = image.get_image_data_mut();
for j in 0..h {
for i in 0..w {
let lightness = 1.0 - i as f32 * ratio;
let hue = j as f32 * ratio;
image_data[i + j * w] = color::hsl_to_rgb(hue, 1.0, lightness).into();
}
}
(Texture2D::from_image(&image), image)
}
More examples
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
async fn main() {
let w = screen_width() as usize;
let h = screen_height() as usize;
let mut cells = vec![CellState::Dead; w * h];
let mut buffer = vec![CellState::Dead; w * h];
let mut image = Image::gen_image_color(w as u16, h as u16, WHITE);
for cell in cells.iter_mut() {
if rand::gen_range(0, 5) == 0 {
*cell = CellState::Alive;
}
}
let texture = Texture2D::from_image(&image);
loop {
clear_background(WHITE);
let w = image.width();
let h = image.height();
for y in 0..h as i32 {
for x in 0..w as i32 {
let mut neighbors_count = 0;
for j in -1i32..=1 {
for i in -1i32..=1 {
// out of bounds
if y + j < 0 || y + j >= h as i32 || x + i < 0 || x + i >= w as i32 {
continue;
}
// cell itself
if i == 0 && j == 0 {
continue;
}
let neighbor = cells[(y + j) as usize * w + (x + i) as usize];
if neighbor == CellState::Alive {
neighbors_count += 1;
}
}
}
let current_cell = cells[y as usize * w + x as usize];
buffer[y as usize * w + x as usize] = match (current_cell, neighbors_count) {
// Rule 1: Any live cell with fewer than two live neighbours
// dies, as if caused by underpopulation.
(CellState::Alive, x) if x < 2 => CellState::Dead,
// Rule 2: Any live cell with two or three live neighbours
// lives on to the next generation.
(CellState::Alive, 2) | (CellState::Alive, 3) => CellState::Alive,
// Rule 3: Any live cell with more than three live
// neighbours dies, as if by overpopulation.
(CellState::Alive, x) if x > 3 => CellState::Dead,
// Rule 4: Any dead cell with exactly three live neighbours
// becomes a live cell, as if by reproduction.
(CellState::Dead, 3) => CellState::Alive,
// All other cells remain in the same state.
(otherwise, _) => otherwise,
};
}
}
for i in 0..buffer.len() {
cells[i] = buffer[i];
image.set_pixel(
(i % w) as u32,
(i / w) as u32,
match buffer[i as usize] {
CellState::Alive => BLACK,
CellState::Dead => WHITE,
},
);
}
texture.update(&image);
draw_texture(&texture, 0., 0., WHITE);
next_frame().await
}
}
sourcepub fn from_miniquad_texture(texture: TextureId) -> Texture2D
pub fn from_miniquad_texture(texture: TextureId) -> Texture2D
Creates a Texture2D from a miniquad Texture
sourcepub fn from_rgba8(width: u16, height: u16, bytes: &[u8]) -> Texture2D
pub fn from_rgba8(width: u16, height: u16, bytes: &[u8]) -> Texture2D
Creates a Texture2D from a slice of bytes in an R,G,B,A sequence, with the given width and height.
§Example
// Create a 2x2 texture from a byte slice with 4 rgba pixels
let bytes: Vec<u8> = vec![255, 0, 0, 192, 0, 255, 0, 192, 0, 0, 255, 192, 255, 255, 255, 192];
let texture = Texture2D::from_rgba8(2, 2, &bytes);
sourcepub fn update(&self, image: &Image)
pub fn update(&self, image: &Image)
Uploads Image data to this texture.
Examples found in repository?
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
async fn main() {
let w = screen_width() as usize;
let h = screen_height() as usize;
let mut cells = vec![CellState::Dead; w * h];
let mut buffer = vec![CellState::Dead; w * h];
let mut image = Image::gen_image_color(w as u16, h as u16, WHITE);
for cell in cells.iter_mut() {
if rand::gen_range(0, 5) == 0 {
*cell = CellState::Alive;
}
}
let texture = Texture2D::from_image(&image);
loop {
clear_background(WHITE);
let w = image.width();
let h = image.height();
for y in 0..h as i32 {
for x in 0..w as i32 {
let mut neighbors_count = 0;
for j in -1i32..=1 {
for i in -1i32..=1 {
// out of bounds
if y + j < 0 || y + j >= h as i32 || x + i < 0 || x + i >= w as i32 {
continue;
}
// cell itself
if i == 0 && j == 0 {
continue;
}
let neighbor = cells[(y + j) as usize * w + (x + i) as usize];
if neighbor == CellState::Alive {
neighbors_count += 1;
}
}
}
let current_cell = cells[y as usize * w + x as usize];
buffer[y as usize * w + x as usize] = match (current_cell, neighbors_count) {
// Rule 1: Any live cell with fewer than two live neighbours
// dies, as if caused by underpopulation.
(CellState::Alive, x) if x < 2 => CellState::Dead,
// Rule 2: Any live cell with two or three live neighbours
// lives on to the next generation.
(CellState::Alive, 2) | (CellState::Alive, 3) => CellState::Alive,
// Rule 3: Any live cell with more than three live
// neighbours dies, as if by overpopulation.
(CellState::Alive, x) if x > 3 => CellState::Dead,
// Rule 4: Any dead cell with exactly three live neighbours
// becomes a live cell, as if by reproduction.
(CellState::Dead, 3) => CellState::Alive,
// All other cells remain in the same state.
(otherwise, _) => otherwise,
};
}
}
for i in 0..buffer.len() {
cells[i] = buffer[i];
image.set_pixel(
(i % w) as u32,
(i / w) as u32,
match buffer[i as usize] {
CellState::Alive => BLACK,
CellState::Dead => WHITE,
},
);
}
texture.update(&image);
draw_texture(&texture, 0., 0., WHITE);
next_frame().await
}
}
sourcepub fn update_part(
&self,
image: &Image,
x_offset: i32,
y_offset: i32,
width: i32,
height: i32
)
pub fn update_part( &self, image: &Image, x_offset: i32, y_offset: i32, width: i32, height: i32 )
Uploads Image data to part of this texture.
sourcepub fn width(&self) -> f32
pub fn width(&self) -> f32
Returns the width of this texture.
Examples found in repository?
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
async fn main() {
let mut rustaceanes: Vec<Rustaceane> = Vec::new();
let rustacean_tex = load_texture("examples/rustacean_happy.png").await.unwrap();
rustacean_tex.set_filter(FilterMode::Nearest);
loop {
clear_background(Color::default());
if macroquad::input::is_mouse_button_down(MouseButton::Left) {
for _i in 0..100 {
rustaceanes.push(Rustaceane {
pos: Vec2::from(macroquad::input::mouse_position()),
speed: Vec2::new(
rand::gen_range(-250., 250.) / 60.,
rand::gen_range(-250., 250.) / 60.,
),
color: Color::from_rgba(
rand::gen_range(50, 240),
rand::gen_range(80, 240),
rand::gen_range(100, 240),
255,
),
})
}
}
for rustaceane in &mut rustaceanes {
rustaceane.pos += rustaceane.speed;
if ((rustaceane.pos.x + rustacean_tex.width() / 2.) > screen_width())
|| ((rustaceane.pos.x + rustacean_tex.width() / 2.) < 0.)
{
rustaceane.speed.x *= -1.;
}
if ((rustaceane.pos.y + rustacean_tex.height() / 2.) > screen_height())
|| ((rustaceane.pos.y + rustacean_tex.height() / 2.) < 0.)
{
rustaceane.speed.y *= -1.;
}
draw_texture(
&rustacean_tex,
rustaceane.pos.x,
rustaceane.pos.y,
rustaceane.color,
);
}
draw_text(format!("FPS: {}", get_fps()).as_str(), 0., 16., 32., WHITE);
draw_text(
format!("Rustaceanes: {}", rustaceanes.len()).as_str(),
0.,
32.,
32.,
WHITE,
);
next_frame().await
}
}
sourcepub fn height(&self) -> f32
pub fn height(&self) -> f32
Returns the height of this texture.
Examples found in repository?
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
async fn main() {
let mut rustaceanes: Vec<Rustaceane> = Vec::new();
let rustacean_tex = load_texture("examples/rustacean_happy.png").await.unwrap();
rustacean_tex.set_filter(FilterMode::Nearest);
loop {
clear_background(Color::default());
if macroquad::input::is_mouse_button_down(MouseButton::Left) {
for _i in 0..100 {
rustaceanes.push(Rustaceane {
pos: Vec2::from(macroquad::input::mouse_position()),
speed: Vec2::new(
rand::gen_range(-250., 250.) / 60.,
rand::gen_range(-250., 250.) / 60.,
),
color: Color::from_rgba(
rand::gen_range(50, 240),
rand::gen_range(80, 240),
rand::gen_range(100, 240),
255,
),
})
}
}
for rustaceane in &mut rustaceanes {
rustaceane.pos += rustaceane.speed;
if ((rustaceane.pos.x + rustacean_tex.width() / 2.) > screen_width())
|| ((rustaceane.pos.x + rustacean_tex.width() / 2.) < 0.)
{
rustaceane.speed.x *= -1.;
}
if ((rustaceane.pos.y + rustacean_tex.height() / 2.) > screen_height())
|| ((rustaceane.pos.y + rustacean_tex.height() / 2.) < 0.)
{
rustaceane.speed.y *= -1.;
}
draw_texture(
&rustacean_tex,
rustaceane.pos.x,
rustaceane.pos.y,
rustaceane.color,
);
}
draw_text(format!("FPS: {}", get_fps()).as_str(), 0., 16., 32., WHITE);
draw_text(
format!("Rustaceanes: {}", rustaceanes.len()).as_str(),
0.,
32.,
32.,
WHITE,
);
next_frame().await
}
}
pub fn size(&self) -> Vec2
sourcepub fn set_filter(&self, filter_mode: FilterMode)
pub fn set_filter(&self, filter_mode: FilterMode)
Sets the FilterMode of this texture.
Use Nearest if you need integer-ratio scaling for pixel art, for example.
§Example
let texture = Texture2D::empty();
texture.set_filter(FilterMode::Linear);
Examples found in repository?
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
async fn main() {
let render_target = render_target(320, 150);
render_target.texture.set_filter(FilterMode::Nearest);
let material = load_material(
ShaderSource::Glsl {
vertex: CRT_VERTEX_SHADER,
fragment: CRT_FRAGMENT_SHADER,
},
Default::default(),
)
.unwrap();
loop {
// drawing to the texture
// 0..100, 0..100 camera
set_camera(&Camera2D {
zoom: vec2(0.01, 0.01),
target: vec2(0.0, 0.0),
render_target: Some(render_target.clone()),
..Default::default()
});
clear_background(LIGHTGRAY);
draw_line(-30.0, 45.0, 30.0, 45.0, 3.0, BLUE);
draw_circle(-45.0, -35.0, 20.0, YELLOW);
draw_circle(45.0, -35.0, 20.0, GREEN);
// drawing to the screen
set_default_camera();
clear_background(WHITE);
gl_use_material(&material);
draw_texture_ex(
&render_target.texture,
0.,
0.,
WHITE,
DrawTextureParams {
dest_size: Some(vec2(screen_width(), screen_height())),
..Default::default()
},
);
gl_use_default_material();
next_frame().await;
}
}
More examples
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
async fn main() {
let mut rustaceanes: Vec<Rustaceane> = Vec::new();
let rustacean_tex = load_texture("examples/rustacean_happy.png").await.unwrap();
rustacean_tex.set_filter(FilterMode::Nearest);
loop {
clear_background(Color::default());
if macroquad::input::is_mouse_button_down(MouseButton::Left) {
for _i in 0..100 {
rustaceanes.push(Rustaceane {
pos: Vec2::from(macroquad::input::mouse_position()),
speed: Vec2::new(
rand::gen_range(-250., 250.) / 60.,
rand::gen_range(-250., 250.) / 60.,
),
color: Color::from_rgba(
rand::gen_range(50, 240),
rand::gen_range(80, 240),
rand::gen_range(100, 240),
255,
),
})
}
}
for rustaceane in &mut rustaceanes {
rustaceane.pos += rustaceane.speed;
if ((rustaceane.pos.x + rustacean_tex.width() / 2.) > screen_width())
|| ((rustaceane.pos.x + rustacean_tex.width() / 2.) < 0.)
{
rustaceane.speed.x *= -1.;
}
if ((rustaceane.pos.y + rustacean_tex.height() / 2.) > screen_height())
|| ((rustaceane.pos.y + rustacean_tex.height() / 2.) < 0.)
{
rustaceane.speed.y *= -1.;
}
draw_texture(
&rustacean_tex,
rustaceane.pos.x,
rustaceane.pos.y,
rustaceane.color,
);
}
draw_text(format!("FPS: {}", get_fps()).as_str(), 0., 16., 32., WHITE);
draw_text(
format!("Rustaceanes: {}", rustaceanes.len()).as_str(),
0.,
32.,
32.,
WHITE,
);
next_frame().await
}
}
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
async fn main() {
// Setup 'render_target', used to hold the rendering result so we can resize it
let render_target = render_target(VIRTUAL_WIDTH as u32, VIRTUAL_HEIGHT as u32);
render_target.texture.set_filter(FilterMode::Linear);
// Setup camera for the virtual screen, that will render to 'render_target'
let mut render_target_cam =
Camera2D::from_display_rect(Rect::new(0., 0., VIRTUAL_WIDTH, VIRTUAL_HEIGHT));
render_target_cam.render_target = Some(render_target.clone());
loop {
// Get required scaling value
let scale: f32 = f32::min(
screen_width() / VIRTUAL_WIDTH,
screen_height() / VIRTUAL_HEIGHT,
);
// Mouse position in the virtual screen
let virtual_mouse_pos = Vec2 {
x: (mouse_position().0 - (screen_width() - (VIRTUAL_WIDTH * scale)) * 0.5) / scale,
y: (mouse_position().1 - (screen_height() - (VIRTUAL_HEIGHT * scale)) * 0.5) / scale,
};
// ------------------------------------------------------------------------
// Begin drawing the virtual screen to 'render_target'
// ------------------------------------------------------------------------
set_camera(&render_target_cam);
clear_background(LIGHTGRAY);
draw_text("Hello Letterbox", 20.0, 20.0, 30.0, DARKGRAY);
draw_circle(VIRTUAL_WIDTH / 2.0 - 65.0, VIRTUAL_HEIGHT / 2.0, 35.0, RED);
draw_circle(VIRTUAL_WIDTH / 2.0 + 65.0, VIRTUAL_HEIGHT / 2.0, 35.0, BLUE);
draw_circle(
VIRTUAL_WIDTH / 2.0,
VIRTUAL_HEIGHT / 2.0 - 65.0,
35.0,
YELLOW,
);
draw_circle(virtual_mouse_pos.x, virtual_mouse_pos.y, 15.0, BLACK);
// ------------------------------------------------------------------------
// Begin drawing the window screen
// ------------------------------------------------------------------------
set_default_camera();
clear_background(BLACK); // Will be the letterbox color
// Draw 'render_target' to window screen, porperly scaled and letterboxed
draw_texture_ex(
&render_target.texture,
(screen_width() - (VIRTUAL_WIDTH * scale)) * 0.5,
(screen_height() - (VIRTUAL_HEIGHT * scale)) * 0.5,
WHITE,
DrawTextureParams {
dest_size: Some(vec2(VIRTUAL_WIDTH * scale, VIRTUAL_HEIGHT * scale)),
flip_y: true, // Must flip y otherwise 'render_target' will be upside down
..Default::default()
},
);
next_frame().await;
}
}
sourcepub fn raw_miniquad_id(&self) -> TextureId
pub fn raw_miniquad_id(&self) -> TextureId
Returns the handle for this texture.
sourcepub fn grab_screen(&self)
pub fn grab_screen(&self)
Updates this texture from the screen.
sourcepub fn get_texture_data(&self) -> Image
pub fn get_texture_data(&self) -> Image
Returns an Image from the pixel data in this texture.
This operation can be expensive.