]> git.lizzy.rs Git - minetest.git/blob - src/shader.cpp
Copy zlib and freetype dll to windows package too
[minetest.git] / src / shader.cpp
1 /*
2 Minetest
3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4 Copyright (C) 2013 Kahrl <kahrl@gmx.net>
5
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.
10
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.
15
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.
19 */
20
21 #include "shader.h"
22 #include "irrlichttypes_extrabloated.h"
23 #include "debug.h"
24 #include "main.h" // for g_settings
25 #include "filesys.h"
26 #include "util/container.h"
27 #include "util/thread.h"
28 #include "settings.h"
29 #include <iterator>
30 #include <ICameraSceneNode.h>
31 #include <IGPUProgrammingServices.h>
32 #include <IMaterialRenderer.h>
33 #include <IMaterialRendererServices.h>
34 #include <IShaderConstantSetCallBack.h>
35 #include "EShaderTypes.h"
36 #include "log.h"
37 #include "gamedef.h"
38 #include "strfnd.h" // trim()
39 #include "tile.h"
40
41 /*
42         A cache from shader name to shader path
43 */
44 MutexedMap<std::string, std::string> g_shadername_to_path_cache;
45
46 /*
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.
50
51         If not found, returns "".
52
53         Utilizes a thread-safe cache.
54 */
55 std::string getShaderPath(const std::string &name_of_shader,
56                 const std::string &filename)
57 {
58         std::string combined = name_of_shader + DIR_DELIM + filename;
59         std::string fullpath = "";
60         /*
61                 Check from cache
62         */
63         bool incache = g_shadername_to_path_cache.get(combined, &fullpath);
64         if(incache)
65                 return fullpath;
66
67         /*
68                 Check from shader_path
69         */
70         std::string shader_path = g_settings->get("shader_path");
71         if(shader_path != "")
72         {
73                 std::string testpath = shader_path + DIR_DELIM + combined;
74                 if(fs::PathExists(testpath))
75                         fullpath = testpath;
76         }
77
78         /*
79                 Check from default data directory
80         */
81         if(fullpath == "")
82         {
83                 std::string rel_path = std::string("client") + DIR_DELIM
84                                 + "shaders" + DIR_DELIM
85                                 + name_of_shader + DIR_DELIM
86                                 + filename;
87                 std::string testpath = porting::path_share + DIR_DELIM + rel_path;
88                 if(fs::PathExists(testpath))
89                         fullpath = testpath;
90         }
91
92         // Add to cache (also an empty result is cached)
93         g_shadername_to_path_cache.set(combined, fullpath);
94
95         // Finally return it
96         return fullpath;
97 }
98
99 /*
100         SourceShaderCache: A cache used for storing source shaders.
101 */
102
103 class SourceShaderCache
104 {
105 public:
106         void insert(const std::string &name_of_shader,
107                         const std::string &filename,
108                         const std::string &program,
109                         bool prefer_local)
110         {
111                 std::string combined = name_of_shader + DIR_DELIM + filename;
112                 // Try to use local shader instead if asked to
113                 if(prefer_local){
114                         std::string path = getShaderPath(name_of_shader, filename);
115                         if(path != ""){
116                                 std::string p = readFile(path);
117                                 if(p != ""){
118                                         m_programs[combined] = p;
119                                         return;
120                                 }
121                         }
122                 }
123                 m_programs[combined] = program;
124         }
125         std::string get(const std::string &name_of_shader,
126                         const std::string &filename)
127         {
128                 std::string combined = name_of_shader + DIR_DELIM + filename;
129                 std::map<std::string, std::string>::iterator n;
130                 n = m_programs.find(combined);
131                 if(n != m_programs.end())
132                         return n->second;
133                 return "";
134         }
135         // Primarily fetches from cache, secondarily tries to read from filesystem
136         std::string getOrLoad(const std::string &name_of_shader,
137                         const std::string &filename)
138         {
139                 std::string combined = name_of_shader + DIR_DELIM + filename;
140                 std::map<std::string, std::string>::iterator n;
141                 n = m_programs.find(combined);
142                 if(n != m_programs.end())
143                         return n->second;
144                 std::string path = getShaderPath(name_of_shader, filename);
145                 if(path == ""){
146                         infostream<<"SourceShaderCache::getOrLoad(): No path found for \""
147                                         <<combined<<"\""<<std::endl;
148                         return "";
149                 }
150                 infostream<<"SourceShaderCache::getOrLoad(): Loading path \""<<path
151                                 <<"\""<<std::endl;
152                 std::string p = readFile(path);
153                 if(p != ""){
154                         m_programs[combined] = p;
155                         return p;
156                 }
157                 return "";
158         }
159 private:
160         std::map<std::string, std::string> m_programs;
161         std::string readFile(const std::string &path)
162         {
163                 std::ifstream is(path.c_str(), std::ios::binary);
164                 if(!is.is_open())
165                         return "";
166                 std::ostringstream tmp_os;
167                 tmp_os << is.rdbuf();
168                 return tmp_os.str();
169         }
170 };
171
172 /*
173         ShaderCallback: Sets constants that can be used in shaders
174 */
175
176 class IShaderConstantSetterRegistry
177 {
178 public:
179         virtual ~IShaderConstantSetterRegistry(){};
180         virtual void onSetConstants(video::IMaterialRendererServices *services,
181                         bool is_highlevel, const std::string &name) = 0;
182 };
183
184 class ShaderCallback : public video::IShaderConstantSetCallBack
185 {
186         IShaderConstantSetterRegistry *m_scsr;
187         std::string m_name;
188
189 public:
190         ShaderCallback(IShaderConstantSetterRegistry *scsr, const std::string &name):
191                 m_scsr(scsr),
192                 m_name(name)
193         {}
194         ~ShaderCallback() {}
195
196         virtual void OnSetConstants(video::IMaterialRendererServices *services, s32 userData)
197         {
198                 video::IVideoDriver *driver = services->getVideoDriver();
199                 assert(driver);
200
201                 bool is_highlevel = userData;
202
203                 m_scsr->onSetConstants(services, is_highlevel, m_name);
204         }
205 };
206
207 /*
208         MainShaderConstantSetter: Set basic constants required for almost everything
209 */
210
211 class MainShaderConstantSetter : public IShaderConstantSetter
212 {
213 public:
214         MainShaderConstantSetter(IrrlichtDevice *device):
215                 m_device(device)
216         {}
217         ~MainShaderConstantSetter() {}
218
219         virtual void onSetConstants(video::IMaterialRendererServices *services,
220                         bool is_highlevel)
221         {
222                 video::IVideoDriver *driver = services->getVideoDriver();
223                 assert(driver);
224
225                 // set inverted world matrix
226                 core::matrix4 invWorld = driver->getTransform(video::ETS_WORLD);
227                 invWorld.makeInverse();
228                 if(is_highlevel)
229                         services->setVertexShaderConstant("mInvWorld", invWorld.pointer(), 16);
230                 else
231                         services->setVertexShaderConstant(invWorld.pointer(), 0, 4);
232
233                 // set clip matrix
234                 core::matrix4 worldViewProj;
235                 worldViewProj = driver->getTransform(video::ETS_PROJECTION);
236                 worldViewProj *= driver->getTransform(video::ETS_VIEW);
237                 worldViewProj *= driver->getTransform(video::ETS_WORLD);
238                 if(is_highlevel)
239                         services->setVertexShaderConstant("mWorldViewProj", worldViewProj.pointer(), 16);
240                 else
241                         services->setVertexShaderConstant(worldViewProj.pointer(), 4, 4);
242
243                 // set transposed world matrix
244                 core::matrix4 transWorld = driver->getTransform(video::ETS_WORLD);
245                 transWorld = transWorld.getTransposed();
246                 if(is_highlevel)
247                         services->setVertexShaderConstant("mTransWorld", transWorld.pointer(), 16);
248                 else
249                         services->setVertexShaderConstant(transWorld.pointer(), 8, 4);
250
251                 // set world matrix
252                 core::matrix4 world = driver->getTransform(video::ETS_WORLD);
253                 if(is_highlevel)
254                         services->setVertexShaderConstant("mWorld", world.pointer(), 16);
255                 else
256                         services->setVertexShaderConstant(world.pointer(), 8, 4);
257
258         }
259
260 private:
261         IrrlichtDevice *m_device;
262 };
263
264 /*
265         ShaderSource
266 */
267
268 class ShaderSource : public IWritableShaderSource, public IShaderConstantSetterRegistry
269 {
270 public:
271         ShaderSource(IrrlichtDevice *device);
272         ~ShaderSource();
273
274         /*
275                 - If shader material specified by name is found from cache,
276                   return the cached id.
277                 - Otherwise generate the shader material, add to cache and return id.
278
279                 The id 0 points to a null shader. Its material is EMT_SOLID.
280         */
281         u32 getShaderIdDirect(const std::string &name, 
282                 const u8 material_type, const u8 drawtype);
283
284         /*
285                 If shader specified by the name pointed by the id doesn't
286                 exist, create it, then return id. 
287
288                 Can be called from any thread. If called from some other thread
289                 and not found in cache, the call is queued to the main thread
290                 for processing.
291         */
292         
293         u32 getShader(const std::string &name,
294                 const u8 material_type, const u8 drawtype);
295         
296         ShaderInfo getShaderInfo(u32 id);
297         
298         // Processes queued shader requests from other threads.
299         // Shall be called from the main thread.
300         void processQueue();
301
302         // Insert a shader program into the cache without touching the
303         // filesystem. Shall be called from the main thread.
304         void insertSourceShader(const std::string &name_of_shader,
305                 const std::string &filename, const std::string &program);
306
307         // Rebuild shaders from the current set of source shaders
308         // Shall be called from the main thread.
309         void rebuildShaders();
310
311         void addGlobalConstantSetter(IShaderConstantSetter *setter)
312         {
313                 m_global_setters.push_back(setter);
314         }
315
316         void onSetConstants(video::IMaterialRendererServices *services,
317                         bool is_highlevel, const std::string &name);
318
319 private:
320
321         // The id of the thread that is allowed to use irrlicht directly
322         threadid_t m_main_thread;
323         // The irrlicht device
324         IrrlichtDevice *m_device;
325         // The set-constants callback
326         ShaderCallback *m_shader_callback;
327
328         // Cache of source shaders
329         // This should be only accessed from the main thread
330         SourceShaderCache m_sourcecache;
331
332         // A shader id is index in this array.
333         // The first position contains a dummy shader.
334         std::vector<ShaderInfo> m_shaderinfo_cache;
335         // The former container is behind this mutex
336         JMutex m_shaderinfo_cache_mutex;
337
338         // Queued shader fetches (to be processed by the main thread)
339         RequestQueue<std::string, u32, u8, u8> m_get_shader_queue;
340
341         // Global constant setters
342         // TODO: Delete these in the destructor
343         std::vector<IShaderConstantSetter*> m_global_setters;
344 };
345
346 IWritableShaderSource* createShaderSource(IrrlichtDevice *device)
347 {
348         return new ShaderSource(device);
349 }
350
351 /*
352         Generate shader given the shader name.
353 */
354 ShaderInfo generate_shader(std::string name,
355                 u8 material_type, u8 drawtype,
356                 IrrlichtDevice *device,
357                 video::IShaderConstantSetCallBack *callback,
358                 SourceShaderCache *sourcecache);
359
360 /*
361         Load shader programs
362 */
363 void load_shaders(std::string name, SourceShaderCache *sourcecache,
364                 video::E_DRIVER_TYPE drivertype, bool enable_shaders,
365                 std::string &vertex_program, std::string &pixel_program,
366                 std::string &geometry_program, bool &is_highlevel);
367
368 ShaderSource::ShaderSource(IrrlichtDevice *device):
369                 m_device(device)
370 {
371         assert(m_device);
372
373         m_shader_callback = new ShaderCallback(this, "default");
374
375         m_main_thread = get_current_thread_id();
376
377         // Add a dummy ShaderInfo as the first index, named ""
378         m_shaderinfo_cache.push_back(ShaderInfo());
379
380         // Add main global constant setter
381         addGlobalConstantSetter(new MainShaderConstantSetter(device));
382 }
383
384 ShaderSource::~ShaderSource()
385 {
386         //m_shader_callback->drop();
387
388         for (std::vector<IShaderConstantSetter*>::iterator iter = m_global_setters.begin();
389                         iter != m_global_setters.end(); iter++) {
390                 delete *iter;
391         }
392         m_global_setters.clear();
393 }
394
395 u32 ShaderSource::getShader(const std::string &name, 
396                 const u8 material_type, const u8 drawtype)
397 {
398         /*
399                 Get shader
400         */
401
402         if(get_current_thread_id() == m_main_thread){
403                 return getShaderIdDirect(name, material_type, drawtype);
404         } else {
405                 /*errorstream<<"getShader(): Queued: name=\""<<name<<"\""<<std::endl;*/
406
407                 // We're gonna ask the result to be put into here
408
409                 static ResultQueue<std::string, u32, u8, u8> result_queue;
410
411                 // Throw a request in
412                 m_get_shader_queue.add(name, 0, 0, &result_queue);
413
414                 /* infostream<<"Waiting for shader from main thread, name=\""
415                                 <<name<<"\""<<std::endl;*/
416
417                 while(true) {
418                         GetResult<std::string, u32, u8, u8>
419                                 result = result_queue.pop_frontNoEx();
420
421                         if (result.key == name) {
422                                 return result.item;
423                         }
424                         else {
425                                 errorstream << "Got shader with invalid name: " << result.key << std::endl;
426                         }
427                 }
428
429         }
430
431         infostream<<"getShader(): Failed"<<std::endl;
432
433         return 0;
434 }
435
436 /*
437         This method generates all the shaders
438 */
439 u32 ShaderSource::getShaderIdDirect(const std::string &name, 
440                 const u8 material_type, const u8 drawtype)
441 {
442         //infostream<<"getShaderIdDirect(): name=\""<<name<<"\""<<std::endl;
443
444         // Empty name means shader 0
445         if(name == ""){
446                 infostream<<"getShaderIdDirect(): name is empty"<<std::endl;
447                 return 0;
448         }
449
450         // Check if already have such instance
451         for(u32 i=0; i<m_shaderinfo_cache.size(); i++){
452                 ShaderInfo *info = &m_shaderinfo_cache[i];
453                 if(info->name == name && info->material_type == material_type &&
454                         info->drawtype == drawtype)
455                         return i;
456         }
457
458         /*
459                 Calling only allowed from main thread
460         */
461         if(get_current_thread_id() != m_main_thread){
462                 errorstream<<"ShaderSource::getShaderIdDirect() "
463                                 "called not from main thread"<<std::endl;
464                 return 0;
465         }
466
467         ShaderInfo info = generate_shader(name, material_type, drawtype, m_device,
468                         m_shader_callback, &m_sourcecache);
469
470         /*
471                 Add shader to caches (add dummy shaders too)
472         */
473
474         JMutexAutoLock lock(m_shaderinfo_cache_mutex);
475
476         u32 id = m_shaderinfo_cache.size();
477         m_shaderinfo_cache.push_back(info);
478
479         infostream<<"getShaderIdDirect(): "
480                         <<"Returning id="<<id<<" for name \""<<name<<"\""<<std::endl;
481
482         return id;
483 }
484
485
486 ShaderInfo ShaderSource::getShaderInfo(u32 id)
487 {
488         JMutexAutoLock lock(m_shaderinfo_cache_mutex);
489
490         if(id >= m_shaderinfo_cache.size())
491                 return ShaderInfo();
492
493         return m_shaderinfo_cache[id];
494 }
495
496 void ShaderSource::processQueue()
497 {
498  
499
500 }
501
502 void ShaderSource::insertSourceShader(const std::string &name_of_shader,
503                 const std::string &filename, const std::string &program)
504 {
505         /*infostream<<"ShaderSource::insertSourceShader(): "
506                         "name_of_shader=\""<<name_of_shader<<"\", "
507                         "filename=\""<<filename<<"\""<<std::endl;*/
508
509         assert(get_current_thread_id() == m_main_thread);
510
511         m_sourcecache.insert(name_of_shader, filename, program, true);
512 }
513
514 void ShaderSource::rebuildShaders()
515 {
516         JMutexAutoLock lock(m_shaderinfo_cache_mutex);
517
518         /*// Oh well... just clear everything, they'll load sometime.
519         m_shaderinfo_cache.clear();
520         m_name_to_id.clear();*/
521
522         /*
523                 FIXME: Old shader materials can't be deleted in Irrlicht,
524                 or can they?
525                 (This would be nice to do in the destructor too)
526         */
527
528         // Recreate shaders
529         for(u32 i=0; i<m_shaderinfo_cache.size(); i++){
530                 ShaderInfo *info = &m_shaderinfo_cache[i];
531                 if(info->name != ""){
532                         *info = generate_shader(info->name, info->material_type,
533                                         info->drawtype, m_device, m_shader_callback, &m_sourcecache);
534                 }
535         }
536 }
537
538 void ShaderSource::onSetConstants(video::IMaterialRendererServices *services,
539                 bool is_highlevel, const std::string &name)
540 {
541         for(u32 i=0; i<m_global_setters.size(); i++){
542                 IShaderConstantSetter *setter = m_global_setters[i];
543                 setter->onSetConstants(services, is_highlevel);
544         }
545 }
546
547 ShaderInfo generate_shader(std::string name, u8 material_type, u8 drawtype,
548                 IrrlichtDevice *device, video::IShaderConstantSetCallBack *callback,
549                 SourceShaderCache *sourcecache)
550 {
551         ShaderInfo shaderinfo;
552         shaderinfo.name = name;
553         shaderinfo.material_type = material_type;
554         shaderinfo.drawtype = drawtype;
555         shaderinfo.material = video::EMT_SOLID;
556         switch(material_type){
557                 case TILE_MATERIAL_BASIC:
558                         shaderinfo.base_material = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
559                         break;
560                 case TILE_MATERIAL_ALPHA:
561                         shaderinfo.base_material = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
562                         break;
563                 case TILE_MATERIAL_LIQUID_TRANSPARENT:
564                         shaderinfo.base_material = video::EMT_TRANSPARENT_VERTEX_ALPHA;
565                         break;
566                 case TILE_MATERIAL_LIQUID_OPAQUE:
567                         shaderinfo.base_material = video::EMT_SOLID;
568                         break;
569                 case TILE_MATERIAL_WAVING_LEAVES:
570                         shaderinfo.base_material = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
571                         break;
572                 case TILE_MATERIAL_WAVING_PLANTS:
573                         shaderinfo.base_material = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
574                 break;
575         }
576         
577         bool enable_shaders = g_settings->getBool("enable_shaders");
578         if(!enable_shaders)
579                 return shaderinfo;
580
581         video::IVideoDriver* driver = device->getVideoDriver();
582         assert(driver);
583
584         video::IGPUProgrammingServices *gpu = driver->getGPUProgrammingServices();
585         if(!gpu){
586                 errorstream<<"generate_shader(): "
587                                 "failed to generate \""<<name<<"\", "
588                                 "GPU programming not supported."
589                                 <<std::endl;
590                 return shaderinfo;
591         }
592
593         // Choose shader language depending on driver type and settings
594         // Then load shaders
595         std::string vertex_program;
596         std::string pixel_program;
597         std::string geometry_program;
598         bool is_highlevel;
599         load_shaders(name, sourcecache, driver->getDriverType(),
600                         enable_shaders, vertex_program, pixel_program,
601                         geometry_program, is_highlevel);
602         // Check hardware/driver support
603         if(vertex_program != "" &&
604                         !driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1) &&
605                         !driver->queryFeature(video::EVDF_ARB_VERTEX_PROGRAM_1)){
606                 infostream<<"generate_shader(): vertex shaders disabled "
607                                 "because of missing driver/hardware support."
608                                 <<std::endl;
609                 vertex_program = "";
610         }
611         if(pixel_program != "" &&
612                         !driver->queryFeature(video::EVDF_PIXEL_SHADER_1_1) &&
613                         !driver->queryFeature(video::EVDF_ARB_FRAGMENT_PROGRAM_1)){
614                 infostream<<"generate_shader(): pixel shaders disabled "
615                                 "because of missing driver/hardware support."
616                                 <<std::endl;
617                 pixel_program = "";
618         }
619         if(geometry_program != "" &&
620                         !driver->queryFeature(video::EVDF_GEOMETRY_SHADER)){
621                 infostream<<"generate_shader(): geometry shaders disabled "
622                                 "because of missing driver/hardware support."
623                                 <<std::endl;
624                 geometry_program = "";
625         }
626
627         // If no shaders are used, don't make a separate material type
628         if(vertex_program == "" && pixel_program == "" && geometry_program == "")
629                 return shaderinfo;
630
631         // Create shaders header
632         std::string shaders_header = "#version 120\n";
633
634         static const char* drawTypes[] = {
635                 "NDT_NORMAL",
636                 "NDT_AIRLIKE",
637                 "NDT_LIQUID",
638                 "NDT_FLOWINGLIQUID",
639                 "NDT_GLASSLIKE",
640                 "NDT_ALLFACES",
641                 "NDT_ALLFACES_OPTIONAL",
642                 "NDT_TORCHLIKE",
643                 "NDT_SIGNLIKE",
644                 "NDT_PLANTLIKE",
645                 "NDT_FENCELIKE",
646                 "NDT_RAILLIKE",
647                 "NDT_NODEBOX",
648                 "NDT_GLASSLIKE_FRAMED"
649         };
650         
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";
657         }
658
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"
666         };
667
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";
674         }
675
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";
682
683         if (g_settings->getBool("generate_normalmaps")){
684                 shaders_header += "#define GENERATE_NORMALMAPS\n";
685                 shaders_header += "#define NORMALMAPS_STRENGTH ";
686                 shaders_header += ftos(g_settings->getFloat("normalmaps_strength"));
687                 shaders_header += "\n";
688                 float sample_step;
689                 int smooth = (int)g_settings->getFloat("normalmaps_smooth");
690                 switch (smooth){
691                 case 0:
692                         sample_step = 0.0078125; // 1.0 / 128.0
693                         break;
694                 case 1:
695                         sample_step = 0.00390625; // 1.0 / 256.0
696                         break;
697                 case 2:
698                         sample_step = 0.001953125; // 1.0 / 512.0
699                         break;
700                 default:
701                         sample_step = 0.0078125;
702                         break;
703                 }
704                 shaders_header += "#define SAMPLE_STEP ";
705                 shaders_header += ftos(sample_step);
706                 shaders_header += "\n";
707         }
708
709         if (g_settings->getBool("enable_bumpmapping"))
710                 shaders_header += "#define ENABLE_BUMPMAPPING\n";
711
712         if (g_settings->getBool("enable_parallax_occlusion")){
713                 shaders_header += "#define ENABLE_PARALLAX_OCCLUSION\n";
714                 shaders_header += "#define PARALLAX_OCCLUSION_SCALE ";
715                 shaders_header += ftos(g_settings->getFloat("parallax_occlusion_scale"));
716                 shaders_header += "\n";
717                 shaders_header += "#define PARALLAX_OCCLUSION_BIAS ";
718                 shaders_header += ftos(g_settings->getFloat("parallax_occlusion_bias"));
719                 shaders_header += "\n";
720         }
721
722         if (g_settings->getBool("enable_bumpmapping") || g_settings->getBool("enable_parallax_occlusion"))
723                 shaders_header += "#define USE_NORMALMAPS\n";
724
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";
736         } else{
737                 shaders_header += "#define ENABLE_WAVING_WATER 0\n";
738         }
739
740         shaders_header += "#define ENABLE_WAVING_LEAVES ";
741         if (g_settings->getBool("enable_waving_leaves"))
742                 shaders_header += "1\n";
743         else    
744                 shaders_header += "0\n";
745
746         shaders_header += "#define ENABLE_WAVING_PLANTS ";              
747         if (g_settings->getBool("enable_waving_plants"))
748                 shaders_header += "1\n";
749         else
750                 shaders_header += "0\n";
751
752         if(pixel_program != "")
753                 pixel_program = shaders_header + pixel_program;
754         if(vertex_program != "")
755                 vertex_program = shaders_header + vertex_program;
756         if(geometry_program != "")
757                 geometry_program = shaders_header + geometry_program;
758
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 != "")
764                 vertex_program_ptr = vertex_program.c_str();
765         if(pixel_program != "")
766                 pixel_program_ptr = pixel_program.c_str();
767         if(geometry_program != "")
768                 geometry_program_ptr = geometry_program.c_str();
769         s32 shadermat = -1;
770         if(is_highlevel){
771                 infostream<<"Compiling high level shaders for "<<name<<std::endl;
772                 shadermat = gpu->addHighLevelShaderMaterial(
773                         vertex_program_ptr,   // Vertex shader program
774                         "vertexMain",         // Vertex shader entry point
775                         video::EVST_VS_1_1,   // Vertex shader version
776                         pixel_program_ptr,    // Pixel shader program
777                         "pixelMain",          // Pixel shader entry point
778                         video::EPST_PS_1_1,   // Pixel shader version
779                         geometry_program_ptr, // Geometry shader program
780                         "geometryMain",       // Geometry shader entry point
781                         video::EGST_GS_4_0,   // Geometry shader version
782                         scene::EPT_TRIANGLES,      // Geometry shader input
783                         scene::EPT_TRIANGLE_STRIP, // Geometry shader output
784                         0,                         // Support maximum number of vertices
785                         callback,                  // Set-constant callback
786                         shaderinfo.base_material,  // Base material
787                         1                          // Userdata passed to callback
788                         );
789                 if(shadermat == -1){
790                         errorstream<<"generate_shader(): "
791                                         "failed to generate \""<<name<<"\", "
792                                         "addHighLevelShaderMaterial failed."
793                                         <<std::endl;
794                         return shaderinfo;
795                 }
796         }
797         else{
798                 infostream<<"Compiling assembly shaders for "<<name<<std::endl;
799                 shadermat = gpu->addShaderMaterial(
800                         vertex_program_ptr,   // Vertex shader program
801                         pixel_program_ptr,    // Pixel shader program
802                         callback,             // Set-constant callback
803                         shaderinfo.base_material,  // Base material
804                         0                     // Userdata passed to callback
805                         );
806
807                 if(shadermat == -1){
808                         errorstream<<"generate_shader(): "
809                                         "failed to generate \""<<name<<"\", "
810                                         "addShaderMaterial failed."
811                                         <<std::endl;
812                         return shaderinfo;
813                 }
814         }
815
816         // HACK, TODO: investigate this better
817         // Grab the material renderer once more so minetest doesn't crash on exit
818         driver->getMaterialRenderer(shadermat)->grab();
819
820         // Apply the newly created material type
821         shaderinfo.material = (video::E_MATERIAL_TYPE) shadermat;
822         return shaderinfo;
823 }
824
825 void load_shaders(std::string name, SourceShaderCache *sourcecache,
826                 video::E_DRIVER_TYPE drivertype, bool enable_shaders,
827                 std::string &vertex_program, std::string &pixel_program,
828                 std::string &geometry_program, bool &is_highlevel)
829 {
830         vertex_program = "";
831         pixel_program = "";
832         geometry_program = "";
833         is_highlevel = false;
834
835         if(enable_shaders){
836                 // Look for high level shaders
837                 if(drivertype == video::EDT_DIRECT3D9){
838                         // Direct3D 9: HLSL
839                         // (All shaders in one file)
840                         vertex_program = sourcecache->getOrLoad(name, "d3d9.hlsl");
841                         pixel_program = vertex_program;
842                         geometry_program = vertex_program;
843                 }
844                 else if(drivertype == video::EDT_OPENGL){
845                         // OpenGL: GLSL
846                         vertex_program = sourcecache->getOrLoad(name, "opengl_vertex.glsl");
847                         pixel_program = sourcecache->getOrLoad(name, "opengl_fragment.glsl");
848                         geometry_program = sourcecache->getOrLoad(name, "opengl_geometry.glsl");
849                 }
850                 if(vertex_program != "" || pixel_program != "" || geometry_program != ""){
851                         is_highlevel = true;
852                         return;
853                 }
854         }
855
856 }