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 "strfnd.h" // trim()
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;
59 std::string fullpath = "";
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");
73 std::string testpath = shader_path + DIR_DELIM + combined;
74 if(fs::PathExists(testpath))
79 Check from default data directory
83 std::string rel_path = std::string("client") + DIR_DELIM
84 + "shaders" + DIR_DELIM
85 + name_of_shader + DIR_DELIM
87 std::string testpath = porting::path_share + DIR_DELIM + rel_path;
88 if(fs::PathExists(testpath))
92 // Add to cache (also an empty result is cached)
93 g_shadername_to_path_cache.set(combined, fullpath);
100 SourceShaderCache: A cache used for storing source shaders.
103 class SourceShaderCache
106 void insert(const std::string &name_of_shader, const std::string &filename,
107 const std::string &program, bool prefer_local)
109 std::string combined = name_of_shader + DIR_DELIM + filename;
110 // Try to use local shader instead if asked to
112 std::string path = getShaderPath(name_of_shader, filename);
114 std::string p = readFile(path);
116 m_programs[combined] = p;
121 m_programs[combined] = program;
124 std::string get(const std::string &name_of_shader,
125 const std::string &filename)
127 std::string combined = name_of_shader + DIR_DELIM + filename;
128 StringMap::iterator n = m_programs.find(combined);
129 if (n != m_programs.end())
134 // Primarily fetches from cache, secondarily tries to read from filesystem
135 std::string getOrLoad(const std::string &name_of_shader,
136 const std::string &filename)
138 std::string combined = name_of_shader + DIR_DELIM + filename;
139 StringMap::iterator n = m_programs.find(combined);
140 if (n != m_programs.end())
142 std::string path = getShaderPath(name_of_shader, filename);
144 infostream << "SourceShaderCache::getOrLoad(): No path found for \""
145 << combined << "\"" << std::endl;
148 infostream << "SourceShaderCache::getOrLoad(): Loading path \""
149 << path << "\"" << std::endl;
150 std::string p = readFile(path);
152 m_programs[combined] = p;
158 StringMap m_programs;
160 std::string readFile(const std::string &path)
162 std::ifstream is(path.c_str(), std::ios::binary);
165 std::ostringstream tmp_os;
166 tmp_os << is.rdbuf();
172 ShaderCallback: Sets constants that can be used in shaders
175 class IShaderConstantSetterRegistry
178 virtual ~IShaderConstantSetterRegistry(){};
179 virtual void onSetConstants(video::IMaterialRendererServices *services,
180 bool is_highlevel, const std::string &name) = 0;
183 class ShaderCallback : public video::IShaderConstantSetCallBack
185 IShaderConstantSetterRegistry *m_scsr;
189 ShaderCallback(IShaderConstantSetterRegistry *scsr, const std::string &name):
195 virtual void OnSetConstants(video::IMaterialRendererServices *services, s32 userData)
197 video::IVideoDriver *driver = services->getVideoDriver();
198 sanity_check(driver != NULL);
200 bool is_highlevel = userData;
202 m_scsr->onSetConstants(services, is_highlevel, m_name);
207 MainShaderConstantSetter: Set basic constants required for almost everything
210 class MainShaderConstantSetter : public IShaderConstantSetter
213 MainShaderConstantSetter(IrrlichtDevice *device)
215 ~MainShaderConstantSetter() {}
217 virtual void onSetConstants(video::IMaterialRendererServices *services,
220 video::IVideoDriver *driver = services->getVideoDriver();
221 sanity_check(driver);
223 // set inverted world matrix
224 core::matrix4 invWorld = driver->getTransform(video::ETS_WORLD);
225 invWorld.makeInverse();
227 services->setVertexShaderConstant("mInvWorld", invWorld.pointer(), 16);
229 services->setVertexShaderConstant(invWorld.pointer(), 0, 4);
232 core::matrix4 worldViewProj;
233 worldViewProj = driver->getTransform(video::ETS_PROJECTION);
234 worldViewProj *= driver->getTransform(video::ETS_VIEW);
235 worldViewProj *= driver->getTransform(video::ETS_WORLD);
237 services->setVertexShaderConstant("mWorldViewProj", worldViewProj.pointer(), 16);
239 services->setVertexShaderConstant(worldViewProj.pointer(), 4, 4);
241 // set transposed world matrix
242 core::matrix4 transWorld = driver->getTransform(video::ETS_WORLD);
243 transWorld = transWorld.getTransposed();
245 services->setVertexShaderConstant("mTransWorld", transWorld.pointer(), 16);
247 services->setVertexShaderConstant(transWorld.pointer(), 8, 4);
250 core::matrix4 world = driver->getTransform(video::ETS_WORLD);
252 services->setVertexShaderConstant("mWorld", world.pointer(), 16);
254 services->setVertexShaderConstant(world.pointer(), 8, 4);
263 class ShaderSource : public IWritableShaderSource, public IShaderConstantSetterRegistry
266 ShaderSource(IrrlichtDevice *device);
270 - If shader material specified by name is found from cache,
271 return the cached id.
272 - Otherwise generate the shader material, add to cache and return id.
274 The id 0 points to a null shader. Its material is EMT_SOLID.
276 u32 getShaderIdDirect(const std::string &name,
277 const u8 material_type, const u8 drawtype);
280 If shader specified by the name pointed by the id doesn't
281 exist, create it, then return id.
283 Can be called from any thread. If called from some other thread
284 and not found in cache, the call is queued to the main thread
288 u32 getShader(const std::string &name,
289 const u8 material_type, const u8 drawtype);
291 ShaderInfo getShaderInfo(u32 id);
293 // Processes queued shader requests from other threads.
294 // Shall be called from the main thread.
297 // Insert a shader program into the cache without touching the
298 // filesystem. Shall be called from the main thread.
299 void insertSourceShader(const std::string &name_of_shader,
300 const std::string &filename, const std::string &program);
302 // Rebuild shaders from the current set of source shaders
303 // Shall be called from the main thread.
304 void rebuildShaders();
306 void addGlobalConstantSetter(IShaderConstantSetter *setter)
308 m_global_setters.push_back(setter);
311 void onSetConstants(video::IMaterialRendererServices *services,
312 bool is_highlevel, const std::string &name);
316 // The id of the thread that is allowed to use irrlicht directly
317 threadid_t m_main_thread;
318 // The irrlicht device
319 IrrlichtDevice *m_device;
320 // The set-constants callback
321 ShaderCallback *m_shader_callback;
323 // Cache of source shaders
324 // This should be only accessed from the main thread
325 SourceShaderCache m_sourcecache;
327 // A shader id is index in this array.
328 // The first position contains a dummy shader.
329 std::vector<ShaderInfo> m_shaderinfo_cache;
330 // The former container is behind this mutex
331 Mutex m_shaderinfo_cache_mutex;
333 // Queued shader fetches (to be processed by the main thread)
334 RequestQueue<std::string, u32, u8, u8> m_get_shader_queue;
336 // Global constant setters
337 // TODO: Delete these in the destructor
338 std::vector<IShaderConstantSetter*> m_global_setters;
341 IWritableShaderSource* createShaderSource(IrrlichtDevice *device)
343 return new ShaderSource(device);
347 Generate shader given the shader name.
349 ShaderInfo generate_shader(std::string name,
350 u8 material_type, u8 drawtype,
351 IrrlichtDevice *device,
352 video::IShaderConstantSetCallBack *callback,
353 SourceShaderCache *sourcecache);
358 void load_shaders(std::string name, SourceShaderCache *sourcecache,
359 video::E_DRIVER_TYPE drivertype, bool enable_shaders,
360 std::string &vertex_program, std::string &pixel_program,
361 std::string &geometry_program, bool &is_highlevel);
363 ShaderSource::ShaderSource(IrrlichtDevice *device):
366 assert(m_device); // Pre-condition
368 m_shader_callback = new ShaderCallback(this, "default");
370 m_main_thread = get_current_thread_id();
372 // Add a dummy ShaderInfo as the first index, named ""
373 m_shaderinfo_cache.push_back(ShaderInfo());
375 // Add main global constant setter
376 addGlobalConstantSetter(new MainShaderConstantSetter(device));
379 ShaderSource::~ShaderSource()
381 for (std::vector<IShaderConstantSetter*>::iterator iter = m_global_setters.begin();
382 iter != m_global_setters.end(); iter++) {
385 m_global_setters.clear();
387 if (m_shader_callback) {
388 m_shader_callback->drop();
389 m_shader_callback = NULL;
393 u32 ShaderSource::getShader(const std::string &name,
394 const u8 material_type, const u8 drawtype)
400 if(get_current_thread_id() == m_main_thread){
401 return getShaderIdDirect(name, material_type, drawtype);
403 /*errorstream<<"getShader(): Queued: name=\""<<name<<"\""<<std::endl;*/
405 // We're gonna ask the result to be put into here
407 static ResultQueue<std::string, u32, u8, u8> result_queue;
409 // Throw a request in
410 m_get_shader_queue.add(name, 0, 0, &result_queue);
412 /* infostream<<"Waiting for shader from main thread, name=\""
413 <<name<<"\""<<std::endl;*/
416 GetResult<std::string, u32, u8, u8>
417 result = result_queue.pop_frontNoEx();
419 if (result.key == name) {
423 errorstream << "Got shader with invalid name: " << result.key << std::endl;
429 infostream<<"getShader(): Failed"<<std::endl;
435 This method generates all the shaders
437 u32 ShaderSource::getShaderIdDirect(const std::string &name,
438 const u8 material_type, const u8 drawtype)
440 //infostream<<"getShaderIdDirect(): name=\""<<name<<"\""<<std::endl;
442 // Empty name means shader 0
444 infostream<<"getShaderIdDirect(): name is empty"<<std::endl;
448 // Check if already have such instance
449 for(u32 i=0; i<m_shaderinfo_cache.size(); i++){
450 ShaderInfo *info = &m_shaderinfo_cache[i];
451 if(info->name == name && info->material_type == material_type &&
452 info->drawtype == drawtype)
457 Calling only allowed from main thread
459 if(get_current_thread_id() != m_main_thread){
460 errorstream<<"ShaderSource::getShaderIdDirect() "
461 "called not from main thread"<<std::endl;
465 ShaderInfo info = generate_shader(name, material_type, drawtype, m_device,
466 m_shader_callback, &m_sourcecache);
469 Add shader to caches (add dummy shaders too)
472 MutexAutoLock lock(m_shaderinfo_cache_mutex);
474 u32 id = m_shaderinfo_cache.size();
475 m_shaderinfo_cache.push_back(info);
477 infostream<<"getShaderIdDirect(): "
478 <<"Returning id="<<id<<" for name \""<<name<<"\""<<std::endl;
484 ShaderInfo ShaderSource::getShaderInfo(u32 id)
486 MutexAutoLock lock(m_shaderinfo_cache_mutex);
488 if(id >= m_shaderinfo_cache.size())
491 return m_shaderinfo_cache[id];
494 void ShaderSource::processQueue()
500 void ShaderSource::insertSourceShader(const std::string &name_of_shader,
501 const std::string &filename, const std::string &program)
503 /*infostream<<"ShaderSource::insertSourceShader(): "
504 "name_of_shader=\""<<name_of_shader<<"\", "
505 "filename=\""<<filename<<"\""<<std::endl;*/
507 sanity_check(get_current_thread_id() == m_main_thread);
509 m_sourcecache.insert(name_of_shader, filename, program, true);
512 void ShaderSource::rebuildShaders()
514 MutexAutoLock lock(m_shaderinfo_cache_mutex);
516 /*// Oh well... just clear everything, they'll load sometime.
517 m_shaderinfo_cache.clear();
518 m_name_to_id.clear();*/
521 FIXME: Old shader materials can't be deleted in Irrlicht,
523 (This would be nice to do in the destructor too)
527 for(u32 i=0; i<m_shaderinfo_cache.size(); i++){
528 ShaderInfo *info = &m_shaderinfo_cache[i];
529 if(info->name != ""){
530 *info = generate_shader(info->name, info->material_type,
531 info->drawtype, m_device, m_shader_callback, &m_sourcecache);
536 void ShaderSource::onSetConstants(video::IMaterialRendererServices *services,
537 bool is_highlevel, const std::string &name)
539 for(u32 i=0; i<m_global_setters.size(); i++){
540 IShaderConstantSetter *setter = m_global_setters[i];
541 setter->onSetConstants(services, is_highlevel);
545 ShaderInfo generate_shader(std::string name, u8 material_type, u8 drawtype,
546 IrrlichtDevice *device, video::IShaderConstantSetCallBack *callback,
547 SourceShaderCache *sourcecache)
549 ShaderInfo shaderinfo;
550 shaderinfo.name = name;
551 shaderinfo.material_type = material_type;
552 shaderinfo.drawtype = drawtype;
553 shaderinfo.material = video::EMT_SOLID;
554 switch(material_type){
555 case TILE_MATERIAL_BASIC:
556 shaderinfo.base_material = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
558 case TILE_MATERIAL_ALPHA:
559 shaderinfo.base_material = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
561 case TILE_MATERIAL_LIQUID_TRANSPARENT:
562 shaderinfo.base_material = video::EMT_TRANSPARENT_VERTEX_ALPHA;
564 case TILE_MATERIAL_LIQUID_OPAQUE:
565 shaderinfo.base_material = video::EMT_SOLID;
567 case TILE_MATERIAL_WAVING_LEAVES:
568 shaderinfo.base_material = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
570 case TILE_MATERIAL_WAVING_PLANTS:
571 shaderinfo.base_material = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
575 bool enable_shaders = g_settings->getBool("enable_shaders");
579 video::IVideoDriver* driver = device->getVideoDriver();
580 sanity_check(driver);
582 video::IGPUProgrammingServices *gpu = driver->getGPUProgrammingServices();
584 errorstream<<"generate_shader(): "
585 "failed to generate \""<<name<<"\", "
586 "GPU programming not supported."
591 // Choose shader language depending on driver type and settings
593 std::string vertex_program;
594 std::string pixel_program;
595 std::string geometry_program;
597 load_shaders(name, sourcecache, driver->getDriverType(),
598 enable_shaders, vertex_program, pixel_program,
599 geometry_program, is_highlevel);
600 // Check hardware/driver support
601 if(vertex_program != "" &&
602 !driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1) &&
603 !driver->queryFeature(video::EVDF_ARB_VERTEX_PROGRAM_1)){
604 infostream<<"generate_shader(): vertex shaders disabled "
605 "because of missing driver/hardware support."
609 if(pixel_program != "" &&
610 !driver->queryFeature(video::EVDF_PIXEL_SHADER_1_1) &&
611 !driver->queryFeature(video::EVDF_ARB_FRAGMENT_PROGRAM_1)){
612 infostream<<"generate_shader(): pixel shaders disabled "
613 "because of missing driver/hardware support."
617 if(geometry_program != "" &&
618 !driver->queryFeature(video::EVDF_GEOMETRY_SHADER)){
619 infostream<<"generate_shader(): geometry shaders disabled "
620 "because of missing driver/hardware support."
622 geometry_program = "";
625 // If no shaders are used, don't make a separate material type
626 if(vertex_program == "" && pixel_program == "" && geometry_program == "")
629 // Create shaders header
630 std::string shaders_header = "#version 120\n";
632 static const char* drawTypes[] = {
639 "NDT_ALLFACES_OPTIONAL",
646 "NDT_GLASSLIKE_FRAMED",
648 "NDT_GLASSLIKE_FRAMED_OPTIONAL"
651 for (int i = 0; i < 14; i++){
652 shaders_header += "#define ";
653 shaders_header += drawTypes[i];
654 shaders_header += " ";
655 shaders_header += itos(i);
656 shaders_header += "\n";
659 static const char* materialTypes[] = {
660 "TILE_MATERIAL_BASIC",
661 "TILE_MATERIAL_ALPHA",
662 "TILE_MATERIAL_LIQUID_TRANSPARENT",
663 "TILE_MATERIAL_LIQUID_OPAQUE",
664 "TILE_MATERIAL_WAVING_LEAVES",
665 "TILE_MATERIAL_WAVING_PLANTS"
668 for (int i = 0; i < 6; i++){
669 shaders_header += "#define ";
670 shaders_header += materialTypes[i];
671 shaders_header += " ";
672 shaders_header += itos(i);
673 shaders_header += "\n";
676 shaders_header += "#define MATERIAL_TYPE ";
677 shaders_header += itos(material_type);
678 shaders_header += "\n";
679 shaders_header += "#define DRAW_TYPE ";
680 shaders_header += itos(drawtype);
681 shaders_header += "\n";
683 if (g_settings->getBool("generate_normalmaps")) {
684 shaders_header += "#define GENERATE_NORMALMAPS 1\n";
686 shaders_header += "#define GENERATE_NORMALMAPS 0\n";
688 shaders_header += "#define NORMALMAPS_STRENGTH ";
689 shaders_header += ftos(g_settings->getFloat("normalmaps_strength"));
690 shaders_header += "\n";
692 int smooth = (int)g_settings->getFloat("normalmaps_smooth");
695 sample_step = 0.0078125; // 1.0 / 128.0
698 sample_step = 0.00390625; // 1.0 / 256.0
701 sample_step = 0.001953125; // 1.0 / 512.0
704 sample_step = 0.0078125;
707 shaders_header += "#define SAMPLE_STEP ";
708 shaders_header += ftos(sample_step);
709 shaders_header += "\n";
711 if (g_settings->getBool("enable_bumpmapping"))
712 shaders_header += "#define ENABLE_BUMPMAPPING\n";
714 if (g_settings->getBool("enable_parallax_occlusion")){
715 int mode = g_settings->getFloat("parallax_occlusion_mode");
716 float scale = g_settings->getFloat("parallax_occlusion_scale");
717 float bias = g_settings->getFloat("parallax_occlusion_bias");
718 int iterations = g_settings->getFloat("parallax_occlusion_iterations");
719 shaders_header += "#define ENABLE_PARALLAX_OCCLUSION\n";
720 shaders_header += "#define PARALLAX_OCCLUSION_MODE ";
721 shaders_header += itos(mode);
722 shaders_header += "\n";
723 shaders_header += "#define PARALLAX_OCCLUSION_SCALE ";
724 shaders_header += ftos(scale);
725 shaders_header += "\n";
726 shaders_header += "#define PARALLAX_OCCLUSION_BIAS ";
727 shaders_header += ftos(bias);
728 shaders_header += "\n";
729 shaders_header += "#define PARALLAX_OCCLUSION_ITERATIONS ";
730 shaders_header += itos(iterations);
731 shaders_header += "\n";
734 shaders_header += "#define USE_NORMALMAPS ";
735 if (g_settings->getBool("enable_bumpmapping") || g_settings->getBool("enable_parallax_occlusion"))
736 shaders_header += "1\n";
738 shaders_header += "0\n";
740 if (g_settings->getBool("enable_waving_water")){
741 shaders_header += "#define ENABLE_WAVING_WATER 1\n";
742 shaders_header += "#define WATER_WAVE_HEIGHT ";
743 shaders_header += ftos(g_settings->getFloat("water_wave_height"));
744 shaders_header += "\n";
745 shaders_header += "#define WATER_WAVE_LENGTH ";
746 shaders_header += ftos(g_settings->getFloat("water_wave_length"));
747 shaders_header += "\n";
748 shaders_header += "#define WATER_WAVE_SPEED ";
749 shaders_header += ftos(g_settings->getFloat("water_wave_speed"));
750 shaders_header += "\n";
752 shaders_header += "#define ENABLE_WAVING_WATER 0\n";
755 shaders_header += "#define ENABLE_WAVING_LEAVES ";
756 if (g_settings->getBool("enable_waving_leaves"))
757 shaders_header += "1\n";
759 shaders_header += "0\n";
761 shaders_header += "#define ENABLE_WAVING_PLANTS ";
762 if (g_settings->getBool("enable_waving_plants"))
763 shaders_header += "1\n";
765 shaders_header += "0\n";
767 if(pixel_program != "")
768 pixel_program = shaders_header + pixel_program;
769 if(vertex_program != "")
770 vertex_program = shaders_header + vertex_program;
771 if(geometry_program != "")
772 geometry_program = shaders_header + geometry_program;
773 // Call addHighLevelShaderMaterial() or addShaderMaterial()
774 const c8* vertex_program_ptr = 0;
775 const c8* pixel_program_ptr = 0;
776 const c8* geometry_program_ptr = 0;
777 if(vertex_program != "")
778 vertex_program_ptr = vertex_program.c_str();
779 if(pixel_program != "")
780 pixel_program_ptr = pixel_program.c_str();
781 if(geometry_program != "")
782 geometry_program_ptr = geometry_program.c_str();
785 infostream<<"Compiling high level shaders for "<<name<<std::endl;
786 shadermat = gpu->addHighLevelShaderMaterial(
787 vertex_program_ptr, // Vertex shader program
788 "vertexMain", // Vertex shader entry point
789 video::EVST_VS_1_1, // Vertex shader version
790 pixel_program_ptr, // Pixel shader program
791 "pixelMain", // Pixel shader entry point
792 video::EPST_PS_1_1, // Pixel shader version
793 geometry_program_ptr, // Geometry shader program
794 "geometryMain", // Geometry shader entry point
795 video::EGST_GS_4_0, // Geometry shader version
796 scene::EPT_TRIANGLES, // Geometry shader input
797 scene::EPT_TRIANGLE_STRIP, // Geometry shader output
798 0, // Support maximum number of vertices
799 callback, // Set-constant callback
800 shaderinfo.base_material, // Base material
801 1 // Userdata passed to callback
804 errorstream<<"generate_shader(): "
805 "failed to generate \""<<name<<"\", "
806 "addHighLevelShaderMaterial failed."
812 infostream<<"Compiling assembly shaders for "<<name<<std::endl;
813 shadermat = gpu->addShaderMaterial(
814 vertex_program_ptr, // Vertex shader program
815 pixel_program_ptr, // Pixel shader program
816 callback, // Set-constant callback
817 shaderinfo.base_material, // Base material
818 0 // Userdata passed to callback
822 errorstream<<"generate_shader(): "
823 "failed to generate \""<<name<<"\", "
824 "addShaderMaterial failed."
830 // HACK, TODO: investigate this better
831 // Grab the material renderer once more so minetest doesn't crash on exit
832 driver->getMaterialRenderer(shadermat)->grab();
834 // Apply the newly created material type
835 shaderinfo.material = (video::E_MATERIAL_TYPE) shadermat;
839 void load_shaders(std::string name, SourceShaderCache *sourcecache,
840 video::E_DRIVER_TYPE drivertype, bool enable_shaders,
841 std::string &vertex_program, std::string &pixel_program,
842 std::string &geometry_program, bool &is_highlevel)
846 geometry_program = "";
847 is_highlevel = false;
850 // Look for high level shaders
851 if(drivertype == video::EDT_DIRECT3D9){
853 // (All shaders in one file)
854 vertex_program = sourcecache->getOrLoad(name, "d3d9.hlsl");
855 pixel_program = vertex_program;
856 geometry_program = vertex_program;
858 else if(drivertype == video::EDT_OPENGL){
860 vertex_program = sourcecache->getOrLoad(name, "opengl_vertex.glsl");
861 pixel_program = sourcecache->getOrLoad(name, "opengl_fragment.glsl");
862 geometry_program = sourcecache->getOrLoad(name, "opengl_geometry.glsl");
864 if(vertex_program != "" || pixel_program != "" || geometry_program != ""){