diff --git a/libs/gfx/include/psemek/gfx/program.hpp b/libs/gfx/include/psemek/gfx/program.hpp index 2b6774ba..cf9b1b6c 100644 --- a/libs/gfx/include/psemek/gfx/program.hpp +++ b/libs/gfx/include/psemek/gfx/program.hpp @@ -14,13 +14,39 @@ namespace psemek::gfx { + struct shader_source + { + std::vector sources; + + template + shader_source(char const (&source)[N]) + : sources{std::string_view{source}} + {} + + shader_source(char const * source) + : sources{std::string_view{source}} + {} + + shader_source(std::string_view source) + : sources{source} + {} + + shader_source(std::initializer_list sources) + : sources(sources) + {} + + explicit shader_source(std::vector sources) + : sources{std::move(sources)} + {} + }; + struct program { - program(std::string_view vertex_source, std::string_view fragment_source); + program(shader_source const & vertex_source, shader_source const & fragment_source); #ifndef __EMSCRIPTEN__ - program(std::string_view compute_source); - program(std::string_view vertex_source, std::string_view geometry_source, std::string_view fragment_source); + program(shader_source const & compute_source); + program(shader_source const & vertex_source, shader_source const & geometry_source, shader_source const & fragment_source); #endif program(program && other); diff --git a/libs/gfx/source/effect/blur.cpp b/libs/gfx/source/effect/blur.cpp index 1738994a..4ded46d1 100644 --- a/libs/gfx/source/effect/blur.cpp +++ b/libs/gfx/source/effect/blur.cpp @@ -117,7 +117,7 @@ void main() gfx::array array; blur_impl(int size, float sigma, float gamma, bool horizontal) - : program(std::string(gl::sys::shader_prelude()) + blur_vs, std::string(gl::sys::shader_prelude()) + generate_blur_fs_source(size, sigma, horizontal)) + : program({gl::sys::shader_prelude(), blur_vs}, {gl::sys::shader_prelude(), generate_blur_fs_source(size, sigma, horizontal)}) { program.bind(); program["u_texture"] = 0; diff --git a/libs/gfx/source/effect/fxaa.cpp b/libs/gfx/source/effect/fxaa.cpp index fa5fed58..3310c9ae 100644 --- a/libs/gfx/source/effect/fxaa.cpp +++ b/libs/gfx/source/effect/fxaa.cpp @@ -206,7 +206,7 @@ void main() struct fxaa::impl { - gfx::program program{std::string(gl::sys::shader_prelude()) + fxaa_vs, std::string(gl::sys::shader_prelude()) + fxaa_fs}; + gfx::program program{{gl::sys::shader_prelude(), fxaa_vs}, {gl::sys::shader_prelude(), fxaa_fs}}; gfx::array array; }; diff --git a/libs/gfx/source/effect/gamma.cpp b/libs/gfx/source/effect/gamma.cpp index 3449ea1f..5bedf049 100644 --- a/libs/gfx/source/effect/gamma.cpp +++ b/libs/gfx/source/effect/gamma.cpp @@ -48,7 +48,7 @@ void main() struct gamma_correction::impl { - gfx::program program{std::string(gl::sys::shader_prelude()) + gamma_vs, std::string(gl::sys::shader_prelude()) + gamma_fs}; + gfx::program program{{gl::sys::shader_prelude(), gamma_vs}, {gl::sys::shader_prelude(), gamma_fs}}; gfx::array array; }; diff --git a/libs/gfx/source/effect/overlay.cpp b/libs/gfx/source/effect/overlay.cpp index 1a672e79..066835dc 100644 --- a/libs/gfx/source/effect/overlay.cpp +++ b/libs/gfx/source/effect/overlay.cpp @@ -45,7 +45,7 @@ void main() struct overlay::impl { - gfx::program program{std::string(gl::sys::shader_prelude()) + overlay_vs, std::string(gl::sys::shader_prelude()) + overlay_fs}; + gfx::program program{{gl::sys::shader_prelude(), overlay_vs}, {gl::sys::shader_prelude(), overlay_fs}}; gfx::array array; }; diff --git a/libs/gfx/source/painter.cpp b/libs/gfx/source/painter.cpp index d98c1920..6a75214f 100644 --- a/libs/gfx/source/painter.cpp +++ b/libs/gfx/source/painter.cpp @@ -107,7 +107,7 @@ void main() namespace psemek::gfx { - static std::string shader_prefix = std::string{gl::sys::shader_prelude()}; + static auto const shader_prefix = gl::sys::shader_prelude(); struct painter::impl { @@ -130,9 +130,9 @@ namespace psemek::gfx math::point texcoord; }; - gfx::program program{shader_prefix + vertex_source, shader_prefix + fragment_source}; - gfx::program text_program{shader_prefix + text_vertex_source, shader_prefix + text_fragment_source}; - gfx::program texture_program{shader_prefix + texture_vertex_source, shader_prefix + texture_fragment_source}; + gfx::program program{{shader_prefix, vertex_source}, {shader_prefix, fragment_source}}; + gfx::program text_program{{shader_prefix, text_vertex_source}, {shader_prefix, text_fragment_source}}; + gfx::program texture_program{{shader_prefix, texture_vertex_source}, {shader_prefix, texture_fragment_source}}; gfx::mesh mesh; gfx::mesh text_mesh; gfx::mesh texture_mesh; diff --git a/libs/gfx/source/program.cpp b/libs/gfx/source/program.cpp index a0d39c27..b5947883 100644 --- a/libs/gfx/source/program.cpp +++ b/libs/gfx/source/program.cpp @@ -216,37 +216,46 @@ namespace psemek::gfx (*this) = q.coords; } - static std::string annotated_source(std::string_view source) + static std::string annotated_source(shader_source const & sources) { std::ostringstream os; bool first = true; int line = 1; - for (char c : source) + for (auto const & source : sources.sources) { - if (first) + for (char c : source) { - os << line << ": "; - first = false; - } + if (first) + { + os << line << ": "; + first = false; + } - os.put(c); - if (c == '\n') - { - ++line; - first = true; + os.put(c); + if (c == '\n') + { + ++line; + first = true; + } } } return os.str(); } - static void load_shader(GLuint shader, std::string_view source) + static void load_shader(GLuint shader, shader_source const & sources) { - char const * vert_sources[1] { source.data() }; - GLint vert_sources_len[1] { static_cast(source.size()) }; - gl::ShaderSource(shader, 1, vert_sources, vert_sources_len); + std::vector source_ptrs; + std::vector source_lens; + for (auto const & source : sources.sources) + { + source_ptrs.push_back(source.data()); + source_lens.push_back(source.size()); + } + + gl::ShaderSource(shader, sources.sources.size(), source_ptrs.data(), source_lens.data()); gl::CompileShader(shader); GLint status; @@ -257,7 +266,7 @@ namespace psemek::gfx gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &log_len); std::unique_ptr log(new char [log_len]); gl::GetShaderInfoLog(shader, log_len, nullptr, log.get()); - throw util::exception(util::to_string("Shader compilation failed: ", log.get(), "\nShader source: \n", annotated_source(source))); + throw util::exception(util::to_string("Shader compilation failed: ", log.get(), "\nShader source: \n", annotated_source(sources))); } } @@ -282,7 +291,7 @@ namespace psemek::gfx gl::DetachShader(program, s); } - static GLuint create_program(std::vector> const & sources) + static GLuint create_program(std::vector> const & sources) { std::vector shaders; @@ -295,7 +304,7 @@ namespace psemek::gfx { GLuint sh = gl::CreateShader(p.first); shaders.push_back(sh); - load_shader(sh, p.second); + load_shader(sh, *p.second); } GLuint program = gl::CreateProgram(); @@ -313,20 +322,20 @@ namespace psemek::gfx return program; } - program::program(std::string_view vertex_source, std::string_view fragment_source) + program::program(shader_source const & vertex_source, shader_source const & fragment_source) { - program_ = create_program({{gl::VERTEX_SHADER, vertex_source}, {gl::FRAGMENT_SHADER, fragment_source}}); + program_ = create_program({{gl::VERTEX_SHADER, &vertex_source}, {gl::FRAGMENT_SHADER, &fragment_source}}); } #ifndef __EMSCRIPTEN__ - program::program(std::string_view compute_source) + program::program(shader_source const & compute_source) { - program_ = create_program({{gl::COMPUTE_SHADER, compute_source}}); + program_ = create_program({{gl::COMPUTE_SHADER, &compute_source}}); } - program::program(std::string_view vertex_source, std::string_view geometry_source, std::string_view fragment_source) + program::program(shader_source const & vertex_source, shader_source const & geometry_source, shader_source const & fragment_source) { - program_ = create_program({{gl::VERTEX_SHADER, vertex_source}, {gl::GEOMETRY_SHADER, geometry_source}, {gl::FRAGMENT_SHADER, fragment_source}}); + program_ = create_program({{gl::VERTEX_SHADER, &vertex_source}, {gl::GEOMETRY_SHADER, &geometry_source}, {gl::FRAGMENT_SHADER, &fragment_source}}); } #endif diff --git a/libs/gfx/source/renderer/deferred.cpp b/libs/gfx/source/renderer/deferred.cpp index f96a9810..457373d4 100644 --- a/libs/gfx/source/renderer/deferred.cpp +++ b/libs/gfx/source/renderer/deferred.cpp @@ -811,16 +811,16 @@ void main(){} deferred_renderer::position_mode position_mode = deferred_renderer::position_mode::float32; bool position_mode_changed = true; - gfx::program occlusion_pass_program{occlusion_pass_vs, occlusion_pass_fs}; - gfx::program g_buffer_pass_program{std::string(g_buffer_pass_common) + g_buffer_pass_vs, std::string(g_buffer_pass_common) + g_buffer_pass_fs}; - gfx::program ambient_pass_program{fullscreen_vs, std::string(light_common) + ambient_pass_fs}; - gfx::program directional_light_pass_program{screen_vs, std::string(light_common) + directional_light_pass_fs}; - gfx::program point_light_pass_program{screen_vs, std::string(light_common) + point_light_pass_fs}; - gfx::program shadow_builder_program{std::string(g_buffer_pass_common) + shadow_builder_vs, shadow_builder_fs}; - gfx::program cubemap_shadow_builder_program{std::string(g_buffer_pass_common) + shadow_builder_vs, shadow_builder_gs, shadow_builder_fs}; - gfx::program transparent_pass_program{std::string(g_buffer_pass_common) + transparent_pass_vs, std::string(g_buffer_pass_common) + transparent_pass_fs}; - gfx::program bloom_pass_program{std::string(g_buffer_pass_common) + transparent_pass_vs, std::string(g_buffer_pass_common) + transparent_pass_fs}; - gfx::program ssao_pass_program{fullscreen_vs, std::string(light_common) + ssao_pass_fs}; + gfx::program occlusion_pass_program{{occlusion_pass_vs}, {occlusion_pass_fs}}; + gfx::program g_buffer_pass_program{{g_buffer_pass_common, g_buffer_pass_vs}, {g_buffer_pass_common, g_buffer_pass_fs}}; + gfx::program ambient_pass_program{{fullscreen_vs}, {light_common, ambient_pass_fs}}; + gfx::program directional_light_pass_program{{screen_vs}, {light_common, directional_light_pass_fs}}; + gfx::program point_light_pass_program{{screen_vs}, {light_common, point_light_pass_fs}}; + gfx::program shadow_builder_program{{g_buffer_pass_common, shadow_builder_vs}, {shadow_builder_fs}}; + gfx::program cubemap_shadow_builder_program{{g_buffer_pass_common, shadow_builder_vs}, {shadow_builder_gs}, {shadow_builder_fs}}; + gfx::program transparent_pass_program{{g_buffer_pass_common, transparent_pass_vs}, {g_buffer_pass_common, transparent_pass_fs}}; + gfx::program bloom_pass_program{{g_buffer_pass_common, transparent_pass_vs}, {g_buffer_pass_common, transparent_pass_fs}}; + gfx::program ssao_pass_program{{fullscreen_vs}, {light_common, ssao_pass_fs}}; // G-buffer attachments: // 0 - position (rbg)