bevy icon indicating copy to clipboard operation
bevy copied to clipboard

Mesh is missing requested attribute: Vertex_Normal error

Open EngoDev opened this issue 1 year ago • 1 comments

Bevy version

0.13.1

[Optional] Relevant system information

If your bug is rendering-related, copy the adapter info that appears when you run Bevy.

AdapterInfo { name: "NVIDIA GeForce RTX 4060", vendor: 4318, device: 10370, device_type: DiscreteGpu, driver: "NVIDIA", driver_info: "550.54.14", backend: Vulkan }

What you did

I created a custom shader that uses compressed normals and position data into a u32 . Meaning I only needed my custom attribute in my shader layout so I removed the rest of the standard layout items like POSITION and NORMAL

This is my code:

pub const ATTRIBUTE_VOXEL_DATA: MeshVertexAttribute =
    MeshVertexAttribute::new("VoxelTypeId", 988540917, VertexFormat::Uint32x2);


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

impl Material for ChunkMaterial {
    fn vertex_shader() -> ShaderRef {
        "shaders/chunk_shader_new.wgsl".into()
    }

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

    fn alpha_mode(&self) -> AlphaMode {
        AlphaMode::Opaque
    }

    fn specialize(
            _pipeline: &bevy::pbr::MaterialPipeline<Self>,
            descriptor: &mut bevy::render::render_resource::RenderPipelineDescriptor,
            layout: &bevy::render::mesh::MeshVertexBufferLayout,
            _key: bevy::pbr::MaterialPipelineKey<Self>,
        ) -> Result<(), bevy::render::render_resource::SpecializedMeshPipelineError> {

        // The shader location needs to match the one in the prepass_io
        // https://github.com/bevyengine/bevy/blob/main/crates/bevy_pbr/src/prepass/prepass_io.wgsl
        let vertex_layout = layout.get_layout(&[
            ATTRIBUTE_VOXEL_DATA.at_shader_location(30),
        ])?;

        descriptor.vertex.buffers = vec![vertex_layout];
        // descriptor.primitive.cull_mode = None;

        Ok(())
    }

    fn prepass_vertex_shader() -> ShaderRef {
        "shaders/chunk_prepass.wgsl".into()
    }

    fn prepass_fragment_shader() -> ShaderRef {
        "shaders/chunk_prepass.wgsl".into()
    }
}

What went wrong

I get the following error from bevy: Mesh is missing requested attribute: Vertex_Normal (MeshVertexAttributeId(1), pipeline type: Some("bevy_pbr::prepass::PrepassPipeline<bevy_voxel::voxel_engine::rendering::ChunkMaterial>"))

Additional information

More info can be checked by reading this message and the conversation that lead to it and after: https://discord.com/channels/691052431525675048/866787577687310356/1231657933490753666

It contains a possible explanation from Jasmine on what is the problem.

I used a workaround to add the Normal attribute in my layout and then supply dummy data to make it happy.

let vertex_layout = layout.get_layout(&[
    Mesh::ATTRIBUTE_NORMAL.at_shader_location(3),
    ATTRIBUTE_VOXEL_DATA.at_shader_location(30),
])?;
let mut normals: Vec<[f32; 3]> = Vec::new();
normals.resize(mesh.vertices.len(), [0.0, 0.0, 0.0]);
mesh.insert_attribute(Mesh::ATTRIBUTE_NORMAL, normals);

EngoDev avatar Apr 21 '24 18:04 EngoDev

The issue is here: https://github.com/bevyengine/bevy/blob/13cac2eeff7e3c4da7ae636ba3766f59b4e343d0/crates/bevy_pbr/src/prepass/mod.rs#L402

JMS55 avatar Apr 21 '24 18:04 JMS55