use bevy::{diagnostic::LogDiagnosticsPlugin, ecs::{component::Component, query::With, schedule::IntoSystemConfigs, system::{Commands, Query, Res, ResMut, Resource}}, render::{settings::{Backends, RenderCreation, WgpuSettings}, RenderPlugin}, time::{Time, Timer, TimerMode}, window::PresentMode, DefaultPlugins};
use bevy::app::*;
use bevy::{prelude::*, window::WindowResized};
use bevy_fps_counter::{FpsCounter, FpsCounterPlugin};
const WINDOW_WIDTH: f32 = 2000.;
const WINDOW_HEIGHT: f32 = 1300.;
const BLOCK_SIZE: f32 = 10.;
const BLOCKS_PER_ROW: f32 = WINDOW_WIDTH / BLOCK_SIZE;
const BLOCKS_PER_COL: f32 = WINDOW_HEIGHT / BLOCK_SIZE;
fn main() {
App::new()
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
present_mode: PresentMode::AutoNoVsync,
title: "UwU".into(),
resolution: (WINDOW_WIDTH, WINDOW_HEIGHT).into(),
..default()
}),
..default()
}))
.add_plugins(FpsCounterPlugin)
.add_systems(Startup, setup)
.run();
}
fn setup(mut commands: Commands) {
commands.spawn(Camera2dBundle::default());
for row in 0..BLOCKS_PER_ROW as i32{
for col in 0..BLOCKS_PER_COL as i32{
draw_rect(&mut commands, row as f32 * BLOCK_SIZE, col as f32 * BLOCK_SIZE, Color::rgb(255., 0., 0.), BLOCK_SIZE, BLOCK_SIZE);
}
}
}
fn draw_rect(commands: &mut Commands, x: f32, y: f32, color: Color, h: f32, w: f32){
commands.spawn(SpriteBundle {
sprite: Sprite {
color,
custom_size: Some(Vec2::new(h, w)),
..default()
},
transform: Transform::from_translation(Vec3::new(x - WINDOW_WIDTH/2., y - WINDOW_HEIGHT/2., 0.)),
..default()
});
}```
#how pixel data into base_color_texture?
104 messages ยท Page 1 of 1 (latest)
You probably want to construct an Image type manually if you're interested in easily setting the values of pixels directly ๐
There's probably faster approaches with shaders
But this is a simple middle ground
https://docs.rs/bevy/latest/bevy/prelude/struct.Image.html
This is the type
API documentation for the Rust Image struct in crate bevy.
Not the friendliest API ๐ค
ive noticed
pub struct Image {
pub data: Vec<u8>,
pub texture_descriptor: TextureDescriptor<Option<&'static str>, &'static [TextureFormat]>,
pub sampler: ImageSampler,
pub texture_view_descriptor: Option<TextureViewDescriptor<'static>>,
}```
ok this is how i make one
what is the data
These are going to be bytes (u8) corresponding to the colors in your chosen TextureFormat
how i store color as a u8
I wouild use the new method, rather than the fields
pub fn new(
size: Extent3d,
dimension: TextureDimension,
data: Vec<u8>,
format: TextureFormat
) -> Image```
So, you pick one of these formats: https://docs.rs/bevy/latest/bevy/render/render_resource/enum.TextureFormat.html
Underlying texture data format.
You probably want RGB, with linear color spaces and a 32 bit color depth
Rgba32Sint I believe
is that a data type or a conversion function
It's a description of how to interpret the bytes
but how does it know which one im giving it
You pass in the TextureFormat argument to the new function, to describe the format to it
Pixels are arrange left-to-right, top-to-bottom by convention
Just like reading a book
(this API and the docs are not great; I'll make an issue or two)
so i make a function that turns human readable rgb into a Rgba32Sint. I pass that as an array of every pixel converted
what is the difference between size and dimension?
Dimensionality is line vs. image vs. 3D grid of pixels
Size is width and height
huh
oh ok
2D
am i creating a new image every frame or am i able to modify the data and reuse the image
probably modify
You should be able to modify it ๐
The image that you create will get registered in the asset server, like any other asset
And then you hand out a handle to e.g. a single SpriteBundle entity
its refering the wrong Image even being told exactly which one to reference
u right
fn rgb_to_bytes(r: u8, g: u8, b: u8) -> u8 {
let rgba32_sint: u32 = (r as i32 | g as i32 | b as i32 | 255_i32) as u32;
rgba32_sint as u8
}
is it not sus that it lets me turn a u32 into a u8
if r g and b are each u8s isnt that only going to account for red
Your colors will just be very black :p
If you only want 8 bit colors use one of the 8 bit formats
Which will be more memory efficient
It should return a [u8;3]
Presumably?
Or a [u32;3], but that seems pointless
Since you're only using a small fraction of the actual information if you pass in u8s
Ah, I see
fn rgb_to_bytes(r: u8, g: u8, b: u8) -> u32 {
return r as u32 | g as u32 | b as u32 | 255_u32;
}```
better?
I would do:
fn rgb_to_bytes(r: u8, g: u8, b: u8) -> [u8;3]{
[r, g, b]
}
Nice and easy
but thats not a u8
i thought it has to be a u8
not 3 u8s
pub data: Vec<u8>,```
You want to pass in a long vector of u8
And you'll use multiple bytes to represent each pixel
The adjacent ones will correspond to the same pixel
so the data array is expecting someting in the form of
[pixel1_r, pixel1_g, pixel1_b, pixel1_t, pixel2_r, pixel2_g...
This actually looks like the best format for you
Underlying texture data format.
Yep, exactly
ok that makes sense i didnt know that
does it need the tranperency?
seems like a wasted byte
Yeah, looks like there's no Rgb8 format listed ๐ค
I filed:
- https://github.com/bevyengine/bevy/issues/11886
- https://github.com/bevyengine/bevy/issues/11887
- https://github.com/bevyengine/bevy/issues/11888
as a result of this discussion ๐
GitHub
How can Bevy's documentation be improved? The Image type is very low-level, and not approachable for beginners. For example: What does the data field store, in what order, and how is it related...
GitHub
What problem does this solve or what need does it fill? Building images from programmatically controlled data can be a useful tool for getting reasonably high performance without having to swap to ...
It's not just you :p
But writing out bytes directly is a fun and useful little exercise ๐
let mut grid_image = Image::new(
Extent3d {
width: WINDOW_WIDTH as u32,
height: WINDOW_HEIGHT as u32,
depth_or_array_layers: 1,
},
TextureDimension::D2,
(0..100).flat_map(|_| vec![255, 0, 0, 255]).collect(),
TextureFormat::Rgba32Sint
);```
You seem to be missing alpha ๐
yay
now i need to draw the image to screen
chat gpt is unhelpful
and the docs dont show how to do it
AssetServer::load will get you a Handle<Image>
whats a Handle Image
Which you can use in a SpriteSheetBundle like before
A handle is basically a fancy reference to this data
ok
But it's centrally tracked and reference counted
what do i do with a SpriteSheetBundle
ty
use bevy::{ecs::system::Commands, render::{render_resource::{Extent3d, Texture, TextureDimension, TextureFormat}, settings::{Backends, RenderCreation, WgpuSettings}, RenderPlugin}, time::{Time, Timer, TimerMode}, window::PresentMode, DefaultPlugins};
use bevy::app::*;
use bevy::{prelude::*, window::WindowResized};
use bevy_fps_counter::{FpsCounter, FpsCounterPlugin};
use bevy::prelude::Image;
const WINDOW_WIDTH: f32 = 2000.;
const WINDOW_HEIGHT: f32 = 1300.;
const BLOCK_SIZE: f32 = 10.;
const BLOCKS_PER_ROW: f32 = WINDOW_WIDTH / BLOCK_SIZE;
const BLOCKS_PER_COL: f32 = WINDOW_HEIGHT / BLOCK_SIZE;
const TOTAL_PIXELS: f32 = WINDOW_WIDTH * WINDOW_HEIGHT;
fn main() {
App::new()
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
present_mode: PresentMode::AutoNoVsync,
title: "UwU".into(),
resolution: (WINDOW_WIDTH, WINDOW_HEIGHT).into(),
..default()
}),
..default()
}))
.add_plugins(FpsCounterPlugin)
.add_systems(Startup, setup)
.run();
}
fn setup(mut commands: Commands, mut materials: ResMut<Assets<ColorMaterial>>, asset_server: Res<AssetServer>) {
commands.spawn(Camera2dBundle::default());
let mut grid_data = Image::new(
Extent3d {
width: WINDOW_WIDTH as u32,
height: WINDOW_HEIGHT as u32,
depth_or_array_layers: 1,
},
TextureDimension::D2,
(0..TOTAL_PIXELS as i32).flat_map(|_| vec![255, 0, 0, 255]).collect(),
TextureFormat::Rgba8UnormSrgb
);
let handle = asset_server.add(grid_data);
commands.spawn(handle);
}
fn rgb_to_bytes(r: u8, g: u8, b: u8) -> u32 {
return r as u32 | g as u32 | b as u32 | 255_u32;
}```
no display on the screen