#Creating a texture image from array

13 messages · Page 1 of 1 (latest)

modest nest
#

Hello,

In order to test a Noise function I've translated from JavaScript, I need to learn first how to create images from arrays.

I've naively tried the following

fn assets_loading(mut commands: Commands, mut assets: ResMut<Assets<Image>>) {

    let mut data: Vec<u8> = Vec::new();

    for i in 0..255 {
        data.push(50);
        data.push(255);
        data.push(50);
        data.push(255);
    }

    let image = Image::new(Extent3d {
        width: 1,
        height: 1,
        depth_or_array_layers: 1
    }, TextureDimension::D2, data, TextureFormat::Rgba16Unorm);

    commands.insert_resource(WorldAssets {
        texture: assets.add(image),
    })
}

but I receive thread 'main' panicked at 'cannot get pixel info for type' because (I suspect) the data array is not of the expected size.

My question is how can I exactly know the size of the data: Vec<u8> I need to build?

Thanks

left saddle
#

@modest nest at the risk of getting something wrong, the i way thought about it when doing something very similar, was width * height * textureformat / dimension where from the code above, the dimension number would be 2 and the texture format number would be 16.

#

here's where I did my own similar thing

hollow gulch
#

this is fixed on main branch, so you could potentially use that or switch to one of the formats that is listed

modest nest
#

Thanks,

you were both right:

First I replaced Rgba16Unorm with Rgba16Float. @hollow gulch
Then I used the @left saddle formula to compute the size of the data.

Now I receive no errors anymore, but the texture looks always black no matter what numbers I put in the data.

this is the modified image creation:

    let mut data: Vec<u8> = Vec::new();
    let size = (1 * 1 * 16 / 2) / 4;

    for i in 0..size {
        data.push(100);     // red?
        data.push(10);      // green?
        data.push(10);      // blue?
        data.push(255);     // alpha?
    }

    let image = Image::new(Extent3d {
        width: 1,
        height: 1,
        depth_or_array_layers: 1
    }, TextureDimension::D2, data, TextureFormat::Rgba16Float);

and this is the image texture loading:

    commands
        .spawn((
            PbrBundle {
                mesh: meshes.add(Mesh::from(shape::Icosphere {
                    radius: 0.7,
                    subdivisions: 0,
                })),
                material: materials.add(StandardMaterial {
                    base_color: Color::rgba(1.0, 0.3, 0.3, 0.2).into(),
                    base_color_texture: Some(world_assets.texture.clone()),
                    ..default()
                }),
                ..default()
            },
            Wireframe,
        ))...

Can you please explain how can I get some colours from the texture?

Also I was wondering why when I control clicked on TextureFormat , Rgba16Unorm was available when is clearly not available in bevy 0.9.1.

I'm using Visual Studio Code as IDE.

Thanks.

hollow gulch
#

you're pushing u8's into your data buffer, but you specified the format as 16bit floats for each color

#

So push(100) push(10) is going into the red channel

#

What that translates into in float 16 land, I have no clue, but I wouldn't be surprised if it's a very small number

modest nest
#

But the Image::new constructor only accepts u8 as data parameter. How am I supposed to use Rgba16Float texture format given such restriction?

vague galleon
#

My guess is the Vec<u8> that it wants is meant to be the raw bytes, and then the texture format indicates how those bytes should be interpreted. So you'd need to somehow obtain each f16 as two individual bytes and push both of those to the data vector in the right order

left saddle
#

with more or less what you have there @modest nest I can get a sprite rendering with TextureFormat::Rgba8Unorm but unfortunately don't know what it takes to build up an Rgba16Float image. Fwiw you might be able to use an image editor like Gimp to create some small raw image with that pixel format to inspect manually 🤔 also, while poking around TextureFormat, I realized you can get the pixel size for the format directly with TextureFormat::Rgba16Float.pixel_size() so I can revise my initial formula to width * height * TextureFormat::Rgba16Float.pixel_size()