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