#how pixel data into base_color_texture?

104 messages ยท Page 1 of 1 (latest)

strange crypt
#
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()
    });
}```
#

this renders each block 1 at a time and the fps dies

worn steeple
#

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

strange crypt
#

construct an image type

#

how i do that

worn steeple
#

Not the friendliest API ๐Ÿค”

strange crypt
#
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

worn steeple
#

These are going to be bytes (u8) corresponding to the colors in your chosen TextureFormat

strange crypt
#

how i store color as a u8

worn steeple
#

I wouild use the new method, rather than the fields

strange crypt
#
pub fn new(
    size: Extent3d,
    dimension: TextureDimension,
    data: Vec<u8>,
    format: TextureFormat
) -> Image```
worn steeple
#

You probably want RGB, with linear color spaces and a 32 bit color depth

#

Rgba32Sint I believe

strange crypt
#

is that a data type or a conversion function

worn steeple
#

It's a description of how to interpret the bytes

strange crypt
#

but how does it know which one im giving it

worn steeple
#

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)

strange crypt
#

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?

worn steeple
#

Size is width and height

strange crypt
#

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

worn steeple
#

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

strange crypt
worn steeple
#

Hmm ๐Ÿค”

#

Why are you calling Image()?

#

That shouldn't be a thing

strange crypt
#

u right

strange crypt
#

if r g and b are each u8s isnt that only going to account for red

worn steeple
#

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

strange crypt
#

so it shouldnt returna u8

#

it should return a u32

worn steeple
#

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

strange crypt
#

wym im using a small fraction

#

im passing in 3 u8s

#

r g and b

worn steeple
#

Ah, I see

strange crypt
#
fn rgb_to_bytes(r: u8, g: u8, b: u8) -> u32 {
    return r as u32 | g as u32 | b as u32 | 255_u32;
}```
#

better?

worn steeple
#

I would do:

fn rgb_to_bytes(r: u8, g: u8, b: u8) -> [u8;3]{
   [r, g, b]
}
#

Nice and easy

strange crypt
#

but thats not a u8

#

i thought it has to be a u8

#

not 3 u8s

#
    pub data: Vec<u8>,```
worn steeple
#

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

strange crypt
#

so the data array is expecting someting in the form of
[pixel1_r, pixel1_g, pixel1_b, pixel1_t, pixel2_r, pixel2_g...

worn steeple
strange crypt
#

does it need the tranperency?

#

seems like a wasted byte

worn steeple
#

Yeah, looks like there's no Rgb8 format listed ๐Ÿค”

#
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 ...

GitHub

What problem does this solve or what need does it fill? The Image type has quite a few complex invariants to uphold, around data layout and byte intepretation. As a result, it has several nice cons...

#

It's not just you :p

#

But writing out bytes directly is a fun and useful little exercise ๐Ÿ™‚

strange crypt
# worn steeple You want to pass in a long vector of u8
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
    );```
worn steeple
strange crypt
#

no

#

second 255

worn steeple
#

ah, I can't count

#

Getting too late here

#

Nice stuff!

strange crypt
#

yay

#

now i need to draw the image to screen

#

chat gpt is unhelpful

#

and the docs dont show how to do it

worn steeple
strange crypt
#

whats a Handle Image

worn steeple
#

Which you can use in a SpriteSheetBundle like before

worn steeple
strange crypt
#

ok

worn steeple
#

But it's centrally tracked and reference counted

strange crypt
#

what do i do with a SpriteSheetBundle

worn steeple
#

Spawn it!

#

Probably in the middle of your screen

#

(going to bed now, good luck :))

strange crypt
#

ty

strange crypt
#
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