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}