Skip to content

Commit

Permalink
Merge pull request #181 from Ralith/pbr-specular-glossiness
Browse files Browse the repository at this point in the history
Implement KHR_materials_pbrSpecularGlossiness
  • Loading branch information
alteous committed Jul 17, 2018
2 parents b081eac + 3619968 commit 086420c
Show file tree
Hide file tree
Showing 5 changed files with 206 additions and 3 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ extras = ["gltf-json/extras"]
names = ["gltf-json/names"]
utils = []
import = ["base64", "image"]
KHR_materials_pbrSpecularGlossiness = ["gltf-json/KHR_materials_pbrSpecularGlossiness"]

[[example]]
name = "gltf-display"
Expand Down
1 change: 1 addition & 0 deletions gltf-json/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ serde_json = "1.0"
default = []
names = []
extras = []
KHR_materials_pbrSpecularGlossiness = []
116 changes: 115 additions & 1 deletion gltf-json/src/extensions/material.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,130 @@
use validation::{Error, Validate};
use material::StrengthFactor;
use {texture, Extras, Root, Path};

/// The material appearance of a primitive.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct Material {}
pub struct Material {
#[cfg(feature = "KHR_materials_pbrSpecularGlossiness")]
#[serde(default, rename = "KHR_materials_pbrSpecularGlossiness", skip_serializing_if = "Option::is_none")]
pub pbr_specular_glossiness: Option<PbrSpecularGlossiness>,
}

/// A set of parameter values that are used to define the metallic-roughness
/// material model from Physically-Based Rendering (PBR) methodology.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct PbrMetallicRoughness {}

/// A set of parameter values that are used to define the specular-glossiness
/// material model from Physically-Based Rendering (PBR) methodology.
///
/// This model supports more materials than metallic-roughness, at the cost of
/// increased memory use. When both are available, specular-glossiness should be
/// preferred.
#[cfg(feature = "KHR_materials_pbrSpecularGlossiness")]
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
#[serde(default, rename_all = "camelCase")]
pub struct PbrSpecularGlossiness {
/// The material's diffuse factor.
///
/// The RGBA components of the reflected diffuse color of the
/// material. Metals have a diffuse value of `[0.0, 0.0, 0.0]`. The fourth
/// component (A) is the alpha coverage of the material. The `alphaMode`
/// property specifies how alpha is interpreted. The values are linear.
pub diffuse_factor: PbrDiffuseFactor,

/// The diffuse texture.
///
/// This texture contains RGB(A) components of the reflected diffuse color
/// of the material in sRGB color space. If the fourth component (A) is
/// present, it represents the alpha coverage of the material. Otherwise, an
/// alpha of 1.0 is assumed. The `alphaMode` property specifies how alpha is
/// interpreted. The stored texels must not be premultiplied.
#[serde(skip_serializing_if = "Option::is_none")]
pub diffuse_texture: Option<texture::Info>,

/// The material's specular factor.
pub specular_factor: PbrSpecularFactor,

/// The glossiness or smoothness of the material.
///
/// A value of 1.0 means the material has full glossiness or is perfectly
/// smooth. A value of 0.0 means the material has no glossiness or is
/// completely rough. This value is linear.
pub glossiness_factor: StrengthFactor,

/// The specular-glossiness texture.
///
/// A RGBA texture, containing the specular color of the material (RGB
/// components) and its glossiness (A component). The values are in sRGB
/// space.
#[serde(skip_serializing_if = "Option::is_none")]
pub specular_glossiness_texture: Option<texture::Info>,

/// Optional application specific data.
#[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
pub extras: Extras,
}


/// Defines the normal texture of a material.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct NormalTexture {}

/// Defines the occlusion texture of a material.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct OcclusionTexture {}

/// The diffuse factor of a material.
#[cfg(feature = "KHR_materials_pbrSpecularGlossiness")]
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub struct PbrDiffuseFactor(pub [f32; 4]);

#[cfg(feature = "KHR_materials_pbrSpecularGlossiness")]
impl Default for PbrDiffuseFactor {
fn default() -> Self {
PbrDiffuseFactor([1.0, 1.0, 1.0, 1.0])
}
}

#[cfg(feature = "KHR_materials_pbrSpecularGlossiness")]
impl Validate for PbrDiffuseFactor {
fn validate_completely<P, R>(&self, _: &Root, path: P, report: &mut R)
where P: Fn() -> Path, R: FnMut(&Fn() -> Path, Error)
{
for x in &self.0 {
if *x < 0.0 || *x > 1.0 {
report(&path, Error::Invalid);
// Only report once
break;
}
}
}
}

/// The specular factor of a material.
#[cfg(feature = "KHR_materials_pbrSpecularGlossiness")]
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub struct PbrSpecularFactor(pub [f32; 3]);

