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