From 27373919f4369c0c511f9f0ac66854b7f76e101d Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Sat, 1 Dec 2012 03:02:16 +0200 Subject: Implement a global shader parameter passing system and useful shaders --- src/game.cpp | 52 +++++++++++++++++++++++++++++++++++++- src/mapblock_mesh.cpp | 15 ++++++++--- src/shader.cpp | 70 ++++++++++++++++++++++++++++++++++++++++++++++++--- src/shader.h | 17 +++++++++++++ 4 files changed, 145 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/game.cpp b/src/game.cpp index 1339afbf0..0c1a21370 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include #include +#include #include "client.h" #include "server.h" #include "guiPauseMenu.h" @@ -835,6 +836,49 @@ public: } }; +class GameGlobalShaderConstantSetter : public IShaderConstantSetter +{ + Sky *m_sky; + bool *m_force_fog_off; + f32 *m_fog_range; + +public: + GameGlobalShaderConstantSetter(Sky *sky, bool *force_fog_off, + f32 *fog_range): + m_sky(sky), + m_force_fog_off(force_fog_off), + m_fog_range(fog_range) + {} + ~GameGlobalShaderConstantSetter() {} + + virtual void onSetConstants(video::IMaterialRendererServices *services, + bool is_highlevel) + { + if(!is_highlevel) + return; + + // Background color + video::SColor bgcolor = m_sky->getBgColor(); + video::SColorf bgcolorf(bgcolor); + float bgcolorfa[4] = { + bgcolorf.r, + bgcolorf.g, + bgcolorf.b, + bgcolorf.a, + }; + services->setPixelShaderConstant("skyBgColor", bgcolorfa, 4); + + // Fog distance + float fog_distance = *m_fog_range; + if(*m_force_fog_off) + fog_distance = 10000*BS; + services->setPixelShaderConstant("fogDistance", &fog_distance, 1); + } + +private: + IrrlichtDevice *m_device; +}; + void the_game( bool &kill, bool random_input, @@ -1250,6 +1294,7 @@ void the_game( bool show_hud = true; bool show_chat = true; bool force_fog_off = false; + f32 fog_range = 100*BS; bool disable_camera_update = false; bool show_debug = g_settings->getBool("show_debug"); bool show_profiler_graph = false; @@ -1259,6 +1304,12 @@ void the_game( float time_of_day = 0; float time_of_day_smooth = 0; + /* + Shader constants + */ + shsrc->addGlobalConstantSetter( + new GameGlobalShaderConstantSetter(sky, &force_fog_off, &fog_range)); + /* Main loop */ @@ -2434,7 +2485,6 @@ void the_game( Fog range */ - f32 fog_range; if(farmesh) { fog_range = BS*farmesh_range; diff --git a/src/mapblock_mesh.cpp b/src/mapblock_mesh.cpp index cbc38ddb5..c871b6dbe 100644 --- a/src/mapblock_mesh.cpp +++ b/src/mapblock_mesh.cpp @@ -1012,8 +1012,11 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data): Convert MeshCollector to SMesh Also store animation info */ - video::E_MATERIAL_TYPE shadermat = m_gamedef->getShaderSource()-> - getShader("the_darkness_of_light").material; + bool enable_shaders = (g_settings->getS32("enable_shaders") > 0); + video::E_MATERIAL_TYPE shadermat1 = m_gamedef->getShaderSource()-> + getShader("test_shader_1").material; + video::E_MATERIAL_TYPE shadermat2 = m_gamedef->getShaderSource()-> + getShader("test_shader_2").material; for(u32 i = 0; i < collector.prebuffers.size(); i++) { PreMeshBuffer &p = collector.prebuffers[i]; @@ -1080,8 +1083,12 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data): material.setTexture(0, p.tile.texture.atlas); p.tile.applyMaterialOptions(material); - //if(material.MaterialType == video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF) - material.MaterialType = shadermat; + if(enable_shaders){ + if(material.MaterialType == video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF) + material.MaterialType = shadermat1; + if(material.MaterialType == video::EMT_TRANSPARENT_VERTEX_ALPHA) + material.MaterialType = shadermat2; + } // Create meshbuffer diff --git a/src/shader.cpp b/src/shader.cpp index ba0b8600a..9e1a51f23 100644 --- a/src/shader.cpp +++ b/src/shader.cpp @@ -35,6 +35,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "EShaderTypes.h" #include "log.h" #include "gamedef.h" +#include "strfnd.h" // trim() /* A cache from shader name to shader path @@ -171,10 +172,24 @@ private: ShaderCallback: Sets constants that can be used in shaders */ +class IShaderConstantSetterRegistry +{ +public: + virtual ~IShaderConstantSetterRegistry(){}; + virtual void onSetConstants(video::IMaterialRendererServices *services, + bool is_highlevel, const std::string &name) = 0; +}; + class ShaderCallback : public video::IShaderConstantSetCallBack { + IShaderConstantSetterRegistry *m_scsr; + std::string m_name; + public: - ShaderCallback(IrrlichtDevice *device): m_device(device) {} + ShaderCallback(IShaderConstantSetterRegistry *scsr, const std::string &name): + m_scsr(scsr), + m_name(name) + {} ~ShaderCallback() {} virtual void OnSetConstants(video::IMaterialRendererServices *services, s32 userData) @@ -184,6 +199,28 @@ public: bool is_highlevel = userData; + m_scsr->onSetConstants(services, is_highlevel, m_name); + } +}; + +/* + MainShaderConstantSetter: Set basic constants required for almost everything +*/ + +class MainShaderConstantSetter : public IShaderConstantSetter +{ +public: + MainShaderConstantSetter(IrrlichtDevice *device): + m_device(device) + {} + ~MainShaderConstantSetter() {} + + virtual void onSetConstants(video::IMaterialRendererServices *services, + bool is_highlevel) + { + video::IVideoDriver *driver = services->getVideoDriver(); + assert(driver); + // set inverted world matrix core::matrix4 invWorld = driver->getTransform(video::ETS_WORLD); invWorld.makeInverse(); @@ -219,7 +256,7 @@ private: ShaderSource */ -class ShaderSource : public IWritableShaderSource +class ShaderSource : public IWritableShaderSource, public IShaderConstantSetterRegistry { public: ShaderSource(IrrlichtDevice *device); @@ -272,6 +309,14 @@ public: // Shall be called from the main thread. void rebuildShaders(); + void addGlobalConstantSetter(IShaderConstantSetter *setter) + { + m_global_setters.push_back(setter); + } + + void onSetConstants(video::IMaterialRendererServices *services, + bool is_highlevel, const std::string &name); + private: // The id of the thread that is allowed to use irrlicht directly @@ -295,6 +340,10 @@ private: // Queued shader fetches (to be processed by the main thread) RequestQueue m_get_shader_queue; + + // Global constant setters + // TODO: Delete these in the destructor + core::array m_global_setters; }; IWritableShaderSource* createShaderSource(IrrlichtDevice *device) @@ -322,7 +371,7 @@ ShaderSource::ShaderSource(IrrlichtDevice *device): { assert(m_device); - m_shader_callback = new ShaderCallback(device); + m_shader_callback = new ShaderCallback(this, "default"); m_shaderinfo_cache_mutex.Init(); @@ -331,6 +380,9 @@ ShaderSource::ShaderSource(IrrlichtDevice *device): // Add a dummy ShaderInfo as the first index, named "" m_shaderinfo_cache.push_back(ShaderInfo()); m_name_to_id[""] = 0; + + // Add main global constant setter + addGlobalConstantSetter(new MainShaderConstantSetter(device)); } ShaderSource::~ShaderSource() @@ -531,6 +583,15 @@ void ShaderSource::rebuildShaders() m_shader_callback, &m_sourcecache); } } + +void ShaderSource::onSetConstants(video::IMaterialRendererServices *services, + bool is_highlevel, const std::string &name) +{ + for(u32 i=0; ionSetConstants(services, is_highlevel); + } +} ShaderInfo generate_shader(std::string name, IrrlichtDevice *device, video::IShaderConstantSetCallBack *callback, @@ -546,7 +607,8 @@ ShaderInfo generate_shader(std::string name, IrrlichtDevice *device, /* Get the base material */ - std::string base_material_name = sourcecache->getOrLoad(name, "base.txt"); + std::string base_material_name = + trim(sourcecache->getOrLoad(name, "base.txt")); for(s32 i = 0; video::sBuiltInMaterialTypeNames[i] != 0; i++){ if(video::sBuiltInMaterialTypeNames[i] == base_material_name){ shaderinfo.material = (video::E_MATERIAL_TYPE) i; diff --git a/src/shader.h b/src/shader.h index d6a425311..774a17b20 100644 --- a/src/shader.h +++ b/src/shader.h @@ -51,6 +51,22 @@ struct ShaderInfo ShaderInfo(): name(""), material(video::EMT_SOLID) {} }; +/* + Setter of constants for shaders +*/ + +namespace irr { namespace video { + class IMaterialRendererServices; +} } + +class IShaderConstantSetter +{ +public: + virtual ~IShaderConstantSetter(){}; + virtual void onSetConstants(video::IMaterialRendererServices *services, + bool is_highlevel) = 0; +}; + /* ShaderSource creates and caches shaders. */ @@ -82,6 +98,7 @@ public: virtual void insertSourceShader(const std::string &name_of_shader, const std::string &filename, const std::string &program)=0; virtual void rebuildShaders()=0; + virtual void addGlobalConstantSetter(IShaderConstantSetter *setter)=0; }; IWritableShaderSource* createShaderSource(IrrlichtDevice *device); -- cgit v1.2.3