From 842c817bb679a5a0abc05e8149e2e6e0ae1a0412 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sat, 27 Feb 2021 01:27:16 +0200 Subject: [PATCH] Use specialization constants in the builtin material shaders This has the side effect that RenderPass now requires a collection to use the builtin shaders. --- shaderlib/common.glsl | 2 +- shaderlib/cooktorrance.glsl | 12 ++++---- shaderlib/phong.glsl | 20 ++++++------- shaderlib/shadow.glsl | 2 +- source/materials/basicmaterial.cpp | 45 ++++++++++-------------------- source/materials/basicmaterial.h | 2 +- source/materials/material.cpp | 19 +++++++------ source/materials/material.h | 3 +- source/materials/pbrmaterial.cpp | 34 ++++++++-------------- source/materials/pbrmaterial.h | 2 +- source/materials/renderpass.cpp | 2 +- source/materials/unlitmaterial.cpp | 11 +++----- source/materials/unlitmaterial.h | 2 +- 13 files changed, 65 insertions(+), 91 deletions(-) diff --git a/shaderlib/common.glsl b/shaderlib/common.glsl index 4a816360..5c10d06f 100644 --- a/shaderlib/common.glsl +++ b/shaderlib/common.glsl @@ -1,7 +1,7 @@ import msp_interface; import shadow; -const bool use_normal_map = false; +layout(constant_id=auto) const bool use_normal_map = false; #pragma MSP stage(vertex) vec4 get_vertex_position() diff --git a/shaderlib/cooktorrance.glsl b/shaderlib/cooktorrance.glsl index 6a7ebb38..89b4c99c 100644 --- a/shaderlib/cooktorrance.glsl +++ b/shaderlib/cooktorrance.glsl @@ -2,12 +2,12 @@ import msp_interface; import common; import shadow; -const bool use_base_color_map = false; -const bool use_metalness_map = false; -const bool use_roughness_map = false; -const bool use_occlusion_map = false; -const bool use_emission = false; -const bool use_emission_map = false; +layout(constant_id=auto) const bool use_base_color_map = false; +layout(constant_id=auto) const bool use_metalness_map = false; +layout(constant_id=auto) const bool use_roughness_map = false; +layout(constant_id=auto) const bool use_occlusion_map = false; +layout(constant_id=auto) const bool use_emission = false; +layout(constant_id=auto) const bool use_emission_map = false; const float PI = 3.1415926535; diff --git a/shaderlib/phong.glsl b/shaderlib/phong.glsl index 90f0ac8a..56fa68c7 100644 --- a/shaderlib/phong.glsl +++ b/shaderlib/phong.glsl @@ -2,16 +2,16 @@ import msp_interface; import common; import shadow; -const bool use_diffuse_map = false; -const bool use_specular = false; -const bool use_specular_map = false; -const bool use_shininess_map = false; -const bool use_emission = false; -const bool use_emission_map = false; -const bool use_reflectivity = false; -const bool use_reflectivity_map = false; -const bool use_sky = false; -const bool use_fog = false; +layout(constant_id=auto) const bool use_diffuse_map = false; +layout(constant_id=auto) const bool use_specular = false; +layout(constant_id=auto) const bool use_specular_map = false; +layout(constant_id=auto) const bool use_shininess_map = false; +layout(constant_id=auto) const bool use_emission = false; +layout(constant_id=auto) const bool use_emission_map = false; +layout(constant_id=auto) const bool use_reflectivity = false; +layout(constant_id=auto) const bool use_reflectivity_map = false; +layout(constant_id=auto) const bool use_sky = false; +layout(constant_id=auto) const bool use_fog = false; #pragma MSP stage(fragment) vec4 get_diffuse_color() diff --git a/shaderlib/shadow.glsl b/shaderlib/shadow.glsl index 0a20b3a5..d751b460 100644 --- a/shaderlib/shadow.glsl +++ b/shaderlib/shadow.glsl @@ -1,6 +1,6 @@ import msp_interface; -const bool use_shadow_map = false; +layout(constant_id=auto) const bool use_shadow_map = false; #pragma MSP stage(vertex) void shadow_transform(vec4 eye_vertex) diff --git a/source/materials/basicmaterial.cpp b/source/materials/basicmaterial.cpp index 362fc9db..33dced53 100644 --- a/source/materials/basicmaterial.cpp +++ b/source/materials/basicmaterial.cpp @@ -15,36 +15,21 @@ BasicMaterial::BasicMaterial(): set_reflectivity(0.0f); } -string BasicMaterial::create_program_source() const -{ - string source = "import phong;\n"; - if(diffuse.texture) - source += "const bool use_diffuse_map = true;\n"; - if(specular.texture || specular.value.r || specular.value.g || specular.value.b) - { - source += "const bool use_specular = true;\n"; - if(specular.texture) - source += "const bool use_specular_map = true;\n"; - if(shininess.texture) - source += "const bool use_shininess_map = true;\n"; - } - if(normal.texture) - source += "const bool use_normal_map = true;\n"; - if(emission.texture || emission.value.r || emission.value.g || emission.value.b) - { - source += "const bool use_emission = true;\n"; - if(emission.texture) - source += "const bool use_emission_map = true;\n"; - } - if(reflectivity.value || reflectivity.texture) - { - source += "const bool use_reflectivity = true;\n"; - if (reflectivity.texture) - source += "const bool use_reflectivity_map = true;\n"; - } - if(receive_shadows) - source += "const bool use_shadow_map = true;\n"; - return source; +void BasicMaterial::fill_program_info(string &module_name, map &spec_values) const +{ + module_name = "phong.glsl"; + spec_values["use_diffuse_map"] = (diffuse.texture!=0); + bool use_specular = (specular.texture || specular.value.r || specular.value.g || specular.value.b); + spec_values["use_specular"] = use_specular; + spec_values["use_specular_map"] = (specular.texture!=0); + spec_values["use_shininess_map"] = (use_specular && shininess.texture!=0); + spec_values["use_normal_map"] = (normal.texture!=0); + bool use_emission = (emission.texture || emission.value.r || emission.value.g || emission.value.b); + spec_values["use_emission"] = use_emission; + spec_values["use_emission_map"] = (emission.texture!=0); + spec_values["use_reflectivity"] = (reflectivity.value!=0 || reflectivity.texture!=0); + spec_values["use_reflectivity_map"] = (reflectivity.texture!=0); + spec_values["use_shadow_map"] = receive_shadows; } void BasicMaterial::attach_textures_to(Texturing &texturing, ProgramData &tex_shdata) const diff --git a/source/materials/basicmaterial.h b/source/materials/basicmaterial.h index 95259f47..ef7d1526 100644 --- a/source/materials/basicmaterial.h +++ b/source/materials/basicmaterial.h @@ -35,7 +35,7 @@ public: BasicMaterial(); protected: - virtual std::string create_program_source() const; + virtual void fill_program_info(std::string &, std::map &) const; public: virtual void attach_textures_to(Texturing &, ProgramData &) const; diff --git a/source/materials/material.cpp b/source/materials/material.cpp index 17fa546b..25ed7218 100644 --- a/source/materials/material.cpp +++ b/source/materials/material.cpp @@ -13,20 +13,23 @@ using namespace std; namespace Msp { namespace GL { -Program *Material::create_compatible_shader() const -{ - return new Program(create_program_source()); -} - const Program *Material::create_compatible_shader(DataFile::Collection &coll) const { - string source = create_program_source(); - string name = format("_material_%016x.glsl", hash64(source)); + string module_name; + map spec_values; + fill_program_info(module_name, spec_values); + + string info = module_name; + for(map::const_iterator i=spec_values.begin(); i!=spec_values.end(); ++i) + info += format(",%s:%d", i->first, i->second); + + string name = format("_material_%016x.shader", hash64(info)); Program *shprog = coll.find(name); if(shprog) return shprog; - shprog = new Program(create_program_source()); + const Module &module = coll.get(module_name); + shprog = new Program(module, spec_values); try { coll.add(name, shprog); diff --git a/source/materials/material.h b/source/materials/material.h index 350372dd..727c61b7 100644 --- a/source/materials/material.h +++ b/source/materials/material.h @@ -96,10 +96,9 @@ protected: public: virtual ~Material() { } - virtual Program *create_compatible_shader() const; virtual const Program *create_compatible_shader(DataFile::Collection &) const; protected: - virtual std::string create_program_source() const = 0; + virtual void fill_program_info(std::string &, std::map &) const = 0; public: /** Returns the uniforms for the material. */ diff --git a/source/materials/pbrmaterial.cpp b/source/materials/pbrmaterial.cpp index bc7104cc..16c287b4 100644 --- a/source/materials/pbrmaterial.cpp +++ b/source/materials/pbrmaterial.cpp @@ -14,28 +14,18 @@ PbrMaterial::PbrMaterial(): set_emission(0.0f); } -string PbrMaterial::create_program_source() const -{ - string source = "import cooktorrance;\n"; - if(base_color.texture) - source += "const bool use_base_color_map = true;\n"; - if(normal.texture) - source += "const bool use_normal_map = true;\n"; - if(metalness.texture) - source += "const bool use_metalness_map = true;\n"; - if(roughness.texture) - source += "const bool use_roughness_map = true;\n"; - if(occlusion.texture) - source += "const bool use_occlusion_map = true;\n"; - if(emission.texture || emission.value.r || emission.value.g || emission.value.b) - { - source += "const bool use_emission = true;\n"; - if(emission.texture) - source += "const bool use_emission_map = true;\n"; - } - if(receive_shadows) - source += "const bool use_shadow_map = true;\n"; - return source; +void PbrMaterial::fill_program_info(string &module_name, map &spec_values) const +{ + module_name = "cooktorrance.glsl"; + spec_values["use_base_color_map"] = (base_color.texture!=0); + spec_values["use_normal_map"] = (normal.texture!=0); + spec_values["use_metalness_map"] = (metalness.texture!=0); + spec_values["use_roughness_map"] = (roughness.texture!=0); + spec_values["use_occlusion_map"] = (occlusion.texture!=0); + bool use_emission = (emission.texture || emission.value.r || emission.value.g || emission.value.b); + spec_values["use_emission"] = use_emission; + spec_values["use_emission_map"] = (emission.texture!=0); + spec_values["use_shadow_map"] = receive_shadows; } void PbrMaterial::attach_textures_to(Texturing &texturing, ProgramData &tex_shdata) const diff --git a/source/materials/pbrmaterial.h b/source/materials/pbrmaterial.h index 2a0eef35..a1f736f4 100644 --- a/source/materials/pbrmaterial.h +++ b/source/materials/pbrmaterial.h @@ -35,7 +35,7 @@ public: PbrMaterial(); protected: - virtual std::string create_program_source() const; + virtual void fill_program_info(std::string &, std::map &) const; public: virtual void attach_textures_to(Texturing &, ProgramData &) const; diff --git a/source/materials/renderpass.cpp b/source/materials/renderpass.cpp index fb092624..5ee50f8a 100644 --- a/source/materials/renderpass.cpp +++ b/source/materials/renderpass.cpp @@ -77,7 +77,7 @@ void RenderPass::maybe_create_material_shader(DataFile::Collection *coll) shprog.keep(); } else - shprog = material->create_compatible_shader(); + throw invalid_operation("no collection"); if(shdata) shdata = new ProgramData(*shdata, shprog.get()); diff --git a/source/materials/unlitmaterial.cpp b/source/materials/unlitmaterial.cpp index 5eddd669..9aded252 100644 --- a/source/materials/unlitmaterial.cpp +++ b/source/materials/unlitmaterial.cpp @@ -12,14 +12,11 @@ UnlitMaterial::UnlitMaterial(): set_tint(Color(1.0f)); } -string UnlitMaterial::create_program_source() const +void UnlitMaterial::fill_program_info(string &module_name, map &spec_values) const { - string source = "import unlit;\n"; - if(texture) - source += "const bool use_texture = true;\n"; - if(vertex_color) - source += "const bool use_vertex_color = true;\n"; - return source; + module_name = "unlit.glsl"; + spec_values["use_texture"] = (texture!=0); + spec_values["use_vertex_color"] = vertex_color; } void UnlitMaterial::attach_textures_to(Texturing &texturing, ProgramData &tex_shdata) const diff --git a/source/materials/unlitmaterial.h b/source/materials/unlitmaterial.h index b8b28835..22e22691 100644 --- a/source/materials/unlitmaterial.h +++ b/source/materials/unlitmaterial.h @@ -33,7 +33,7 @@ public: UnlitMaterial(); protected: - virtual std::string create_program_source() const; + virtual void fill_program_info(std::string &, std::map &) const; public: virtual void attach_textures_to(Texturing &, ProgramData &) const; -- 2.43.0