diff --git a/src/client/game.cpp b/src/client/game.cpp index 13ebffc7c..18a2ecc0e 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -1495,6 +1495,8 @@ bool Game::createClient(const GameStartData &start_data) &m_flags.force_fog_off, &runData.fog_range, client); shader_src->addShaderConstantSetterFactory(scsf); + ShadowRenderer::preInit(shader_src); + // Update cached textures, meshes and materials client->afterContentReceived(); diff --git a/src/client/shader.cpp b/src/client/shader.cpp index 04253f3b4..219b4d807 100644 --- a/src/client/shader.cpp +++ b/src/client/shader.cpp @@ -34,7 +34,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include #include "client/renderingengine.h" -#include "EShaderTypes.h" +#include #include "gettext.h" #include "log.h" #include "gamedef.h" @@ -162,12 +162,10 @@ private: std::string readFile(const std::string &path) { - std::ifstream is(path.c_str(), std::ios::binary); - if(!is.is_open()) - return ""; - std::ostringstream tmp_os; - tmp_os << is.rdbuf(); - return tmp_os.str(); + std::string ret; + if (!fs::ReadFile(path, ret)) + ret.clear(); + return ret; } }; @@ -184,15 +182,15 @@ public: template ShaderCallback(const Factories &factories) { - for (auto &&factory : factories) - m_setters.emplace_back(factory->create()); + for (auto &&factory : factories) { + auto *setter = factory->create(); + if (setter) + m_setters.emplace_back(setter); + } } virtual void OnSetConstants(video::IMaterialRendererServices *services, s32 userData) override { - video::IVideoDriver *driver = services->getVideoDriver(); - sanity_check(driver != NULL); - for (auto &&setter : m_setters) setter->onSetConstants(services); } @@ -214,27 +212,6 @@ class MainShaderConstantSetter : public IShaderConstantSetter CachedVertexShaderSetting m_world_view_proj{"mWorldViewProj"}; CachedVertexShaderSetting m_world{"mWorld"}; - // Shadow-related - CachedPixelShaderSetting m_shadow_view_proj{"m_ShadowViewProj"}; - CachedPixelShaderSetting m_light_direction{"v_LightDirection"}; - CachedPixelShaderSetting m_texture_res{"f_textureresolution"}; - CachedPixelShaderSetting m_shadow_strength{"f_shadow_strength"}; - CachedPixelShaderSetting m_time_of_day{"f_timeofday"}; - CachedPixelShaderSetting m_shadowfar{"f_shadowfar"}; - CachedPixelShaderSetting m_camera_pos{"CameraPos"}; - CachedPixelShaderSetting m_shadow_texture{"ShadowMapSampler"}; - CachedVertexShaderSetting - m_perspective_bias0_vertex{"xyPerspectiveBias0"}; - CachedPixelShaderSetting - m_perspective_bias0_pixel{"xyPerspectiveBias0"}; - CachedVertexShaderSetting - m_perspective_bias1_vertex{"xyPerspectiveBias1"}; - CachedPixelShaderSetting - m_perspective_bias1_pixel{"xyPerspectiveBias1"}; - CachedVertexShaderSetting - m_perspective_zbias_vertex{"zPerspectiveBias"}; - CachedPixelShaderSetting m_perspective_zbias_pixel{"zPerspectiveBias"}; - // Modelview matrix CachedVertexShaderSetting m_world_view{"mWorldView"}; // Texture matrix @@ -267,50 +244,6 @@ public: m_world_view.set(*reinterpret_cast(worldView.pointer()), services); m_texture.set(*reinterpret_cast(texture.pointer()), services); } - - // Set uniforms for Shadow shader - if (ShadowRenderer *shadow = RenderingEngine::get_shadow_renderer()) { - const auto &light = shadow->getDirectionalLight(); - - core::matrix4 shadowViewProj = light.getProjectionMatrix(); - shadowViewProj *= light.getViewMatrix(); - m_shadow_view_proj.set(shadowViewProj.pointer(), services); - - f32 v_LightDirection[3]; - light.getDirection().getAs3Values(v_LightDirection); - m_light_direction.set(v_LightDirection, services); - - f32 TextureResolution = light.getMapResolution(); - m_texture_res.set(&TextureResolution, services); - - f32 ShadowStrength = shadow->getShadowStrength(); - m_shadow_strength.set(&ShadowStrength, services); - - f32 timeOfDay = shadow->getTimeOfDay(); - m_time_of_day.set(&timeOfDay, services); - - f32 shadowFar = shadow->getMaxShadowFar(); - m_shadowfar.set(&shadowFar, services); - - f32 cam_pos[4]; - shadowViewProj.transformVect(cam_pos, light.getPlayerPos()); - m_camera_pos.set(cam_pos, services); - - // I don't like using this hardcoded value. maybe something like - // MAX_TEXTURE - 1 or somthing like that?? - s32 TextureLayerID = 3; - m_shadow_texture.set(&TextureLayerID, services); - - f32 bias0 = shadow->getPerspectiveBiasXY(); - m_perspective_bias0_vertex.set(&bias0, services); - m_perspective_bias0_pixel.set(&bias0, services); - f32 bias1 = 1.0f - bias0 + 1e-5f; - m_perspective_bias1_vertex.set(&bias1, services); - m_perspective_bias1_pixel.set(&bias1, services); - f32 zbias = shadow->getPerspectiveBiasZ(); - m_perspective_zbias_vertex.set(&zbias, services); - m_perspective_zbias_pixel.set(&zbias, services); - } } }; diff --git a/src/client/shadows/dynamicshadowsrender.cpp b/src/client/shadows/dynamicshadowsrender.cpp index fc8592a21..ca61d8467 100644 --- a/src/client/shadows/dynamicshadowsrender.cpp +++ b/src/client/shadows/dynamicshadowsrender.cpp @@ -118,14 +118,20 @@ void ShadowRenderer::disable() }); } +void ShadowRenderer::preInit(IWritableShaderSource *shsrc) +{ + if (g_settings->getBool("enable_shaders") && + g_settings->getBool("enable_dynamic_shadows")) { + shsrc->addShaderConstantSetterFactory(new ShadowConstantSetterFactory()); + } +} + void ShadowRenderer::initialize() { auto *gpu = m_driver->getGPUProgrammingServices(); // we need glsl - if (m_shadows_supported && gpu && m_driver->queryFeature(video::EVDF_ARB_GLSL)) { - createShaders(); - } else { + if (!m_shadows_supported || !gpu || !m_driver->queryFeature(video::EVDF_ARB_GLSL)) { m_shadows_supported = false; warningstream << "Shadows: GLSL Shader not supported on this system." @@ -133,6 +139,9 @@ void ShadowRenderer::initialize() return; } + createShaders(); + + m_texture_format = m_shadow_map_texture_32bit ? video::ECOLOR_FORMAT::ECF_R32F : video::ECOLOR_FORMAT::ECF_R16F; diff --git a/src/client/shadows/dynamicshadowsrender.h b/src/client/shadows/dynamicshadowsrender.h index 7fe3461bc..fc139e28b 100644 --- a/src/client/shadows/dynamicshadowsrender.h +++ b/src/client/shadows/dynamicshadowsrender.h @@ -27,6 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc., class ShadowDepthShaderCB; class shadowScreenQuad; class shadowScreenQuadCB; +class IWritableShaderSource; enum E_SHADOW_MODE : u8 { @@ -54,9 +55,13 @@ public: static const int TEXTURE_LAYER_SHADOW = 3; ShadowRenderer(IrrlichtDevice *device, Client *client); - ~ShadowRenderer(); + // Call before generating any shaders + // This is required because this class is initialized much later than all + // the shaders are dealt with. + static void preInit(IWritableShaderSource *shsrc); + void initialize(); /// Adds a directional light shadow map (Usually just one (the sun) except in diff --git a/src/client/shadows/shadowsshadercallbacks.cpp b/src/client/shadows/shadowsshadercallbacks.cpp index b571ea939..4cfe0f081 100644 --- a/src/client/shadows/shadowsshadercallbacks.cpp +++ b/src/client/shadows/shadowsshadercallbacks.cpp @@ -18,6 +18,53 @@ with this program; if not, write to the Free Software Foundation, Inc., */ #include "client/shadows/shadowsshadercallbacks.h" +#include "client/renderingengine.h" + +void ShadowConstantSetter::onSetConstants(video::IMaterialRendererServices *services) +{ + auto *shadow = RenderingEngine::get_shadow_renderer(); + if (!shadow) + return; + + const auto &light = shadow->getDirectionalLight(); + + core::matrix4 shadowViewProj = light.getProjectionMatrix(); + shadowViewProj *= light.getViewMatrix(); + m_shadow_view_proj.set(shadowViewProj.pointer(), services); + + f32 v_LightDirection[3]; + light.getDirection().getAs3Values(v_LightDirection); + m_light_direction.set(v_LightDirection, services); + + f32 TextureResolution = light.getMapResolution(); + m_texture_res.set(&TextureResolution, services); + + f32 ShadowStrength = shadow->getShadowStrength(); + m_shadow_strength.set(&ShadowStrength, services); + + f32 timeOfDay = shadow->getTimeOfDay(); + m_time_of_day.set(&timeOfDay, services); + + f32 shadowFar = shadow->getMaxShadowFar(); + m_shadowfar.set(&shadowFar, services); + + f32 cam_pos[4]; + shadowViewProj.transformVect(cam_pos, light.getPlayerPos()); + m_camera_pos.set(cam_pos, services); + + s32 TextureLayerID = ShadowRenderer::TEXTURE_LAYER_SHADOW; + m_shadow_texture.set(&TextureLayerID, services); + + f32 bias0 = shadow->getPerspectiveBiasXY(); + m_perspective_bias0_vertex.set(&bias0, services); + m_perspective_bias0_pixel.set(&bias0, services); + f32 bias1 = 1.0f - bias0 + 1e-5f; + m_perspective_bias1_vertex.set(&bias1, services); + m_perspective_bias1_pixel.set(&bias1, services); + f32 zbias = shadow->getPerspectiveBiasZ(); + m_perspective_zbias_vertex.set(&zbias, services); + m_perspective_zbias_pixel.set(&zbias, services); +} void ShadowDepthShaderCB::OnSetConstants( video::IMaterialRendererServices *services, s32 userData) diff --git a/src/client/shadows/shadowsshadercallbacks.h b/src/client/shadows/shadowsshadercallbacks.h index 4d006fea6..af83f021e 100644 --- a/src/client/shadows/shadowsshadercallbacks.h +++ b/src/client/shadows/shadowsshadercallbacks.h @@ -23,6 +23,47 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include "client/shader.h" +// Used by main game rendering + +class ShadowConstantSetter : public IShaderConstantSetter +{ + CachedPixelShaderSetting m_shadow_view_proj{"m_ShadowViewProj"}; + CachedPixelShaderSetting m_light_direction{"v_LightDirection"}; + CachedPixelShaderSetting m_texture_res{"f_textureresolution"}; + CachedPixelShaderSetting m_shadow_strength{"f_shadow_strength"}; + CachedPixelShaderSetting m_time_of_day{"f_timeofday"}; + CachedPixelShaderSetting m_shadowfar{"f_shadowfar"}; + CachedPixelShaderSetting m_camera_pos{"CameraPos"}; + CachedPixelShaderSetting m_shadow_texture{"ShadowMapSampler"}; + CachedVertexShaderSetting + m_perspective_bias0_vertex{"xyPerspectiveBias0"}; + CachedPixelShaderSetting + m_perspective_bias0_pixel{"xyPerspectiveBias0"}; + CachedVertexShaderSetting + m_perspective_bias1_vertex{"xyPerspectiveBias1"}; + CachedPixelShaderSetting + m_perspective_bias1_pixel{"xyPerspectiveBias1"}; + CachedVertexShaderSetting + m_perspective_zbias_vertex{"zPerspectiveBias"}; + CachedPixelShaderSetting m_perspective_zbias_pixel{"zPerspectiveBias"}; + +public: + ShadowConstantSetter() = default; + ~ShadowConstantSetter() = default; + + virtual void onSetConstants(video::IMaterialRendererServices *services) override; +}; + +class ShadowConstantSetterFactory : public IShaderConstantSetterFactory +{ +public: + virtual IShaderConstantSetter *create() { + return new ShadowConstantSetter(); + } +}; + +// Used by depth shader + class ShadowDepthShaderCB : public video::IShaderConstantSetCallBack { public: