diff options
author | Quentin Bazin <quent42340@gmail.com> | 2018-11-28 20:01:49 +0100 |
---|---|---|
committer | SmallJoker <SmallJoker@users.noreply.github.com> | 2018-11-28 20:01:49 +0100 |
commit | 5f1cd555cd9d1c64426e173b30b5b792d211c835 (patch) | |
tree | 2c8508467d3bf28d549cce2d25144fa8ef42beae /src/shader.cpp | |
parent | ddd9317b733857630499972179caebc236b4d991 (diff) | |
download | minetest-5f1cd555cd9d1c64426e173b30b5b792d211c835.tar.gz minetest-5f1cd555cd9d1c64426e173b30b5b792d211c835.tar.bz2 minetest-5f1cd555cd9d1c64426e173b30b5b792d211c835.zip |
Move client-specific files to 'src/client' (#7902)
Update Android.mk
Remove 'src/client' from include_directories
Diffstat (limited to 'src/shader.cpp')
-rw-r--r-- | src/shader.cpp | 873 |
1 files changed, 0 insertions, 873 deletions
diff --git a/src/shader.cpp b/src/shader.cpp deleted file mode 100644 index 3b49a36ba..000000000 --- a/src/shader.cpp +++ /dev/null @@ -1,873 +0,0 @@ -/* -Minetest -Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com> -Copyright (C) 2013 Kahrl <kahrl@gmx.net> - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along -with this program; if not, write to the Free Software Foundation, Inc., -51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include <fstream> -#include <iterator> -#include "shader.h" -#include "irrlichttypes_extrabloated.h" -#include "debug.h" -#include "filesys.h" -#include "util/container.h" -#include "util/thread.h" -#include "settings.h" -#include <ICameraSceneNode.h> -#include <IGPUProgrammingServices.h> -#include <IMaterialRenderer.h> -#include <IMaterialRendererServices.h> -#include <IShaderConstantSetCallBack.h> -#include "client/renderingengine.h" -#include "EShaderTypes.h" -#include "log.h" -#include "gamedef.h" -#include "client/tile.h" - -/* - A cache from shader name to shader path -*/ -MutexedMap<std::string, std::string> g_shadername_to_path_cache; - -/* - Gets the path to a shader by first checking if the file - name_of_shader/filename - exists in shader_path and if not, using the data path. - - If not found, returns "". - - Utilizes a thread-safe cache. -*/ -std::string getShaderPath(const std::string &name_of_shader, - const std::string &filename) -{ - std::string combined = name_of_shader + DIR_DELIM + filename; - std::string fullpath; - /* - Check from cache - */ - bool incache = g_shadername_to_path_cache.get(combined, &fullpath); - if(incache) - return fullpath; - - /* - Check from shader_path - */ - std::string shader_path = g_settings->get("shader_path"); - if (!shader_path.empty()) { - std::string testpath = shader_path + DIR_DELIM + combined; - if(fs::PathExists(testpath)) - fullpath = testpath; - } - - /* - Check from default data directory - */ - if (fullpath.empty()) { - std::string rel_path = std::string("client") + DIR_DELIM - + "shaders" + DIR_DELIM - + name_of_shader + DIR_DELIM - + filename; - std::string testpath = porting::path_share + DIR_DELIM + rel_path; - if(fs::PathExists(testpath)) - fullpath = testpath; - } - - // Add to cache (also an empty result is cached) - g_shadername_to_path_cache.set(combined, fullpath); - - // Finally return it - return fullpath; -} - -/* - SourceShaderCache: A cache used for storing source shaders. -*/ - -class SourceShaderCache -{ -public: - void insert(const std::string &name_of_shader, const std::string &filename, - const std::string &program, bool prefer_local) - { - std::string combined = name_of_shader + DIR_DELIM + filename; - // Try to use local shader instead if asked to - if(prefer_local){ - std::string path = getShaderPath(name_of_shader, filename); - if(!path.empty()){ - std::string p = readFile(path); - if (!p.empty()) { - m_programs[combined] = p; - return; - } - } - } - m_programs[combined] = program; - } - - std::string get(const std::string &name_of_shader, - const std::string &filename) - { - std::string combined = name_of_shader + DIR_DELIM + filename; - StringMap::iterator n = m_programs.find(combined); - if (n != m_programs.end()) - return n->second; - return ""; - } - - // Primarily fetches from cache, secondarily tries to read from filesystem - std::string getOrLoad(const std::string &name_of_shader, - const std::string &filename) - { - std::string combined = name_of_shader + DIR_DELIM + filename; - StringMap::iterator n = m_programs.find(combined); - if (n != m_programs.end()) - return n->second; - std::string path = getShaderPath(name_of_shader, filename); - if (path.empty()) { - infostream << "SourceShaderCache::getOrLoad(): No path found for \"" - << combined << "\"" << std::endl; - return ""; - } - infostream << "SourceShaderCache::getOrLoad(): Loading path \"" - << path << "\"" << std::endl; - std::string p = readFile(path); - if (!p.empty()) { - m_programs[combined] = p; - return p; - } - return ""; - } -private: - StringMap m_programs; - - 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(); - } -}; - - -/* - ShaderCallback: Sets constants that can be used in shaders -*/ - -class ShaderCallback : public video::IShaderConstantSetCallBack -{ - std::vector<IShaderConstantSetter*> m_setters; - -public: - ShaderCallback(const std::vector<IShaderConstantSetterFactory *> &factories) - { - for (IShaderConstantSetterFactory *factory : factories) - m_setters.push_back(factory->create()); - } - - ~ShaderCallback() - { - for (IShaderConstantSetter *setter : m_setters) - delete setter; - } - - virtual void OnSetConstants(video::IMaterialRendererServices *services, s32 userData) - { - video::IVideoDriver *driver = services->getVideoDriver(); - sanity_check(driver != NULL); - - bool is_highlevel = userData; - - for (IShaderConstantSetter *setter : m_setters) - setter->onSetConstants(services, is_highlevel); - } -}; - - -/* - MainShaderConstantSetter: Set basic constants required for almost everything -*/ - -class MainShaderConstantSetter : public IShaderConstantSetter -{ - CachedVertexShaderSetting<float, 16> m_world_view_proj; - CachedVertexShaderSetting<float, 16> m_world; - -public: - MainShaderConstantSetter() : - m_world_view_proj("mWorldViewProj"), - m_world("mWorld") - {} - ~MainShaderConstantSetter() = default; - - virtual void onSetConstants(video::IMaterialRendererServices *services, - bool is_highlevel) - { - video::IVideoDriver *driver = services->getVideoDriver(); - sanity_check(driver); - - // Set clip matrix - core::matrix4 worldViewProj; - worldViewProj = driver->getTransform(video::ETS_PROJECTION); - worldViewProj *= driver->getTransform(video::ETS_VIEW); - worldViewProj *= driver->getTransform(video::ETS_WORLD); - if (is_highlevel) - m_world_view_proj.set(*reinterpret_cast<float(*)[16]>(worldViewProj.pointer()), services); - else - services->setVertexShaderConstant(worldViewProj.pointer(), 0, 4); - - // Set world matrix - core::matrix4 world = driver->getTransform(video::ETS_WORLD); - if (is_highlevel) - m_world.set(*reinterpret_cast<float(*)[16]>(world.pointer()), services); - else - services->setVertexShaderConstant(world.pointer(), 4, 4); - - } -}; - - -class MainShaderConstantSetterFactory : public IShaderConstantSetterFactory -{ -public: - virtual IShaderConstantSetter* create() - { return new MainShaderConstantSetter(); } -}; - - -/* - ShaderSource -*/ - -class ShaderSource : public IWritableShaderSource -{ -public: - ShaderSource(); - ~ShaderSource(); - - /* - - If shader material specified by name is found from cache, - return the cached id. - - Otherwise generate the shader material, add to cache and return id. - - The id 0 points to a null shader. Its material is EMT_SOLID. - */ - u32 getShaderIdDirect(const std::string &name, - const u8 material_type, const u8 drawtype); - - /* - If shader specified by the name pointed by the id doesn't - exist, create it, then return id. - - Can be called from any thread. If called from some other thread - and not found in cache, the call is queued to the main thread - for processing. - */ - - u32 getShader(const std::string &name, - const u8 material_type, const u8 drawtype); - - ShaderInfo getShaderInfo(u32 id); - - // Processes queued shader requests from other threads. - // Shall be called from the main thread. - void processQueue(); - - // Insert a shader program into the cache without touching the - // filesystem. Shall be called from the main thread. - void insertSourceShader(const std::string &name_of_shader, - const std::string &filename, const std::string &program); - - // Rebuild shaders from the current set of source shaders - // Shall be called from the main thread. - void rebuildShaders(); - - void addShaderConstantSetterFactory(IShaderConstantSetterFactory *setter) - { - m_setter_factories.push_back(setter); - } - -private: - - // The id of the thread that is allowed to use irrlicht directly - std::thread::id m_main_thread; - - // Cache of source shaders - // This should be only accessed from the main thread - SourceShaderCache m_sourcecache; - - // A shader id is index in this array. - // The first position contains a dummy shader. - std::vector<ShaderInfo> m_shaderinfo_cache; - // The former container is behind this mutex - std::mutex m_shaderinfo_cache_mutex; - - // Queued shader fetches (to be processed by the main thread) - RequestQueue<std::string, u32, u8, u8> m_get_shader_queue; - - // Global constant setter factories - std::vector<IShaderConstantSetterFactory *> m_setter_factories; - - // Shader callbacks - std::vector<ShaderCallback *> m_callbacks; -}; - -IWritableShaderSource *createShaderSource() -{ - return new ShaderSource(); -} - -/* - Generate shader given the shader name. -*/ -ShaderInfo generate_shader(const std::string &name, - u8 material_type, u8 drawtype, std::vector<ShaderCallback *> &callbacks, - const std::vector<IShaderConstantSetterFactory *> &setter_factories, - SourceShaderCache *sourcecache); - -/* - Load shader programs -*/ -void load_shaders(const std::string &name, SourceShaderCache *sourcecache, - video::E_DRIVER_TYPE drivertype, bool enable_shaders, - std::string &vertex_program, std::string &pixel_program, - std::string &geometry_program, bool &is_highlevel); - -ShaderSource::ShaderSource() -{ - m_main_thread = std::this_thread::get_id(); - - // Add a dummy ShaderInfo as the first index, named "" - m_shaderinfo_cache.emplace_back(); - - // Add main global constant setter - addShaderConstantSetterFactory(new MainShaderConstantSetterFactory()); -} - -ShaderSource::~ShaderSource() -{ - for (ShaderCallback *callback : m_callbacks) { - delete callback; - } - for (IShaderConstantSetterFactory *setter_factorie : m_setter_factories) { - delete setter_factorie; - } -} - -u32 ShaderSource::getShader(const std::string &name, - const u8 material_type, const u8 drawtype) -{ - /* - Get shader - */ - - if (std::this_thread::get_id() == m_main_thread) { - return getShaderIdDirect(name, material_type, drawtype); - } - - /*errorstream<<"getShader(): Queued: name=\""<<name<<"\""<<std::endl;*/ - - // We're gonna ask the result to be put into here - - static ResultQueue<std::string, u32, u8, u8> result_queue; - - // Throw a request in - m_get_shader_queue.add(name, 0, 0, &result_queue); - - /* infostream<<"Waiting for shader from main thread, name=\"" - <<name<<"\""<<std::endl;*/ - - while(true) { - GetResult<std::string, u32, u8, u8> - result = result_queue.pop_frontNoEx(); - - if (result.key == name) { - return result.item; - } - - errorstream << "Got shader with invalid name: " << result.key << std::endl; - } - - infostream << "getShader(): Failed" << std::endl; - - return 0; -} - -/* - This method generates all the shaders -*/ -u32 ShaderSource::getShaderIdDirect(const std::string &name, - const u8 material_type, const u8 drawtype) -{ - //infostream<<"getShaderIdDirect(): name=\""<<name<<"\""<<std::endl; - - // Empty name means shader 0 - if (name.empty()) { - infostream<<"getShaderIdDirect(): name is empty"<<std::endl; - return 0; - } - - // Check if already have such instance - for(u32 i=0; i<m_shaderinfo_cache.size(); i++){ - ShaderInfo *info = &m_shaderinfo_cache[i]; - if(info->name == name && info->material_type == material_type && - info->drawtype == drawtype) - return i; - } - - /* - Calling only allowed from main thread - */ - if (std::this_thread::get_id() != m_main_thread) { - errorstream<<"ShaderSource::getShaderIdDirect() " - "called not from main thread"<<std::endl; - return 0; - } - - ShaderInfo info = generate_shader(name, material_type, drawtype, - m_callbacks, m_setter_factories, &m_sourcecache); - - /* - Add shader to caches (add dummy shaders too) - */ - - MutexAutoLock lock(m_shaderinfo_cache_mutex); - - u32 id = m_shaderinfo_cache.size(); - m_shaderinfo_cache.push_back(info); - - infostream<<"getShaderIdDirect(): " - <<"Returning id="<<id<<" for name \""<<name<<"\""<<std::endl; - - return id; -} - - -ShaderInfo ShaderSource::getShaderInfo(u32 id) -{ - MutexAutoLock lock(m_shaderinfo_cache_mutex); - - if(id >= m_shaderinfo_cache.size()) - return ShaderInfo(); - - return m_shaderinfo_cache[id]; -} - -void ShaderSource::processQueue() -{ - - -} - -void ShaderSource::insertSourceShader(const std::string &name_of_shader, - const std::string &filename, const std::string &program) -{ - /*infostream<<"ShaderSource::insertSourceShader(): " - "name_of_shader=\""<<name_of_shader<<"\", " - "filename=\""<<filename<<"\""<<std::endl;*/ - - sanity_check(std::this_thread::get_id() == m_main_thread); - - m_sourcecache.insert(name_of_shader, filename, program, true); -} - -void ShaderSource::rebuildShaders() -{ - MutexAutoLock lock(m_shaderinfo_cache_mutex); - - /*// Oh well... just clear everything, they'll load sometime. - m_shaderinfo_cache.clear(); - m_name_to_id.clear();*/ - - /* - FIXME: Old shader materials can't be deleted in Irrlicht, - or can they? - (This would be nice to do in the destructor too) - */ - - // Recreate shaders - for (ShaderInfo &i : m_shaderinfo_cache) { - ShaderInfo *info = &i; - if (!info->name.empty()) { - *info = generate_shader(info->name, info->material_type, - info->drawtype, m_callbacks, - m_setter_factories, &m_sourcecache); - } - } -} - - -ShaderInfo generate_shader(const std::string &name, u8 material_type, u8 drawtype, - std::vector<ShaderCallback *> &callbacks, - const std::vector<IShaderConstantSetterFactory *> &setter_factories, - SourceShaderCache *sourcecache) -{ - ShaderInfo shaderinfo; - shaderinfo.name = name; - shaderinfo.material_type = material_type; - shaderinfo.drawtype = drawtype; - shaderinfo.material = video::EMT_SOLID; - switch (material_type) { - case TILE_MATERIAL_OPAQUE: - case TILE_MATERIAL_LIQUID_OPAQUE: - shaderinfo.base_material = video::EMT_SOLID; - break; - case TILE_MATERIAL_ALPHA: - case TILE_MATERIAL_LIQUID_TRANSPARENT: - shaderinfo.base_material = video::EMT_TRANSPARENT_ALPHA_CHANNEL; - break; - case TILE_MATERIAL_BASIC: - case TILE_MATERIAL_WAVING_LEAVES: - case TILE_MATERIAL_WAVING_PLANTS: - shaderinfo.base_material = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; - break; - } - - bool enable_shaders = g_settings->getBool("enable_shaders"); - if (!enable_shaders) - return shaderinfo; - - video::IVideoDriver *driver = RenderingEngine::get_video_driver(); - - video::IGPUProgrammingServices *gpu = driver->getGPUProgrammingServices(); - if(!gpu){ - errorstream<<"generate_shader(): " - "failed to generate \""<<name<<"\", " - "GPU programming not supported." - <<std::endl; - return shaderinfo; - } - - // Choose shader language depending on driver type and settings - // Then load shaders - std::string vertex_program; - std::string pixel_program; - std::string geometry_program; - bool is_highlevel; - load_shaders(name, sourcecache, driver->getDriverType(), - enable_shaders, vertex_program, pixel_program, - geometry_program, is_highlevel); - // Check hardware/driver support - if (!vertex_program.empty() && - !driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1) && - !driver->queryFeature(video::EVDF_ARB_VERTEX_PROGRAM_1)){ - infostream<<"generate_shader(): vertex shaders disabled " - "because of missing driver/hardware support." - <<std::endl; - vertex_program = ""; - } - if (!pixel_program.empty() && - !driver->queryFeature(video::EVDF_PIXEL_SHADER_1_1) && - !driver->queryFeature(video::EVDF_ARB_FRAGMENT_PROGRAM_1)){ - infostream<<"generate_shader(): pixel shaders disabled " - "because of missing driver/hardware support." - <<std::endl; - pixel_program = ""; - } - if (!geometry_program.empty() && - !driver->queryFeature(video::EVDF_GEOMETRY_SHADER)){ - infostream<<"generate_shader(): geometry shaders disabled " - "because of missing driver/hardware support." - <<std::endl; - geometry_program = ""; - } - - // If no shaders are used, don't make a separate material type - if (vertex_program.empty() && pixel_program.empty() && geometry_program.empty()) - return shaderinfo; - - // Create shaders header - std::string shaders_header = "#version 120\n"; - - static const char* drawTypes[] = { - "NDT_NORMAL", - "NDT_AIRLIKE", - "NDT_LIQUID", - "NDT_FLOWINGLIQUID", - "NDT_GLASSLIKE", - "NDT_ALLFACES", - "NDT_ALLFACES_OPTIONAL", - "NDT_TORCHLIKE", - "NDT_SIGNLIKE", - "NDT_PLANTLIKE", - "NDT_FENCELIKE", - "NDT_RAILLIKE", - "NDT_NODEBOX", - "NDT_GLASSLIKE_FRAMED", - "NDT_FIRELIKE", - "NDT_GLASSLIKE_FRAMED_OPTIONAL", - "NDT_PLANTLIKE_ROOTED", - }; - - for (int i = 0; i < 14; i++){ - shaders_header += "#define "; - shaders_header += drawTypes[i]; - shaders_header += " "; - shaders_header += itos(i); - shaders_header += "\n"; - } - - static const char* materialTypes[] = { - "TILE_MATERIAL_BASIC", - "TILE_MATERIAL_ALPHA", - "TILE_MATERIAL_LIQUID_TRANSPARENT", - "TILE_MATERIAL_LIQUID_OPAQUE", - "TILE_MATERIAL_WAVING_LEAVES", - "TILE_MATERIAL_WAVING_PLANTS", - "TILE_MATERIAL_OPAQUE" - }; - - for (int i = 0; i < 7; i++){ - shaders_header += "#define "; - shaders_header += materialTypes[i]; - shaders_header += " "; - shaders_header += itos(i); - shaders_header += "\n"; - } - - shaders_header += "#define MATERIAL_TYPE "; - shaders_header += itos(material_type); - shaders_header += "\n"; - shaders_header += "#define DRAW_TYPE "; - shaders_header += itos(drawtype); - shaders_header += "\n"; - - if (g_settings->getBool("generate_normalmaps")) { - shaders_header += "#define GENERATE_NORMALMAPS 1\n"; - } else { - shaders_header += "#define GENERATE_NORMALMAPS 0\n"; - } - shaders_header += "#define NORMALMAPS_STRENGTH "; - shaders_header += ftos(g_settings->getFloat("normalmaps_strength")); - shaders_header += "\n"; - float sample_step; - int smooth = (int)g_settings->getFloat("normalmaps_smooth"); - switch (smooth){ - case 0: - sample_step = 0.0078125; // 1.0 / 128.0 - break; - case 1: - sample_step = 0.00390625; // 1.0 / 256.0 - break; - case 2: - sample_step = 0.001953125; // 1.0 / 512.0 - break; - default: - sample_step = 0.0078125; - break; - } - shaders_header += "#define SAMPLE_STEP "; - shaders_header += ftos(sample_step); - shaders_header += "\n"; - - if (g_settings->getBool("enable_bumpmapping")) - shaders_header += "#define ENABLE_BUMPMAPPING\n"; - - if (g_settings->getBool("enable_parallax_occlusion")){ - int mode = g_settings->getFloat("parallax_occlusion_mode"); - float scale = g_settings->getFloat("parallax_occlusion_scale"); - float bias = g_settings->getFloat("parallax_occlusion_bias"); - int iterations = g_settings->getFloat("parallax_occlusion_iterations"); - shaders_header += "#define ENABLE_PARALLAX_OCCLUSION\n"; - shaders_header += "#define PARALLAX_OCCLUSION_MODE "; - shaders_header += itos(mode); - shaders_header += "\n"; - shaders_header += "#define PARALLAX_OCCLUSION_SCALE "; - shaders_header += ftos(scale); - shaders_header += "\n"; - shaders_header += "#define PARALLAX_OCCLUSION_BIAS "; - shaders_header += ftos(bias); - shaders_header += "\n"; - shaders_header += "#define PARALLAX_OCCLUSION_ITERATIONS "; - shaders_header += itos(iterations); - shaders_header += "\n"; - } - - shaders_header += "#define USE_NORMALMAPS "; - if (g_settings->getBool("enable_bumpmapping") || g_settings->getBool("enable_parallax_occlusion")) - shaders_header += "1\n"; - else - shaders_header += "0\n"; - - if (g_settings->getBool("enable_waving_water")){ - shaders_header += "#define ENABLE_WAVING_WATER 1\n"; - shaders_header += "#define WATER_WAVE_HEIGHT "; - shaders_header += ftos(g_settings->getFloat("water_wave_height")); - shaders_header += "\n"; - shaders_header += "#define WATER_WAVE_LENGTH "; - shaders_header += ftos(g_settings->getFloat("water_wave_length")); - shaders_header += "\n"; - shaders_header += "#define WATER_WAVE_SPEED "; - shaders_header += ftos(g_settings->getFloat("water_wave_speed")); - shaders_header += "\n"; - } else{ - shaders_header += "#define ENABLE_WAVING_WATER 0\n"; - } - - shaders_header += "#define ENABLE_WAVING_LEAVES "; - if (g_settings->getBool("enable_waving_leaves")) - shaders_header += "1\n"; - else - shaders_header += "0\n"; - - shaders_header += "#define ENABLE_WAVING_PLANTS "; - if (g_settings->getBool("enable_waving_plants")) - shaders_header += "1\n"; - else - shaders_header += "0\n"; - - if (g_settings->getBool("tone_mapping")) - shaders_header += "#define ENABLE_TONE_MAPPING\n"; - - shaders_header += "#define FOG_START "; - shaders_header += ftos(rangelim(g_settings->getFloat("fog_start"), 0.0f, 0.99f)); - shaders_header += "\n"; - - // Call addHighLevelShaderMaterial() or addShaderMaterial() - const c8* vertex_program_ptr = 0; - const c8* pixel_program_ptr = 0; - const c8* geometry_program_ptr = 0; - if (!vertex_program.empty()) { - vertex_program = shaders_header + vertex_program; - vertex_program_ptr = vertex_program.c_str(); - } - if (!pixel_program.empty()) { - pixel_program = shaders_header + pixel_program; - pixel_program_ptr = pixel_program.c_str(); - } - if (!geometry_program.empty()) { - geometry_program = shaders_header + geometry_program; - geometry_program_ptr = geometry_program.c_str(); - } - ShaderCallback *cb = new ShaderCallback(setter_factories); - s32 shadermat = -1; - if(is_highlevel){ - infostream<<"Compiling high level shaders for "<<name<<std::endl; - shadermat = gpu->addHighLevelShaderMaterial( - vertex_program_ptr, // Vertex shader program - "vertexMain", // Vertex shader entry point - video::EVST_VS_1_1, // Vertex shader version - pixel_program_ptr, // Pixel shader program - "pixelMain", // Pixel shader entry point - video::EPST_PS_1_2, // Pixel shader version - geometry_program_ptr, // Geometry shader program - "geometryMain", // Geometry shader entry point - video::EGST_GS_4_0, // Geometry shader version - scene::EPT_TRIANGLES, // Geometry shader input - scene::EPT_TRIANGLE_STRIP, // Geometry shader output - 0, // Support maximum number of vertices - cb, // Set-constant callback - shaderinfo.base_material, // Base material - 1 // Userdata passed to callback - ); - if(shadermat == -1){ - errorstream<<"generate_shader(): " - "failed to generate \""<<name<<"\", " - "addHighLevelShaderMaterial failed." - <<std::endl; - dumpShaderProgram(warningstream, "Vertex", vertex_program); - dumpShaderProgram(warningstream, "Pixel", pixel_program); - dumpShaderProgram(warningstream, "Geometry", geometry_program); - delete cb; - return shaderinfo; - } - } - else{ - infostream<<"Compiling assembly shaders for "<<name<<std::endl; - shadermat = gpu->addShaderMaterial( - vertex_program_ptr, // Vertex shader program - pixel_program_ptr, // Pixel shader program - cb, // Set-constant callback - shaderinfo.base_material, // Base material - 0 // Userdata passed to callback - ); - - if(shadermat == -1){ - errorstream<<"generate_shader(): " - "failed to generate \""<<name<<"\", " - "addShaderMaterial failed." - <<std::endl; - dumpShaderProgram(warningstream, "Vertex", vertex_program); - dumpShaderProgram(warningstream,"Pixel", pixel_program); - delete cb; - return shaderinfo; - } - } - callbacks.push_back(cb); - - // HACK, TODO: investigate this better - // Grab the material renderer once more so minetest doesn't crash on exit - driver->getMaterialRenderer(shadermat)->grab(); - - // Apply the newly created material type - shaderinfo.material = (video::E_MATERIAL_TYPE) shadermat; - return shaderinfo; -} - -void load_shaders(const std::string &name, SourceShaderCache *sourcecache, - video::E_DRIVER_TYPE drivertype, bool enable_shaders, - std::string &vertex_program, std::string &pixel_program, - std::string &geometry_program, bool &is_highlevel) -{ - vertex_program = ""; - pixel_program = ""; - geometry_program = ""; - is_highlevel = false; - - if(enable_shaders){ - // Look for high level shaders - if(drivertype == video::EDT_DIRECT3D9){ - // Direct3D 9: HLSL - // (All shaders in one file) - vertex_program = sourcecache->getOrLoad(name, "d3d9.hlsl"); - pixel_program = vertex_program; - geometry_program = vertex_program; - } - else if(drivertype == video::EDT_OPENGL){ - // OpenGL: GLSL - vertex_program = sourcecache->getOrLoad(name, "opengl_vertex.glsl"); - pixel_program = sourcecache->getOrLoad(name, "opengl_fragment.glsl"); - geometry_program = sourcecache->getOrLoad(name, "opengl_geometry.glsl"); - } - if (!vertex_program.empty() || !pixel_program.empty() || !geometry_program.empty()){ - is_highlevel = true; - return; - } - } - -} - -void dumpShaderProgram(std::ostream &output_stream, - const std::string &program_type, const std::string &program) -{ - output_stream << program_type << " shader program:" << std::endl << - "----------------------------------" << std::endl; - size_t pos = 0; - size_t prev = 0; - s16 line = 1; - while ((pos = program.find('\n', prev)) != std::string::npos) { - output_stream << line++ << ": "<< program.substr(prev, pos - prev) << - std::endl; - prev = pos + 1; - } - output_stream << line << ": " << program.substr(prev) << std::endl << - "End of " << program_type << " shader program." << std::endl << - " " << std::endl; -} |