#[cfg(feature = "KHR_materials_pbrSpecularGlossiness")]
impl Default for PbrSpecularFactor {
fn default() -> Self {
PbrSpecularFactor([1.0, 1.0, 1.0])
}
}

#[cfg(feature = "KHR_materials_pbrSpecularGlossiness")]
impl Validate for PbrSpecularFactor {
fn validate_completely<P, R>(&self, _: &Root, path: P, report: &mut R)
where P: Fn() -> Path, R: FnMut(&Fn() -> Path, Error)
{
for x in &self.0 {
if *x < 0.0 || *x > 1.0 {
report(&path, Error::Invalid);
// Only report once
break;
}
}
}
}
9 changes: 7 additions & 2 deletions gltf-json/src/extensions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,12 @@ pub mod texture;
pub use self::root::Root;

/// Names of glTF 2.0 extensions enabled by the user.
pub const ENABLED_EXTENSIONS: &'static [&'static str] = &[];
pub const ENABLED_EXTENSIONS: &'static [&'static str] = &[
#[cfg(feature = "KHR_materials_pbrSpecularGlossiness")]
"KHR_materials_pbrSpecularGlossiness",
];

/// Names of glTF 2.0 extensions supported by the library.
pub const SUPPORTED_EXTENSIONS: &'static [&'static str] = &[];
pub const SUPPORTED_EXTENSIONS: &'static [&'static str] = &[
"KHR_materials_pbrSpecularGlossiness"
];
82 changes: 82 additions & 0 deletions src/material.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,13 @@ impl<'a> Material<'a> {
PbrMetallicRoughness::new(self.document, &self.json.pbr_metallic_roughness)
}

/// Parameter values that define the specular-glossiness material model from
/// Physically-Based Rendering (PBR) methodology.
#[cfg(feature = "KHR_materials_pbrSpecularGlossiness")]
pub fn pbr_specular_glossiness(&self) -> Option<PbrSpecularGlossiness<'a>> {
self.json.extensions.pbr_specular_glossiness.as_ref().map(|x| PbrSpecularGlossiness::new(self.document, x))
}

/// A tangent space normal map.
///
/// The texture contains RGB components in linear space. Each texel represents
Expand Down Expand Up @@ -225,6 +232,81 @@ impl<'a> PbrMetallicRoughness<'a> {
}
}

/// A set of parameter values that are used to define the specular-glossiness
/// material model from Physically-Based Rendering (PBR) methodology.
#[cfg(feature = "KHR_materials_pbrSpecularGlossiness")]
pub struct PbrSpecularGlossiness<'a> {
/// The parent `Document` struct.
document: &'a Document,

/// The corresponding JSON struct.
json: &'a json::extensions::material::PbrSpecularGlossiness,
}

#[cfg(feature = "KHR_materials_pbrSpecularGlossiness")]
impl<'a> PbrSpecularGlossiness<'a> {
/// Constructs `PbrSpecularGlossiness`.
pub(crate) fn new(
document: &'a Document,
json: &'a json::extensions::material::PbrSpecularGlossiness,
) -> Self {
Self {
document: document,
json: json,
}
}

/// Returns the material's base color factor.
///
/// The default value is `[1.0, 1.0, 1.0, 1.0]`.
pub fn diffuse_factor(&self) -> [f32; 4] {
self.json.diffuse_factor.0
}

/// Returns the base color texture.
pub fn diffuse_texture(&self) -> Option<texture::Info<'a>> {
self.json.diffuse_texture.as_ref().map(|json| {
let texture = self.document.textures().nth(json.index.value()).unwrap();
texture::Info::new(texture, json)
})
}

/// Returns the specular factor of the material.
///
/// The default value is `[1.0, 1.0, 1.0]`.
pub fn specular_factor(&self) -> [f32; 3] {
self.json.specular_factor.0
}

/// Returns the glossiness factor of the material.
///
/// A value of 1.0 means the material has full glossiness or is perfectly
/// smooth. A value of 0.0 means the material has no glossiness or is
/// completely rough. This value is linear.
///
/// The default value is `1.0`.
pub fn glossiness_factor(&self) -> f32 {
self.json.glossiness_factor.0
}

/// The specular-glossiness texture.
///
/// A RGBA texture, containing the specular color of the material (RGB
/// components) and its glossiness (A component). The color values are in
/// sRGB space.
pub fn specular_glossiness_texture(&self) -> Option<texture::Info<'a>> {
self.json.specular_glossiness_texture.as_ref().map(|json| {
let texture = self.document.textures().nth(json.index.value()).unwrap();
texture::Info::new(texture, json)
})
}

/// Optional application specific data.
pub fn extras(&self) -> &json::Extras {
&self.json.extras
}
}

/// Defines the normal texture of a material.
pub struct NormalTexture<'a> {
/// The parent `Texture` struct.
Expand Down

0 comments on commit 086420c

Please sign in to comment.