use bevy::{
asset::LoadContext,
gltf::GltfAssetLabel,
image::Image,
prelude::*,
};
use bevy_shader_mtoon::{
MtoonMaterial,
VrmOutlineMode,
};
use serde_vrm::vrm0::MaterialProperty;
fn texture_handle(load_context: &mut LoadContext, index: u32) -> Handle<Image> {
load_context.get_label_handle(GltfAssetLabel::Texture(index as usize).to_string())
}
pub fn build_mtoon_material(
load_context: &mut LoadContext,
props: &MaterialProperty,
) -> MtoonMaterial {
let mut mtoon = MtoonMaterial::default();
let float = props.float.as_ref();
let vector = props.vector.as_ref();
let texture = props.texture.as_ref();
let keyword = props.keyword_map.as_ref();
if let Some(value) = float.and_then(|f| f.double_sided) {
mtoon.double_sided = value == 0.0;
}
if let Some(value) = float.and_then(|f| f.cutoff) {
mtoon.alpha_mode = AlphaMode::Mask(value);
}
if let Some(value) = vector.and_then(|v| v.color) {
mtoon.base_color = LinearRgba::from_f32_array(value).into();
}
mtoon.base_color_texture = texture
.and_then(|t| t.base_color)
.map(|i| texture_handle(load_context, i));
if let Some(value) = float.and_then(|f| f.normal_scale) {
mtoon.normal_map_scale = value;
}
mtoon.normal_map_texture = texture
.and_then(|t| t.normal)
.map(|i| texture_handle(load_context, i));
if let Some(value) = vector.and_then(|v| v.emissive_factor) {
mtoon.emissive_factor = LinearRgba::from_f32_array(value).into();
}
mtoon.emissive_texture = texture
.and_then(|t| t.emissive)
.map(|i| texture_handle(load_context, i));
if let Some(value) = float.and_then(|f| f.outline_factor) {
mtoon.outline_width = value;
}
if let Some(value) = vector.and_then(|v| v.outline_color) {
mtoon.outline_color = LinearRgba::from_f32_array(value).into();
}
mtoon.outline_mode = match float.and_then(|f| f.outline_width_mode).map(|m| m as u32) {
Some(1) => VrmOutlineMode::World,
Some(2) => VrmOutlineMode::Screen,
Some(_) => VrmOutlineMode::None,
None => match keyword.and_then(|k| k.outline_width_world) {
Some(true) => VrmOutlineMode::World,
Some(false) => VrmOutlineMode::Screen,
None => VrmOutlineMode::None,
},
};
if mtoon.outline_mode != VrmOutlineMode::None {
mtoon.outline_width *= 0.01;
}
if let Some(value) = float.and_then(|f| f.gi_intensity_factor) {
mtoon.gi_equalization_factor = 1.0 - value;
}
if let Some(value) = float.and_then(|f| f.shade_shift) {
mtoon.shading_shift_factor = -value;
}
if let Some(value) = float.and_then(|f| f.shade_toony) {
mtoon.shading_toony_factor = value;
}
if let Some(value) = vector.and_then(|v| v.shade_color) {
mtoon.shade_factor = LinearRgba::from_f32_array(value).into();
}
mtoon.shade_multiply_texture = texture
.and_then(|t| t.shade)
.map(|i| texture_handle(load_context, i));
mtoon
}