bevy_vrm1 0.1.2

Allows you to use VRM and VRMA in Bevy
Documentation
#import bevy_pbr::{
    skinning::skin_model,
    mesh_functions::{
        mesh_position_local_to_world,
        mesh_normal_local_to_world,
        get_world_from_local,
    },
    mesh_bindings::mesh,
    morph,
    view_transformations::position_world_to_clip
}

struct OutlineUniform{
    width_factor: f32,
    color: vec4<f32>,
    lighting_mix_factor: f32,
}

@group(2) @binding(0) var<uniform> outline: OutlineUniform;

struct Vertex {
    @builtin(instance_index) instance_index: u32,
    @location(0) position: vec3<f32>,
    @location(1) normal: vec3<f32>,
    #ifdef SKINNED
        @location(5) joint_indices: vec4<u32>,
        @location(6) joint_weights: vec4<f32>,
    #endif
};

struct VertexOutput {
    @builtin(position) clip_position: vec4<f32>,
    @location(0) world_position: vec4<f32>,
};

@vertex
fn vertex(vertex_no_morph: Vertex) -> VertexOutput {
#ifdef MORPH_TARGETS
    var vertex = morph_vertex(vertex_no_morph);
#else
    var vertex = vertex_no_morph;
#endif

#ifdef SKINNED
    let world_from_local = skin_model(
        vertex.joint_indices,
        vertex.joint_weights,
        vertex.instance_index
    );
#else // SKINNED
    let world_from_local = get_world_from_local(vertex.instance_index);
#endif // SKINNED
    var world_position = mesh_position_local_to_world(world_from_local, vec4(vertex.position, 1.0));
    let world_normal = normalize(mesh_normal_local_to_world(vertex.normal, vertex.instance_index));
    var out: VertexOutput;
    world_position = vec4(world_position.xyz + world_normal.xyz * outline.width_factor, 1.0);
    out.world_position = world_position;
    out.clip_position = position_world_to_clip(out.world_position.xyz);
    return out;
}

@fragment
fn fragment(in: VertexOutput) -> @location(0) vec4<f32> {
    //TODO: Apply lighting mix factor
//        let color = outline.color.rgb * mix(vec3(1.), outline.base_color, outline.lighting_mix_factor);
//        return half4(outlineCol, outline.color.a);
    return outline.color;
}


#ifdef MORPH_TARGETS
fn morph_vertex(vertex_in: Vertex) -> Vertex {
    var vertex = vertex_in;
    let first_vertex = mesh[vertex.instance_index].first_vertex_index;
    let vertex_index = vertex.instance_index - first_vertex;

    let weight_count = morph::layer_count();
    for (var i: u32 = 0u; i < weight_count; i ++) {
        let weight = morph::weight_at(i);
        if weight == 0.0 {
            continue;
        }
        vertex.position += weight * morph::morph(vertex_index, morph::position_offset, i);
#ifdef VERTEX_NORMALS
        vertex.normal += weight * morph::morph(vertex_index, morph::normal_offset, i);
#endif
#ifdef VERTEX_TANGENTS
        vertex.tangent += vec4(weight * morph::morph(vertex_index, morph::tangent_offset, i), 0.0);
#endif
    }
    return vertex;
}
#endif