Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_gltf/src/loader/extensions/khr_materials_specular.rs
6598 views
1
use bevy_asset::LoadContext;
2
3
use gltf::{Document, Material};
4
5
use serde_json::Value;
6
7
#[cfg(feature = "pbr_specular_textures")]
8
use {
9
crate::loader::gltf_ext::material::parse_material_extension_texture, bevy_asset::Handle,
10
bevy_image::Image, bevy_pbr::UvChannel,
11
};
12
13
/// Parsed data from the `KHR_materials_specular` extension.
14
///
15
/// We currently don't parse `specularFactor` and `specularTexture`, since
16
/// they're incompatible with Filament.
17
///
18
/// Note that the map is a *specular map*, not a *reflectance map*. In Bevy and
19
/// Filament terms, the reflectance values in the specular map range from [0.0,
20
/// 0.5], rather than [0.0, 1.0]. This is an unfortunate
21
/// `KHR_materials_specular` specification requirement that stems from the fact
22
/// that glTF is specified in terms of a specular strength model, not the
23
/// reflectance model that Filament and Bevy use. A workaround, which is noted
24
/// in the [`StandardMaterial`](bevy_pbr::StandardMaterial) documentation, is to set the reflectance value
25
/// to 2.0, which spreads the specular map range from [0.0, 1.0] as normal.
26
///
27
/// See the specification:
28
/// <https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_specular/README.md>
29
#[derive(Default)]
30
pub(crate) struct SpecularExtension {
31
pub(crate) specular_factor: Option<f64>,
32
#[cfg(feature = "pbr_specular_textures")]
33
pub(crate) specular_channel: UvChannel,
34
#[cfg(feature = "pbr_specular_textures")]
35
pub(crate) specular_texture: Option<Handle<Image>>,
36
pub(crate) specular_color_factor: Option<[f64; 3]>,
37
#[cfg(feature = "pbr_specular_textures")]
38
pub(crate) specular_color_channel: UvChannel,
39
#[cfg(feature = "pbr_specular_textures")]
40
pub(crate) specular_color_texture: Option<Handle<Image>>,
41
}
42
43
impl SpecularExtension {
44
pub(crate) fn parse(
45
_load_context: &mut LoadContext,
46
_document: &Document,
47
material: &Material,
48
) -> Option<Self> {
49
let extension = material
50
.extensions()?
51
.get("KHR_materials_specular")?
52
.as_object()?;
53
54
#[cfg(feature = "pbr_specular_textures")]
55
let (_specular_channel, _specular_texture) = parse_material_extension_texture(
56
material,
57
_load_context,
58
_document,
59
extension,
60
"specularTexture",
61
"specular",
62
);
63
64
#[cfg(feature = "pbr_specular_textures")]
65
let (_specular_color_channel, _specular_color_texture) = parse_material_extension_texture(
66
material,
67
_load_context,
68
_document,
69
extension,
70
"specularColorTexture",
71
"specular color",
72
);
73
74
Some(SpecularExtension {
75
specular_factor: extension.get("specularFactor").and_then(Value::as_f64),
76
#[cfg(feature = "pbr_specular_textures")]
77
specular_channel: _specular_channel,
78
#[cfg(feature = "pbr_specular_textures")]
79
specular_texture: _specular_texture,
80
specular_color_factor: extension
81
.get("specularColorFactor")
82
.and_then(Value::as_array)
83
.and_then(|json_array| {
84
if json_array.len() < 3 {
85
None
86
} else {
87
Some([
88
json_array[0].as_f64()?,
89
json_array[1].as_f64()?,
90
json_array[2].as_f64()?,
91
])
92
}
93
}),
94
#[cfg(feature = "pbr_specular_textures")]
95
specular_color_channel: _specular_color_channel,
96
#[cfg(feature = "pbr_specular_textures")]
97
specular_color_texture: _specular_color_texture,
98
})
99
}
100
}
101
102