fyrox_graphics/
gpu_program.rs

1// Copyright (c) 2019-present Dmitry Stepanov and Fyrox Engine contributors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in all
11// copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19// SOFTWARE.
20
21use crate::{
22    core::{
23        algebra::{Matrix2, Matrix3, Matrix4, Vector2, Vector3, Vector4},
24        reflect::prelude::*,
25        sstorage::ImmutableString,
26        type_traits::prelude::*,
27        visitor::prelude::*,
28        Downcast,
29    },
30    error::FrameworkError,
31};
32use serde::{Deserialize, Serialize};
33use std::marker::PhantomData;
34use strum_macros::{AsRefStr, EnumString, VariantNames};
35
36pub trait GpuProgram: Downcast {
37    fn uniform_location(&self, name: &ImmutableString) -> Result<UniformLocation, FrameworkError>;
38    fn uniform_block_index(&self, name: &ImmutableString) -> Result<usize, FrameworkError>;
39}
40
41#[derive(Clone, Debug)]
42pub struct UniformLocation {
43    pub id: glow::UniformLocation,
44    // Force compiler to not implement Send and Sync, because OpenGL is not thread-safe.
45    pub thread_mark: PhantomData<*const u8>,
46}
47
48/// A fallback value for the sampler.
49///
50/// # Notes
51///
52/// Sometimes you don't want to set a value to a sampler, or you even don't have the appropriate
53/// one. There is fallback value that helps you with such situations, it defines a values that
54/// will be fetched from a sampler when there is no texture.
55///
56/// For example, standard shader has a lot of samplers defined: diffuse, normal, height, emission,
57/// mask, metallic, roughness, etc. In some situations you may not have all the textures, you have
58/// only diffuse texture, to keep rendering correct, each other property has appropriate fallback
59/// value. Normal sampler - a normal vector pointing up (+Y), height - zero, emission - zero, etc.
60///
61/// Fallback value is also helpful to catch missing textures, you'll definitely know the texture is
62/// missing by very specific value in the fallback texture.
63#[derive(
64    Serialize,
65    Deserialize,
66    Default,
67    Debug,
68    PartialEq,
69    Clone,
70    Copy,
71    Visit,
72    Eq,
73    Reflect,
74    AsRefStr,
75    EnumString,
76    VariantNames,
77    TypeUuidProvider,
78)]
79#[type_uuid(id = "791b333c-eb3f-4279-97fe-cf2ba45c6d78")]
80pub enum SamplerFallback {
81    /// A 1x1px white texture.
82    #[default]
83    White,
84    /// A 1x1px texture with (0, 1, 0) vector.
85    Normal,
86    /// A 1x1px black texture.
87    Black,
88    /// A 1x1x1 volume texture with 1 black pixel.
89    Volume,
90}
91
92#[derive(Serialize, Deserialize, Default, Debug, PartialEq, Clone, Copy, Visit, Eq, Reflect)]
93pub enum SamplerKind {
94    Sampler1D,
95    #[default]
96    Sampler2D,
97    Sampler3D,
98    SamplerCube,
99    USampler1D,
100    USampler2D,
101    USampler3D,
102    USamplerCube,
103}
104
105/// Shader property with default value.
106#[derive(Serialize, Deserialize, Debug, PartialEq, Reflect, Visit)]
107pub enum ShaderResourceKind {
108    /// A texture.
109    Texture {
110        /// Kind of the texture.
111        kind: SamplerKind,
112
113        /// Fallback value.
114        ///
115        /// Sometimes you don't want to set a value to a texture binding, or you even don't have the appropriate
116        /// one. There is fallback value that helps you with such situations, it defines a set of values that
117        /// will be fetched from a texture binding point when there is no actual texture.
118        ///
119        /// For example, standard shader has a lot of samplers defined: diffuse, normal, height, emission,
120        /// mask, metallic, roughness, etc. In some situations you may not have all the textures, you have
121        /// only diffuse texture, to keep rendering correct, each other property has appropriate fallback
122        /// value. Normal sampler - a normal vector pointing up (+Y), height - zero, emission - zero, etc.
123        ///
124        /// Fallback value is also helpful to catch missing textures, you'll definitely know the texture is
125        /// missing by very specific value in the fallback texture.
126        fallback: SamplerFallback,
127    },
128    PropertyGroup(Vec<ShaderProperty>),
129}
130
131#[derive(Serialize, Deserialize, Debug, PartialEq, Reflect, Visit)]
132pub enum ShaderPropertyKind {
133    /// Real number.
134    Float(f32),
135
136    /// Real number array.
137    FloatArray {
138        value: Vec<f32>,
139        /// `max_len` defines the maximum number of elements in the shader.
140        max_len: usize,
141    },
142
143    /// Integer number.
144    Int(i32),
145
146    /// Integer number array.
147    IntArray {
148        value: Vec<i32>,
149        /// `max_len` defines the maximum number of elements in the shader.
150        max_len: usize,
151    },
152
153    /// Natural number.
154    UInt(u32),
155
156    /// Natural number array.
157    UIntArray {
158        value: Vec<u32>,
159        /// `max_len` defines the maximum number of elements in the shader.
160        max_len: usize,
161    },
162
163    /// Boolean value.
164    Bool(bool),
165
166    /// Two-dimensional vector.
167    Vector2(Vector2<f32>),
168
169    /// Two-dimensional vector array.
170    Vector2Array {
171        value: Vec<Vector2<f32>>,
172        /// `max_len` defines the maximum number of elements in the shader.
173        max_len: usize,
174    },
175
176    /// Three-dimensional vector.
177    Vector3(Vector3<f32>),
178
179    /// Three-dimensional vector array.
180    Vector3Array {
181        value: Vec<Vector3<f32>>,
182        /// `max_len` defines the maximum number of elements in the shader.
183        max_len: usize,
184    },
185
186    /// Four-dimensional vector.
187    Vector4(Vector4<f32>),
188
189    /// Four-dimensional vector array.
190    Vector4Array {
191        value: Vec<Vector4<f32>>,
192        /// `max_len` defines the maximum number of elements in the shader.
193        max_len: usize,
194    },
195
196    /// 2x2 Matrix.
197    Matrix2(Matrix2<f32>),
198
199    /// 2x2 Matrix array.
200    Matrix2Array {
201        value: Vec<Matrix2<f32>>,
202        /// `max_len` defines the maximum number of elements in the shader.
203        max_len: usize,
204    },
205
206    /// 3x3 Matrix.
207    Matrix3(Matrix3<f32>),
208
209    /// 3x3 Matrix array.
210    Matrix3Array {
211        value: Vec<Matrix3<f32>>,
212        /// `max_len` defines the maximum number of elements in the shader.
213        max_len: usize,
214    },
215
216    /// 4x4 Matrix.
217    Matrix4(Matrix4<f32>),
218
219    /// 4x4 Matrix array.
220    Matrix4Array {
221        value: Vec<Matrix4<f32>>,
222        /// `max_len` defines the maximum number of elements in the shader.
223        max_len: usize,
224    },
225
226    /// An sRGB color.
227    ///
228    /// # Conversion
229    ///
230    /// The colors you see on your monitor are in sRGB color space, this is fine for simple cases
231    /// of rendering, but not for complex things like lighting. Such things require color to be
232    /// linear. Value of this variant will be automatically **converted to linear color space**
233    /// before it passed to shader.
234    Color {
235        /// Default Red.
236        r: u8,
237
238        /// Default Green.
239        g: u8,
240
241        /// Default Blue.
242        b: u8,
243
244        /// Default Alpha.
245        a: u8,
246    },
247}
248
249#[derive(Serialize, Deserialize, Debug, PartialEq, Reflect, Visit, Default)]
250pub struct ShaderProperty {
251    pub name: ImmutableString,
252    pub kind: ShaderPropertyKind,
253}
254
255impl ShaderProperty {
256    pub fn new(name: impl Into<ImmutableString>, kind: ShaderPropertyKind) -> Self {
257        Self {
258            name: name.into(),
259            kind,
260        }
261    }
262}
263
264impl Default for ShaderPropertyKind {
265    fn default() -> Self {
266        Self::Float(0.0)
267    }
268}
269
270impl Default for ShaderResourceKind {
271    fn default() -> Self {
272        Self::PropertyGroup(Default::default())
273    }
274}
275
276/// Shader resource definition.
277#[derive(Default, Serialize, Deserialize, Debug, PartialEq, Reflect, Visit)]
278pub struct ShaderResourceDefinition {
279    /// A name of the resource.
280    pub name: ImmutableString,
281    /// A kind of resource.
282    pub kind: ShaderResourceKind,
283    pub binding: usize,
284}
285
286impl ShaderResourceDefinition {
287    pub fn is_built_in(&self) -> bool {
288        self.name.starts_with("fyrox_")
289    }
290}