diff --git a/sources.cmake b/sources.cmake index d4f28ae4d..ba4868d71 100644 --- a/sources.cmake +++ b/sources.cmake @@ -1,5 +1,5 @@ # Modify this file to change the last-modified date when you add/remove a file. -# This will then trigger a new cmake run automatically. +# This will then trigger a new cmake run automatically. file(GLOB_RECURSE STK_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.hpp") file(GLOB_RECURSE STK_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.cpp") file(GLOB_RECURSE STK_SHADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "data/shaders/*") diff --git a/src/graphics/2dutils.cpp b/src/graphics/2dutils.cpp index 87bf3a16e..42fab11e0 100644 --- a/src/graphics/2dutils.cpp +++ b/src/graphics/2dutils.cpp @@ -24,6 +24,7 @@ #include "graphics/shader.hpp" #include "graphics/shaders.hpp" #include "graphics/shared_gpu_objects.hpp" +#include "graphics/shared_shaders.hpp" #include "graphics/texture_manager.hpp" #include "graphics/texture_shader.hpp" #include "utils/cpp2011.hpp" @@ -43,7 +44,7 @@ public: Primitive2DList() { loadProgram(OBJECT, GL_VERTEX_SHADER, "primitive2dlist.vert", - GL_FRAGMENT_SHADER, "transparent.frag"); + GET_SS(SharedTransparent)); assignUniforms("custom_alpha"); assignSamplerNames(0, "tex", ST_BILINEAR_FILTERED); } // Primitive2DList @@ -58,7 +59,7 @@ class UniformColoredTextureRectShader : public TextureShaderkill(); resetTextureTable(); cleanUnicolorTextures(); @@ -930,6 +929,7 @@ void IrrDriver::applyResolutionSettings() } delete m_renderer; initDevice(); + ShaderBase::updateShaders(); font_manager = new FontManager(); font_manager->loadFonts(); diff --git a/src/graphics/lighting_passes.cpp b/src/graphics/lighting_passes.cpp index 55675ed8d..cf321c176 100644 --- a/src/graphics/lighting_passes.cpp +++ b/src/graphics/lighting_passes.cpp @@ -26,7 +26,8 @@ #include "graphics/post_processing.hpp" #include "graphics/rtts.hpp" #include "graphics/shaders.hpp" -#include "graphics/shadow_matrices.hpp" +#include "graphics/shadow_matrices.hpp" +#include "graphics/shared_shaders.hpp" #include "modes/world.hpp" #include "tracks/track.hpp" #include "utils/profiler.hpp" @@ -63,7 +64,7 @@ class FogShader : public TextureShader public: FogShader() { - loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", + loadProgram(OBJECT, GET_SS(SharedScreenQuad), GL_FRAGMENT_SHADER, "fog.frag"); assignUniforms("density", "col"); assignSamplerNames(0, "tex", ST_NEAREST_FILTERED); @@ -190,12 +191,12 @@ public: { if (CVS->isAMDVertexShaderLayerUsable()) { - loadProgram(OBJECT, GL_VERTEX_SHADER, "slicedscreenquad.vert", + loadProgram(OBJECT, GET_SS(SharedSlicedScreenQuad), GL_FRAGMENT_SHADER, "rh.frag"); } else { - loadProgram(OBJECT, GL_VERTEX_SHADER, "slicedscreenquad.vert", + loadProgram(OBJECT, GET_SS(SharedSlicedScreenQuad), GL_GEOMETRY_SHADER, "rhpassthrough.geom", GL_FRAGMENT_SHADER, "rh.frag"); } @@ -238,7 +239,7 @@ class GlobalIlluminationReconstructionShader public: GlobalIlluminationReconstructionShader() { - loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", + loadProgram(OBJECT, GET_SS(SharedScreenQuad), GL_FRAGMENT_SHADER, "gi.frag"); assignUniforms("rh_matrix", "inv_rh_matrix", "extents"); @@ -271,7 +272,7 @@ class IBLShader : public TextureShader public: IBLShader() { - loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", + loadProgram(OBJECT, GET_SS(SharedScreenQuad), GL_FRAGMENT_SHADER, "IBL.frag"); assignUniforms(); assignSamplerNames(0, "ntex", ST_NEAREST_FILTERED, @@ -286,7 +287,7 @@ class DegradedIBLShader : public TextureShader public: DegradedIBLShader() { - loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", + loadProgram(OBJECT, GET_SS(SharedScreenQuad), GL_FRAGMENT_SHADER, "degraded_ibl.frag"); assignUniforms(); assignSamplerNames(0, "ntex", ST_NEAREST_FILTERED); @@ -301,7 +302,7 @@ class ShadowedSunLightShaderPCF : public TextureShader { public: InstancedObjectPass1Shader() { - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_object_pass.vert", - GL_FRAGMENT_SHADER, "instanced_object_pass1.frag"); + loadProgram(OBJECT, GET_SS(SharedInstanced), + GET_SS(SharedInstancedPass1)); assignUniforms(); assignSamplerNames(0, "glosstex", ST_TRILINEAR_ANISOTROPIC_FILTERED); @@ -46,8 +46,8 @@ class InstancedObjectRefPass1Shader : public TextureShaderisAMDVertexShaderLayerUsable()) { - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanciedshadow.vert", + loadProgram(OBJECT, GET_SS(SharedInstancedShadow), GL_FRAGMENT_SHADER, "shadow.frag"); } else { - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanciedshadow.vert", + loadProgram(OBJECT, GET_SS(SharedInstancedShadow), GL_GEOMETRY_SHADER, "instanced_shadow.geom", GL_FRAGMENT_SHADER, "shadow.frag"); } @@ -222,7 +222,7 @@ class SphereMapShader : public TextureShader public: SplattingShader() { - loadProgram(OBJECT, GL_VERTEX_SHADER, "object_pass.vert", + loadProgram(OBJECT, GET_SS(SharedObject), GL_FRAGMENT_SHADER, "splatting.frag"); assignUniforms("ModelMatrix"); @@ -277,7 +277,7 @@ class ObjectRefPass1Shader : public TextureShaderisAMDVertexShaderLayerUsable()) { - loadProgram(OBJECT,GL_VERTEX_SHADER, "instanciedshadow.vert", + loadProgram(OBJECT,GET_SS(SharedInstancedShadow), GL_FRAGMENT_SHADER, "instanced_shadowref.frag"); } else { - loadProgram(OBJECT,GL_VERTEX_SHADER, "instanciedshadow.vert", + loadProgram(OBJECT,GET_SS(SharedInstancedShadow), GL_GEOMETRY_SHADER, "instanced_shadow.geom", GL_FRAGMENT_SHADER, "instanced_shadowref.frag"); } @@ -442,9 +442,9 @@ public: NormalVisualizer() { #if !defined(USE_GLES2) - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_object_pass.vert", + loadProgram(OBJECT, GET_SS(SharedInstanced), GL_GEOMETRY_SHADER, "normal_visualizer.geom", - GL_FRAGMENT_SHADER, "coloredquad.frag"); + GET_SS(SharedColoredQuad)); assignUniforms("color"); #endif } // NormalVisualizer @@ -473,8 +473,8 @@ class InstancedGrassPass1Shader : public TextureShadersupportsHardwareSkinning()) return; - loadProgram(OBJECT, GL_VERTEX_SHADER, "skinning.vert", - GL_FRAGMENT_SHADER, "object_pass1.frag"); + loadProgram(OBJECT, GET_SS(SharedSkinning), + GET_SS(SharedPass1)); assignUniforms("ModelMatrix", "InverseModelMatrix", "skinning_offset"); assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED); } // SkinnedPass1Shader @@ -640,8 +640,8 @@ public: InstancedSkinnedPass1Shader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning.vert", - GL_FRAGMENT_SHADER, "instanced_object_pass1.frag"); + loadProgram(OBJECT, GET_SS(SharedInstancedSkinning), + GET_SS(SharedInstancedPass1)); assignUniforms(); assignSamplerNames(0, "glosstex", ST_TRILINEAR_ANISOTROPIC_FILTERED); } // InstancedSkinnedPass1Shader @@ -656,7 +656,7 @@ public: SkinnedPass2Shader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GL_VERTEX_SHADER, "skinning.vert", + loadProgram(OBJECT, GET_SS(SharedSkinning), GL_FRAGMENT_SHADER, "object_pass2.frag"); assignUniforms("ModelMatrix", "texture_trans", "color_change", "skinning_offset"); @@ -676,8 +676,8 @@ public: InstancedSkinnedPass2Shader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning.vert", - GL_FRAGMENT_SHADER, "instanced_object_pass2.frag"); + loadProgram(OBJECT, GET_SS(SharedInstancedSkinning), + GET_SS(SharedInstancedPass2)); assignUniforms(); assignSamplerNames(0, "DiffuseMap", ST_NEAREST_FILTERED, 1, "SpecularMap", ST_NEAREST_FILTERED, @@ -698,7 +698,7 @@ public: SkinnedRefPass1Shader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GL_VERTEX_SHADER, "skinning.vert", + loadProgram(OBJECT, GET_SS(SharedSkinning), GL_FRAGMENT_SHADER, "objectref_pass1.frag"); assignUniforms("ModelMatrix", "InverseModelMatrix", "texture_trans", "skinning_offset"); @@ -714,8 +714,8 @@ public: InstancedSkinnedRefPass1Shader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning.vert", - GL_FRAGMENT_SHADER, "instanced_objectref_pass1.frag"); + loadProgram(OBJECT, GET_SS(SharedInstancedSkinning), + GET_SS(SharedInstancedRefPass1)); assignUniforms(); assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED, 1, "glosstex", ST_TRILINEAR_ANISOTROPIC_FILTERED); @@ -732,7 +732,7 @@ public: SkinnedRefPass2Shader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GL_VERTEX_SHADER, "skinning.vert", + loadProgram(OBJECT, GET_SS(SharedSkinning), GL_FRAGMENT_SHADER, "objectref_pass2.frag"); assignUniforms("ModelMatrix", "texture_trans", "color_change", "skinning_offset"); @@ -752,8 +752,8 @@ public: InstancedSkinnedRefPass2Shader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning.vert", - GL_FRAGMENT_SHADER, "instanced_objectref_pass2.frag"); + loadProgram(OBJECT, GET_SS(SharedInstancedSkinning), + GET_SS(SharedInstancedRefPass2)); assignUniforms(); assignSamplerNames(0, "DiffuseMap", ST_NEAREST_FILTERED, 1, "SpecularMap", ST_NEAREST_FILTERED, @@ -773,7 +773,7 @@ public: SkinnedUnlitShader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GL_VERTEX_SHADER, "skinning.vert", + loadProgram(OBJECT, GET_SS(SharedSkinning), GL_FRAGMENT_SHADER, "object_unlit.frag"); assignUniforms("ModelMatrix", "texture_trans", "skinning_offset"); assignSamplerNames(0, "DiffuseMap", ST_NEAREST_FILTERED, @@ -790,8 +790,8 @@ public: InstancedSkinnedUnlitShader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning.vert", - GL_FRAGMENT_SHADER, "instanced_object_unlit.frag"); + loadProgram(OBJECT, GET_SS(SharedInstancedSkinning), + GET_SS(SharedInstancedUnlit)); assignUniforms(); assignSamplerNames(0, "DiffuseMap", ST_NEAREST_FILTERED, 1, "SpecularMap", ST_NEAREST_FILTERED, @@ -809,7 +809,7 @@ public: SkinnedNormalMapShader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GL_VERTEX_SHADER, "skinning.vert", + loadProgram(OBJECT, GET_SS(SharedSkinning), GL_FRAGMENT_SHADER, "normalmap.frag"); assignUniforms("ModelMatrix", "InverseModelMatrix", "skinning_offset"); assignSamplerNames(0, "normalMap", ST_TRILINEAR_ANISOTROPIC_FILTERED, @@ -824,8 +824,8 @@ public: InstancedSkinnedNormalMapShader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning.vert", - GL_FRAGMENT_SHADER, "instanced_normalmap.frag"); + loadProgram(OBJECT, GET_SS(SharedInstancedSkinning), + GET_SS(SharedInstancedNormal)); assignUniforms(); assignSamplerNames(0, "normalMap", ST_TRILINEAR_ANISOTROPIC_FILTERED, 1, "glossMap", ST_TRILINEAR_ANISOTROPIC_FILTERED); @@ -871,12 +871,12 @@ public: return; if (CVS->isAMDVertexShaderLayerUsable()) { - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning_shadow.vert", + loadProgram(OBJECT, GET_SS(SharedInstancedSkinningShadow), GL_FRAGMENT_SHADER, "shadow.frag"); } else { - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning_shadow.vert", + loadProgram(OBJECT, GET_SS(SharedInstancedSkinningShadow), GL_GEOMETRY_SHADER, "instanced_shadow.geom", GL_FRAGMENT_SHADER, "shadow.frag"); } @@ -926,12 +926,12 @@ public: return; if (CVS->isAMDVertexShaderLayerUsable()) { - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning_shadow.vert", + loadProgram(OBJECT, GET_SS(SharedInstancedSkinningShadow), GL_FRAGMENT_SHADER, "instanced_shadowref.frag"); } else { - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning_shadow.vert", + loadProgram(OBJECT, GET_SS(SharedInstancedSkinningShadow), GL_GEOMETRY_SHADER, "instanced_shadow.geom", GL_FRAGMENT_SHADER, "instanced_shadowref.frag"); } diff --git a/src/graphics/post_processing.cpp b/src/graphics/post_processing.cpp index 3ba0be240..da6e1f8bb 100644 --- a/src/graphics/post_processing.cpp +++ b/src/graphics/post_processing.cpp @@ -30,6 +30,7 @@ #include "graphics/rtts.hpp" #include "graphics/shaders.hpp" #include "graphics/shared_gpu_objects.hpp" +#include "graphics/shared_shaders.hpp" #include "graphics/stk_mesh_scene_node.hpp" #include "graphics/texture_manager.hpp" #include "graphics/weather.hpp" @@ -56,7 +57,7 @@ class Gaussian3HBlurShader : public TextureShader public: BloomShader() { - loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", + loadProgram(OBJECT, GET_SS(SharedScreenQuad), GL_FRAGMENT_SHADER, "bloom.frag"); assignUniforms("scale"); assignSamplerNames(0, "tex", ST_NEAREST_FILTERED); @@ -364,7 +365,7 @@ public: if (!lensDustTex) lensDustTex = irr_driver->getTexture(FileManager::TEXTURE, "gfx_lensDust_a.png"); - loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", + loadProgram(OBJECT, GET_SS(SharedScreenQuad), GL_FRAGMENT_SHADER, "bloomblend.frag"); assignUniforms(); assignSamplerNames(0, "tex_128", ST_BILINEAR_FILTERED, @@ -391,7 +392,7 @@ class LensBlendShader : public TextureShader public: LensBlendShader() { - loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", + loadProgram(OBJECT, GET_SS(SharedScreenQuad), GL_FRAGMENT_SHADER, "lensblend.frag"); assignUniforms(); @@ -419,7 +420,7 @@ public: ToneMapShader() { - loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", + loadProgram(OBJECT, GET_SS(SharedScreenQuad), GL_FRAGMENT_SHADER, "tonemap.frag"); assignUniforms("vignette_weight"); assignSamplerNames(0, "text", ST_NEAREST_FILTERED); @@ -439,7 +440,7 @@ class DepthOfFieldShader : public TextureShader public: DepthOfFieldShader() { - loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", + loadProgram(OBJECT, GET_SS(SharedScreenQuad), GL_FRAGMENT_SHADER, "dof.frag"); assignUniforms(); @@ -481,7 +482,7 @@ class PassThroughShader : public TextureShader public: PassThroughShader() { - loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", + loadProgram(OBJECT, GET_SS(SharedScreenQuad), GL_FRAGMENT_SHADER, "passthrough.frag"); assignUniforms("width", "height"); assignSamplerNames(0, "tex", ST_BILINEAR_FILTERED); @@ -505,7 +506,7 @@ private: public: LayerPassThroughShader() { - loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", + loadProgram(OBJECT, GET_SS(SharedScreenQuad), GL_FRAGMENT_SHADER, "layertexturequad.frag"); m_tu_texture = 0; assignUniforms("layer"); @@ -531,7 +532,7 @@ class LinearizeDepthShader : public TextureShader public: SSAOShader() { - loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", + loadProgram(OBJECT, GET_SS(SharedScreenQuad), GL_FRAGMENT_SHADER, "ssao.frag"); assignUniforms("radius", "k", "sigma"); @@ -605,7 +606,7 @@ class MotionBlurShader : public TextureShader public: GodFadeShader() { - loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", + loadProgram(OBJECT, GET_SS(SharedScreenQuad), GL_FRAGMENT_SHADER, "godfade.frag"); assignUniforms("col"); assignSamplerNames(0, "tex", ST_BILINEAR_FILTERED); @@ -650,7 +651,7 @@ class GodRayShader : public TextureShader public: GodRayShader() { - loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", + loadProgram(OBJECT, GET_SS(SharedScreenQuad), GL_FRAGMENT_SHADER, "godray.frag"); assignUniforms("sunpos"); @@ -671,7 +672,7 @@ class MLAAColorEdgeDetectionSHader public: MLAAColorEdgeDetectionSHader() { - loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", + loadProgram(OBJECT, GET_SS(SharedScreenQuad), GL_FRAGMENT_SHADER, "mlaa_color1.frag"); assignUniforms("PIXEL_SIZE"); assignSamplerNames(0, "colorMapG", ST_NEAREST_FILTERED); @@ -692,7 +693,7 @@ class MLAABlendWeightSHader : public TextureShader + void loadAndAttachShader(SharedShader* ss, Types ... args) + { + GLint shader_id = ss->getShaderID(); + glAttachShader(m_program, shader_id); + GLint is_deleted = GL_TRUE; + glGetShaderiv(shader_id, GL_DELETE_STATUS, &is_deleted); + if (is_deleted == GL_FALSE) + glDeleteShader(shader_id); + loadAndAttachShader(args...); + } // loadAndAttachShader + // ------------------------------------------------------------------------ /** Convenience interface using const char. */ template void loadAndAttachShader(GLint shader_type, const char *name, @@ -90,12 +103,12 @@ protected: } // loadAndAttachShader // ------------------------------------------------------------------------ - const std::string& getHeader(); - GLuint loadShader(const std::string &file, unsigned type); + static const std::string& getHeader(); void setAttribute(AttributeType type); public: ShaderBase(); + static GLuint loadShader(const std::string &file, unsigned type); int loadTFBProgram(const std::string &vertex_file_path, const char **varyings, unsigned varyingscount); @@ -285,7 +298,13 @@ protected: Log::error("shader", filepath); printFileList(args...); } // printFileList - + // ------------------------------------------------------------------------ + template + void printFileList(SharedShader* ss, Types ... args) + { + Log::error("shader", ss->getName()); + printFileList(args...); + } // printFileList // ------------------------------------------------------------------------ /** End recursion for variadic template. */ private: diff --git a/src/graphics/shader_based_renderer.cpp b/src/graphics/shader_based_renderer.cpp index 4c8e3e278..6253bfb56 100644 --- a/src/graphics/shader_based_renderer.cpp +++ b/src/graphics/shader_based_renderer.cpp @@ -31,6 +31,7 @@ #include "graphics/render_target.hpp" #include "graphics/rtts.hpp" #include "graphics/shaders.hpp" +#include "graphics/shared_shaders.hpp" #include "graphics/skybox.hpp" #include "graphics/spherical_harmonics.hpp" #include "graphics/texture_manager.hpp" @@ -641,7 +642,8 @@ ShaderBasedRenderer::ShaderBasedRenderer() m_skybox = NULL; m_spherical_harmonics = new SphericalHarmonics(irr_driver->getAmbientLight().toSColor()); m_nb_static_glowing = 0; - + preloadSharedShaders(); + if (CVS->isAZDOEnabled()) { m_geometry_passes = new GeometryPasses(); @@ -681,6 +683,7 @@ ShaderBasedRenderer::~ShaderBasedRenderer() delete m_spherical_harmonics; delete m_skybox; delete m_rtts; + SharedShaderManager::kill(); } // ---------------------------------------------------------------------------- @@ -961,4 +964,41 @@ void ShaderBasedRenderer::renderToTexture(GL3RenderTarget *render_target, } //renderToTexture +void ShaderBasedRenderer::preloadSharedShaders() +{ + SharedShaderManager* ssm = SharedShaderManager::getInstance(); + // Common shaders: + ssm->addSharedShader(new SharedObject()); + ssm->addSharedShader(new SharedPass1()); + if (CVS->supportsHardwareSkinning()) + ssm->addSharedShader(new SharedSkinning()); + ssm->addSharedShader(new SharedTransparent()); + ssm->addSharedShader(new SharedTexturedQuad()); + ssm->addSharedShader(new SharedColoredQuad()); + ssm->addSharedShader(new SharedSlicedScreenQuad()); + ssm->addSharedShader(new SharedScreenQuad()); + + if (CVS->supportsIndirectInstancingRendering()) + { + ssm->addSharedShader(new SharedInstanced()); + if (CVS->supportsHardwareSkinning()) + ssm->addSharedShader(new SharedInstancedSkinning()); + ssm->addSharedShader(new SharedInstancedPass1()); + ssm->addSharedShader(new SharedInstancedPass2()); + ssm->addSharedShader(new SharedInstancedRefPass1()); + ssm->addSharedShader(new SharedInstancedRefPass2()); + ssm->addSharedShader(new SharedInstancedUnlit()); + ssm->addSharedShader(new SharedInstancedNormal()); + ssm->addSharedShader(new SharedInstancedGrass()); + ssm->addSharedShader(new SharedInstancedGrassPass2()); + if (CVS->isShadowEnabled()) + { + ssm->addSharedShader(new SharedInstancedShadow()); + if (CVS->supportsHardwareSkinning()) + ssm->addSharedShader(new SharedInstancedSkinningShadow()); + } + } + +} //preLoadSharedShaders + #endif // !SERVER_ONLY diff --git a/src/graphics/shader_based_renderer.hpp b/src/graphics/shader_based_renderer.hpp index e5e33752d..e3a97ed88 100644 --- a/src/graphics/shader_based_renderer.hpp +++ b/src/graphics/shader_based_renderer.hpp @@ -85,7 +85,7 @@ private: void debugPhysics(); void renderPostProcessing(Camera * const camera); - + void preloadSharedShaders(); public: ShaderBasedRenderer(); diff --git a/src/graphics/shaders.cpp b/src/graphics/shaders.cpp index ed8e6c238..f448bd488 100644 --- a/src/graphics/shaders.cpp +++ b/src/graphics/shaders.cpp @@ -100,6 +100,7 @@ #include "graphics/gpu_particles.hpp" #include "graphics/irr_driver.hpp" #include "graphics/shared_gpu_objects.hpp" +#include "graphics/shared_shaders.hpp" #include "io/file_manager.hpp" #include "utils/log.hpp" @@ -340,8 +341,8 @@ void Shaders::check(const int num) // Solid Normal and depth pass shaders Shaders::ObjectPass1Shader::ObjectPass1Shader() { - loadProgram(OBJECT, GL_VERTEX_SHADER, "object_pass.vert", - GL_FRAGMENT_SHADER, "object_pass1.frag"); + loadProgram(OBJECT, GET_SS(SharedObject), + GET_SS(SharedPass1)); assignUniforms("ModelMatrix", "InverseModelMatrix"); assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED); } // ObjectPass1Shader @@ -350,7 +351,7 @@ Shaders::ObjectPass1Shader::ObjectPass1Shader() // Solid Lit pass shaders Shaders::ObjectPass2Shader::ObjectPass2Shader() { - loadProgram(OBJECT, GL_VERTEX_SHADER, "object_pass.vert", + loadProgram(OBJECT, GET_SS(SharedObject), GL_FRAGMENT_SHADER, "object_pass2.frag"); assignUniforms("ModelMatrix", "texture_trans", "color_change"); assignSamplerNames(0, "DiffuseMap", ST_NEAREST_FILTERED, @@ -365,8 +366,8 @@ Shaders::ObjectPass2Shader::ObjectPass2Shader() Shaders::SkinnedTransparentShader::SkinnedTransparentShader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GL_VERTEX_SHADER, "skinning.vert", - GL_FRAGMENT_SHADER, "transparent.frag"); + loadProgram(OBJECT, GET_SS(SharedSkinning), + GET_SS(SharedTransparent)); assignUniforms("ModelMatrix", "texture_trans", "skinning_offset", "custom_alpha"); assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED); } // SkinnedTransparentShader @@ -374,8 +375,8 @@ Shaders::SkinnedTransparentShader::SkinnedTransparentShader() // ============================================================================ Shaders::TransparentShader::TransparentShader() { - loadProgram(OBJECT, GL_VERTEX_SHADER, "object_pass.vert", - GL_FRAGMENT_SHADER, "transparent.frag"); + loadProgram(OBJECT, GET_SS(SharedObject), + GET_SS(SharedTransparent)); assignUniforms("ModelMatrix", "texture_trans", "custom_alpha"); assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED); } // TransparentShader @@ -383,7 +384,7 @@ Shaders::TransparentShader::TransparentShader() // ============================================================================ Shaders::TransparentFogShader::TransparentFogShader() { - loadProgram(OBJECT, GL_VERTEX_SHADER, "object_pass.vert", + loadProgram(OBJECT, GET_SS(SharedObject), GL_FRAGMENT_SHADER, "transparentfog.frag"); assignUniforms("ModelMatrix", "texture_trans", "fogmax", "startH", "endH", "start", "end", "col"); @@ -393,9 +394,8 @@ Shaders::TransparentFogShader::TransparentFogShader() // ============================================================================ Shaders::ColoredLine::ColoredLine() { - loadProgram(OBJECT, GL_VERTEX_SHADER, "object_pass.vert", - GL_FRAGMENT_SHADER, "coloredquad.frag"); - + loadProgram(OBJECT, GET_SS(SharedObject), + GET_SS(SharedColoredQuad)); assignUniforms("color"); glGenVertexArrays(1, &m_vao); diff --git a/src/graphics/shadow_matrices.cpp b/src/graphics/shadow_matrices.cpp index 9ba9f0b6a..c3dc5e51b 100644 --- a/src/graphics/shadow_matrices.cpp +++ b/src/graphics/shadow_matrices.cpp @@ -27,6 +27,7 @@ #include "graphics/rtts.hpp" #include "graphics/shaders.hpp" #include "graphics/shared_gpu_objects.hpp" +#include "graphics/shared_shaders.hpp" #include "modes/world.hpp" #include "physics/triangle_mesh.hpp" #include "tracks/track.hpp" @@ -95,7 +96,7 @@ private: public: ViewFrustrumShader() { loadProgram(OBJECT, GL_VERTEX_SHADER, "frustrum.vert", - GL_FRAGMENT_SHADER, "coloredquad.frag"); + GET_SS(SharedColoredQuad)); assignUniforms("color", "idx"); diff --git a/src/graphics/shared_shader.cpp b/src/graphics/shared_shader.cpp new file mode 100644 index 000000000..238c86b7a --- /dev/null +++ b/src/graphics/shared_shader.cpp @@ -0,0 +1,28 @@ +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2016 SuperTuxKart-Team +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef SERVER_ONLY + +#include "graphics/shared_shader.hpp" +#include "graphics/shader.hpp" + +void SharedShader::loadSharedShader() +{ + m_shader_id = ShaderBase::loadShader(getName(), getShaderType()); +}; // loadSharedShader + +#endif // !SERVER_ONLY diff --git a/src/graphics/shared_shader.hpp b/src/graphics/shared_shader.hpp new file mode 100644 index 000000000..68a941e4e --- /dev/null +++ b/src/graphics/shared_shader.hpp @@ -0,0 +1,49 @@ +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2016 SuperTuxKart-Team +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef SERVER_ONLY + +#ifndef HEADER_SHARED_SHADER_HPP +#define HEADER_SHARED_SHADER_HPP + +#include "graphics/gl_headers.hpp" +#include "utils/no_copy.hpp" + +class SharedShader : public NoCopy +{ +private: + GLuint m_shader_id; +public: + // ------------------------------------------------------------------------ + SharedShader() { m_shader_id = 0; } + // ------------------------------------------------------------------------ + virtual ~SharedShader() {} + // ------------------------------------------------------------------------ + GLuint getShaderID() const { return m_shader_id; } + // ------------------------------------------------------------------------ + virtual const char* getName() = 0; + // ------------------------------------------------------------------------ + virtual unsigned getShaderType() = 0; + // ------------------------------------------------------------------------ + void loadSharedShader(); + +}; // SharedShader + +#endif + +#endif // !SERVER_ONLY + diff --git a/src/graphics/shared_shader_manager.hpp b/src/graphics/shared_shader_manager.hpp new file mode 100644 index 000000000..17a8fd45d --- /dev/null +++ b/src/graphics/shared_shader_manager.hpp @@ -0,0 +1,81 @@ +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2016 SuperTuxKart-Team +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef SERVER_ONLY + +#ifndef HEADER_SHARED_SHADER_MANAGER_HPP +#define HEADER_SHARED_SHADER_MANAGER_HPP + +#include "graphics/shared_shader.hpp" +#include "utils/no_copy.hpp" +#include "utils/singleton.hpp" + +#include +#include +#include +#include + +class SharedShaderManager : public Singleton, NoCopy +{ +private: + std::unordered_map m_shaders_map; + + std::vector m_shared_shaders; + + unsigned int m_shared_shader_loaded; + +public: + // ------------------------------------------------------------------------ + SharedShaderManager() { m_shared_shader_loaded = 0; } + // ------------------------------------------------------------------------ + ~SharedShaderManager() + { + for (SharedShader* ss : m_shared_shaders) + delete ss; + } // ~SharedShaderManager + // ------------------------------------------------------------------------ + template + void addSharedShader(T* ss) + { + ss->loadSharedShader(); + m_shaders_map[std::type_index(typeid(T))] = m_shared_shader_loaded++; + m_shared_shaders.push_back(ss); + } // addSharedShader + // ------------------------------------------------------------------------ + template T* getSharedShader() + { + std::unordered_map::const_iterator i = + m_shaders_map.find(std::type_index(typeid(T))); + if (i != m_shaders_map.end()) + { + T* ss = dynamic_cast(m_shared_shaders[i->second]); + assert(ss != NULL); + return ss; + } + else + { + T* new_ss = new T(); + addSharedShader(new_ss); + return new_ss; + } + } // getSharedShader +}; // SharedShaderManager + +#endif + +#endif // !SERVER_ONLY + diff --git a/src/graphics/shared_shaders.hpp b/src/graphics/shared_shaders.hpp new file mode 100644 index 000000000..98ed601c2 --- /dev/null +++ b/src/graphics/shared_shaders.hpp @@ -0,0 +1,244 @@ +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2016 SuperTuxKart-Team +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef SERVER_ONLY + +#ifndef HEADER_SHARED_SHADERS_HPP +#define HEADER_SHARED_SHADERS_HPP + +#include "graphics/shared_shader_manager.hpp" +#include "utils/cpp2011.hpp" + +#define GET_SS(SS) SharedShaderManager::getInstance()->getSharedShader() + +// ============================================================================ +// Common shaders: +class SharedObject : public SharedShader +{ +public: + // ------------------------------------------------------------------------ + virtual const char* getName() OVERRIDE { return "object_pass.vert"; } + // ------------------------------------------------------------------------ + virtual unsigned getShaderType() OVERRIDE { return GL_VERTEX_SHADER; } +}; // SharedObject + +// ============================================================================ +class SharedPass1 : public SharedShader +{ +public: + // ------------------------------------------------------------------------ + virtual const char* getName() OVERRIDE { return "object_pass1.frag"; } + // ------------------------------------------------------------------------ + virtual unsigned getShaderType() OVERRIDE { return GL_FRAGMENT_SHADER; } +}; // SharedPass1 + +// ============================================================================ +class SharedSkinning : public SharedShader +{ +public: + // ------------------------------------------------------------------------ + virtual const char* getName() OVERRIDE { return "skinning.vert"; } + // ------------------------------------------------------------------------ + virtual unsigned getShaderType() OVERRIDE { return GL_VERTEX_SHADER; } +}; // SharedSkinning + +// ============================================================================ +class SharedTransparent : public SharedShader +{ +public: + // ------------------------------------------------------------------------ + virtual const char* getName() OVERRIDE { return "transparent.frag"; } + // ------------------------------------------------------------------------ + virtual unsigned getShaderType() OVERRIDE { return GL_FRAGMENT_SHADER; } +}; // SharedTransparent + +// ============================================================================ +class SharedTexturedQuad : public SharedShader +{ +public: + // ------------------------------------------------------------------------ + virtual const char* getName() OVERRIDE { return "texturedquad.vert"; } + // ------------------------------------------------------------------------ + virtual unsigned getShaderType() OVERRIDE { return GL_VERTEX_SHADER; } +}; // SharedTexturedQuad + +// ============================================================================ +class SharedColoredQuad : public SharedShader +{ +public: + // ------------------------------------------------------------------------ + virtual const char* getName() OVERRIDE { return "coloredquad.frag"; } + // ------------------------------------------------------------------------ + virtual unsigned getShaderType() OVERRIDE { return GL_FRAGMENT_SHADER; } +}; // SharedColoredQuad + +// ============================================================================ +class SharedSlicedScreenQuad : public SharedShader +{ +public: + // ------------------------------------------------------------------------ + virtual const char* getName() OVERRIDE { return "slicedscreenquad.vert"; } + // ------------------------------------------------------------------------ + virtual unsigned getShaderType() OVERRIDE { return GL_VERTEX_SHADER; } +}; // SharedSlicedScreenQuad + +// ============================================================================ +class SharedScreenQuad : public SharedShader +{ +public: + // ------------------------------------------------------------------------ + virtual const char* getName() OVERRIDE { return "screenquad.vert"; } + // ------------------------------------------------------------------------ + virtual unsigned getShaderType() OVERRIDE { return GL_VERTEX_SHADER; } +}; // SharedScreenQuad + +// ============================================================================ +// Instanced shaders: +class SharedInstanced : public SharedShader +{ +public: + // ------------------------------------------------------------------------ + virtual const char* getName() OVERRIDE + { return "instanced_object_pass.vert"; } + // ------------------------------------------------------------------------ + virtual unsigned getShaderType() OVERRIDE { return GL_VERTEX_SHADER; } +}; // SharedInstanced + +// ============================================================================ +class SharedInstancedSkinning : public SharedShader +{ +public: + // ------------------------------------------------------------------------ + virtual const char* getName() OVERRIDE + { return "instanced_skinning.vert"; } + // ------------------------------------------------------------------------ + virtual unsigned getShaderType() OVERRIDE { return GL_VERTEX_SHADER; } +}; // SharedInstancedSkinning + +// ============================================================================ +class SharedInstancedPass1 : public SharedShader +{ +public: + // ------------------------------------------------------------------------ + virtual const char* getName() OVERRIDE + { return "instanced_object_pass1.frag"; } + // ------------------------------------------------------------------------ + virtual unsigned getShaderType() OVERRIDE { return GL_FRAGMENT_SHADER; } +}; // SharedInstancedPass1 + +// ============================================================================ +class SharedInstancedPass2 : public SharedShader +{ +public: + // ------------------------------------------------------------------------ + virtual const char* getName() OVERRIDE + { return "instanced_object_pass2.frag"; } + // ------------------------------------------------------------------------ + virtual unsigned getShaderType() OVERRIDE { return GL_FRAGMENT_SHADER; } +}; // SharedInstancedPass2 + +// ============================================================================ +class SharedInstancedRefPass1 : public SharedShader +{ +public: + // ------------------------------------------------------------------------ + virtual const char* getName() OVERRIDE + { return "instanced_objectref_pass1.frag"; } + // ------------------------------------------------------------------------ + virtual unsigned getShaderType() OVERRIDE { return GL_FRAGMENT_SHADER; } +}; // SharedInstancedRefPass1 + +// ============================================================================ +class SharedInstancedRefPass2 : public SharedShader +{ +public: + // ------------------------------------------------------------------------ + virtual const char* getName() OVERRIDE + { return "instanced_objectref_pass2.frag"; } + // ------------------------------------------------------------------------ + virtual unsigned getShaderType() OVERRIDE { return GL_FRAGMENT_SHADER; } +}; // SharedInstancedRefPass2 + +// ============================================================================ +class SharedInstancedUnlit : public SharedShader +{ +public: + // ------------------------------------------------------------------------ + virtual const char* getName() OVERRIDE + { return "instanced_object_unlit.frag"; } + // ------------------------------------------------------------------------ + virtual unsigned getShaderType() OVERRIDE { return GL_FRAGMENT_SHADER; } +}; // SharedInstancedUnlit + +// ============================================================================ +class SharedInstancedNormal : public SharedShader +{ +public: + // ------------------------------------------------------------------------ + virtual const char* getName() OVERRIDE + { return "instanced_normalmap.frag"; } + // ------------------------------------------------------------------------ + virtual unsigned getShaderType() OVERRIDE { return GL_FRAGMENT_SHADER; } +}; // SharedInstancedNormal + +// ============================================================================ +class SharedInstancedGrass : public SharedShader +{ +public: + // ------------------------------------------------------------------------ + virtual const char* getName() OVERRIDE + { return "instanced_grass.vert"; } + // ------------------------------------------------------------------------ + virtual unsigned getShaderType() OVERRIDE { return GL_VERTEX_SHADER; } +}; // SharedInstancedGrass + +// ============================================================================ +class SharedInstancedGrassPass2 : public SharedShader +{ +public: + // ------------------------------------------------------------------------ + virtual const char* getName() OVERRIDE + { return "instanced_grass_pass2.frag"; } + // ------------------------------------------------------------------------ + virtual unsigned getShaderType() OVERRIDE { return GL_FRAGMENT_SHADER; } +}; // SharedInstancedGrassPass2 + +// ============================================================================ +class SharedInstancedShadow : public SharedShader +{ +public: + // ------------------------------------------------------------------------ + virtual const char* getName() OVERRIDE { return "instanciedshadow.vert"; } + // ------------------------------------------------------------------------ + virtual unsigned getShaderType() OVERRIDE { return GL_VERTEX_SHADER; } +}; // SharedInstancedShadow + +// ============================================================================ +class SharedInstancedSkinningShadow : public SharedShader +{ +public: + // ------------------------------------------------------------------------ + virtual const char* getName() OVERRIDE + { return "instanced_skinning_shadow.vert"; } + // ------------------------------------------------------------------------ + virtual unsigned getShaderType() OVERRIDE { return GL_VERTEX_SHADER; } +}; // SharedInstancedSkinningShadow + +#endif + +#endif // !SERVER_ONLY + diff --git a/src/graphics/skybox.cpp b/src/graphics/skybox.cpp index fd1c597b8..0bb22c5ce 100644 --- a/src/graphics/skybox.cpp +++ b/src/graphics/skybox.cpp @@ -21,7 +21,7 @@ #include "graphics/central_settings.hpp" #include "graphics/irr_driver.hpp" #include "graphics/shaders.hpp" - +#include "graphics/shared_shaders.hpp" #include #include @@ -64,7 +64,7 @@ public: GLuint m_tu_samples; SpecularIBLGenerator() { - loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", + loadProgram(OBJECT, GET_SS(SharedScreenQuad), GL_FRAGMENT_SHADER, "importance_sampling_specular.frag"); assignUniforms("PermutationMatrix", "ViewportSize"); m_tu_samples = 1; diff --git a/src/graphics/stk_mesh_scene_node.cpp b/src/graphics/stk_mesh_scene_node.cpp index 7b2c6c0ab..e915e53e4 100644 --- a/src/graphics/stk_mesh_scene_node.cpp +++ b/src/graphics/stk_mesh_scene_node.cpp @@ -24,6 +24,7 @@ #include "graphics/material_manager.hpp" #include "graphics/render_info.hpp" #include "graphics/rtts.hpp" +#include "graphics/shared_shaders.hpp" #include "graphics/stk_mesh.hpp" #include "graphics/texture_manager.hpp" #include "graphics/vao_manager.hpp" @@ -40,7 +41,7 @@ class ColorizeShader : public ShadersetDebugMode(IrrDebugDrawer::DM_NONE);