GCC Code Coverage Report


./
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
0 of 260, 0 excluded
0.0%
Functions:
0 of 25, 0 excluded
0.0%
Branches:
0 of 592, 0 excluded
0.0%

libs/render/src/eu/render/shader_resource.cc
Line Branch Exec Source
1 #include "eu/render/shader_resource.h"
2
3 #include "eu/assert/assert.h"
4
5
6
7 #include "eu/render/camera.h"
8 #include "eu/render/constants.h"
9 #include "eu/render/fullscreen.h"
10 #include "eu/render/render_settings.h"
11 #include "eu/render/shader.h"
12 #include "eu/render/shader.source.h"
13
14
15 namespace eu::render
16 {
17
18
19
20 ✗ void CameraUniformBuffer::set_props(const CompiledCamera& cc) // NOLINT(readability-make-member-function-const)
21 {
22 ✗ buffer->set_mat4(clip_from_view_uni, cc.clip_from_view);
23 ✗ buffer->set_mat4(view_from_world_uni, cc.view_from_world);
24 ✗ }
25
26
27
28 ✗ LoadedShader_SingleColor::LoadedShader_SingleColor(
29 std::shared_ptr<ShaderProgram> p, core::CompiledGeomVertexAttributes l, const CameraUniformBuffer& desc
30 ✗ )
31 ✗ : program(std::move(p))
32 ✗ , geom_layout(std::move(l))
33 ✗ , tint_color_uni(program->get_uniform("u_material.diffuse_tint"))
34 ✗ , world_from_local_uni(program->get_uniform("u_world_from_local"))
35 {
36 ✗ program->setup_uniform_block(desc.setup);
37 ✗ }
38
39
40
41 ✗ LoadedShader_Skybox::LoadedShader_Skybox(
42 std::shared_ptr<ShaderProgram> p, core::CompiledGeomVertexAttributes l, const CameraUniformBuffer& desc
43 ✗ )
44 ✗ : program(std::move(p))
45 ✗ , geom_layout(std::move(l))
46 ✗ , tex_skybox_uniform(program->get_uniform("u_skybox_tex"))
47 {
48 ✗ setup_textures(program.get(), {&tex_skybox_uniform});
49 ✗ program->setup_uniform_block(desc.setup);
50 ✗ }
51
52 ✗ LoadedShader_OnlyDepth::LoadedShader_OnlyDepth(
53 TransformSource model_source,
54 std::shared_ptr<ShaderProgram> p,
55 core::CompiledGeomVertexAttributes l,
56 const CameraUniformBuffer& desc
57 ✗ )
58 ✗ : program(std::move(p))
59 ✗ , geom_layout(std::move(l))
60 ✗ , world_from_local_uni(
61 ✗ model_source == TransformSource::uniform ? std::optional<Uniform>{program->get_uniform("u_world_from_local")}
62 : std::nullopt
63 )
64 {
65 ✗ program->setup_uniform_block(desc.setup);
66 ✗ }
67
68 ✗ LoadedShader_Unlit::LoadedShader_Unlit(
69 TransformSource model_source,
70 std::shared_ptr<ShaderProgram> p,
71 const CameraUniformBuffer& desc
72 ✗ )
73 ✗ : program(std::move(p))
74 ✗ , tint_color_uni(program->get_uniform("u_material.diffuse_tint"))
75 ✗ , tex_diffuse_uniform(program->get_uniform("u_material.diffuse_tex"))
76 ✗ , world_from_local_uni(
77 ✗ model_source == TransformSource::uniform ? std::optional<Uniform>{program->get_uniform("u_world_from_local")} : std::nullopt
78 )
79 {
80 ✗ setup_textures(program.get(), {&tex_diffuse_uniform});
81 ✗ program->setup_uniform_block(desc.setup);
82 ✗ }
83
84
85
86 ✗ DirectionalLightUniforms::DirectionalLightUniforms(const ShaderProgram* program, const std::string& base)
87 ✗ : light_diffuse_color_uni(program->get_uniform(base + "diffuse"))
88 ✗ , light_specular_color_uni(program->get_uniform(base + "specular"))
89 ✗ , dir_uni(program->get_uniform(base + "dir"))
90 {
91 ✗ }
92
93
94
95 ✗ PointLightUniforms::PointLightUniforms(const ShaderProgram* program, const std::string& base)
96 ✗ : light_diffuse_color_uni(program->get_uniform(base + "diffuse"))
97 ✗ , light_specular_color_uni(program->get_uniform(base + "specular"))
98 ✗ , light_attenuation_uni(program->get_uniform(base + "attenuation"))
99 ✗ , light_world_uni(program->get_uniform(base + "world_pos"))
100 {
101 ✗ }
102
103
104
105 ✗ FrustumLightUniforms::FrustumLightUniforms(const ShaderProgram* program, const std::string& base)
106 ✗ : diffuse_uni(program->get_uniform(base + "diffuse"))
107 ✗ , specular_uni(program->get_uniform(base + "specular"))
108 ✗ , attenuation_uni(program->get_uniform(base + "attenuation"))
109 ✗ , clip_from_world_uni(program->get_uniform(base + "clip_from_world"))
110 ✗ , world_pos_uni(program->get_uniform(base + "world_pos"))
111 ✗ , tex_cookie_uniform(program->get_uniform(base + "cookie"))
112 {
113 ✗ }
114
115
116
117 ✗ PostProcSetup operator|(PostProcSetup lhs, PostProcSetup rhs)
118 {
119 ✗ return static_cast<PostProcSetup>(base_cast(lhs) | base_cast(rhs));
120 }
121
122
123
124 ✗ std::optional<Uniform> get_uniform(
125 ShaderProgram& prog, const std::string& name, PostProcSetup setup, PostProcSetup flag
126 )
127 {
128 ✗ if (is_flag_set(setup, flag))
129 {
130 ✗ return prog.get_uniform(name);
131 }
132 else
133 {
134 ✗ return std::nullopt;
135 }
136 }
137
138
139
140 ✗ LoadedPostProcShader::LoadedPostProcShader(std::shared_ptr<ShaderProgram> s, PostProcSetup setup)
141 ✗ : program(std::move(s))
142 ✗ , tex_input_uniform(program->get_uniform("u_texture"))
143 ✗ , factor_uni(get_uniform(*program, "u_factor", setup, PostProcSetup::factor))
144 ✗ , resolution_uni(get_uniform(*program, "u_resolution", setup, PostProcSetup::resolution))
145 ✗ , time_uni(get_uniform(*program, "u_time", setup, PostProcSetup::time))
146 {
147 ✗ setup_textures(program.get(), {&tex_input_uniform});
148 ✗ }
149
150
151
152 ✗ LoadedShader_Default::LoadedShader_Default(
153 TransformSource model_source,
154 std::shared_ptr<ShaderProgram> p,
155 const RenderSettings& settings,
156 const CameraUniformBuffer& desc
157 ✗ )
158 ✗ : program(std::move(p))
159 ✗ , tint_color_uni(program->get_uniform("u_material.diffuse_tint"))
160 ✗ , tex_directional_light_depth_uni(program->get_uniform("u_directional_light_depth_tex"))
161 ✗ , directional_shadow_clip_from_world_uni(program->get_uniform("u_directional_shadow_clip_from_world"))
162 ✗ , tex_diffuse_uniform(program->get_uniform("u_material.diffuse_tex"))
163 ✗ , tex_specular_uniform(program->get_uniform("u_material.specular_tex"))
164 ✗ , tex_emissive_uniform(program->get_uniform("u_material.emissive_tex"))
165 ✗ , ambient_tint_uni(program->get_uniform("u_material.ambient_tint"))
166 ✗ , specular_color_uni(program->get_uniform("u_material.specular_tint"))
167 ✗ , shininess_uni(program->get_uniform("u_material.shininess"))
168 ✗ , emissive_factor_uni(program->get_uniform("u_material.emissive_factor"))
169 ✗ , world_from_local_uni(
170 ✗ model_source == TransformSource::uniform ? std::optional<Uniform>{program->get_uniform("u_world_from_local")} : std::nullopt
171 )
172 ✗ , view_position_uni(program->get_uniform("u_view_position"))
173 ✗ , light_ambient_color_uni(program->get_uniform("u_ambient_light"))
174 {
175 ✗ for (int index = 0; index < settings.number_of_directional_lights; index += 1)
176 {
177 ✗ const std::string base = fmt::format("u_directional_lights[{}].", index);
178 ✗ directional_lights.emplace_back(program.get(), base);
179 ✗ }
180
181 ✗ for (int index = 0; index < settings.number_of_point_lights; index += 1)
182 {
183 ✗ const std::string base = fmt::format("u_point_lights[{}].", index);
184 ✗ point_lights.emplace_back(program.get(), base);
185 ✗ }
186
187 ✗ for (int index = 0; index < settings.number_of_frustum_lights; index += 1)
188 {
189 ✗ const std::string base = fmt::format("u_frustum_lights[{}].", index);
190 ✗ frustum_lights.emplace_back(program.get(), base);
191 ✗ }
192
193 ✗ std::vector<Uniform*> textures = {&tex_directional_light_depth_uni, &tex_diffuse_uniform, &tex_specular_uniform, &tex_emissive_uniform};
194 ✗ for (auto& fl: frustum_lights)
195 {
196 ✗ textures.emplace_back(&fl.tex_cookie_uniform);
197 }
198
199 ✗ setup_textures(program.get(), textures);
200 ✗ program->setup_uniform_block(desc.setup);
201 ✗ }
202
203
204
205 ✗ bool LoadedShader_Unlit_Container::is_loaded() const
206 {
207 ✗ return default_shader.program->is_loaded() && transparency_shader.program->is_loaded();
208 }
209
210
211
212 ✗ const LoadedShader_Unlit& shader_from_container(const LoadedShader_Unlit_Container& container, const RenderContext& rc)
213 {
214 ✗ return rc.use_transparency == UseTransparency::yes ? container.transparency_shader : container.default_shader;
215 }
216
217 ✗ const LoadedShader_Default& shader_from_container(const LoadedShader_Default_Container& container, const RenderContext& rc)
218 {
219 ✗ switch (rc.model_source)
220 {
221 ✗ case TransformSource::uniform:
222 ✗ return rc.use_transparency == UseTransparency::yes ? container.transparency_shader : container.default_shader;
223 ✗ case TransformSource::instanced_mat4:
224 ✗ ASSERT(rc.use_transparency == UseTransparency::no); // not currently supporting instanced transparency
225 ✗ return container.default_shader_instance;
226 ✗ default: ASSERT(false && "unhandled"); return container.default_shader;
227 }
228 }
229
230
231
232
233 ✗ bool LoadedShader_Default_Container::is_loaded() const
234 {
235 ✗ return default_shader.program->is_loaded() && transparency_shader.program->is_loaded();
236 }
237
238
239
240
241 ✗ RealizeShader::RealizeShader(std::shared_ptr<ShaderProgram> s)
242 ✗ : program(std::move(s))
243 ✗ , tex_input_uniform(program->get_uniform("u_texture"))
244 ✗ , tex_blurred_bloom_uniform(program->get_uniform("u_blurred_bloom"))
245 ✗ , use_blur_uniform(program->get_uniform("u_use_blur"))
246 ✗ , gamma_uniform(program->get_uniform("u_gamma"))
247 ✗ , exposure_uniform(program->get_uniform("u_exposure"))
248 {
249 ✗ setup_textures(program.get(), {&tex_input_uniform, &tex_blurred_bloom_uniform});
250 ✗ }
251
252
253
254 ✗ ExtractShader::ExtractShader(std::shared_ptr<LoadedPostProcShader>&& sh)
255 ✗ : shader(std::move(sh))
256 ✗ , cutoff_uniform(shader->program->get_uniform("u_cutoff"))
257 ✗ , softness_uniform(shader->program->get_uniform("u_softness"))
258 {
259 ✗ }
260
261 ✗ PingPongBlurShader::PingPongBlurShader(std::shared_ptr<LoadedPostProcShader>&& sh)
262 ✗ : shader(std::move(sh))
263 ✗ , is_horizontal_uniform(shader->program->get_uniform("u_is_horizontal"))
264 {
265 ✗ }
266
267
268
269 ✗ bool ShaderResource::is_loaded() const
270 {
271 ✗ return single_color_shader.program->is_loaded()
272 ✗ && depth_transform_uniform.program->is_loaded()
273 ✗ && depth_transform_instanced_mat4.program->is_loaded()
274 ✗ && skybox_shader.program->is_loaded()
275 ✗ && unlit_shader_container.is_loaded()
276 ✗ && default_shader_container.is_loaded()
277 ✗ && pp_realize.program->is_loaded();
278 }
279
280
281
282 using BaseShaderData = std::vector<core::VertexType>;
283
284
285
286 template<std::size_t count>
287 ✗ BaseShaderData get_vertex_types(const std::array<const core::ShaderVertexAttributes*, count>& vas)
288 {
289 ✗ std::set<core::VertexType> unique_types;
290 ✗ auto ret = BaseShaderData{};
291 ✗ for (const auto& va: vas)
292 {
293 ✗ for (const auto& v: *va)
294 {
295 ✗ const auto [_, is_unique] = unique_types.insert(v.type);
296 ✗ if (is_unique)
297 {
298 ✗ ret.emplace_back(v.type);
299 }
300 }
301 }
302 ✗ return ret;
303 ✗ }
304
305
306
307 // todo(Gustav): should this be a tuple instead? this way the members are named
308 struct LoadedShader
309 {
310 ✗ LoadedShader(std::shared_ptr<ShaderProgram> p, core::CompiledGeomVertexAttributes l)
311 ✗ : program(std::move(p))
312 ✗ , geom_layout(std::move(l))
313 ✗ {}
314
315 std::shared_ptr<ShaderProgram> program;
316 core::CompiledGeomVertexAttributes geom_layout;
317 };
318
319 ✗ std::optional<int> get_instance_start_index(const LoadedShader* shader)
320 {
321 ✗ if (shader == nullptr)
322 {
323 ✗ return std::nullopt;
324 }
325
326 ✗ const core::CompiledGeomVertexAttributes& layout = shader->geom_layout;
327
328 ✗ int max = 0;
329
330 ✗ for (const auto& entry: layout.elements)
331 {
332 ✗ max = std::max(entry.index, max);
333 }
334
335 ✗ return max + 1;
336 }
337
338 ✗ LoadedShader load_shader(DEBUG_LABEL_ARG_MANY const BaseShaderData& base_layout, const ShaderSource_withLayout& source, TransformSource model_source, const LoadedShader* instance_base = nullptr)
339 {
340 ✗ auto layout_compiler = compile_attribute_layouts(base_layout, {source.layout});
341 ✗ const auto geom_layout = get_geom_layout(layout_compiler);
342
343 ✗ std::optional<core::InstanceProp> instance_prop = std::nullopt;
344 ✗ std::optional<int> start_index = std::nullopt;
345 ✗ switch (model_source)
346 {
347 ✗ case TransformSource::instanced_mat4:
348 ✗ instance_prop = core::InstanceProp{core::VertexType::instance_transform, "u_world_from_local"};
349 ✗ start_index = get_instance_start_index(instance_base);
350 ✗ break;
351 ✗ case TransformSource::uniform: break;
352 ✗ default: ASSERT(false && "unhandled ModelSource");
353 }
354
355 ✗ const auto compiled_layout = compile_shader_layout(layout_compiler, source.layout, instance_prop, start_index);
356
357 ✗ auto program = std::make_shared<ShaderProgram>(USE_DEBUG_LABEL_MANY(debug_label) source.vertex, source.fragment, compiled_layout);
358
359 ✗ return {program, geom_layout};
360 ✗ }
361
362
363
364 ✗ ShaderResource load_shaders(const Assets& assets, const CameraUniformBuffer& desc, const RenderSettings& settings, const FullScreenGeom& full_screen)
365 {
366 ✗ const auto& default_shader_source = assets.default_shader_source;
367 ✗ const auto& skybox_shader_source = assets.skybox_shader_source;
368
369 ✗ const auto single_color_shader = load_shader_source(default_shader_source, {}, desc.setup.source);
370
371 ✗ ShaderOptions depth_shader_options;
372 ✗ depth_shader_options.only_depth = true;
373 ✗ const auto depth_transform_uniform = load_shader_source(default_shader_source, depth_shader_options, desc.setup.source);
374 ✗ const auto depth_transform_instanced_mat4 = load_shader_source(default_shader_source, depth_shader_options.with_instanced_mat4(), desc.setup.source);
375
376 ✗ const auto skybox_source = load_skybox_source(skybox_shader_source, desc.setup.source);
377 const auto skybox_shader = ShaderSource_withLayout{
378 ✗ core::ShaderVertexAttributes{{core::VertexType::position3, "a_position"}}, skybox_source.vertex, skybox_source.fragment
379 ✗ };
380
381 const BaseShaderData global_shader_data = get_vertex_types<3>
382 ({
383 &single_color_shader.layout,
384 &depth_transform_uniform.layout,
385 &depth_transform_instanced_mat4.layout
386 ✗ });
387
388 ✗ ShaderOptions unlit_shader_options;
389 ✗ unlit_shader_options.use_texture = true;
390
391 ✗ ShaderOptions default_shader_options;
392 ✗ default_shader_options.use_lights = true;
393 ✗ default_shader_options.use_texture = true;
394 ✗ default_shader_options.number_of_directional_lights = settings.number_of_directional_lights;
395 ✗ default_shader_options.number_of_point_lights = settings.number_of_point_lights;
396 ✗ default_shader_options.number_of_frustum_lights = settings.number_of_frustum_lights;
397
398 auto loaded_unlit = load_shader(
399 ✗ USE_DEBUG_LABEL_MANY("unlit")
400 global_shader_data,
401 ✗ load_shader_source(default_shader_source, unlit_shader_options.with_transparent_cutoff(), desc.setup.source),
402 TransformSource::uniform
403 ✗ );
404 auto loaded_default = load_shader(
405 ✗ USE_DEBUG_LABEL_MANY("default")
406 global_shader_data,
407 ✗ load_shader_source(default_shader_source, default_shader_options.with_transparent_cutoff(), desc.setup.source),
408 TransformSource::uniform
409 ✗ );
410 auto loaded_default_instanced = load_shader(
411 ✗ USE_DEBUG_LABEL_MANY("default instanced")
412 global_shader_data,
413 ✗ load_shader_source(default_shader_source, default_shader_options.with_transparent_cutoff().with_instanced_mat4(), desc.setup.source),
414 TransformSource::instanced_mat4
415 ✗ );
416
417 auto loaded_unlit_transparency = load_shader(
418 ✗ USE_DEBUG_LABEL_MANY("unlit transparency")
419 ✗ global_shader_data, load_shader_source(default_shader_source, unlit_shader_options, desc.setup.source), TransformSource::uniform
420 ✗ );
421 auto loaded_default_transparency = load_shader(
422 ✗ USE_DEBUG_LABEL_MANY("default transparency")
423 ✗ global_shader_data, load_shader_source(default_shader_source, default_shader_options, desc.setup.source), TransformSource::uniform
424 ✗ );
425
426 // todo(Gustav): should the asserts here be runtime errors? currently all setups are compile-time...
427 ✗ ASSERT(loaded_unlit.geom_layout.debug_types == loaded_unlit_transparency.geom_layout.debug_types);
428 ✗ ASSERT(loaded_default.geom_layout.debug_types == loaded_default_transparency.geom_layout.debug_types);
429 ✗ ASSERT(
430 loaded_default.geom_layout.debug_types == loaded_default_instanced.geom_layout.debug_types
431 ); // is this valid? should this fail?
432
433 #if 0
434
435 auto pp_invert = std::make_shared<LoadedPostProcShader>(
436 std::make_shared<ShaderProgram>(
437 USE_DEBUG_LABEL_MANY("pp invert")
438 std::string{PP_VERT_GLSL}, std::string{PP_INVERT_FRAG_GLSL}, full_screen.layout
439 ),
440 PostProcSetup::factor
441 );
442 auto pp_grayscale = std::make_shared<LoadedPostProcShader>(
443 std::make_shared<ShaderProgram>(
444 USE_DEBUG_LABEL_MANY("pp grayscale")
445 std::string{PP_VERT_GLSL}, std::string{PP_GRAYSCALE_FRAG_GLSL}, full_screen.layout
446 ),
447 PostProcSetup::factor
448 );
449 auto pp_damage = std::make_shared<LoadedPostProcShader>(
450 std::make_shared<ShaderProgram>(
451 USE_DEBUG_LABEL_MANY("pp damage")
452 std::string{PP_VERT_GLSL}, std::string{PP_DAMAGE_FRAG_GLSL}, full_screen.layout
453 ),
454 PostProcSetup::factor | PostProcSetup::resolution | PostProcSetup::time
455 );
456
457 constexpr IsGauss use_gauss =
458 #if FF_HAS(BLUR_USE_GAUSS)
459 IsGauss::yes
460 #else
461 IsGauss::no
462 #endif
463 ;
464
465 auto pp_blurv = std::make_shared<LoadedPostProcShader>(
466 std::make_shared<ShaderProgram>(
467 USE_DEBUG_LABEL_MANY("pp blur vert")
468 std::string{PP_VERT_GLSL},
469 generate_blur(PP_BLUR_FRAG_GLSL, {BlurType::vertical, blur_samples, use_gauss}),
470 full_screen.layout
471 ),
472 PostProcSetup::factor
473 );
474 auto pp_blurh = std::make_shared<LoadedPostProcShader>(
475 std::make_shared<ShaderProgram>(
476 USE_DEBUG_LABEL_MANY("pp blur hor")
477 std::string{PP_VERT_GLSL},
478 generate_blur(PP_BLUR_FRAG_GLSL, {BlurType::horizontal, blur_samples, use_gauss}),
479 full_screen.layout
480 ),
481 PostProcSetup::factor | PostProcSetup::resolution
482 );
483 #endif
484
485 ✗ auto pp_realize = RealizeShader{std::make_shared<ShaderProgram>(
486 USE_DEBUG_LABEL_MANY("pp realize")
487 ✗ assets.pp_vert_glsl, assets.pp_realize_frag_glsl, full_screen.layout
488 ✗ )};
489 ✗ auto pp_extract = ExtractShader{std::make_shared<LoadedPostProcShader>(
490 ✗ std::make_shared<ShaderProgram>(
491 ✗ USE_DEBUG_LABEL_MANY("pp extract") assets.pp_vert_glsl,
492 ✗ assets.pp_extract_frag_glsl,
493 ✗ full_screen.layout
494 ),
495 ✗ PostProcSetup::none
496 ✗ )};
497 ✗ auto pp_ping = PingPongBlurShader{std::make_shared<LoadedPostProcShader>(
498 ✗ std::make_shared<ShaderProgram>(
499 ✗ USE_DEBUG_LABEL_MANY("pp ping-pong") assets.pp_vert_glsl,
500 ✗ assets.pp_ping_pong_blur_frag_glsl,
501 ✗ full_screen.layout
502 ),
503 ✗ PostProcSetup::none
504 ✗ )};
505
506 auto loaded_single_color = load_shader(
507 ✗ USE_DEBUG_LABEL_MANY("single color") global_shader_data, single_color_shader, TransformSource::uniform
508 ✗ );
509 auto loaded_depth_transform_uniform = load_shader(
510 ✗ USE_DEBUG_LABEL_MANY("depth transform uniform") global_shader_data, depth_transform_uniform, TransformSource::uniform
511 ✗ );
512 auto loaded_depth_transform_instanced_mat4 = load_shader(
513 ✗ USE_DEBUG_LABEL_MANY("depth transform instanced") global_shader_data, depth_transform_instanced_mat4, TransformSource::instanced_mat4, &loaded_default_instanced
514 ✗ );
515 auto loaded_skybox_shader
516 ✗ = load_shader(USE_DEBUG_LABEL_MANY("skybox"){}, skybox_shader, TransformSource::uniform);
517
518
519 ✗ return ShaderResource{
520 // todo(Gustav): not really happy with sending "the same" argument twice, loaded_X.program and loaded_X.geom_layout
521 ✗ .single_color_shader = LoadedShader_SingleColor{std::move(loaded_single_color.program), loaded_single_color.geom_layout, desc},
522 .depth_transform_uniform = LoadedShader_OnlyDepth{
523 ✗ TransformSource::uniform, std::move(loaded_depth_transform_uniform.program),
524 loaded_depth_transform_uniform.geom_layout,
525 desc
526 ✗ },
527 .depth_transform_instanced_mat4 = LoadedShader_OnlyDepth{
528 TransformSource::instanced_mat4,
529 ✗ std::move(loaded_depth_transform_instanced_mat4.program),
530 loaded_depth_transform_instanced_mat4.geom_layout,
531 desc
532 ✗ },
533 ✗ .skybox_shader = LoadedShader_Skybox{std::move(loaded_skybox_shader.program), loaded_skybox_shader.geom_layout, desc},
534 .unlit_shader_container = LoadedShader_Unlit_Container{
535 loaded_unlit.geom_layout,
536 ✗ LoadedShader_Unlit{TransformSource::uniform, std::move(loaded_unlit.program), desc},
537 ✗ LoadedShader_Unlit{TransformSource::uniform, std::move(loaded_unlit_transparency.program), desc}
538 },
539 .default_shader_container = LoadedShader_Default_Container{
540 loaded_default.geom_layout,
541 ✗ LoadedShader_Default{TransformSource::uniform, std::move(loaded_default.program), settings, desc},
542 ✗ LoadedShader_Default{TransformSource::uniform, std::move(loaded_default_transparency.program), settings, desc},
543 ✗ LoadedShader_Default{TransformSource::instanced_mat4, std::move(loaded_default_instanced.program), settings, desc}
544 },
545 // .pp_invert = pp_invert,
546 // .pp_grayscale = pp_grayscale,
547 // .pp_damage = pp_damage,
548 // .pp_blurv = pp_blurv,
549 // .pp_blurh = pp_blurh,
550 .pp_realize = pp_realize,
551 .pp_extract = pp_extract,
552 .pp_ping = pp_ping
553 ✗ };
554 ✗ }
555
556
557
558 } // namespace eu::render
559