Minetest 5.10.0-dev
 
Loading...
Searching...
No Matches
shader.h
Go to the documentation of this file.
1/*
2Minetest
3Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4Copyright (C) 2013 Kahrl <kahrl@gmx.net>
5
6This program is free software; you can redistribute it and/or modify
7it under the terms of the GNU Lesser General Public License as published by
8the Free Software Foundation; either version 2.1 of the License, or
9(at your option) any later version.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU Lesser General Public License for more details.
15
16You should have received a copy of the GNU Lesser General Public License along
17with this program; if not, write to the Free Software Foundation, Inc.,
1851 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20
21#pragma once
22
24#include <IMaterialRendererServices.h>
25#include <string>
26#include "nodedef.h"
27
28class IGameDef;
29
30/*
31 shader.{h,cpp}: Shader handling stuff.
32*/
33
34/*
35 Gets the path to a shader by first checking if the file
36 name_of_shader/filename
37 exists in shader_path and if not, using the data path.
38
39 If not found, returns "".
40
41 Utilizes a thread-safe cache.
42*/
43std::string getShaderPath(const std::string &name_of_shader,
44 const std::string &filename);
45
46struct ShaderInfo {
47 std::string name = "";
48 video::E_MATERIAL_TYPE base_material = video::EMT_SOLID;
49 video::E_MATERIAL_TYPE material = video::EMT_SOLID;
52
53 ShaderInfo() = default;
54 virtual ~ShaderInfo() = default;
55};
56
57/*
58 Setter of constants for shaders
59*/
60
61namespace irr::video {
62 class IMaterialRendererServices;
63}
64
65
67public:
68 virtual ~IShaderConstantSetter() = default;
69 virtual void onSetConstants(video::IMaterialRendererServices *services) = 0;
70 virtual void onSetMaterial(const video::SMaterial& material)
71 { }
72};
73
74
76public:
77 virtual ~IShaderConstantSetterFactory() = default;
79};
80
81
82template <typename T, std::size_t count, bool cache>
84 const char *m_name;
85 T m_sent[count];
86 bool has_been_set = false;
88protected:
89 CachedShaderSetting(const char *name, bool is_pixel) :
91 {}
92public:
93 void set(const T value[count], video::IMaterialRendererServices *services)
94 {
95 if (cache && has_been_set && std::equal(m_sent, m_sent + count, value))
96 return;
97 if (is_pixel)
98 services->setPixelShaderConstant(services->getPixelShaderConstantID(m_name), value, count);
99 else
100 services->setVertexShaderConstant(services->getVertexShaderConstantID(m_name), value, count);
101
102 if (cache) {
103 std::copy(value, value + count, m_sent);
104 has_been_set = true;
105 }
106 }
107
108 /* Type specializations */
109
110 /*
111 * T2 looks redundant here but it is necessary so the compiler won't
112 * resolve the templates at class instantiation and then fail because
113 * some of these methods don't have valid types (= are not usable).
114 * ref: <https://stackoverflow.com/a/6972771>
115 *
116 * Note: a `bool dummy` template parameter would have been easier but MSVC
117 * does not like that. Also make sure not to define different specializations
118 * with the same parameters, MSVC doesn't like that either.
119 * I extend my thanks to Microsoft®
120 */
121#define SPECIALIZE(_type, _count_expr) \
122 template<typename T2 = T> \
123 std::enable_if_t<std::is_same_v<T, T2> && std::is_same_v<T2, _type> && (_count_expr)>
124
125 SPECIALIZE(float, count == 2)
126 set(const v2f value, video::IMaterialRendererServices *services)
127 {
128 float array[2] = { value.X, value.Y };
129 set(array, services);
130 }
131
132 SPECIALIZE(float, count == 3)
133 set(const v3f value, video::IMaterialRendererServices *services)
134 {
135 float array[3] = { value.X, value.Y, value.Z };
136 set(array, services);
137 }
138
139 SPECIALIZE(float, count == 3 || count == 4)
140 set(const video::SColorf value, video::IMaterialRendererServices *services)
141 {
142 if constexpr (count == 3) {
143 float array[3] = { value.r, value.g, value.b };
144 set(array, services);
145 } else {
146 float array[4] = { value.r, value.g, value.b, value.a };
147 set(array, services);
148 }
149 }
150
151 SPECIALIZE(float, count == 16)
152 set(const core::matrix4 &value, video::IMaterialRendererServices *services)
153 {
154 set(value.pointer(), services);
155 }
156
157#undef SPECIALIZE
158};
159
160template <typename T, std::size_t count = 1, bool cache=true>
161class CachedPixelShaderSetting : public CachedShaderSetting<T, count, cache> {
162public:
163 CachedPixelShaderSetting(const char *name) :
164 CachedShaderSetting<T, count, cache>(name, true){}
165};
166
167template <typename T, std::size_t count = 1, bool cache=true>
168class CachedVertexShaderSetting : public CachedShaderSetting<T, count, cache> {
169public:
170 CachedVertexShaderSetting(const char *name) :
171 CachedShaderSetting<T, count, cache>(name, false){}
172};
173
174template <typename T, std::size_t count, bool cache, bool is_pixel>
176 const char *m_name;
177 T m_sent[count];
178 bool has_been_set = false;
179 std::array<const char*, count> m_fields;
180public:
181 CachedStructShaderSetting(const char *name, std::array<const char*, count> &&fields) :
182 m_name(name), m_fields(std::move(fields))
183 {}
184
185 void set(const T value[count], video::IMaterialRendererServices *services)
186 {
187 if (cache && has_been_set && std::equal(m_sent, m_sent + count, value))
188 return;
189
190 for (std::size_t i = 0; i < count; i++) {
191 std::string uniform_name = std::string(m_name) + "." + m_fields[i];
192
193 if (is_pixel)
194 services->setPixelShaderConstant(services->getPixelShaderConstantID(uniform_name.c_str()), value + i, 1);
195 else
196 services->setVertexShaderConstant(services->getVertexShaderConstantID(uniform_name.c_str()), value + i, 1);
197 }
198
199 if (cache) {
200 std::copy(value, value + count, m_sent);
201 has_been_set = true;
202 }
203 }
204};
205
206template<typename T, std::size_t count, bool cache = true>
208
209template<typename T, std::size_t count, bool cache = true>
211
212/*
213 ShaderSource creates and caches shaders.
214*/
215
217public:
218 IShaderSource() = default;
219 virtual ~IShaderSource() = default;
220
221 virtual u32 getShaderIdDirect(const std::string &name,
222 MaterialType material_type, NodeDrawType drawtype = NDT_NORMAL){return 0;}
223 virtual ShaderInfo getShaderInfo(u32 id){return ShaderInfo();}
224 virtual u32 getShader(const std::string &name,
225 MaterialType material_type, NodeDrawType drawtype = NDT_NORMAL){return 0;}
226};
227
229public:
231 virtual ~IWritableShaderSource() = default;
232
233 virtual void processQueue()=0;
234 virtual void insertSourceShader(const std::string &name_of_shader,
235 const std::string &filename, const std::string &program)=0;
236 virtual void rebuildShaders()=0;
237
240};
241
243
244void dumpShaderProgram(std::ostream &output_stream,
245 const std::string &program_type, std::string_view program);
Definition shader.h:161
CachedPixelShaderSetting(const char *name)
Definition shader.h:163
Definition shader.h:83
bool is_pixel
Definition shader.h:87
CachedShaderSetting(const char *name, bool is_pixel)
Definition shader.h:89
T m_sent[count]
Definition shader.h:85
bool has_been_set
Definition shader.h:86
const char * m_name
Definition shader.h:84
void set(const T value[count], video::IMaterialRendererServices *services)
Definition shader.h:93
Definition shader.h:175
void set(const T value[count], video::IMaterialRendererServices *services)
Definition shader.h:185
T m_sent[count]
Definition shader.h:177
std::array< const char *, count > m_fields
Definition shader.h:179
bool has_been_set
Definition shader.h:178
CachedStructShaderSetting(const char *name, std::array< const char *, count > &&fields)
Definition shader.h:181
const char * m_name
Definition shader.h:176
Definition shader.h:168
CachedVertexShaderSetting(const char *name)
Definition shader.h:170
Definition gamedef.h:51
Definition shader.h:75
virtual ~IShaderConstantSetterFactory()=default
virtual IShaderConstantSetter * create()=0
Definition shader.h:66
virtual void onSetConstants(video::IMaterialRendererServices *services)=0
virtual void onSetMaterial(const video::SMaterial &material)
Definition shader.h:70
virtual ~IShaderConstantSetter()=default
Definition shader.h:216
IShaderSource()=default
virtual ShaderInfo getShaderInfo(u32 id)
Definition shader.h:223
virtual ~IShaderSource()=default
virtual u32 getShader(const std::string &name, MaterialType material_type, NodeDrawType drawtype=NDT_NORMAL)
Definition shader.h:224
virtual u32 getShaderIdDirect(const std::string &name, MaterialType material_type, NodeDrawType drawtype=NDT_NORMAL)
Definition shader.h:221
Definition shader.h:228
virtual void rebuildShaders()=0
virtual ~IWritableShaderSource()=default
IWritableShaderSource()=default
virtual void insertSourceShader(const std::string &name_of_shader, const std::string &filename, const std::string &program)=0
virtual void processQueue()=0
virtual void addShaderConstantSetterFactory(IShaderConstantSetterFactory *setter)=0
core::vector2d< f32 > v2f
Definition irr_v2d.h:26
core::vector3df v3f
Definition irr_v3d.h:26
Definition pipeline.h:37
NodeDrawType
Definition nodedef.h:198
@ NDT_NORMAL
Definition nodedef.h:200
IWritableShaderSource * createShaderSource()
Definition shader.cpp:351
std::string getShaderPath(const std::string &name_of_shader, const std::string &filename)
Definition shader.cpp:60
#define SPECIALIZE(_type, _count_expr)
Definition shader.h:121
void dumpShaderProgram(std::ostream &output_stream, const std::string &program_type, std::string_view program)
Definition shader.cpp:758
Definition shader.h:46
std::string name
Definition shader.h:47
virtual ~ShaderInfo()=default
video::E_MATERIAL_TYPE base_material
Definition shader.h:48
MaterialType material_type
Definition shader.h:51
NodeDrawType drawtype
Definition shader.h:50
video::E_MATERIAL_TYPE material
Definition shader.h:49
ShaderInfo()=default
MaterialType
Definition tile.h:27
@ TILE_MATERIAL_BASIC
Definition tile.h:28