3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4 Copyright (C) 2013 Kahrl <kahrl@gmx.net>
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License along
17 with this program; if not, write to the Free Software Foundation, Inc.,
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 #include "irrlichttypes_extrabloated.h"
27 #include "util/container.h"
28 #include "util/thread.h"
30 #include <ICameraSceneNode.h>
31 #include <IGPUProgrammingServices.h>
32 #include <IMaterialRenderer.h>
33 #include <IMaterialRendererServices.h>
34 #include <IShaderConstantSetCallBack.h>
35 #include "client/renderingengine.h"
36 #include "EShaderTypes.h"
39 #include "client/tile.h"
42 A cache from shader name to shader path
44 MutexedMap<std::string, std::string> g_shadername_to_path_cache;
47 Gets the path to a shader by first checking if the file
48 name_of_shader/filename
49 exists in shader_path and if not, using the data path.
51 If not found, returns "".
53 Utilizes a thread-safe cache.
55 std::string getShaderPath(const std::string &name_of_shader,
56 const std::string &filename)
58 std::string combined = name_of_shader + DIR_DELIM + filename;
63 bool incache = g_shadername_to_path_cache.get(combined, &fullpath);
68 Check from shader_path
70 std::string shader_path = g_settings->get("shader_path");
71 if (!shader_path.empty()) {
72 std::string testpath = shader_path + DIR_DELIM + combined;
73 if(fs::PathExists(testpath))
78 Check from default data directory
80 if (fullpath.empty()) {
81 std::string rel_path = std::string("client") + DIR_DELIM
82 + "shaders" + DIR_DELIM
83 + name_of_shader + DIR_DELIM
85 std::string testpath = porting::path_share + DIR_DELIM + rel_path;
86 if(fs::PathExists(testpath))
90 // Add to cache (also an empty result is cached)
91 g_shadername_to_path_cache.set(combined, fullpath);
98 SourceShaderCache: A cache used for storing source shaders.
101 class SourceShaderCache
104 void insert(const std::string &name_of_shader, const std::string &filename,
105 const std::string &program, bool prefer_local)
107 std::string combined = name_of_shader + DIR_DELIM + filename;
108 // Try to use local shader instead if asked to
110 std::string path = getShaderPath(name_of_shader, filename);
112 std::string p = readFile(path);
114 m_programs[combined] = p;
119 m_programs[combined] = program;
122 std::string get(const std::string &name_of_shader,
123 const std::string &filename)
125 std::string combined = name_of_shader + DIR_DELIM + filename;
126 StringMap::iterator n = m_programs.find(combined);
127 if (n != m_programs.end())
132 // Primarily fetches from cache, secondarily tries to read from filesystem
133 std::string getOrLoad(const std::string &name_of_shader,
134 const std::string &filename)
136 std::string combined = name_of_shader + DIR_DELIM + filename;
137 StringMap::iterator n = m_programs.find(combined);
138 if (n != m_programs.end())
140 std::string path = getShaderPath(name_of_shader, filename);
142 infostream << "SourceShaderCache::getOrLoad(): No path found for \""
143 << combined << "\"" << std::endl;
146 infostream << "SourceShaderCache::getOrLoad(): Loading path \""
147 << path << "\"" << std::endl;
148 std::string p = readFile(path);
150 m_programs[combined] = p;
156 StringMap m_programs;
158 std::string readFile(const std::string &path)
160 std::ifstream is(path.c_str(), std::ios::binary);
163 std::ostringstream tmp_os;
164 tmp_os << is.rdbuf();
171 ShaderCallback: Sets constants that can be used in shaders
174 class ShaderCallback : public video::IShaderConstantSetCallBack
176 std::vector<IShaderConstantSetter*> m_setters;
179 ShaderCallback(const std::vector<IShaderConstantSetterFactory *> &factories)
181 for (IShaderConstantSetterFactory *factory : factories)
182 m_setters.push_back(factory->create());
187 for (IShaderConstantSetter *setter : m_setters)
191 virtual void OnSetConstants(video::IMaterialRendererServices *services, s32 userData) override
193 video::IVideoDriver *driver = services->getVideoDriver();
194 sanity_check(driver != NULL);
196 bool is_highlevel = userData;
198 for (IShaderConstantSetter *setter : m_setters)
199 setter->onSetConstants(services, is_highlevel);
202 virtual void OnSetMaterial(const video::SMaterial& material) override
204 for (IShaderConstantSetter *setter : m_setters)
205 setter->onSetMaterial(material);
211 MainShaderConstantSetter: Set basic constants required for almost everything
214 class MainShaderConstantSetter : public IShaderConstantSetter
216 CachedVertexShaderSetting<float, 16> m_world_view_proj;
217 CachedVertexShaderSetting<float, 16> m_world;
220 MainShaderConstantSetter() :
221 m_world_view_proj("mWorldViewProj"),
224 ~MainShaderConstantSetter() = default;
226 virtual void onSetConstants(video::IMaterialRendererServices *services,
229 video::IVideoDriver *driver = services->getVideoDriver();
230 sanity_check(driver);
233 core::matrix4 worldViewProj;
234 worldViewProj = driver->getTransform(video::ETS_PROJECTION);
235 worldViewProj *= driver->getTransform(video::ETS_VIEW);
236 worldViewProj *= driver->getTransform(video::ETS_WORLD);
238 m_world_view_proj.set(*reinterpret_cast<float(*)[16]>(worldViewProj.pointer()), services);
240 services->setVertexShaderConstant(worldViewProj.pointer(), 0, 4);
243 core::matrix4 world = driver->getTransform(video::ETS_WORLD);
245 m_world.set(*reinterpret_cast<float(*)[16]>(world.pointer()), services);
247 services->setVertexShaderConstant(world.pointer(), 4, 4);
253 class MainShaderConstantSetterFactory : public IShaderConstantSetterFactory
256 virtual IShaderConstantSetter* create()
257 { return new MainShaderConstantSetter(); }
265 class ShaderSource : public IWritableShaderSource
272 - If shader material specified by name is found from cache,
273 return the cached id.
274 - Otherwise generate the shader material, add to cache and return id.
276 The id 0 points to a null shader. Its material is EMT_SOLID.
278 u32 getShaderIdDirect(const std::string &name,
279 const u8 material_type, const u8 drawtype);
282 If shader specified by the name pointed by the id doesn't
283 exist, create it, then return id.
285 Can be called from any thread. If called from some other thread
286 and not found in cache, the call is queued to the main thread
290 u32 getShader(const std::string &name,
291 const u8 material_type, const u8 drawtype);
293 ShaderInfo getShaderInfo(u32 id);
295 // Processes queued shader requests from other threads.
296 // Shall be called from the main thread.
299 // Insert a shader program into the cache without touching the
300 // filesystem. Shall be called from the main thread.
301 void insertSourceShader(const std::string &name_of_shader,
302 const std::string &filename, const std::string &program);
304 // Rebuild shaders from the current set of source shaders
305 // Shall be called from the main thread.
306 void rebuildShaders();
308 void addShaderConstantSetterFactory(IShaderConstantSetterFactory *setter)
310 m_setter_factories.push_back(setter);
315 // The id of the thread that is allowed to use irrlicht directly
316 std::thread::id m_main_thread;
318 // Cache of source shaders
319 // This should be only accessed from the main thread
320 SourceShaderCache m_sourcecache;
322 // A shader id is index in this array.
323 // The first position contains a dummy shader.
324 std::vector<ShaderInfo> m_shaderinfo_cache;
325 // The former container is behind this mutex
326 std::mutex m_shaderinfo_cache_mutex;
328 // Queued shader fetches (to be processed by the main thread)
329 RequestQueue<std::string, u32, u8, u8> m_get_shader_queue;
331 // Global constant setter factories
332 std::vector<IShaderConstantSetterFactory *> m_setter_factories;
335 std::vector<ShaderCallback *> m_callbacks;
338 IWritableShaderSource *createShaderSource()
340 return new ShaderSource();
344 Generate shader given the shader name.
346 ShaderInfo generate_shader(const std::string &name,
347 u8 material_type, u8 drawtype, std::vector<ShaderCallback *> &callbacks,
348 const std::vector<IShaderConstantSetterFactory *> &setter_factories,
349 SourceShaderCache *sourcecache);
354 void load_shaders(const std::string &name, SourceShaderCache *sourcecache,
355 video::E_DRIVER_TYPE drivertype, bool enable_shaders,
356 std::string &vertex_program, std::string &pixel_program,
357 std::string &geometry_program, bool &is_highlevel);
359 ShaderSource::ShaderSource()
361 m_main_thread = std::this_thread::get_id();
363 // Add a dummy ShaderInfo as the first index, named ""
364 m_shaderinfo_cache.emplace_back();
366 // Add main global constant setter
367 addShaderConstantSetterFactory(new MainShaderConstantSetterFactory());
370 ShaderSource::~ShaderSource()
372 for (ShaderCallback *callback : m_callbacks) {
375 for (IShaderConstantSetterFactory *setter_factorie : m_setter_factories) {
376 delete setter_factorie;
380 u32 ShaderSource::getShader(const std::string &name,
381 const u8 material_type, const u8 drawtype)
387 if (std::this_thread::get_id() == m_main_thread) {
388 return getShaderIdDirect(name, material_type, drawtype);
391 /*errorstream<<"getShader(): Queued: name=\""<<name<<"\""<<std::endl;*/
393 // We're gonna ask the result to be put into here
395 static ResultQueue<std::string, u32, u8, u8> result_queue;
397 // Throw a request in
398 m_get_shader_queue.add(name, 0, 0, &result_queue);
400 /* infostream<<"Waiting for shader from main thread, name=\""
401 <<name<<"\""<<std::endl;*/
404 GetResult<std::string, u32, u8, u8>
405 result = result_queue.pop_frontNoEx();
407 if (result.key == name) {
411 errorstream << "Got shader with invalid name: " << result.key << std::endl;
414 infostream << "getShader(): Failed" << std::endl;
420 This method generates all the shaders
422 u32 ShaderSource::getShaderIdDirect(const std::string &name,
423 const u8 material_type, const u8 drawtype)
425 //infostream<<"getShaderIdDirect(): name=\""<<name<<"\""<<std::endl;
427 // Empty name means shader 0
429 infostream<<"getShaderIdDirect(): name is empty"<<std::endl;
433 // Check if already have such instance
434 for(u32 i=0; i<m_shaderinfo_cache.size(); i++){
435 ShaderInfo *info = &m_shaderinfo_cache[i];
436 if(info->name == name && info->material_type == material_type &&
437 info->drawtype == drawtype)
442 Calling only allowed from main thread
444 if (std::this_thread::get_id() != m_main_thread) {
445 errorstream<<"ShaderSource::getShaderIdDirect() "
446 "called not from main thread"<<std::endl;
450 ShaderInfo info = generate_shader(name, material_type, drawtype,
451 m_callbacks, m_setter_factories, &m_sourcecache);
454 Add shader to caches (add dummy shaders too)
457 MutexAutoLock lock(m_shaderinfo_cache_mutex);
459 u32 id = m_shaderinfo_cache.size();
460 m_shaderinfo_cache.push_back(info);
462 infostream<<"getShaderIdDirect(): "
463 <<"Returning id="<<id<<" for name \""<<name<<"\""<<std::endl;
469 ShaderInfo ShaderSource::getShaderInfo(u32 id)
471 MutexAutoLock lock(m_shaderinfo_cache_mutex);
473 if(id >= m_shaderinfo_cache.size())
476 return m_shaderinfo_cache[id];
479 void ShaderSource::processQueue()
485 void ShaderSource::insertSourceShader(const std::string &name_of_shader,
486 const std::string &filename, const std::string &program)
488 /*infostream<<"ShaderSource::insertSourceShader(): "
489 "name_of_shader=\""<<name_of_shader<<"\", "
490 "filename=\""<<filename<<"\""<<std::endl;*/
492 sanity_check(std::this_thread::get_id() == m_main_thread);
494 m_sourcecache.insert(name_of_shader, filename, program, true);
497 void ShaderSource::rebuildShaders()
499 MutexAutoLock lock(m_shaderinfo_cache_mutex);
501 /*// Oh well... just clear everything, they'll load sometime.
502 m_shaderinfo_cache.clear();
503 m_name_to_id.clear();*/
506 FIXME: Old shader materials can't be deleted in Irrlicht,
508 (This would be nice to do in the destructor too)
512 for (ShaderInfo &i : m_shaderinfo_cache) {
513 ShaderInfo *info = &i;
514 if (!info->name.empty()) {
515 *info = generate_shader(info->name, info->material_type,
516 info->drawtype, m_callbacks,
517 m_setter_factories, &m_sourcecache);
523 ShaderInfo generate_shader(const std::string &name, u8 material_type, u8 drawtype,
524 std::vector<ShaderCallback *> &callbacks,
525 const std::vector<IShaderConstantSetterFactory *> &setter_factories,
526 SourceShaderCache *sourcecache)
528 ShaderInfo shaderinfo;
529 shaderinfo.name = name;
530 shaderinfo.material_type = material_type;
531 shaderinfo.drawtype = drawtype;
532 shaderinfo.material = video::EMT_SOLID;
533 switch (material_type) {
534 case TILE_MATERIAL_OPAQUE:
535 case TILE_MATERIAL_LIQUID_OPAQUE:
536 case TILE_MATERIAL_WAVING_LIQUID_OPAQUE:
537 shaderinfo.base_material = video::EMT_SOLID;
539 case TILE_MATERIAL_ALPHA:
540 case TILE_MATERIAL_PLAIN_ALPHA:
541 case TILE_MATERIAL_LIQUID_TRANSPARENT:
542 case TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT:
543 shaderinfo.base_material = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
545 case TILE_MATERIAL_BASIC:
546 case TILE_MATERIAL_PLAIN:
547 case TILE_MATERIAL_WAVING_LEAVES:
548 case TILE_MATERIAL_WAVING_PLANTS:
549 case TILE_MATERIAL_WAVING_LIQUID_BASIC:
550 shaderinfo.base_material = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
554 bool enable_shaders = g_settings->getBool("enable_shaders");
558 video::IVideoDriver *driver = RenderingEngine::get_video_driver();
560 video::IGPUProgrammingServices *gpu = driver->getGPUProgrammingServices();
562 errorstream<<"generate_shader(): "
563 "failed to generate \""<<name<<"\", "
564 "GPU programming not supported."
569 // Choose shader language depending on driver type and settings
571 std::string vertex_program;
572 std::string pixel_program;
573 std::string geometry_program;
575 load_shaders(name, sourcecache, driver->getDriverType(),
576 enable_shaders, vertex_program, pixel_program,
577 geometry_program, is_highlevel);
578 // Check hardware/driver support
579 if (!vertex_program.empty() &&
580 !driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1) &&
581 !driver->queryFeature(video::EVDF_ARB_VERTEX_PROGRAM_1)){
582 infostream<<"generate_shader(): vertex shaders disabled "
583 "because of missing driver/hardware support."
587 if (!pixel_program.empty() &&
588 !driver->queryFeature(video::EVDF_PIXEL_SHADER_1_1) &&
589 !driver->queryFeature(video::EVDF_ARB_FRAGMENT_PROGRAM_1)){
590 infostream<<"generate_shader(): pixel shaders disabled "
591 "because of missing driver/hardware support."
595 if (!geometry_program.empty() &&
596 !driver->queryFeature(video::EVDF_GEOMETRY_SHADER)){
597 infostream<<"generate_shader(): geometry shaders disabled "
598 "because of missing driver/hardware support."
600 geometry_program = "";
603 // If no shaders are used, don't make a separate material type
604 if (vertex_program.empty() && pixel_program.empty() && geometry_program.empty())
607 // Create shaders header
608 std::string shaders_header = "#version 120\n";
610 static const char* drawTypes[] = {
617 "NDT_ALLFACES_OPTIONAL",
624 "NDT_GLASSLIKE_FRAMED",
626 "NDT_GLASSLIKE_FRAMED_OPTIONAL",
627 "NDT_PLANTLIKE_ROOTED",
630 for (int i = 0; i < 14; i++){
631 shaders_header += "#define ";
632 shaders_header += drawTypes[i];
633 shaders_header += " ";
634 shaders_header += itos(i);
635 shaders_header += "\n";
638 static const char* materialTypes[] = {
639 "TILE_MATERIAL_BASIC",
640 "TILE_MATERIAL_ALPHA",
641 "TILE_MATERIAL_LIQUID_TRANSPARENT",
642 "TILE_MATERIAL_LIQUID_OPAQUE",
643 "TILE_MATERIAL_WAVING_LEAVES",
644 "TILE_MATERIAL_WAVING_PLANTS",
645 "TILE_MATERIAL_OPAQUE",
646 "TILE_MATERIAL_WAVING_LIQUID_BASIC",
647 "TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT",
648 "TILE_MATERIAL_WAVING_LIQUID_OPAQUE",
649 "TILE_MATERIAL_PLAIN",
650 "TILE_MATERIAL_PLAIN_ALPHA",
653 for (int i = 0; i < 12; i++){
654 shaders_header += "#define ";
655 shaders_header += materialTypes[i];
656 shaders_header += " ";
657 shaders_header += itos(i);
658 shaders_header += "\n";
661 shaders_header += "#define MATERIAL_TYPE ";
662 shaders_header += itos(material_type);
663 shaders_header += "\n";
664 shaders_header += "#define DRAW_TYPE ";
665 shaders_header += itos(drawtype);
666 shaders_header += "\n";
668 if (g_settings->getBool("generate_normalmaps")) {
669 shaders_header += "#define GENERATE_NORMALMAPS 1\n";
671 shaders_header += "#define GENERATE_NORMALMAPS 0\n";
673 shaders_header += "#define NORMALMAPS_STRENGTH ";
674 shaders_header += ftos(g_settings->getFloat("normalmaps_strength"));
675 shaders_header += "\n";
677 int smooth = (int)g_settings->getFloat("normalmaps_smooth");
680 sample_step = 0.0078125; // 1.0 / 128.0
683 sample_step = 0.00390625; // 1.0 / 256.0
686 sample_step = 0.001953125; // 1.0 / 512.0
689 sample_step = 0.0078125;
692 shaders_header += "#define SAMPLE_STEP ";
693 shaders_header += ftos(sample_step);
694 shaders_header += "\n";
696 if (g_settings->getBool("enable_bumpmapping"))
697 shaders_header += "#define ENABLE_BUMPMAPPING\n";
699 if (g_settings->getBool("enable_parallax_occlusion")){
700 int mode = g_settings->getFloat("parallax_occlusion_mode");
701 float scale = g_settings->getFloat("parallax_occlusion_scale");
702 float bias = g_settings->getFloat("parallax_occlusion_bias");
703 int iterations = g_settings->getFloat("parallax_occlusion_iterations");
704 shaders_header += "#define ENABLE_PARALLAX_OCCLUSION\n";
705 shaders_header += "#define PARALLAX_OCCLUSION_MODE ";
706 shaders_header += itos(mode);
707 shaders_header += "\n";
708 shaders_header += "#define PARALLAX_OCCLUSION_SCALE ";
709 shaders_header += ftos(scale);
710 shaders_header += "\n";
711 shaders_header += "#define PARALLAX_OCCLUSION_BIAS ";
712 shaders_header += ftos(bias);
713 shaders_header += "\n";
714 shaders_header += "#define PARALLAX_OCCLUSION_ITERATIONS ";
715 shaders_header += itos(iterations);
716 shaders_header += "\n";
719 shaders_header += "#define USE_NORMALMAPS ";
720 if (g_settings->getBool("enable_bumpmapping") || g_settings->getBool("enable_parallax_occlusion"))
721 shaders_header += "1\n";
723 shaders_header += "0\n";
725 if (g_settings->getBool("enable_waving_water")){
726 shaders_header += "#define ENABLE_WAVING_WATER 1\n";
727 shaders_header += "#define WATER_WAVE_HEIGHT ";
728 shaders_header += ftos(g_settings->getFloat("water_wave_height"));
729 shaders_header += "\n";
730 shaders_header += "#define WATER_WAVE_LENGTH ";
731 shaders_header += ftos(g_settings->getFloat("water_wave_length"));
732 shaders_header += "\n";
733 shaders_header += "#define WATER_WAVE_SPEED ";
734 shaders_header += ftos(g_settings->getFloat("water_wave_speed"));
735 shaders_header += "\n";
737 shaders_header += "#define ENABLE_WAVING_WATER 0\n";
740 shaders_header += "#define ENABLE_WAVING_LEAVES ";
741 if (g_settings->getBool("enable_waving_leaves"))
742 shaders_header += "1\n";
744 shaders_header += "0\n";
746 shaders_header += "#define ENABLE_WAVING_PLANTS ";
747 if (g_settings->getBool("enable_waving_plants"))
748 shaders_header += "1\n";
750 shaders_header += "0\n";
752 if (g_settings->getBool("tone_mapping"))
753 shaders_header += "#define ENABLE_TONE_MAPPING\n";
755 shaders_header += "#define FOG_START ";
756 shaders_header += ftos(rangelim(g_settings->getFloat("fog_start"), 0.0f, 0.99f));
757 shaders_header += "\n";
759 // Call addHighLevelShaderMaterial() or addShaderMaterial()
760 const c8* vertex_program_ptr = 0;
761 const c8* pixel_program_ptr = 0;
762 const c8* geometry_program_ptr = 0;
763 if (!vertex_program.empty()) {
764 vertex_program = shaders_header + vertex_program;
765 vertex_program_ptr = vertex_program.c_str();
767 if (!pixel_program.empty()) {
768 pixel_program = shaders_header + pixel_program;
769 pixel_program_ptr = pixel_program.c_str();
771 if (!geometry_program.empty()) {
772 geometry_program = shaders_header + geometry_program;
773 geometry_program_ptr = geometry_program.c_str();
775 ShaderCallback *cb = new ShaderCallback(setter_factories);
778 infostream<<"Compiling high level shaders for "<<name<<std::endl;
779 shadermat = gpu->addHighLevelShaderMaterial(
780 vertex_program_ptr, // Vertex shader program
781 "vertexMain", // Vertex shader entry point
782 video::EVST_VS_1_1, // Vertex shader version
783 pixel_program_ptr, // Pixel shader program
784 "pixelMain", // Pixel shader entry point
785 video::EPST_PS_1_2, // Pixel shader version
786 geometry_program_ptr, // Geometry shader program
787 "geometryMain", // Geometry shader entry point
788 video::EGST_GS_4_0, // Geometry shader version
789 scene::EPT_TRIANGLES, // Geometry shader input
790 scene::EPT_TRIANGLE_STRIP, // Geometry shader output
791 0, // Support maximum number of vertices
792 cb, // Set-constant callback
793 shaderinfo.base_material, // Base material
794 1 // Userdata passed to callback
797 errorstream<<"generate_shader(): "
798 "failed to generate \""<<name<<"\", "
799 "addHighLevelShaderMaterial failed."
801 dumpShaderProgram(warningstream, "Vertex", vertex_program);
802 dumpShaderProgram(warningstream, "Pixel", pixel_program);
803 dumpShaderProgram(warningstream, "Geometry", geometry_program);
809 infostream<<"Compiling assembly shaders for "<<name<<std::endl;
810 shadermat = gpu->addShaderMaterial(
811 vertex_program_ptr, // Vertex shader program
812 pixel_program_ptr, // Pixel shader program
813 cb, // Set-constant callback
814 shaderinfo.base_material, // Base material
815 0 // Userdata passed to callback
819 errorstream<<"generate_shader(): "
820 "failed to generate \""<<name<<"\", "
821 "addShaderMaterial failed."
823 dumpShaderProgram(warningstream, "Vertex", vertex_program);
824 dumpShaderProgram(warningstream,"Pixel", pixel_program);
829 callbacks.push_back(cb);
831 // HACK, TODO: investigate this better
832 // Grab the material renderer once more so minetest doesn't crash on exit
833 driver->getMaterialRenderer(shadermat)->grab();
835 // Apply the newly created material type
836 shaderinfo.material = (video::E_MATERIAL_TYPE) shadermat;
840 void load_shaders(const std::string &name, SourceShaderCache *sourcecache,
841 video::E_DRIVER_TYPE drivertype, bool enable_shaders,
842 std::string &vertex_program, std::string &pixel_program,
843 std::string &geometry_program, bool &is_highlevel)
847 geometry_program = "";
848 is_highlevel = false;
851 // Look for high level shaders
852 if(drivertype == video::EDT_DIRECT3D9){
854 // (All shaders in one file)
855 vertex_program = sourcecache->getOrLoad(name, "d3d9.hlsl");
856 pixel_program = vertex_program;
857 geometry_program = vertex_program;
859 else if(drivertype == video::EDT_OPENGL){
861 vertex_program = sourcecache->getOrLoad(name, "opengl_vertex.glsl");
862 pixel_program = sourcecache->getOrLoad(name, "opengl_fragment.glsl");
863 geometry_program = sourcecache->getOrLoad(name, "opengl_geometry.glsl");
865 if (!vertex_program.empty() || !pixel_program.empty() || !geometry_program.empty()){
873 void dumpShaderProgram(std::ostream &output_stream,
874 const std::string &program_type, const std::string &program)
876 output_stream << program_type << " shader program:" << std::endl <<
877 "----------------------------------" << std::endl;
881 while ((pos = program.find('\n', prev)) != std::string::npos) {
882 output_stream << line++ << ": "<< program.substr(prev, pos - prev) <<
886 output_stream << line << ": " << program.substr(prev) << std::endl <<
887 "End of " << program_type << " shader program." << std::endl <<