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 "EShaderTypes.h"
38 #include "client/tile.h"
41 A cache from shader name to shader path
43 MutexedMap<std::string, std::string> g_shadername_to_path_cache;
46 Gets the path to a shader by first checking if the file
47 name_of_shader/filename
48 exists in shader_path and if not, using the data path.
50 If not found, returns "".
52 Utilizes a thread-safe cache.
54 std::string getShaderPath(const std::string &name_of_shader,
55 const std::string &filename)
57 std::string combined = name_of_shader + DIR_DELIM + filename;
58 std::string fullpath = "";
62 bool incache = g_shadername_to_path_cache.get(combined, &fullpath);
67 Check from shader_path
69 std::string shader_path = g_settings->get("shader_path");
72 std::string testpath = shader_path + DIR_DELIM + combined;
73 if(fs::PathExists(testpath))
78 Check from default data directory
82 std::string rel_path = std::string("client") + DIR_DELIM
83 + "shaders" + DIR_DELIM
84 + name_of_shader + DIR_DELIM
86 std::string testpath = porting::path_share + DIR_DELIM + rel_path;
87 if(fs::PathExists(testpath))
91 // Add to cache (also an empty result is cached)
92 g_shadername_to_path_cache.set(combined, fullpath);
99 SourceShaderCache: A cache used for storing source shaders.
102 class SourceShaderCache
105 void insert(const std::string &name_of_shader, const std::string &filename,
106 const std::string &program, bool prefer_local)
108 std::string combined = name_of_shader + DIR_DELIM + filename;
109 // Try to use local shader instead if asked to
111 std::string path = getShaderPath(name_of_shader, filename);
113 std::string p = readFile(path);
115 m_programs[combined] = p;
120 m_programs[combined] = program;
123 std::string get(const std::string &name_of_shader,
124 const std::string &filename)
126 std::string combined = name_of_shader + DIR_DELIM + filename;
127 StringMap::iterator n = m_programs.find(combined);
128 if (n != m_programs.end())
133 // Primarily fetches from cache, secondarily tries to read from filesystem
134 std::string getOrLoad(const std::string &name_of_shader,
135 const std::string &filename)
137 std::string combined = name_of_shader + DIR_DELIM + filename;
138 StringMap::iterator n = m_programs.find(combined);
139 if (n != m_programs.end())
141 std::string path = getShaderPath(name_of_shader, filename);
143 infostream << "SourceShaderCache::getOrLoad(): No path found for \""
144 << combined << "\"" << std::endl;
147 infostream << "SourceShaderCache::getOrLoad(): Loading path \""
148 << path << "\"" << std::endl;
149 std::string p = readFile(path);
151 m_programs[combined] = p;
157 StringMap m_programs;
159 std::string readFile(const std::string &path)
161 std::ifstream is(path.c_str(), std::ios::binary);
164 std::ostringstream tmp_os;
165 tmp_os << is.rdbuf();
171 ShaderCallback: Sets constants that can be used in shaders
174 class IShaderConstantSetterRegistry
177 virtual ~IShaderConstantSetterRegistry(){};
178 virtual void onSetConstants(video::IMaterialRendererServices *services,
179 bool is_highlevel, const std::string &name) = 0;
182 class ShaderCallback : public video::IShaderConstantSetCallBack
184 IShaderConstantSetterRegistry *m_scsr;
188 ShaderCallback(IShaderConstantSetterRegistry *scsr, const std::string &name):
194 virtual void OnSetConstants(video::IMaterialRendererServices *services, s32 userData)
196 video::IVideoDriver *driver = services->getVideoDriver();
197 sanity_check(driver != NULL);
199 bool is_highlevel = userData;
201 m_scsr->onSetConstants(services, is_highlevel, m_name);
206 MainShaderConstantSetter: Set basic constants required for almost everything
209 class MainShaderConstantSetter : public IShaderConstantSetter
212 MainShaderConstantSetter(IrrlichtDevice *device)
214 ~MainShaderConstantSetter() {}
216 virtual void onSetConstants(video::IMaterialRendererServices *services,
219 video::IVideoDriver *driver = services->getVideoDriver();
220 sanity_check(driver);
222 // set inverted world matrix
223 core::matrix4 invWorld = driver->getTransform(video::ETS_WORLD);
224 invWorld.makeInverse();
226 services->setVertexShaderConstant("mInvWorld", invWorld.pointer(), 16);
228 services->setVertexShaderConstant(invWorld.pointer(), 0, 4);
231 core::matrix4 worldViewProj;
232 worldViewProj = driver->getTransform(video::ETS_PROJECTION);
233 worldViewProj *= driver->getTransform(video::ETS_VIEW);
234 worldViewProj *= driver->getTransform(video::ETS_WORLD);
236 services->setVertexShaderConstant("mWorldViewProj", worldViewProj.pointer(), 16);
238 services->setVertexShaderConstant(worldViewProj.pointer(), 4, 4);
240 // set transposed world matrix
241 core::matrix4 transWorld = driver->getTransform(video::ETS_WORLD);
242 transWorld = transWorld.getTransposed();
244 services->setVertexShaderConstant("mTransWorld", transWorld.pointer(), 16);
246 services->setVertexShaderConstant(transWorld.pointer(), 8, 4);
249 core::matrix4 world = driver->getTransform(video::ETS_WORLD);
251 services->setVertexShaderConstant("mWorld", world.pointer(), 16);
253 services->setVertexShaderConstant(world.pointer(), 8, 4);
262 class ShaderSource : public IWritableShaderSource, public IShaderConstantSetterRegistry
265 ShaderSource(IrrlichtDevice *device);
269 - If shader material specified by name is found from cache,
270 return the cached id.
271 - Otherwise generate the shader material, add to cache and return id.
273 The id 0 points to a null shader. Its material is EMT_SOLID.
275 u32 getShaderIdDirect(const std::string &name,
276 const u8 material_type, const u8 drawtype);
279 If shader specified by the name pointed by the id doesn't
280 exist, create it, then return id.
282 Can be called from any thread. If called from some other thread
283 and not found in cache, the call is queued to the main thread
287 u32 getShader(const std::string &name,
288 const u8 material_type, const u8 drawtype);
290 ShaderInfo getShaderInfo(u32 id);
292 // Processes queued shader requests from other threads.
293 // Shall be called from the main thread.
296 // Insert a shader program into the cache without touching the
297 // filesystem. Shall be called from the main thread.
298 void insertSourceShader(const std::string &name_of_shader,
299 const std::string &filename, const std::string &program);
301 // Rebuild shaders from the current set of source shaders
302 // Shall be called from the main thread.
303 void rebuildShaders();
305 void addGlobalConstantSetter(IShaderConstantSetter *setter)
307 m_global_setters.push_back(setter);
310 void onSetConstants(video::IMaterialRendererServices *services,
311 bool is_highlevel, const std::string &name);
315 // The id of the thread that is allowed to use irrlicht directly
316 threadid_t m_main_thread;
317 // The irrlicht device
318 IrrlichtDevice *m_device;
319 // The set-constants callback
320 ShaderCallback *m_shader_callback;
322 // Cache of source shaders
323 // This should be only accessed from the main thread
324 SourceShaderCache m_sourcecache;
326 // A shader id is index in this array.
327 // The first position contains a dummy shader.
328 std::vector<ShaderInfo> m_shaderinfo_cache;
329 // The former container is behind this mutex
330 Mutex m_shaderinfo_cache_mutex;
332 // Queued shader fetches (to be processed by the main thread)
333 RequestQueue<std::string, u32, u8, u8> m_get_shader_queue;
335 // Global constant setters
336 // TODO: Delete these in the destructor
337 std::vector<IShaderConstantSetter*> m_global_setters;
340 IWritableShaderSource* createShaderSource(IrrlichtDevice *device)
342 return new ShaderSource(device);
346 Generate shader given the shader name.
348 ShaderInfo generate_shader(std::string name,
349 u8 material_type, u8 drawtype,
350 IrrlichtDevice *device,
351 video::IShaderConstantSetCallBack *callback,
352 SourceShaderCache *sourcecache);
357 void load_shaders(std::string name, SourceShaderCache *sourcecache,
358 video::E_DRIVER_TYPE drivertype, bool enable_shaders,
359 std::string &vertex_program, std::string &pixel_program,
360 std::string &geometry_program, bool &is_highlevel);
362 ShaderSource::ShaderSource(IrrlichtDevice *device):
365 assert(m_device); // Pre-condition
367 m_shader_callback = new ShaderCallback(this, "default");
369 m_main_thread = thr_get_current_thread_id();
371 // Add a dummy ShaderInfo as the first index, named ""
372 m_shaderinfo_cache.push_back(ShaderInfo());
374 // Add main global constant setter
375 addGlobalConstantSetter(new MainShaderConstantSetter(device));
378 ShaderSource::~ShaderSource()
380 for (std::vector<IShaderConstantSetter*>::iterator iter = m_global_setters.begin();
381 iter != m_global_setters.end(); ++iter) {
384 m_global_setters.clear();
386 if (m_shader_callback) {
387 m_shader_callback->drop();
388 m_shader_callback = NULL;
392 u32 ShaderSource::getShader(const std::string &name,
393 const u8 material_type, const u8 drawtype)
399 if (thr_is_current_thread(m_main_thread)) {
400 return getShaderIdDirect(name, material_type, drawtype);
402 /*errorstream<<"getShader(): Queued: name=\""<<name<<"\""<<std::endl;*/
404 // We're gonna ask the result to be put into here
406 static ResultQueue<std::string, u32, u8, u8> result_queue;
408 // Throw a request in
409 m_get_shader_queue.add(name, 0, 0, &result_queue);
411 /* infostream<<"Waiting for shader from main thread, name=\""
412 <<name<<"\""<<std::endl;*/
415 GetResult<std::string, u32, u8, u8>
416 result = result_queue.pop_frontNoEx();
418 if (result.key == name) {
422 errorstream << "Got shader with invalid name: " << result.key << std::endl;
428 infostream<<"getShader(): Failed"<<std::endl;
434 This method generates all the shaders
436 u32 ShaderSource::getShaderIdDirect(const std::string &name,
437 const u8 material_type, const u8 drawtype)
439 //infostream<<"getShaderIdDirect(): name=\""<<name<<"\""<<std::endl;
441 // Empty name means shader 0
443 infostream<<"getShaderIdDirect(): name is empty"<<std::endl;
447 // Check if already have such instance
448 for(u32 i=0; i<m_shaderinfo_cache.size(); i++){
449 ShaderInfo *info = &m_shaderinfo_cache[i];
450 if(info->name == name && info->material_type == material_type &&
451 info->drawtype == drawtype)
456 Calling only allowed from main thread
458 if (!thr_is_current_thread(m_main_thread)) {
459 errorstream<<"ShaderSource::getShaderIdDirect() "
460 "called not from main thread"<<std::endl;
464 ShaderInfo info = generate_shader(name, material_type, drawtype, m_device,
465 m_shader_callback, &m_sourcecache);
468 Add shader to caches (add dummy shaders too)
471 MutexAutoLock lock(m_shaderinfo_cache_mutex);
473 u32 id = m_shaderinfo_cache.size();
474 m_shaderinfo_cache.push_back(info);
476 infostream<<"getShaderIdDirect(): "
477 <<"Returning id="<<id<<" for name \""<<name<<"\""<<std::endl;
483 ShaderInfo ShaderSource::getShaderInfo(u32 id)
485 MutexAutoLock lock(m_shaderinfo_cache_mutex);
487 if(id >= m_shaderinfo_cache.size())
490 return m_shaderinfo_cache[id];
493 void ShaderSource::processQueue()
499 void ShaderSource::insertSourceShader(const std::string &name_of_shader,
500 const std::string &filename, const std::string &program)
502 /*infostream<<"ShaderSource::insertSourceShader(): "
503 "name_of_shader=\""<<name_of_shader<<"\", "
504 "filename=\""<<filename<<"\""<<std::endl;*/
506 sanity_check(thr_is_current_thread(m_main_thread));
508 m_sourcecache.insert(name_of_shader, filename, program, true);
511 void ShaderSource::rebuildShaders()
513 MutexAutoLock lock(m_shaderinfo_cache_mutex);
515 /*// Oh well... just clear everything, they'll load sometime.
516 m_shaderinfo_cache.clear();
517 m_name_to_id.clear();*/
520 FIXME: Old shader materials can't be deleted in Irrlicht,
522 (This would be nice to do in the destructor too)
526 for(u32 i=0; i<m_shaderinfo_cache.size(); i++){
527 ShaderInfo *info = &m_shaderinfo_cache[i];
528 if(info->name != ""){
529 *info = generate_shader(info->name, info->material_type,
530 info->drawtype, m_device, m_shader_callback, &m_sourcecache);
535 void ShaderSource::onSetConstants(video::IMaterialRendererServices *services,
536 bool is_highlevel, const std::string &name)
538 for(u32 i=0; i<m_global_setters.size(); i++){
539 IShaderConstantSetter *setter = m_global_setters[i];
540 setter->onSetConstants(services, is_highlevel);
544 ShaderInfo generate_shader(std::string name, u8 material_type, u8 drawtype,
545 IrrlichtDevice *device, video::IShaderConstantSetCallBack *callback,
546 SourceShaderCache *sourcecache)
548 ShaderInfo shaderinfo;
549 shaderinfo.name = name;
550 shaderinfo.material_type = material_type;
551 shaderinfo.drawtype = drawtype;
552 shaderinfo.material = video::EMT_SOLID;
553 switch(material_type){
554 case TILE_MATERIAL_BASIC:
555 shaderinfo.base_material = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
557 case TILE_MATERIAL_ALPHA:
558 shaderinfo.base_material = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
560 case TILE_MATERIAL_LIQUID_TRANSPARENT:
561 shaderinfo.base_material = video::EMT_TRANSPARENT_VERTEX_ALPHA;
563 case TILE_MATERIAL_LIQUID_OPAQUE:
564 shaderinfo.base_material = video::EMT_SOLID;
566 case TILE_MATERIAL_WAVING_LEAVES:
567 shaderinfo.base_material = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
569 case TILE_MATERIAL_WAVING_PLANTS:
570 shaderinfo.base_material = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
574 bool enable_shaders = g_settings->getBool("enable_shaders");
578 video::IVideoDriver* driver = device->getVideoDriver();
579 sanity_check(driver);
581 video::IGPUProgrammingServices *gpu = driver->getGPUProgrammingServices();
583 errorstream<<"generate_shader(): "
584 "failed to generate \""<<name<<"\", "
585 "GPU programming not supported."
590 // Choose shader language depending on driver type and settings
592 std::string vertex_program;
593 std::string pixel_program;
594 std::string geometry_program;
596 load_shaders(name, sourcecache, driver->getDriverType(),
597 enable_shaders, vertex_program, pixel_program,
598 geometry_program, is_highlevel);
599 // Check hardware/driver support
600 if(vertex_program != "" &&
601 !driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1) &&
602 !driver->queryFeature(video::EVDF_ARB_VERTEX_PROGRAM_1)){
603 infostream<<"generate_shader(): vertex shaders disabled "
604 "because of missing driver/hardware support."
608 if(pixel_program != "" &&
609 !driver->queryFeature(video::EVDF_PIXEL_SHADER_1_1) &&
610 !driver->queryFeature(video::EVDF_ARB_FRAGMENT_PROGRAM_1)){
611 infostream<<"generate_shader(): pixel shaders disabled "
612 "because of missing driver/hardware support."
616 if(geometry_program != "" &&
617 !driver->queryFeature(video::EVDF_GEOMETRY_SHADER)){
618 infostream<<"generate_shader(): geometry shaders disabled "
619 "because of missing driver/hardware support."
621 geometry_program = "";
624 // If no shaders are used, don't make a separate material type
625 if(vertex_program == "" && pixel_program == "" && geometry_program == "")
628 // Create shaders header
629 std::string shaders_header = "#version 120\n";
631 static const char* drawTypes[] = {
638 "NDT_ALLFACES_OPTIONAL",
645 "NDT_GLASSLIKE_FRAMED",
647 "NDT_GLASSLIKE_FRAMED_OPTIONAL"
650 for (int i = 0; i < 14; i++){
651 shaders_header += "#define ";
652 shaders_header += drawTypes[i];
653 shaders_header += " ";
654 shaders_header += itos(i);
655 shaders_header += "\n";
658 static const char* materialTypes[] = {
659 "TILE_MATERIAL_BASIC",
660 "TILE_MATERIAL_ALPHA",
661 "TILE_MATERIAL_LIQUID_TRANSPARENT",
662 "TILE_MATERIAL_LIQUID_OPAQUE",
663 "TILE_MATERIAL_WAVING_LEAVES",
664 "TILE_MATERIAL_WAVING_PLANTS"
667 for (int i = 0; i < 6; i++){
668 shaders_header += "#define ";
669 shaders_header += materialTypes[i];
670 shaders_header += " ";
671 shaders_header += itos(i);
672 shaders_header += "\n";
675 shaders_header += "#define MATERIAL_TYPE ";
676 shaders_header += itos(material_type);
677 shaders_header += "\n";
678 shaders_header += "#define DRAW_TYPE ";
679 shaders_header += itos(drawtype);
680 shaders_header += "\n";
682 if (g_settings->getBool("generate_normalmaps")) {
683 shaders_header += "#define GENERATE_NORMALMAPS 1\n";
685 shaders_header += "#define GENERATE_NORMALMAPS 0\n";
687 shaders_header += "#define NORMALMAPS_STRENGTH ";
688 shaders_header += ftos(g_settings->getFloat("normalmaps_strength"));
689 shaders_header += "\n";
691 int smooth = (int)g_settings->getFloat("normalmaps_smooth");
694 sample_step = 0.0078125; // 1.0 / 128.0
697 sample_step = 0.00390625; // 1.0 / 256.0
700 sample_step = 0.001953125; // 1.0 / 512.0
703 sample_step = 0.0078125;
706 shaders_header += "#define SAMPLE_STEP ";
707 shaders_header += ftos(sample_step);
708 shaders_header += "\n";
710 if (g_settings->getBool("enable_bumpmapping"))
711 shaders_header += "#define ENABLE_BUMPMAPPING\n";
713 if (g_settings->getBool("enable_parallax_occlusion")){
714 int mode = g_settings->getFloat("parallax_occlusion_mode");
715 float scale = g_settings->getFloat("parallax_occlusion_scale");
716 float bias = g_settings->getFloat("parallax_occlusion_bias");
717 int iterations = g_settings->getFloat("parallax_occlusion_iterations");
718 shaders_header += "#define ENABLE_PARALLAX_OCCLUSION\n";
719 shaders_header += "#define PARALLAX_OCCLUSION_MODE ";
720 shaders_header += itos(mode);
721 shaders_header += "\n";
722 shaders_header += "#define PARALLAX_OCCLUSION_SCALE ";
723 shaders_header += ftos(scale);
724 shaders_header += "\n";
725 shaders_header += "#define PARALLAX_OCCLUSION_BIAS ";
726 shaders_header += ftos(bias);
727 shaders_header += "\n";
728 shaders_header += "#define PARALLAX_OCCLUSION_ITERATIONS ";
729 shaders_header += itos(iterations);
730 shaders_header += "\n";
733 shaders_header += "#define USE_NORMALMAPS ";
734 if (g_settings->getBool("enable_bumpmapping") || g_settings->getBool("enable_parallax_occlusion"))
735 shaders_header += "1\n";
737 shaders_header += "0\n";
739 if (g_settings->getBool("enable_waving_water")){
740 shaders_header += "#define ENABLE_WAVING_WATER 1\n";
741 shaders_header += "#define WATER_WAVE_HEIGHT ";
742 shaders_header += ftos(g_settings->getFloat("water_wave_height"));
743 shaders_header += "\n";
744 shaders_header += "#define WATER_WAVE_LENGTH ";
745 shaders_header += ftos(g_settings->getFloat("water_wave_length"));
746 shaders_header += "\n";
747 shaders_header += "#define WATER_WAVE_SPEED ";
748 shaders_header += ftos(g_settings->getFloat("water_wave_speed"));
749 shaders_header += "\n";
751 shaders_header += "#define ENABLE_WAVING_WATER 0\n";
754 shaders_header += "#define ENABLE_WAVING_LEAVES ";
755 if (g_settings->getBool("enable_waving_leaves"))
756 shaders_header += "1\n";
758 shaders_header += "0\n";
760 shaders_header += "#define ENABLE_WAVING_PLANTS ";
761 if (g_settings->getBool("enable_waving_plants"))
762 shaders_header += "1\n";
764 shaders_header += "0\n";
766 if (g_settings->getBool("tone_mapping"))
767 shaders_header += "#define ENABLE_TONE_MAPPING\n";
769 // Call addHighLevelShaderMaterial() or addShaderMaterial()
770 const c8* vertex_program_ptr = 0;
771 const c8* pixel_program_ptr = 0;
772 const c8* geometry_program_ptr = 0;
773 if (!vertex_program.empty()) {
774 vertex_program = shaders_header + vertex_program;
775 vertex_program_ptr = vertex_program.c_str();
777 if (!pixel_program.empty()) {
778 pixel_program = shaders_header + pixel_program;
779 pixel_program_ptr = pixel_program.c_str();
781 if (!geometry_program.empty()) {
782 geometry_program = shaders_header + geometry_program;
783 geometry_program_ptr = geometry_program.c_str();
787 infostream<<"Compiling high level shaders for "<<name<<std::endl;
788 shadermat = gpu->addHighLevelShaderMaterial(
789 vertex_program_ptr, // Vertex shader program
790 "vertexMain", // Vertex shader entry point
791 video::EVST_VS_1_1, // Vertex shader version
792 pixel_program_ptr, // Pixel shader program
793 "pixelMain", // Pixel shader entry point
794 video::EPST_PS_1_2, // Pixel shader version
795 geometry_program_ptr, // Geometry shader program
796 "geometryMain", // Geometry shader entry point
797 video::EGST_GS_4_0, // Geometry shader version
798 scene::EPT_TRIANGLES, // Geometry shader input
799 scene::EPT_TRIANGLE_STRIP, // Geometry shader output
800 0, // Support maximum number of vertices
801 callback, // Set-constant callback
802 shaderinfo.base_material, // Base material
803 1 // Userdata passed to callback
806 errorstream<<"generate_shader(): "
807 "failed to generate \""<<name<<"\", "
808 "addHighLevelShaderMaterial failed."
810 dumpShaderProgram(warningstream, "Vertex", vertex_program);
811 dumpShaderProgram(warningstream, "Pixel", pixel_program);
812 dumpShaderProgram(warningstream, "Geometry", geometry_program);
817 infostream<<"Compiling assembly shaders for "<<name<<std::endl;
818 shadermat = gpu->addShaderMaterial(
819 vertex_program_ptr, // Vertex shader program
820 pixel_program_ptr, // Pixel shader program
821 callback, // Set-constant callback
822 shaderinfo.base_material, // Base material
823 0 // Userdata passed to callback
827 errorstream<<"generate_shader(): "
828 "failed to generate \""<<name<<"\", "
829 "addShaderMaterial failed."
831 dumpShaderProgram(warningstream, "Vertex", vertex_program);
832 dumpShaderProgram(warningstream,"Pixel", pixel_program);
837 // HACK, TODO: investigate this better
838 // Grab the material renderer once more so minetest doesn't crash on exit
839 driver->getMaterialRenderer(shadermat)->grab();
841 // Apply the newly created material type
842 shaderinfo.material = (video::E_MATERIAL_TYPE) shadermat;
846 void load_shaders(std::string name, SourceShaderCache *sourcecache,
847 video::E_DRIVER_TYPE drivertype, bool enable_shaders,
848 std::string &vertex_program, std::string &pixel_program,
849 std::string &geometry_program, bool &is_highlevel)
853 geometry_program = "";
854 is_highlevel = false;
857 // Look for high level shaders
858 if(drivertype == video::EDT_DIRECT3D9){
860 // (All shaders in one file)
861 vertex_program = sourcecache->getOrLoad(name, "d3d9.hlsl");
862 pixel_program = vertex_program;
863 geometry_program = vertex_program;
865 else if(drivertype == video::EDT_OPENGL){
867 vertex_program = sourcecache->getOrLoad(name, "opengl_vertex.glsl");
868 pixel_program = sourcecache->getOrLoad(name, "opengl_fragment.glsl");
869 geometry_program = sourcecache->getOrLoad(name, "opengl_geometry.glsl");
871 if(vertex_program != "" || pixel_program != "" || geometry_program != ""){
879 void dumpShaderProgram(std::ostream &output_stream,
880 const std::string &program_type, const std::string &program)
882 output_stream << program_type << " shader program:" << std::endl <<
883 "----------------------------------" << std::endl;
887 while ((pos = program.find("\n", prev)) != std::string::npos) {
888 output_stream << line++ << ": "<< program.substr(prev, pos - prev) <<
892 output_stream << line << ": " << program.substr(prev) << std::endl <<
893 "End of " << program_type << " shader program." << std::endl <<