diff --git a/src/graphics/shader_based_renderer.cpp b/src/graphics/shader_based_renderer.cpp index 19b7a1047..bf3a3dd29 100644 --- a/src/graphics/shader_based_renderer.cpp +++ b/src/graphics/shader_based_renderer.cpp @@ -383,7 +383,7 @@ void ShaderBasedRenderer::renderSceneDeferred(scene::ICameraSceneNode * const ca PROFILER_PUSH_CPU_MARKER("- Transparent Pass", 0xFF, 0x00, 0x00); ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_TRANSPARENT)); SP::draw(SP::RP_1ST, SP::DCT_TRANSPARENT); - SP::draw(SP::RP_2ND, SP::DCT_TRANSPARENT); + SP::draw(SP::RP_RESERVED, SP::DCT_TRANSPARENT); PROFILER_POP_CPU_MARKER(); } @@ -493,7 +493,7 @@ void ShaderBasedRenderer::renderScene(scene::ICameraSceneNode * const camnode, PROFILER_PUSH_CPU_MARKER("- Transparent Pass", 0xFF, 0x00, 0x00); ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_TRANSPARENT)); SP::draw(SP::RP_1ST, SP::DCT_TRANSPARENT); - SP::draw(SP::RP_2ND, SP::DCT_TRANSPARENT); + SP::draw(SP::RP_RESERVED, SP::DCT_TRANSPARENT); PROFILER_POP_CPU_MARKER(); } diff --git a/src/graphics/sp/sp_base.cpp b/src/graphics/sp/sp_base.cpp index 620e900df..55f30c7cb 100644 --- a/src/graphics/sp/sp_base.cpp +++ b/src/graphics/sp/sp_base.cpp @@ -70,6 +70,8 @@ bool g_handle_shadow = false; // ---------------------------------------------------------------------------- std::unordered_map g_shaders; // ---------------------------------------------------------------------------- +SPShader* g_normal_visualizer = NULL; +// ---------------------------------------------------------------------------- SPShader* g_glow_shader = NULL; // ---------------------------------------------------------------------------- // std::string is layer_1 and layer_2 texture name combined @@ -414,7 +416,7 @@ void loadShaders() addShader(shader); // ======================================================================== - shader = new SPShader("alphatest", 3, false, 0, true); + shader = new SPShader("alphatest", {{ 0, 1, -1 }}, false, 0, true); shader->addShaderFile("sp_pass.vert", GL_VERTEX_SHADER, RP_1ST); shader->addShaderFile("sp_alpha_test.frag", GL_FRAGMENT_SHADER, RP_1ST); @@ -435,7 +437,7 @@ void loadShaders() addShader(shader); - shader = new SPShader("alphatest_skinned", 3, false, 0, true); + shader = new SPShader("alphatest_skinned", {{ 0, 1, -1 }}, false, 0, true); shader->addShaderFile("sp_skinning.vert", GL_VERTEX_SHADER, RP_1ST); shader->addShaderFile("sp_alpha_test.frag", GL_FRAGMENT_SHADER, RP_1ST); @@ -457,7 +459,7 @@ void loadShaders() addShader(shader); // ======================================================================== - shader = new SPShader("unlit", 3, false, 0, true); + shader = new SPShader("unlit", {{ 0, 1, -1 }}, false, 0, true); shader->addShaderFile("sp_pass.vert", GL_VERTEX_SHADER, RP_1ST); shader->addShaderFile("sp_unlit.frag", GL_FRAGMENT_SHADER, RP_1ST); @@ -478,7 +480,7 @@ void loadShaders() addShader(shader); - shader = new SPShader("unlit_skinned", 3, false, 0, true); + shader = new SPShader("unlit_skinned", {{ 0, 1, -1 }}, false, 0, true); shader->addShaderFile("sp_skinning.vert", GL_VERTEX_SHADER, RP_1ST); shader->addShaderFile("sp_unlit.frag", GL_FRAGMENT_SHADER, RP_1ST); @@ -521,7 +523,7 @@ void loadShaders() addShader(shader); - shader = new SPShader("normalmap_skinned", 3, false); + shader = new SPShader("normalmap_skinned", {{ 0, 1, -1 }}, false); shader->addShaderFile("sp_skinning.vert", GL_VERTEX_SHADER, RP_1ST); shader->addShaderFile("sp_normal_map.frag", GL_FRAGMENT_SHADER, RP_1ST); @@ -543,7 +545,7 @@ void loadShaders() addShader(shader); // ======================================================================== - shader = new SPShader("grass", 3, false, 0, true); + shader = new SPShader("grass", {{ 0, 1, -1 }}, false, 0, true); shader->addShaderFile("sp_grass_pass.vert", GL_VERTEX_SHADER, RP_1ST); shader->addShaderFile("sp_grass.frag", GL_FRAGMENT_SHADER, RP_1ST); @@ -574,7 +576,7 @@ void loadShaders() // ======================================================================== // Transparent shader // ======================================================================== - shader = new SPShader("alphablend_skinned", 1, true); + shader = new SPShader("alphablend_skinned", {{ 0, -1, -1 }}, true); shader->addShaderFile("sp_skinning.vert", GL_VERTEX_SHADER, RP_1ST); shader->addShaderFile("sp_transparent.frag", GL_FRAGMENT_SHADER, RP_1ST); shader->linkShaderFiles(RP_1ST); @@ -590,7 +592,7 @@ void loadShaders() ->addAssignerFunction("custom_alpha", zeroAlphaUniformAssigner); addShader(shader); - shader = new SPShader("alphablend", 1, true); + shader = new SPShader("alphablend", {{ 0, -1, -1}}, true); shader->addShaderFile("sp_pass.vert", GL_VERTEX_SHADER, RP_1ST); shader->addShaderFile("sp_transparent.frag", GL_FRAGMENT_SHADER, RP_1ST); shader->linkShaderFiles(RP_1ST); @@ -606,7 +608,7 @@ void loadShaders() ->addAssignerFunction("custom_alpha", zeroAlphaUniformAssigner); addShader(shader); - shader = new SPShader("additive_skinned", 1, true); + shader = new SPShader("additive_skinned", {{ 0, -1, -1 }}, true); shader->addShaderFile("sp_skinning.vert", GL_VERTEX_SHADER, RP_1ST); shader->addShaderFile("sp_transparent.frag", GL_FRAGMENT_SHADER, RP_1ST); shader->linkShaderFiles(RP_1ST); @@ -622,7 +624,7 @@ void loadShaders() ->addAssignerFunction("custom_alpha", zeroAlphaUniformAssigner); addShader(shader); - shader = new SPShader("additive", 1, true); + shader = new SPShader("additive", {{ 0, -1, -1 }}, true); shader->addShaderFile("sp_pass.vert", GL_VERTEX_SHADER, RP_1ST); shader->addShaderFile("sp_transparent.frag", GL_FRAGMENT_SHADER, RP_1ST); shader->linkShaderFiles(RP_1ST); @@ -638,7 +640,7 @@ void loadShaders() ->addAssignerFunction("custom_alpha", zeroAlphaUniformAssigner); addShader(shader); - shader = new SPShader("ghost_skinned", 1, true/*transparent_shader*/, + shader = new SPShader("ghost_skinned", {{ 0, -1, -1 }}, true/*transparent_shader*/, 900/*drawing_priority*/); shader->addShaderFile("sp_skinning.vert", GL_VERTEX_SHADER, RP_1ST); shader->addShaderFile("sp_ghost.frag", GL_FRAGMENT_SHADER, RP_1ST); @@ -652,7 +654,7 @@ void loadShaders() ->addAssignerFunction("custom_alpha", ghostAlphaAssigner); addShader(shader); - shader = new SPShader("ghost", 1, true/*transparent_shader*/, + shader = new SPShader("ghost", {{ 0, -1, -1 }}, true/*transparent_shader*/, 900/*drawing_priority*/); shader->addShaderFile("sp_pass.vert", GL_VERTEX_SHADER, RP_1ST); shader->addShaderFile("sp_ghost.frag", GL_FRAGMENT_SHADER, RP_1ST); @@ -669,7 +671,7 @@ void loadShaders() if (CVS->isDefferedEnabled()) { // This displace shader will be drawn the last in transparent pass - shader = new SPShader("displace", 2, true/*transparent_shader*/, + shader = new SPShader("displace", {{ 0, -1, 2 }}, true/*transparent_shader*/, 999/*drawing_priority*/); shader->addShaderFile("sp_pass.vert", GL_VERTEX_SHADER, RP_1ST); @@ -693,14 +695,14 @@ void loadShaders() glClear(GL_COLOR_BUFFER_BIT); }, RP_1ST); shader->addShaderFile("sp_pass.vert", GL_VERTEX_SHADER, - RP_2ND); + RP_RESERVED); shader->addShaderFile("sp_displace.frag", GL_FRAGMENT_SHADER, - RP_2ND); - shader->linkShaderFiles(RP_2ND); - shader->use(RP_2ND); - shader->addBasicUniforms(RP_2ND); + RP_RESERVED); + shader->linkShaderFiles(RP_RESERVED); + shader->use(RP_RESERVED); + shader->addBasicUniforms(RP_RESERVED); shader->addUniform("direction", typeid(std::array), - RP_2ND); + RP_RESERVED); shader->setUseFunction([]()->void { glEnable(GL_DEPTH_TEST); @@ -712,24 +714,24 @@ void loadShaders() glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); g_stk_sbr->getRTTs()->getFBO(FBO_DISPLACE).bind(), glClear(GL_COLOR_BUFFER_BIT); - }, RP_2ND); + }, RP_RESERVED); shader->addCustomPrefilledTextures(ST_BILINEAR, GL_TEXTURE_2D, "displacement_tex", []()->GLuint { return irr_driver->getTexture(FileManager::TEXTURE, "displace.png")->getOpenGLTextureName(); - }, RP_2ND); + }, RP_RESERVED); shader->addCustomPrefilledTextures(ST_BILINEAR, GL_TEXTURE_2D, "mask_tex", []()->GLuint { return g_stk_sbr->getRTTs()->getFBO(FBO_TMP1_WITH_DS).getRTT()[0]; - }, RP_2ND); + }, RP_RESERVED); shader->addCustomPrefilledTextures(ST_BILINEAR, GL_TEXTURE_2D, "color_tex", []()->GLuint { return g_stk_sbr->getRTTs()->getFBO(FBO_COLORS).getRTT()[0]; - }, RP_2ND); - shader->addAllTextures(RP_2ND); + }, RP_RESERVED); + shader->addAllTextures(RP_RESERVED); shader->setUnuseFunction([]()->void { g_stk_sbr->getRTTs()->getFBO(FBO_COLORS).bind(); @@ -739,7 +741,7 @@ void loadShaders() g_stk_sbr->getRTTs()->getFBO(FBO_COLORS).getWidth(), g_stk_sbr->getRTTs()->getFBO(FBO_COLORS).getHeight()); glDisable(GL_STENCIL_TEST); - }, RP_2ND); + }, RP_RESERVED); static_cast(shader) ->addAssignerFunction("direction", displaceUniformAssigner); addShader(shader); @@ -748,14 +750,17 @@ void loadShaders() // ======================================================================== // Glow shader // ======================================================================== - g_glow_shader = new SPShader("sp_glow_shader", 1); - g_glow_shader->addShaderFile("sp_pass.vert", GL_VERTEX_SHADER, RP_1ST); - g_glow_shader->addShaderFile("colorize.frag", GL_FRAGMENT_SHADER, RP_1ST); - g_glow_shader->linkShaderFiles(RP_1ST); - g_glow_shader->use(RP_1ST); - g_glow_shader->addBasicUniforms(RP_1ST); - g_glow_shader->addUniform("col", typeid(irr::video::SColorf), RP_1ST); - addShader(g_glow_shader); + g_glow_shader = new SPShader("sp_glow_shader", {{ 0, -1, -1 }}); + g_glow_shader->setInitFunction([](SPShader* shader) + { + shader->addShaderFile("sp_pass.vert", GL_VERTEX_SHADER, RP_1ST); + shader->addShaderFile("colorize.frag", GL_FRAGMENT_SHADER, RP_1ST); + shader->linkShaderFiles(RP_1ST); + shader->use(RP_1ST); + shader->addBasicUniforms(RP_1ST); + shader->addUniform("col", typeid(irr::video::SColorf), RP_1ST); + }); + g_glow_shader->init(); // ======================================================================== // Normal visualizer @@ -763,18 +768,22 @@ void loadShaders() #ifndef USE_GLES2 if (CVS->isARBGeometryShadersUsable()) { - shader = new SPShader("sp_normal_visualizer", 1); - shader->addShaderFile("sp_normal_visualizer.vert", GL_VERTEX_SHADER, - RP_1ST); - shader->addShaderFile("sp_normal_visualizer.geom", GL_GEOMETRY_SHADER, - RP_1ST); - shader->addShaderFile("sp_normal_visualizer.frag", GL_FRAGMENT_SHADER, - RP_1ST); - shader->linkShaderFiles(RP_1ST); - shader->use(RP_1ST); - shader->addBasicUniforms(RP_1ST); - shader->addAllTextures(RP_1ST); - addShader(shader); + g_normal_visualizer = + new SPShader("sp_normal_visualizer", {{ 0, -1, -1 }}); + g_normal_visualizer->setInitFunction([](SPShader* shader) + { + shader->addShaderFile("sp_normal_visualizer.vert", + GL_VERTEX_SHADER, RP_1ST); + shader->addShaderFile("sp_normal_visualizer.geom", + GL_GEOMETRY_SHADER, RP_1ST); + shader->addShaderFile("sp_normal_visualizer.frag", + GL_FRAGMENT_SHADER, RP_1ST); + shader->linkShaderFiles(RP_1ST); + shader->use(RP_1ST); + shader->addBasicUniforms(RP_1ST); + shader->addAllTextures(RP_1ST); + }); + g_normal_visualizer->init(); } #endif @@ -965,6 +974,10 @@ void destroy() delete p.second; } g_shaders.clear(); + delete g_glow_shader; + g_glow_shader = NULL; + delete g_normal_visualizer; + g_normal_visualizer = NULL; SPTextureManager::destroy(); @@ -1004,6 +1017,12 @@ SPShader* getGlowShader() return g_glow_shader; } // getGlowShader +// ---------------------------------------------------------------------------- +SPShader* getNormalVisualizer() +{ + return g_normal_visualizer; +} // getNormalVisualizer + // ---------------------------------------------------------------------------- SPShader* getSPShader(const std::string& name) { @@ -1613,13 +1632,12 @@ void uploadAll() // ---------------------------------------------------------------------------- void drawNormal() { - SPShader* nv = getSPShader("sp_normal_visualizer"); - if (nv == NULL) + if (g_normal_visualizer == NULL) { return; } - nv->use(); - nv->bindPrefilledTextures(); + g_normal_visualizer->use(); + g_normal_visualizer->bindPrefilledTextures(); for (unsigned i = 0; i < g_final_draw_calls[0].size(); i++) { auto& p = g_final_draw_calls[0][i]; @@ -1652,12 +1670,16 @@ void drawNormal() } } } - nv->unuse(); + g_normal_visualizer->unuse(); } // ---------------------------------------------------------------------------- void drawGlow() { + if (g_glow_meshes.empty()) + { + return; + } g_glow_shader->use(); SPUniformAssigner* glow_color_assigner = g_glow_shader->getUniformAssigner("col"); diff --git a/src/graphics/sp/sp_base.hpp b/src/graphics/sp/sp_base.hpp index 134690373..702beddec 100644 --- a/src/graphics/sp/sp_base.hpp +++ b/src/graphics/sp/sp_base.hpp @@ -104,6 +104,8 @@ void destroy(); // ---------------------------------------------------------------------------- GLuint getSampler(SamplerType); // ---------------------------------------------------------------------------- +SPShader* getNormalVisualizer(); +// ---------------------------------------------------------------------------- SPShader* getGlowShader(); // ---------------------------------------------------------------------------- SPShader* getSPShader(const std::string& name); diff --git a/src/graphics/sp/sp_shader.cpp b/src/graphics/sp/sp_shader.cpp index 30e5fb490..a1437172b 100644 --- a/src/graphics/sp/sp_shader.cpp +++ b/src/graphics/sp/sp_shader.cpp @@ -47,11 +47,8 @@ SPShader::~SPShader() { glDeleteProgram(m_program[rp]); } - for (auto& p : m_uniforms[rp]) - { - delete p.second; - } } + unload(); #endif } // ~SPShader @@ -60,12 +57,12 @@ void SPShader::addShaderFile(const std::string& name, GLint shader_type, RenderPass rp) { #ifndef SERVER_ONLY - auto shader_id = ShaderFilesManager::getInstance() + auto shader_file = ShaderFilesManager::getInstance() ->getShaderFile(name, shader_type); - if (shader_id) + if (shader_file) { - m_shaders.insert(shader_id); - glAttachShader(m_program[rp], *shader_id); + m_shader_files.push_back(shader_file); + glAttachShader(m_program[rp], *shader_file); } #endif } // addShaderFile @@ -92,7 +89,7 @@ void SPShader::linkShaderFiles(RenderPass rp) GLuint shaders[10] = {}; GLsizei count = 0; glGetAttachedShaders(m_program[rp], 10, &count, shaders); - for (unsigned i = 0; i < count; i++) + for (unsigned i = 0; i < (unsigned)count; i++) { glDetachShader(m_program[rp], shaders[i]); } @@ -252,4 +249,23 @@ SPUniformAssigner* SPShader::getUniformAssigner(const std::string& name, return ret->second; } // getUniformAssigner +// ---------------------------------------------------------------------------- +void SPShader::unload() +{ + for (unsigned rp = RP_1ST; rp < RP_COUNT; rp++) + { + for (auto& p : m_uniforms[rp]) + { + delete p.second; + } + m_uniforms[rp].clear(); + m_custom_prefilled_getter[rp].clear(); + m_prefilled_samplers[rp].clear(); + m_samplers[rp].clear(); + m_shader_files.clear(); + m_use_function[rp] = nullptr; + m_unuse_function[rp] = nullptr; + } +} // unload + } diff --git a/src/graphics/sp/sp_shader.hpp b/src/graphics/sp/sp_shader.hpp index 1a23f7aa5..13bb8814d 100644 --- a/src/graphics/sp/sp_shader.hpp +++ b/src/graphics/sp/sp_shader.hpp @@ -29,7 +29,6 @@ #include #include #include -#include #include #include @@ -55,8 +54,8 @@ enum SamplerType: unsigned int enum RenderPass: unsigned int { RP_1ST = 0, - RP_2ND, RP_SHADOW, + RP_RESERVED, RP_COUNT }; @@ -66,10 +65,10 @@ inline std::ostream& operator<<(std::ostream& os, const RenderPass& rp) { case RP_1ST: return os << "first pass"; - case RP_2ND: - return os << "second pass"; case RP_SHADOW: return os << "shadow pass"; + case RP_RESERVED: + return os << "reserved pass"; default: return os; } @@ -82,7 +81,7 @@ class SPShader : public NoCopy, public SPPerObjectUniform private: std::string m_name; - std::unordered_set > m_shaders; + std::vector > m_shader_files; GLuint m_program[RP_COUNT]; @@ -91,14 +90,15 @@ private: std::vector >m_prefilled_samplers[RP_COUNT]; - std::unordered_map - m_uniforms[RP_COUNT]; + std::unordered_map m_uniforms[RP_COUNT]; std::unordered_map > m_custom_prefilled_getter[RP_COUNT]; std::function m_use_function[RP_COUNT], m_unuse_function[RP_COUNT]; + std::function m_init_function; + const int m_drawing_priority; const bool m_transparent_shader; @@ -107,7 +107,8 @@ private: public: // ------------------------------------------------------------------------ - SPShader(const std::string& name, unsigned pass_count = 3, + SPShader(const std::string& name, + const std::array& pass = {{ 0, 1, -1 }}, bool transparent_shader = false, int drawing_priority = 0, bool use_alpha_channel = false) : m_name(name), m_drawing_priority(drawing_priority), @@ -116,9 +117,12 @@ public: { memset(m_program, 0, 12); #ifndef SERVER_ONLY - for (unsigned rp = RP_1ST; rp < pass_count; rp++) + for (int rp : pass) { - m_program[rp] = glCreateProgram(); + if (rp > -1) + { + m_program[rp] = glCreateProgram(); + } } #endif } @@ -174,12 +178,6 @@ public: block_index = glGetUniformBlockIndex(m_program[rp], "SPFogData"); if (block_index != GL_INVALID_INDEX) glUniformBlockBinding(m_program[rp], block_index, 2); -#ifndef USE_GLES2 - // Assign framebuffer output - glBindFragDataLocation(m_program[rp], 0, "o_diffuse_color"); - glBindFragDataLocation(m_program[rp], 1, "o_normal_depth"); - glBindFragDataLocation(m_program[rp], 2, "o_gloss_map"); -#endif #endif } // ------------------------------------------------------------------------ @@ -213,6 +211,31 @@ public: // ------------------------------------------------------------------------ bool samplerLess(RenderPass rp = RP_1ST) const { return m_samplers[rp].empty(); } + // ------------------------------------------------------------------------ + void setInitFunction(std::function func) + { + m_init_function = func; + } + // ------------------------------------------------------------------------ + void unload(); + // ------------------------------------------------------------------------ + void init() + { + if (!m_shader_files.empty()) + { + Log::error("SPShader", + "Please unload the shader before (re)init."); + return; + } + if (m_init_function) + { + m_init_function(this); + } + else + { + Log::error("SPShader", "Missing init function."); + } + } };