gltf_v1_json/
shader.rs

1use std::fmt;
2
3use gltf_v1_derive::Validate;
4use serde::de;
5use serde::{Deserialize, Serialize};
6
7use super::common::StringIndex;
8use super::validation::Checked;
9
10pub const FRAGMENT_SHADER: u32 = 35632;
11pub const VERTEX_SHADER: u32 = 35633;
12
13#[derive(Clone, Debug, Copy, Default)]
14pub enum ShaderType {
15    #[default]
16    FragmentShader,
17    VertexShader,
18}
19
20impl ShaderType {
21    pub const VALID_SHADER_TYPE: &[u32] = &[FRAGMENT_SHADER, VERTEX_SHADER];
22}
23
24impl From<ShaderType> for u32 {
25    fn from(value: ShaderType) -> Self {
26        match value {
27            ShaderType::FragmentShader => FRAGMENT_SHADER,
28            ShaderType::VertexShader => VERTEX_SHADER,
29        }
30    }
31}
32
33impl TryFrom<u32> for ShaderType {
34    type Error = ();
35
36    fn try_from(value: u32) -> Result<Self, Self::Error> {
37        match value {
38            FRAGMENT_SHADER => Ok(ShaderType::FragmentShader),
39            VERTEX_SHADER => Ok(ShaderType::VertexShader),
40            _ => Err(()),
41        }
42    }
43}
44impl Serialize for ShaderType {
45    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
46    where
47        S: serde::Serializer,
48    {
49        serializer.serialize_u32((*self).into())
50    }
51}
52
53impl<'de> Deserialize<'de> for Checked<ShaderType> {
54    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
55    where
56        D: serde::Deserializer<'de>,
57    {
58        struct Visitor;
59        impl serde::de::Visitor<'_> for Visitor {
60            type Value = Checked<ShaderType>;
61
62            fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
63                write!(f, "any of: {:?}", ShaderType::VALID_SHADER_TYPE)
64            }
65
66            fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
67            where
68                E: de::Error,
69            {
70                Ok((value as u32)
71                    .try_into()
72                    .map(Checked::Valid)
73                    .unwrap_or(Checked::Invalid))
74            }
75        }
76        deserializer.deserialize_u32(Visitor)
77    }
78}
79
80#[derive(Clone, Debug, serde_derive::Deserialize, serde_derive::Serialize, Validate, Default)]
81pub struct Shader {
82    pub uri: String,
83    #[serde(rename = "type")]
84    pub type_: Checked<ShaderType>,
85    #[serde(skip_serializing_if = "Option::is_none")]
86    pub name: Option<String>,
87}
88
89impl Shader {
90    pub(crate) fn default_fragment_shader() -> Self {
91        //For details on the default: https://github.com/KhronosGroup/glTF/blob/main/specification/1.0/README.md#appendix-a-default-material
92        //The strings are base64 encoded variants on the Shaders
93        Self {
94            uri: format!(
95                "{}{}",
96                "data:text/plain;base64,",
97                "cHJlY2lzaW9uIGhpZ2hwIGZsb2F0OwoKdW5pZm9ybSBtYXQ0IHVfbW9kZWxWaWV3TWF0cml4Owp1bmlmb3JtIG1hdDQgdV9wcm9qZWN0aW9uTWF0cml4OwoKYXR0cmlidXRlIHZlYzMgYV9wb3NpdGlvbjsKCnZvaWQgbWFpbih2b2lkKQp7CiAgICBnbF9Qb3NpdGlvbiA9IHVfcHJvamVjdGlvbk1hdHJpeCAqIHVfbW9kZWxWaWV3TWF0cml4ICogdmVjNChhX3Bvc2l0aW9uLDEuMCk7Cn0="
98            ),
99            type_: Checked::Valid(ShaderType::FragmentShader),
100            name: None,
101        }
102    }
103    pub(crate) fn default_vertex_shader() -> Self {
104        Self {
105            uri: format!(
106                "{}{}",
107                "data:text/plain;base64,",
108                "cHJlY2lzaW9uIGhpZ2hwIGZsb2F0OwoKdW5pZm9ybSB2ZWM0IHVfZW1pc3Npb247Cgp2b2lkIG1haW4odm9pZCkKewogICAgZ2xfRnJhZ0NvbG9yID0gdV9lbWlzc2lvbjsKfQ=="
109            ),
110            type_: Checked::Valid(ShaderType::VertexShader),
111            name: None,
112        }
113    }
114}
115
116#[derive(Clone, Debug, serde_derive::Deserialize, serde_derive::Serialize, Validate)]
117pub struct Program {
118    #[serde(default)]
119    #[serde(skip_serializing_if = "Vec::is_empty")]
120    pub attributes: Vec<String>,
121    #[serde(rename = "fragmentShader")]
122    pub fragment_shader: StringIndex<Shader>,
123    #[serde(rename = "vertexShader")]
124    pub vertex_shader: StringIndex<Shader>,
125    pub name: Option<String>,
126}
127
128impl Program {
129    pub(crate) fn default_program(fragment_shader: String, vertex_shader: String) -> Self {
130        let attributes = vec!["a_position".to_string()];
131
132        Self {
133            attributes,
134            fragment_shader: StringIndex::new(fragment_shader),
135            vertex_shader: StringIndex::new(vertex_shader),
136            name: None,
137        }
138    }
139}
140
141#[test]
142fn test_program_deserialize() {
143    let data = r#"{
144            "attributes": [
145                "a_normal",
146                "a_position"
147            ],
148            "fragmentShader": "fs_id",
149            "name": "user-defined program name",
150            "vertexShader": "vs_id",
151            "extensions" : {
152               "extension_name" : {
153                  "extension specific" : "value"
154               }
155            },
156            "extras" : {
157                "Application specific" : "The extra object can contain any properties."
158            }     
159        }"#;
160    let program: Result<Program, _> = serde_json::from_str(data);
161    let program_unwrap = program.unwrap();
162    println!("{}", serde_json::to_string(&program_unwrap).unwrap());
163    assert_eq!(
164        Some("user-defined program name".to_string()),
165        program_unwrap.name
166    );
167}
168
169#[test]
170fn test_shader_deserialize() {
171    let data = r#"{
172            "name": "user-defined vertex shader name",
173            "uri" : "vertexshader.glsl",
174            "type": 35633,
175            "extensions" : {
176               "extension_name" : {
177                  "extension specific" : "value"
178               }
179            },
180            "extras" : {
181                "Application specific" : "The extra object can contain any properties."
182            }
183        }"#;
184    let shader: Result<Shader, _> = serde_json::from_str(data);
185    let shader_unwrap = shader.unwrap();
186    println!("{}", serde_json::to_string(&shader_unwrap).unwrap());
187    assert_eq!(
188        Some("user-defined vertex shader name".to_string()),
189        shader_unwrap.name
190    );
191}