DGriffin91 / bevy_mod_mipmap_generator

A basic mipmap generator for bevy
Apache License 2.0
27 stars 7 forks source link

How to make it work with a Texture Array #6

Open Inspirateur opened 1 month ago

Inspirateur commented 1 month ago

Hi, I'm using a texture array for my voxel game and I badly need mipmaps because Moiré makes distant terrain look like marbled cake.

I tried looking into the new CompressedImageSaver from bevy but I don't know how to make it work, because my texture array is currently generated at runtime. I think the ideal bevy setup would be to use LoadTransformAndSave to build the texture array and add mipmap to it at dev time but for this to work I need to save custom metadata about which index correspond to which block face and it doesn't seem possible right now in bevy.

Anyway all this struggle pushed me to try out your plugin which seems really neat but it doesn't seem to work in my case... I'm not sure if it's because of the texture array or the material extension.

I have this MaterialExtension:

#[derive(Asset, AsBindGroup, Debug, Clone, TypePath)]
pub struct ArrayTextureMaterial {
    #[texture(100, dimension = "2d_array")]
    #[sampler(101)]
    array_texture: Handle<Image>,
}

impl MaterialExtension for ArrayTextureMaterial {
    fn vertex_shader() -> ShaderRef {
        "shaders/chunk.wgsl".into()
    }

    fn fragment_shader() -> ShaderRef {
        "shaders/chunk.wgsl".into()
    }

    fn specialize(
            _pipeline: &MaterialExtensionPipeline,
            descriptor: &mut bevy::render::render_resource::RenderPipelineDescriptor,
            layout: &MeshVertexBufferLayoutRef,
            _key: MaterialExtensionKey<ArrayTextureMaterial>,
        ) -> Result<(), bevy::render::render_resource::SpecializedMeshPipelineError> {
            let vertex_layout = layout.0.get_layout(&[ATTRIBUTE_VOXEL_DATA.at_shader_location(0)])?;
            descriptor.vertex.buffers = vec![vertex_layout];
            Ok(())
    }
}

I also implemented GetImages:

impl GetImages for ArrayTextureMaterial {
    fn get_images(&self) -> Vec<&Handle<Image>> {
        vec![&self.array_texture]
    }
}

And this is how I create the material that is used for every block:

let handle = materials.add(ExtendedMaterial {
    base: StandardMaterial {
        perceptual_roughness: 1.,
        reflectance: 0.1,
        alpha_mode: AlphaMode::AlphaToCoverage,
        ..Default::default()
    },
    extension: ArrayTextureMaterial {
        array_texture: handle,
    }
});

Is this supposed to work with your plugin or am I doing something wrong ? And if it's not supposed to work yet, is adding support to it feasible ?

DGriffin91 commented 2 weeks ago

It doesn't currently support array textures. But support could definitely be added.