Euphoria
materialshader.cc
Go to the documentation of this file.
2 
3 #include <utility>
4 
5 #include "log/log.h"
6 #include "core/texturetypes.h"
7 
9 #include "render/light.h"
10 
11 #include "files/materialshader.h"
12 
13 
14 
15 namespace eu::render
16 {
18  (
19  const core::EnumValue& a_name,
20  const io::FilePath& a_path
21  )
22  : name(a_name)
23  , path(a_path)
24  {
25  }
26 
28 
30  (
31  ShaderUniform a_uniform,
32  const core::EnumValue& a_name
33  )
34  : uniform(std::move(a_uniform))
35  , name(a_name)
36  {
37  }
38 
39 
41 
43  : projection(ShaderUniform::create_null())
44  , view(ShaderUniform::create_null())
45  , model(ShaderUniform::create_null())
46  , ambient(ShaderUniform::create_null())
47  , diffuse(ShaderUniform::create_null())
48  , specular(ShaderUniform::create_null())
49  , shininess(ShaderUniform::create_null())
50  , has_light(false)
51  , light_ambient(ShaderUniform::create_null())
52  , light_diffuse(ShaderUniform::create_null())
53  , light_specular(ShaderUniform::create_null())
54  , light_position(ShaderUniform::create_null())
55  , light_direction(ShaderUniform::create_null())
56  , light_type(ShaderUniform::create_null())
57  , light_attenuation_constant(ShaderUniform::create_null())
58  , light_attenuation_linear(ShaderUniform::create_null())
59  , light_attenuation_quadratic(ShaderUniform::create_null())
60  , light_cutoff_angle_outer(ShaderUniform::create_null())
61  , light_cutoff_angle_inner(ShaderUniform::create_null())
62  , normal_matrix(ShaderUniform::create_null())
63  , view_position(ShaderUniform::create_null())
64  {
65  }
66 
67  void
69  (
70  MaterialShader* sh,
72  const io::FilePath& path
73  )
74  {
75  sh->has_light = file.has_light;
76 
77  for(const auto& texture: file.textures)
78  {
79  const auto uniform = sh->shader.get_uniform(texture.uniform);
80  DEFINE_ENUM_VALUE(core::texture_type, texture_name, texture.texture);
81  sh->bindings.emplace_back(uniform, texture_name);
82  }
83 
84  for(const auto& texture: file.default_textures)
85  {
86  const auto texture_path = io::FilePath::from_script(texture.path);
87  if(texture_path.has_value() == false)
88  {
89  LOG_WARN
90  (
91  "Ignored invalid path for {0} in {1}: {2}",
92  texture.texture,
93  path,
94  texture.path
95  );
96  continue;
97  }
98  DEFINE_ENUM_VALUE(core::texture_type, texture_name, texture.texture);
99  sh->default_textures.emplace_back
100  (
101  texture_name,
102  texture_path.value()
103  );
104  }
105 
106  // todo(Gustav): get the shader names from a trusted source
107  sh->projection = sh->shader.get_uniform("uProjection");
108  sh->view = sh->shader.get_uniform("uView");
109  sh->model = sh->shader.get_uniform("uModel");
110 
111  if(file.ambient)
112  {
113  sh->ambient = sh->shader.get_uniform(*file.ambient);
114  }
115  if(file.diffuse)
116  {
117  sh->diffuse = sh->shader.get_uniform(*file.diffuse);
118  }
119  if(file.specular)
120  {
121  sh->specular = sh->shader.get_uniform(*file.specular);
122  }
123  if(file.shininess)
124  {
125  sh->shininess = sh->shader.get_uniform(*file.shininess);
126  }
127 
128  if(sh->has_light)
129  {
130  sh->light_ambient = sh->shader.get_uniform("uLight.ambient");
131  sh->light_diffuse = sh->shader.get_uniform("uLight.diffuse");
132  sh->light_specular = sh->shader.get_uniform("uLight.specular");
133  sh->light_position = sh->shader.get_uniform("uLight.position");
134  sh->light_direction = sh->shader.get_uniform("uLight.direction");
135  sh->light_type = sh->shader.get_uniform("uLight.type");
136  sh->light_cutoff_angle_outer = sh->shader.get_uniform("uLight.cosCutoffAngleOuter");
137  sh->light_cutoff_angle_inner = sh->shader.get_uniform("uLight.cosCutoffAngleInner");
138 
139  sh->light_attenuation_constant = sh->shader.get_uniform("uLight.attConst");
140  sh->light_attenuation_linear = sh->shader.get_uniform("uLight.attLin");
141  sh->light_attenuation_quadratic = sh->shader.get_uniform("uLight.attQuad");
142 
143  sh->normal_matrix = sh->shader.get_uniform("uNormalMatrix");
144  sh->view_position = sh->shader.get_uniform("uViewPosition");
145  }
146  }
147 
148  bool
150  (
151  io::FileSystem* file_system,
152  const io::FilePath& path
153  )
154  {
156  const bool shader_compile = shader.load(file_system, path);
157  // if (!shader_compile) { return false; }
158 
159  const auto proto_path = path.set_extension_copy("json");
160 
162  if (const auto loaded = io::read_json_file(file_system, proto_path); loaded == false)
163  {
164  LOG_ERROR("Failed to load {}: {}", proto_path, loaded.get_error().display);
165  return false;
166  }
167  else
168  {
169  const auto& json = loaded.get_value();
170  const auto parsed = files::materialshader::parse(log::get_global_logger(), &file, json.root, &json.doc);
171  if (!parsed)
172  {
173  return false;
174  }
175  }
176 
177  // todo(Gustav): set default shader names if file failed to load
178 
179  post_build(this, file, path);
180 
181  return shader_compile;
182  }
183 
184  void
186  {
187  use(&shader);
188  }
189 
190  void
191  MaterialShader::set_projection(const mat4f& projection_data)
192  {
193  shader.set_uniform(projection, projection_data);
194  }
195 
196  void
197  MaterialShader::set_view(const mat4f& view_data)
198  {
199  shader.set_uniform(view, view_data);
200  }
201 
202  void
203  MaterialShader::set_model(const mat4f& model_data)
204  {
205  shader.set_uniform(model, model_data);
206  if(has_light)
207  {
208  mat4f normal = model_data;
209  const bool inverted = normal.invert();
210  ASSERT(inverted);
211  normal = normal.get_transposed();
212  shader.set_uniform(normal_matrix, normal.get_mat3());
213  }
214  }
215 
216  void
217  MaterialShader::setup_light(const Light& light, const vec3f& camera)
218  {
219  if(!has_light)
220  {
221  return;
222  }
223 
231 
232  const auto att = light.attenuation;
236 
237  shader.set_uniform(light_type, static_cast<int>(light.light_type));
239  }
240 
241  void
243  (
244  const Rgb& ambient_data,
245  const Rgb& diffuse_data,
246  const Rgb& specular_data,
247  float shininess_data
248  )
249  {
250  if(!ambient.is_null())
251  {
252  shader.set_uniform(ambient, ambient_data);
253  }
254 
255  if(!diffuse.is_null())
256  {
257  shader.set_uniform(diffuse, diffuse_data);
258  }
259 
260  if(!specular.is_null())
261  {
262  const auto the_specular = shininess_data > 0
263  ? specular_data
265  ;
266  shader.set_uniform(specular, the_specular);
267  }
268 
269  if(!shininess.is_null())
270  {
271  // todo(Gustav): change to 0 instead of 1.0
272  const auto the_shininess = shininess_data > 0 ? shininess_data : 1.0f;
273  shader.set_uniform(shininess, the_shininess);
274  }
275  }
276 
277 }
#define ASSERT(x)
Definition: assert.h:29
#define DEFINE_ENUM_VALUE(TYPE, NAME, STRING)
Definition: enum.h:95
#define LOG_ERROR(...)
Definition: log.h:9
#define LOG_WARN(...)
Definition: log.h:8
JsonResult read_json_file(FileSystem *fs, const FilePath &file_name)
Definition: json.cc:58
Logger * get_global_logger()
Definition: log.cc:34
void add_attributes_to_shader(ShaderProgram *shader)
void use(const ShaderProgram *shader)
Definition: shader.cc:114
void post_build(MaterialShader *sh, const files::materialshader::MaterialShader &file, const io::FilePath &path)
float cos(const Angle &ang)
Definition: angle.cc:68
Definition: rgb.h:62
std::optional< std::string > specular
std::optional< std::string > ambient
std::optional< std::string > diffuse
std::optional< std::string > shininess
std::vector< DefaultTexture > default_textures
FilePath set_extension_copy(const std::string &ext) const
Definition: vfs_path.cc:170
std::string path
contains either .
Definition: vfs_path.h:39
static std::optional< FilePath > from_script(const std::string &path)
apply only minor changes, return null on invalid
Definition: vfs_path.cc:46
Definition: mat4.h:14
LightAttenuation attenuation
Definition: light.h:37
Angle cutoff_angle_outer
Definition: light.h:34
vec3f position
Definition: light.h:29
Type light_type
Definition: light.h:28
unit3f direction
Definition: light.h:30
Angle cutoff_angle_inner
Definition: light.h:35
MaterialShaderBinding(ShaderUniform a_uniform, const core::EnumValue &a_name)
MaterialShaderDefaultTexture(const core::EnumValue &a_name, const io::FilePath &a_path)
Extends a regular Shader with uniform bindings for 3d rendering.
ShaderUniform light_cutoff_angle_outer
void setup_light(const Light &light, const vec3f &camera)
ShaderUniform light_attenuation_constant
void set_projection(const mat4f &projection_data)
std::vector< MaterialShaderDefaultTexture > default_textures
bool load(io::FileSystem *file_system, const io::FilePath &path)
void set_colors(const Rgb &ambient_data, const Rgb &diffuse_data, const Rgb &specular_data, float shininess_data)
void set_model(const mat4f &model_data)
ShaderUniform light_attenuation_linear
void set_view(const mat4f &view_data)
std::vector< MaterialShaderBinding > bindings
render::ShaderProgram shader
ShaderUniform light_cutoff_angle_inner
ShaderUniform light_attenuation_quadratic
void set_uniform(const ShaderUniform &attribute, gl::Int val)
Definition: shader.cc:292
bool load(io::FileSystem *fs, const io::FilePath &file_path)
Definition: shader.cc:398
ShaderUniform get_uniform(const std::string &name)
Definition: shader.cc:262
Definition: vec3.h:48