Remove unused shader matrices. (#4723)
[oweals/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 <fstream>
22 #include <iterator>
23 #include "shader.h"
24 #include "irrlichttypes_extrabloated.h"
25 #include "debug.h"
26 #include "filesys.h"
27 #include "util/container.h"
28 #include "util/thread.h"
29 #include "settings.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"
36 #include "log.h"
37 #include "gamedef.h"
38 #include "client/tile.h"
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, const std::string &filename,
106                 const std::string &program, bool prefer_local)
107         {
108                 std::string combined = name_of_shader + DIR_DELIM + filename;
109                 // Try to use local shader instead if asked to
110                 if(prefer_local){
111                         std::string path = getShaderPath(name_of_shader, filename);
112                         if(path != ""){
113                                 std::string p = readFile(path);
114                                 if(p != ""){
115                                         m_programs[combined] = p;
116                                         return;
117                                 }
118                         }
119                 }
120                 m_programs[combined] = program;
121         }
122
123         std::string get(const std::string &name_of_shader,
124                 const std::string &filename)
125         {
126                 std::string combined = name_of_shader + DIR_DELIM + filename;
127                 StringMap::iterator n = m_programs.find(combined);
128                 if (n != m_programs.end())
129                         return n->second;
130                 return "";
131         }
132
133         // Primarily fetches from cache, secondarily tries to read from filesystem
134         std::string getOrLoad(const std::string &name_of_shader,
135                 const std::string &filename)
136         {
137                 std::string combined = name_of_shader + DIR_DELIM + filename;
138                 StringMap::iterator n = m_programs.find(combined);
139                 if (n != m_programs.end())
140                         return n->second;
141                 std::string path = getShaderPath(name_of_shader, filename);
142                 if (path == "") {
143                         infostream << "SourceShaderCache::getOrLoad(): No path found for \""
144                                 << combined << "\"" << std::endl;
145                         return "";
146                 }
147                 infostream << "SourceShaderCache::getOrLoad(): Loading path \""
148                         << path << "\"" << std::endl;
149                 std::string p = readFile(path);
150                 if (p != "") {
151                         m_programs[combined] = p;
152                         return p;
153                 }
154                 return "";
155         }
156 private:
157         StringMap m_programs;
158
159         std::string readFile(const std::string &path)
160         {
161                 std::ifstream is(path.c_str(), std::ios::binary);
162                 if(!is.is_open())
163                         return "";
164                 std::ostringstream tmp_os;
165                 tmp_os << is.rdbuf();
166                 return tmp_os.str();
167         }
168 };
169
170 /*
171         ShaderCallback: Sets constants that can be used in shaders
172 */
173
174 class IShaderConstantSetterRegistry
175 {
176 public:
177         virtual ~IShaderConstantSetterRegistry(){};
178         virtual void onSetConstants(video::IMaterialRendererServices *services,
179                         bool is_highlevel, const std::string &name) = 0;
180 };
181
182 class ShaderCallback : public video::IShaderConstantSetCallBack
183 {
184         IShaderConstantSetterRegistry *m_scsr;
185         std::string m_name;
186
187 public:
188         ShaderCallback(IShaderConstantSetterRegistry *scsr, const std::string &name):
189                 m_scsr(scsr),
190                 m_name(name)
191         {}
192         ~ShaderCallback() {}
193
194         virtual void OnSetConstants(video::IMaterialRendererServices *services, s32 userData)
195         {
196                 video::IVideoDriver *driver = services->getVideoDriver();
197                 sanity_check(driver != NULL);
198
199                 bool is_highlevel = userData;
200
201                 m_scsr->onSetConstants(services, is_highlevel, m_name);
202         }
203 };
204
205 /*
206         MainShaderConstantSetter: Set basic constants required for almost everything
207 */
208
209 class MainShaderConstantSetter : public IShaderConstantSetter
210 {
211 public:
212         MainShaderConstantSetter(IrrlichtDevice *device)
213         {}
214         ~MainShaderConstantSetter() {}
215
216         virtual void onSetConstants(video::IMaterialRendererServices *services,
217                         bool is_highlevel)
218         {
219                 video::IVideoDriver *driver = services->getVideoDriver();
220                 sanity_check(driver);
221
222                 // set clip matrix
223                 core::matrix4 worldViewProj;
224                 worldViewProj = driver->getTransform(video::ETS_PROJECTION);
225                 worldViewProj *= driver->getTransform(video::ETS_VIEW);
226                 worldViewProj *= driver->getTransform(video::ETS_WORLD);
227                 if(is_highlevel)
228                         services->setVertexShaderConstant("mWorldViewProj", worldViewProj.pointer(), 16);
229                 else
230                         services->setVertexShaderConstant(worldViewProj.pointer(), 4, 4);
231
232                 // set world matrix
233                 core::matrix4 world = driver->getTransform(video::ETS_WORLD);
234                 if(is_highlevel)
235                         services->setVertexShaderConstant("mWorld", world.pointer(), 16);
236                 else
237                         services->setVertexShaderConstant(world.pointer(), 8, 4);
238
239         }
240 };
241
242 /*
243         ShaderSource
244 */
245
246 class ShaderSource : public IWritableShaderSource, public IShaderConstantSetterRegistry
247 {
248 public:
249         ShaderSource(IrrlichtDevice *device);
250         ~ShaderSource();
251
252         /*
253                 - If shader material specified by name is found from cache,
254                   return the cached id.
255                 - Otherwise generate the shader material, add to cache and return id.
256
257                 The id 0 points to a null shader. Its material is EMT_SOLID.
258         */
259         u32 getShaderIdDirect(const std::string &name,
260                 const u8 material_type, const u8 drawtype);
261
262         /*
263                 If shader specified by the name pointed by the id doesn't
264                 exist, create it, then return id.
265
266                 Can be called from any thread. If called from some other thread
267                 and not found in cache, the call is queued to the main thread
268                 for processing.
269         */
270
271         u32 getShader(const std::string &name,
272                 const u8 material_type, const u8 drawtype);
273
274         ShaderInfo getShaderInfo(u32 id);
275
276         // Processes queued shader requests from other threads.
277         // Shall be called from the main thread.
278         void processQueue();
279
280         // Insert a shader program into the cache without touching the
281         // filesystem. Shall be called from the main thread.
282         void insertSourceShader(const std::string &name_of_shader,
283                 const std::string &filename, const std::string &program);
284
285         // Rebuild shaders from the current set of source shaders
286         // Shall be called from the main thread.
287         void rebuildShaders();
288
289         void addGlobalConstantSetter(IShaderConstantSetter *setter)
290         {
291                 m_global_setters.push_back(setter);
292         }
293
294         void onSetConstants(video::IMaterialRendererServices *services,
295                         bool is_highlevel, const std::string &name);
296
297 private:
298
299         // The id of the thread that is allowed to use irrlicht directly
300         threadid_t m_main_thread;
301         // The irrlicht device
302         IrrlichtDevice *m_device;
303         // The set-constants callback
304         ShaderCallback *m_shader_callback;
305
306         // Cache of source shaders
307         // This should be only accessed from the main thread
308         SourceShaderCache m_sourcecache;
309
310         // A shader id is index in this array.
311         // The first position contains a dummy shader.
312         std::vector<ShaderInfo> m_shaderinfo_cache;
313         // The former container is behind this mutex
314         Mutex m_shaderinfo_cache_mutex;
315
316         // Queued shader fetches (to be processed by the main thread)
317         RequestQueue<std::string, u32, u8, u8> m_get_shader_queue;
318
319         // Global constant setters
320         // TODO: Delete these in the destructor
321         std::vector<IShaderConstantSetter*> m_global_setters;
322 };
323
324 IWritableShaderSource* createShaderSource(IrrlichtDevice *device)
325 {
326         return new ShaderSource(device);
327 }
328
329 /*
330         Generate shader given the shader name.
331 */
332 ShaderInfo generate_shader(std::string name,
333                 u8 material_type, u8 drawtype,
334                 IrrlichtDevice *device,
335                 video::IShaderConstantSetCallBack *callback,
336                 SourceShaderCache *sourcecache);
337
338 /*
339         Load shader programs
340 */
341 void load_shaders(std::string name, SourceShaderCache *sourcecache,
342                 video::E_DRIVER_TYPE drivertype, bool enable_shaders,
343                 std::string &vertex_program, std::string &pixel_program,
344                 std::string &geometry_program, bool &is_highlevel);
345
346 ShaderSource::ShaderSource(IrrlichtDevice *device):
347                 m_device(device)
348 {
349         assert(m_device); // Pre-condition
350
351         m_shader_callback = new ShaderCallback(this, "default");
352
353         m_main_thread = thr_get_current_thread_id();
354
355         // Add a dummy ShaderInfo as the first index, named ""
356         m_shaderinfo_cache.push_back(ShaderInfo());
357
358         // Add main global constant setter
359         addGlobalConstantSetter(new MainShaderConstantSetter(device));
360 }
361
362 ShaderSource::~ShaderSource()
363 {
364         for (std::vector<IShaderConstantSetter*>::iterator iter = m_global_setters.begin();
365                         iter != m_global_setters.end(); ++iter) {
366                 delete *iter;
367         }
368         m_global_setters.clear();
369
370         if (m_shader_callback) {
371                 m_shader_callback->drop();
372                 m_shader_callback = NULL;
373         }
374 }
375
376 u32 ShaderSource::getShader(const std::string &name,
377                 const u8 material_type, const u8 drawtype)
378 {
379         /*
380                 Get shader
381         */
382
383         if (thr_is_current_thread(m_main_thread)) {
384                 return getShaderIdDirect(name, material_type, drawtype);
385         } else {
386                 /*errorstream<<"getShader(): Queued: name=\""<<name<<"\""<<std::endl;*/
387
388                 // We're gonna ask the result to be put into here
389
390                 static ResultQueue<std::string, u32, u8, u8> result_queue;
391
392                 // Throw a request in
393                 m_get_shader_queue.add(name, 0, 0, &result_queue);
394
395                 /* infostream<<"Waiting for shader from main thread, name=\""
396                                 <<name<<"\""<<std::endl;*/
397
398                 while(true) {
399                         GetResult<std::string, u32, u8, u8>
400                                 result = result_queue.pop_frontNoEx();
401
402                         if (result.key == name) {
403                                 return result.item;
404                         }
405                         else {
406                                 errorstream << "Got shader with invalid name: " << result.key << std::endl;
407                         }
408                 }
409
410         }
411
412         infostream<<"getShader(): Failed"<<std::endl;
413
414         return 0;
415 }
416
417 /*
418         This method generates all the shaders
419 */
420 u32 ShaderSource::getShaderIdDirect(const std::string &name,
421                 const u8 material_type, const u8 drawtype)
422 {
423         //infostream<<"getShaderIdDirect(): name=\""<<name<<"\""<<std::endl;
424
425         // Empty name means shader 0
426         if(name == ""){
427                 infostream<<"getShaderIdDirect(): name is empty"<<std::endl;
428                 return 0;
429         }
430
431         // Check if already have such instance
432         for(u32 i=0; i<m_shaderinfo_cache.size(); i++){
433                 ShaderInfo *info = &m_shaderinfo_cache[i];
434                 if(info->name == name && info->material_type == material_type &&
435                         info->drawtype == drawtype)
436                         return i;
437         }
438
439         /*
440                 Calling only allowed from main thread
441         */
442         if (!thr_is_current_thread(m_main_thread)) {
443                 errorstream<<"ShaderSource::getShaderIdDirect() "
444                                 "called not from main thread"<<std::endl;
445                 return 0;
446         }
447
448         ShaderInfo info = generate_shader(name, material_type, drawtype, m_device,
449                         m_shader_callback, &m_sourcecache);
450
451         /*
452                 Add shader to caches (add dummy shaders too)
453         */
454
455         MutexAutoLock lock(m_shaderinfo_cache_mutex);
456
457         u32 id = m_shaderinfo_cache.size();
458         m_shaderinfo_cache.push_back(info);
459
460         infostream<<"getShaderIdDirect(): "
461                         <<"Returning id="<<id<<" for name \""<<name<<"\""<<std::endl;
462
463         return id;
464 }
465
466
467 ShaderInfo ShaderSource::getShaderInfo(u32 id)
468 {
469         MutexAutoLock lock(m_shaderinfo_cache_mutex);
470
471         if(id >= m_shaderinfo_cache.size())
472                 return ShaderInfo();
473
474         return m_shaderinfo_cache[id];
475 }
476
477 void ShaderSource::processQueue()
478 {
479
480
481 }
482
483 void ShaderSource::insertSourceShader(const std::string &name_of_shader,
484                 const std::string &filename, const std::string &program)
485 {
486         /*infostream<<"ShaderSource::insertSourceShader(): "
487                         "name_of_shader=\""<<name_of_shader<<"\", "
488                         "filename=\""<<filename<<"\""<<std::endl;*/
489
490         sanity_check(thr_is_current_thread(m_main_thread));
491
492         m_sourcecache.insert(name_of_shader, filename, program, true);
493 }
494
495 void ShaderSource::rebuildShaders()
496 {
497         MutexAutoLock lock(m_shaderinfo_cache_mutex);
498
499         /*// Oh well... just clear everything, they'll load sometime.
500         m_shaderinfo_cache.clear();
501         m_name_to_id.clear();*/
502
503         /*
504                 FIXME: Old shader materials can't be deleted in Irrlicht,
505                 or can they?
506                 (This would be nice to do in the destructor too)
507         */
508
509         // Recreate shaders
510         for(u32 i=0; i<m_shaderinfo_cache.size(); i++){
511                 ShaderInfo *info = &m_shaderinfo_cache[i];
512                 if(info->name != ""){
513                         *info = generate_shader(info->name, info->material_type,
514                                         info->drawtype, m_device, m_shader_callback, &m_sourcecache);
515                 }
516         }
517 }
518
519 void ShaderSource::onSetConstants(video::IMaterialRendererServices *services,
520                 bool is_highlevel, const std::string &name)
521 {
522         for(u32 i=0; i<m_global_setters.size(); i++){
523                 IShaderConstantSetter *setter = m_global_setters[i];
524                 setter->onSetConstants(services, is_highlevel);
525         }
526 }
527
528 ShaderInfo generate_shader(std::string name, u8 material_type, u8 drawtype,
529                 IrrlichtDevice *device, video::IShaderConstantSetCallBack *callback,
530                 SourceShaderCache *sourcecache)
531 {
532         ShaderInfo shaderinfo;
533         shaderinfo.name = name;
534         shaderinfo.material_type = material_type;
535         shaderinfo.drawtype = drawtype;
536         shaderinfo.material = video::EMT_SOLID;
537         switch(material_type){
538                 case TILE_MATERIAL_BASIC:
539                         shaderinfo.base_material = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
540                         break;
541                 case TILE_MATERIAL_ALPHA:
542                         shaderinfo.base_material = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
543                         break;
544                 case TILE_MATERIAL_LIQUID_TRANSPARENT:
545                         shaderinfo.base_material = video::EMT_TRANSPARENT_VERTEX_ALPHA;
546                         break;
547                 case TILE_MATERIAL_LIQUID_OPAQUE:
548                         shaderinfo.base_material = video::EMT_SOLID;
549                         break;
550                 case TILE_MATERIAL_WAVING_LEAVES:
551                         shaderinfo.base_material = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
552                         break;
553                 case TILE_MATERIAL_WAVING_PLANTS:
554                         shaderinfo.base_material = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
555                 break;
556         }
557
558         bool enable_shaders = g_settings->getBool("enable_shaders");
559         if(!enable_shaders)
560                 return shaderinfo;
561
562         video::IVideoDriver* driver = device->getVideoDriver();
563         sanity_check(driver);
564
565         video::IGPUProgrammingServices *gpu = driver->getGPUProgrammingServices();
566         if(!gpu){
567                 errorstream<<"generate_shader(): "
568                                 "failed to generate \""<<name<<"\", "
569                                 "GPU programming not supported."
570                                 <<std::endl;
571                 return shaderinfo;
572         }
573
574         // Choose shader language depending on driver type and settings
575         // Then load shaders
576         std::string vertex_program;
577         std::string pixel_program;
578         std::string geometry_program;
579         bool is_highlevel;
580         load_shaders(name, sourcecache, driver->getDriverType(),
581                         enable_shaders, vertex_program, pixel_program,
582                         geometry_program, is_highlevel);
583         // Check hardware/driver support
584         if(vertex_program != "" &&
585                         !driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1) &&
586                         !driver->queryFeature(video::EVDF_ARB_VERTEX_PROGRAM_1)){
587                 infostream<<"generate_shader(): vertex shaders disabled "
588                                 "because of missing driver/hardware support."
589                                 <<std::endl;
590                 vertex_program = "";
591         }
592         if(pixel_program != "" &&
593                         !driver->queryFeature(video::EVDF_PIXEL_SHADER_1_1) &&
594                         !driver->queryFeature(video::EVDF_ARB_FRAGMENT_PROGRAM_1)){
595                 infostream<<"generate_shader(): pixel shaders disabled "
596                                 "because of missing driver/hardware support."
597                                 <<std::endl;
598                 pixel_program = "";
599         }
600         if(geometry_program != "" &&
601                         !driver->queryFeature(video::EVDF_GEOMETRY_SHADER)){
602                 infostream<<"generate_shader(): geometry shaders disabled "
603                                 "because of missing driver/hardware support."
604                                 <<std::endl;
605                 geometry_program = "";
606         }
607
608         // If no shaders are used, don't make a separate material type
609         if(vertex_program == "" && pixel_program == "" && geometry_program == "")
610                 return shaderinfo;
611
612         // Create shaders header
613         std::string shaders_header = "#version 120\n";
614
615         static const char* drawTypes[] = {
616                 "NDT_NORMAL",
617                 "NDT_AIRLIKE",
618                 "NDT_LIQUID",
619                 "NDT_FLOWINGLIQUID",
620                 "NDT_GLASSLIKE",
621                 "NDT_ALLFACES",
622                 "NDT_ALLFACES_OPTIONAL",
623                 "NDT_TORCHLIKE",
624                 "NDT_SIGNLIKE",
625                 "NDT_PLANTLIKE",
626                 "NDT_FENCELIKE",
627                 "NDT_RAILLIKE",
628                 "NDT_NODEBOX",
629                 "NDT_GLASSLIKE_FRAMED",
630                 "NDT_FIRELIKE",
631                 "NDT_GLASSLIKE_FRAMED_OPTIONAL"
632         };
633
634         for (int i = 0; i < 14; i++){
635                 shaders_header += "#define ";
636                 shaders_header += drawTypes[i];
637                 shaders_header += " ";
638                 shaders_header += itos(i);
639                 shaders_header += "\n";
640         }
641
642         static const char* materialTypes[] = {
643                 "TILE_MATERIAL_BASIC",
644                 "TILE_MATERIAL_ALPHA",
645                 "TILE_MATERIAL_LIQUID_TRANSPARENT",
646                 "TILE_MATERIAL_LIQUID_OPAQUE",
647                 "TILE_MATERIAL_WAVING_LEAVES",
648                 "TILE_MATERIAL_WAVING_PLANTS"
649         };
650
651         for (int i = 0; i < 6; i++){
652                 shaders_header += "#define ";
653                 shaders_header += materialTypes[i];
654                 shaders_header += " ";
655                 shaders_header += itos(i);
656                 shaders_header += "\n";
657         }
658
659         shaders_header += "#define MATERIAL_TYPE ";
660         shaders_header += itos(material_type);
661         shaders_header += "\n";
662         shaders_header += "#define DRAW_TYPE ";
663         shaders_header += itos(drawtype);
664         shaders_header += "\n";
665
666         if (g_settings->getBool("generate_normalmaps")) {
667                 shaders_header += "#define GENERATE_NORMALMAPS 1\n";
668         } else {
669                 shaders_header += "#define GENERATE_NORMALMAPS 0\n";
670         }
671         shaders_header += "#define NORMALMAPS_STRENGTH ";
672         shaders_header += ftos(g_settings->getFloat("normalmaps_strength"));
673         shaders_header += "\n";
674         float sample_step;
675         int smooth = (int)g_settings->getFloat("normalmaps_smooth");
676         switch (smooth){
677         case 0:
678                 sample_step = 0.0078125; // 1.0 / 128.0
679                 break;
680         case 1:
681                 sample_step = 0.00390625; // 1.0 / 256.0
682                 break;
683         case 2:
684                 sample_step = 0.001953125; // 1.0 / 512.0
685                 break;
686         default:
687                 sample_step = 0.0078125;
688                 break;
689         }
690         shaders_header += "#define SAMPLE_STEP ";
691         shaders_header += ftos(sample_step);
692         shaders_header += "\n";
693
694         if (g_settings->getBool("enable_bumpmapping"))
695                 shaders_header += "#define ENABLE_BUMPMAPPING\n";
696
697         if (g_settings->getBool("enable_parallax_occlusion")){
698                 int mode = g_settings->getFloat("parallax_occlusion_mode");
699                 float scale = g_settings->getFloat("parallax_occlusion_scale");
700                 float bias = g_settings->getFloat("parallax_occlusion_bias");
701                 int iterations = g_settings->getFloat("parallax_occlusion_iterations");
702                 shaders_header += "#define ENABLE_PARALLAX_OCCLUSION\n";
703                 shaders_header += "#define PARALLAX_OCCLUSION_MODE ";
704                 shaders_header += itos(mode);
705                 shaders_header += "\n";
706                 shaders_header += "#define PARALLAX_OCCLUSION_SCALE ";
707                 shaders_header += ftos(scale);
708                 shaders_header += "\n";
709                 shaders_header += "#define PARALLAX_OCCLUSION_BIAS ";
710                 shaders_header += ftos(bias);
711                 shaders_header += "\n";
712                 shaders_header += "#define PARALLAX_OCCLUSION_ITERATIONS ";
713                 shaders_header += itos(iterations);
714                 shaders_header += "\n";
715         }
716
717         shaders_header += "#define USE_NORMALMAPS ";
718         if (g_settings->getBool("enable_bumpmapping") || g_settings->getBool("enable_parallax_occlusion"))
719                 shaders_header += "1\n";
720         else
721                 shaders_header += "0\n";
722
723         if (g_settings->getBool("enable_waving_water")){
724                 shaders_header += "#define ENABLE_WAVING_WATER 1\n";
725                 shaders_header += "#define WATER_WAVE_HEIGHT ";
726                 shaders_header += ftos(g_settings->getFloat("water_wave_height"));
727                 shaders_header += "\n";
728                 shaders_header += "#define WATER_WAVE_LENGTH ";
729                 shaders_header += ftos(g_settings->getFloat("water_wave_length"));
730                 shaders_header += "\n";
731                 shaders_header += "#define WATER_WAVE_SPEED ";
732                 shaders_header += ftos(g_settings->getFloat("water_wave_speed"));
733                 shaders_header += "\n";
734         } else{
735                 shaders_header += "#define ENABLE_WAVING_WATER 0\n";
736         }
737
738         shaders_header += "#define ENABLE_WAVING_LEAVES ";
739         if (g_settings->getBool("enable_waving_leaves"))
740                 shaders_header += "1\n";
741         else
742                 shaders_header += "0\n";
743
744         shaders_header += "#define ENABLE_WAVING_PLANTS ";
745         if (g_settings->getBool("enable_waving_plants"))
746                 shaders_header += "1\n";
747         else
748                 shaders_header += "0\n";
749
750         if (g_settings->getBool("tone_mapping"))
751                 shaders_header += "#define ENABLE_TONE_MAPPING\n";
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.empty()) {
758                 vertex_program = shaders_header + vertex_program;
759                 vertex_program_ptr = vertex_program.c_str();
760         }
761         if (!pixel_program.empty()) {
762                 pixel_program = shaders_header + pixel_program;
763                 pixel_program_ptr = pixel_program.c_str();
764         }
765         if (!geometry_program.empty()) {
766                 geometry_program = shaders_header + geometry_program;
767                 geometry_program_ptr = geometry_program.c_str();
768         }
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_2,   // 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                         dumpShaderProgram(warningstream, "Vertex", vertex_program);
795                         dumpShaderProgram(warningstream, "Pixel", pixel_program);
796                         dumpShaderProgram(warningstream, "Geometry", geometry_program);
797                         return shaderinfo;
798                 }
799         }
800         else{
801                 infostream<<"Compiling assembly shaders for "<<name<<std::endl;
802                 shadermat = gpu->addShaderMaterial(
803                         vertex_program_ptr,   // Vertex shader program
804                         pixel_program_ptr,    // Pixel shader program
805                         callback,             // Set-constant callback
806                         shaderinfo.base_material,  // Base material
807                         0                     // Userdata passed to callback
808                         );
809
810                 if(shadermat == -1){
811                         errorstream<<"generate_shader(): "
812                                         "failed to generate \""<<name<<"\", "
813                                         "addShaderMaterial failed."
814                                         <<std::endl;
815                         dumpShaderProgram(warningstream, "Vertex", vertex_program);
816                         dumpShaderProgram(warningstream,"Pixel", pixel_program);
817                         return shaderinfo;
818                 }
819         }
820
821         // HACK, TODO: investigate this better
822         // Grab the material renderer once more so minetest doesn't crash on exit
823         driver->getMaterialRenderer(shadermat)->grab();
824
825         // Apply the newly created material type
826         shaderinfo.material = (video::E_MATERIAL_TYPE) shadermat;
827         return shaderinfo;
828 }
829
830 void load_shaders(std::string name, SourceShaderCache *sourcecache,
831                 video::E_DRIVER_TYPE drivertype, bool enable_shaders,
832                 std::string &vertex_program, std::string &pixel_program,
833                 std::string &geometry_program, bool &is_highlevel)
834 {
835         vertex_program = "";
836         pixel_program = "";
837         geometry_program = "";
838         is_highlevel = false;
839
840         if(enable_shaders){
841                 // Look for high level shaders
842                 if(drivertype == video::EDT_DIRECT3D9){
843                         // Direct3D 9: HLSL
844                         // (All shaders in one file)
845                         vertex_program = sourcecache->getOrLoad(name, "d3d9.hlsl");
846                         pixel_program = vertex_program;
847                         geometry_program = vertex_program;
848                 }
849                 else if(drivertype == video::EDT_OPENGL){
850                         // OpenGL: GLSL
851                         vertex_program = sourcecache->getOrLoad(name, "opengl_vertex.glsl");
852                         pixel_program = sourcecache->getOrLoad(name, "opengl_fragment.glsl");
853                         geometry_program = sourcecache->getOrLoad(name, "opengl_geometry.glsl");
854                 }
855                 if(vertex_program != "" || pixel_program != "" || geometry_program != ""){
856                         is_highlevel = true;
857                         return;
858                 }
859         }
860
861 }
862
863 void dumpShaderProgram(std::ostream &output_stream,
864                 const std::string &program_type, const std::string &program)
865 {
866         output_stream << program_type << " shader program:" << std::endl <<
867                 "----------------------------------" << std::endl;
868         size_t pos = 0;
869         size_t prev = 0;
870         s16 line = 1;
871         while ((pos = program.find("\n", prev)) != std::string::npos) {
872                 output_stream << line++ << ": "<< program.substr(prev, pos - prev) <<
873                         std::endl;
874                 prev = pos + 1;
875         }
876         output_stream << line << ": " << program.substr(prev) << std::endl <<
877                 "End of " << program_type << " shader program." << std::endl <<
878                 " " << std::endl;
879 }