Sky API: Rename *_tint to fog_*_tint for consistency
[oweals/minetest.git] / src / client / 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.empty()) {
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.empty()) {
81                 std::string rel_path = std::string("client") + DIR_DELIM
82                                 + "shaders" + DIR_DELIM
83                                 + name_of_shader + DIR_DELIM
84                                 + filename;
85                 std::string testpath = porting::path_share + DIR_DELIM + rel_path;
86                 if(fs::PathExists(testpath))
87                         fullpath = testpath;
88         }
89
90         // Add to cache (also an empty result is cached)
91         g_shadername_to_path_cache.set(combined, fullpath);
92
93         // Finally return it
94         return fullpath;
95 }
96
97 /*
98         SourceShaderCache: A cache used for storing source shaders.
99 */
100
101 class SourceShaderCache
102 {
103 public:
104         void insert(const std::string &name_of_shader, const std::string &filename,
105                 const std::string &program, bool prefer_local)
106         {
107                 std::string combined = name_of_shader + DIR_DELIM + filename;
108                 // Try to use local shader instead if asked to
109                 if(prefer_local){
110                         std::string path = getShaderPath(name_of_shader, filename);
111                         if(!path.empty()){
112                                 std::string p = readFile(path);
113                                 if (!p.empty()) {
114                                         m_programs[combined] = p;
115                                         return;
116                                 }
117                         }
118                 }
119                 m_programs[combined] = program;
120         }
121
122         std::string get(const std::string &name_of_shader,
123                 const std::string &filename)
124         {
125                 std::string combined = name_of_shader + DIR_DELIM + filename;
126                 StringMap::iterator n = m_programs.find(combined);
127                 if (n != m_programs.end())
128                         return n->second;
129                 return "";
130         }
131
132         // Primarily fetches from cache, secondarily tries to read from filesystem
133         std::string getOrLoad(const std::string &name_of_shader,
134                 const std::string &filename)
135         {
136                 std::string combined = name_of_shader + DIR_DELIM + filename;
137                 StringMap::iterator n = m_programs.find(combined);
138                 if (n != m_programs.end())
139                         return n->second;
140                 std::string path = getShaderPath(name_of_shader, filename);
141                 if (path.empty()) {
142                         infostream << "SourceShaderCache::getOrLoad(): No path found for \""
143                                 << combined << "\"" << std::endl;
144                         return "";
145                 }
146                 infostream << "SourceShaderCache::getOrLoad(): Loading path \""
147                         << path << "\"" << std::endl;
148                 std::string p = readFile(path);
149                 if (!p.empty()) {
150                         m_programs[combined] = p;
151                         return p;
152                 }
153                 return "";
154         }
155 private:
156         StringMap m_programs;
157
158         std::string readFile(const std::string &path)
159         {
160                 std::ifstream is(path.c_str(), std::ios::binary);
161                 if(!is.is_open())
162                         return "";
163                 std::ostringstream tmp_os;
164                 tmp_os << is.rdbuf();
165                 return tmp_os.str();
166         }
167 };
168
169
170 /*
171         ShaderCallback: Sets constants that can be used in shaders
172 */
173
174 class ShaderCallback : public video::IShaderConstantSetCallBack
175 {
176         std::vector<IShaderConstantSetter*> m_setters;
177
178 public:
179         ShaderCallback(const std::vector<IShaderConstantSetterFactory *> &factories)
180         {
181                 for (IShaderConstantSetterFactory *factory : factories)
182                         m_setters.push_back(factory->create());
183         }
184
185         ~ShaderCallback()
186         {
187                 for (IShaderConstantSetter *setter : m_setters)
188                         delete setter;
189         }
190
191         virtual void OnSetConstants(video::IMaterialRendererServices *services, s32 userData) override
192         {
193                 video::IVideoDriver *driver = services->getVideoDriver();
194                 sanity_check(driver != NULL);
195
196                 bool is_highlevel = userData;
197
198                 for (IShaderConstantSetter *setter : m_setters)
199                         setter->onSetConstants(services, is_highlevel);
200         }
201
202         virtual void OnSetMaterial(const video::SMaterial& material) override
203         {
204                 for (IShaderConstantSetter *setter : m_setters)
205                         setter->onSetMaterial(material);
206         }
207 };
208
209
210 /*
211         MainShaderConstantSetter: Set basic constants required for almost everything
212 */
213
214 class MainShaderConstantSetter : public IShaderConstantSetter
215 {
216         CachedVertexShaderSetting<float, 16> m_world_view_proj;
217         CachedVertexShaderSetting<float, 16> m_world;
218
219 public:
220         MainShaderConstantSetter() :
221                 m_world_view_proj("mWorldViewProj"),
222                 m_world("mWorld")
223         {}
224         ~MainShaderConstantSetter() = default;
225
226         virtual void onSetConstants(video::IMaterialRendererServices *services,
227                         bool is_highlevel)
228         {
229                 video::IVideoDriver *driver = services->getVideoDriver();
230                 sanity_check(driver);
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                         m_world_view_proj.set(*reinterpret_cast<float(*)[16]>(worldViewProj.pointer()), services);
239                 else
240                         services->setVertexShaderConstant(worldViewProj.pointer(), 0, 4);
241
242                 // Set world matrix
243                 core::matrix4 world = driver->getTransform(video::ETS_WORLD);
244                 if (is_highlevel)
245                         m_world.set(*reinterpret_cast<float(*)[16]>(world.pointer()), services);
246                 else
247                         services->setVertexShaderConstant(world.pointer(), 4, 4);
248
249         }
250 };
251
252
253 class MainShaderConstantSetterFactory : public IShaderConstantSetterFactory
254 {
255 public:
256         virtual IShaderConstantSetter* create()
257                 { return new MainShaderConstantSetter(); }
258 };
259
260
261 /*
262         ShaderSource
263 */
264
265 class ShaderSource : public IWritableShaderSource
266 {
267 public:
268         ShaderSource();
269         ~ShaderSource();
270
271         /*
272                 - If shader material specified by name is found from cache,
273                   return the cached id.
274                 - Otherwise generate the shader material, add to cache and return id.
275
276                 The id 0 points to a null shader. Its material is EMT_SOLID.
277         */
278         u32 getShaderIdDirect(const std::string &name,
279                 const u8 material_type, const u8 drawtype);
280
281         /*
282                 If shader specified by the name pointed by the id doesn't
283                 exist, create it, then return id.
284
285                 Can be called from any thread. If called from some other thread
286                 and not found in cache, the call is queued to the main thread
287                 for processing.
288         */
289
290         u32 getShader(const std::string &name,
291                 const u8 material_type, const u8 drawtype);
292
293         ShaderInfo getShaderInfo(u32 id);
294
295         // Processes queued shader requests from other threads.
296         // Shall be called from the main thread.
297         void processQueue();
298
299         // Insert a shader program into the cache without touching the
300         // filesystem. Shall be called from the main thread.
301         void insertSourceShader(const std::string &name_of_shader,
302                 const std::string &filename, const std::string &program);
303
304         // Rebuild shaders from the current set of source shaders
305         // Shall be called from the main thread.
306         void rebuildShaders();
307
308         void addShaderConstantSetterFactory(IShaderConstantSetterFactory *setter)
309         {
310                 m_setter_factories.push_back(setter);
311         }
312
313 private:
314
315         // The id of the thread that is allowed to use irrlicht directly
316         std::thread::id m_main_thread;
317
318         // Cache of source shaders
319         // This should be only accessed from the main thread
320         SourceShaderCache m_sourcecache;
321
322         // A shader id is index in this array.
323         // The first position contains a dummy shader.
324         std::vector<ShaderInfo> m_shaderinfo_cache;
325         // The former container is behind this mutex
326         std::mutex m_shaderinfo_cache_mutex;
327
328         // Queued shader fetches (to be processed by the main thread)
329         RequestQueue<std::string, u32, u8, u8> m_get_shader_queue;
330
331         // Global constant setter factories
332         std::vector<IShaderConstantSetterFactory *> m_setter_factories;
333
334         // Shader callbacks
335         std::vector<ShaderCallback *> m_callbacks;
336 };
337
338 IWritableShaderSource *createShaderSource()
339 {
340         return new ShaderSource();
341 }
342
343 /*
344         Generate shader given the shader name.
345 */
346 ShaderInfo generate_shader(const std::string &name,
347                 u8 material_type, u8 drawtype, std::vector<ShaderCallback *> &callbacks,
348                 const std::vector<IShaderConstantSetterFactory *> &setter_factories,
349                 SourceShaderCache *sourcecache);
350
351 /*
352         Load shader programs
353 */
354 void load_shaders(const std::string &name, SourceShaderCache *sourcecache,
355                 video::E_DRIVER_TYPE drivertype, bool enable_shaders,
356                 std::string &vertex_program, std::string &pixel_program,
357                 std::string &geometry_program, bool &is_highlevel);
358
359 ShaderSource::ShaderSource()
360 {
361         m_main_thread = std::this_thread::get_id();
362
363         // Add a dummy ShaderInfo as the first index, named ""
364         m_shaderinfo_cache.emplace_back();
365
366         // Add main global constant setter
367         addShaderConstantSetterFactory(new MainShaderConstantSetterFactory());
368 }
369
370 ShaderSource::~ShaderSource()
371 {
372         for (ShaderCallback *callback : m_callbacks) {
373                 delete callback;
374         }
375         for (IShaderConstantSetterFactory *setter_factorie : m_setter_factories) {
376                 delete setter_factorie;
377         }
378 }
379
380 u32 ShaderSource::getShader(const std::string &name,
381                 const u8 material_type, const u8 drawtype)
382 {
383         /*
384                 Get shader
385         */
386
387         if (std::this_thread::get_id() == m_main_thread) {
388                 return getShaderIdDirect(name, material_type, drawtype);
389         }
390
391         /*errorstream<<"getShader(): Queued: name=\""<<name<<"\""<<std::endl;*/
392
393         // We're gonna ask the result to be put into here
394
395         static ResultQueue<std::string, u32, u8, u8> result_queue;
396
397         // Throw a request in
398         m_get_shader_queue.add(name, 0, 0, &result_queue);
399
400         /* infostream<<"Waiting for shader from main thread, name=\""
401                         <<name<<"\""<<std::endl;*/
402
403         while(true) {
404                 GetResult<std::string, u32, u8, u8>
405                         result = result_queue.pop_frontNoEx();
406
407                 if (result.key == name) {
408                         return result.item;
409                 }
410
411                 errorstream << "Got shader with invalid name: " << result.key << std::endl;
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.empty()) {
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 (ShaderInfo &i : m_shaderinfo_cache) {
513                 ShaderInfo *info = &i;
514                 if (!info->name.empty()) {
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         case TILE_MATERIAL_WAVING_LIQUID_OPAQUE:
537                 shaderinfo.base_material = video::EMT_SOLID;
538                 break;
539         case TILE_MATERIAL_ALPHA:
540         case TILE_MATERIAL_LIQUID_TRANSPARENT:
541         case TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT:
542                 shaderinfo.base_material = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
543                 break;
544         case TILE_MATERIAL_BASIC:
545         case TILE_MATERIAL_WAVING_LEAVES:
546         case TILE_MATERIAL_WAVING_PLANTS:
547         case TILE_MATERIAL_WAVING_LIQUID_BASIC:
548                 shaderinfo.base_material = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
549                 break;
550         }
551
552         bool enable_shaders = g_settings->getBool("enable_shaders");
553         if (!enable_shaders)
554                 return shaderinfo;
555
556         video::IVideoDriver *driver = RenderingEngine::get_video_driver();
557
558         video::IGPUProgrammingServices *gpu = driver->getGPUProgrammingServices();
559         if(!gpu){
560                 errorstream<<"generate_shader(): "
561                                 "failed to generate \""<<name<<"\", "
562                                 "GPU programming not supported."
563                                 <<std::endl;
564                 return shaderinfo;
565         }
566
567         // Choose shader language depending on driver type and settings
568         // Then load shaders
569         std::string vertex_program;
570         std::string pixel_program;
571         std::string geometry_program;
572         bool is_highlevel;
573         load_shaders(name, sourcecache, driver->getDriverType(),
574                         enable_shaders, vertex_program, pixel_program,
575                         geometry_program, is_highlevel);
576         // Check hardware/driver support
577         if (!vertex_program.empty() &&
578                         !driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1) &&
579                         !driver->queryFeature(video::EVDF_ARB_VERTEX_PROGRAM_1)){
580                 infostream<<"generate_shader(): vertex shaders disabled "
581                                 "because of missing driver/hardware support."
582                                 <<std::endl;
583                 vertex_program = "";
584         }
585         if (!pixel_program.empty() &&
586                         !driver->queryFeature(video::EVDF_PIXEL_SHADER_1_1) &&
587                         !driver->queryFeature(video::EVDF_ARB_FRAGMENT_PROGRAM_1)){
588                 infostream<<"generate_shader(): pixel shaders disabled "
589                                 "because of missing driver/hardware support."
590                                 <<std::endl;
591                 pixel_program = "";
592         }
593         if (!geometry_program.empty() &&
594                         !driver->queryFeature(video::EVDF_GEOMETRY_SHADER)){
595                 infostream<<"generate_shader(): geometry shaders disabled "
596                                 "because of missing driver/hardware support."
597                                 <<std::endl;
598                 geometry_program = "";
599         }
600
601         // If no shaders are used, don't make a separate material type
602         if (vertex_program.empty() && pixel_program.empty() && geometry_program.empty())
603                 return shaderinfo;
604
605         // Create shaders header
606         std::string shaders_header = "#version 120\n";
607
608         static const char* drawTypes[] = {
609                 "NDT_NORMAL",
610                 "NDT_AIRLIKE",
611                 "NDT_LIQUID",
612                 "NDT_FLOWINGLIQUID",
613                 "NDT_GLASSLIKE",
614                 "NDT_ALLFACES",
615                 "NDT_ALLFACES_OPTIONAL",
616                 "NDT_TORCHLIKE",
617                 "NDT_SIGNLIKE",
618                 "NDT_PLANTLIKE",
619                 "NDT_FENCELIKE",
620                 "NDT_RAILLIKE",
621                 "NDT_NODEBOX",
622                 "NDT_GLASSLIKE_FRAMED",
623                 "NDT_FIRELIKE",
624                 "NDT_GLASSLIKE_FRAMED_OPTIONAL",
625                 "NDT_PLANTLIKE_ROOTED",
626         };
627
628         for (int i = 0; i < 14; i++){
629                 shaders_header += "#define ";
630                 shaders_header += drawTypes[i];
631                 shaders_header += " ";
632                 shaders_header += itos(i);
633                 shaders_header += "\n";
634         }
635
636         static const char* materialTypes[] = {
637                 "TILE_MATERIAL_BASIC",
638                 "TILE_MATERIAL_ALPHA",
639                 "TILE_MATERIAL_LIQUID_TRANSPARENT",
640                 "TILE_MATERIAL_LIQUID_OPAQUE",
641                 "TILE_MATERIAL_WAVING_LEAVES",
642                 "TILE_MATERIAL_WAVING_PLANTS",
643                 "TILE_MATERIAL_OPAQUE",
644                 "TILE_MATERIAL_WAVING_LIQUID_BASIC",
645                 "TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT",
646                 "TILE_MATERIAL_WAVING_LIQUID_OPAQUE",
647         };
648
649         for (int i = 0; i < 10; i++){
650                 shaders_header += "#define ";
651                 shaders_header += materialTypes[i];
652                 shaders_header += " ";
653                 shaders_header += itos(i);
654                 shaders_header += "\n";
655         }
656
657         shaders_header += "#define MATERIAL_TYPE ";
658         shaders_header += itos(material_type);
659         shaders_header += "\n";
660         shaders_header += "#define DRAW_TYPE ";
661         shaders_header += itos(drawtype);
662         shaders_header += "\n";
663
664         if (g_settings->getBool("generate_normalmaps")) {
665                 shaders_header += "#define GENERATE_NORMALMAPS 1\n";
666         } else {
667                 shaders_header += "#define GENERATE_NORMALMAPS 0\n";
668         }
669         shaders_header += "#define NORMALMAPS_STRENGTH ";
670         shaders_header += ftos(g_settings->getFloat("normalmaps_strength"));
671         shaders_header += "\n";
672         float sample_step;
673         int smooth = (int)g_settings->getFloat("normalmaps_smooth");
674         switch (smooth){
675         case 0:
676                 sample_step = 0.0078125; // 1.0 / 128.0
677                 break;
678         case 1:
679                 sample_step = 0.00390625; // 1.0 / 256.0
680                 break;
681         case 2:
682                 sample_step = 0.001953125; // 1.0 / 512.0
683                 break;
684         default:
685                 sample_step = 0.0078125;
686                 break;
687         }
688         shaders_header += "#define SAMPLE_STEP ";
689         shaders_header += ftos(sample_step);
690         shaders_header += "\n";
691
692         if (g_settings->getBool("enable_bumpmapping"))
693                 shaders_header += "#define ENABLE_BUMPMAPPING\n";
694
695         if (g_settings->getBool("enable_parallax_occlusion")){
696                 int mode = g_settings->getFloat("parallax_occlusion_mode");
697                 float scale = g_settings->getFloat("parallax_occlusion_scale");
698                 float bias = g_settings->getFloat("parallax_occlusion_bias");
699                 int iterations = g_settings->getFloat("parallax_occlusion_iterations");
700                 shaders_header += "#define ENABLE_PARALLAX_OCCLUSION\n";
701                 shaders_header += "#define PARALLAX_OCCLUSION_MODE ";
702                 shaders_header += itos(mode);
703                 shaders_header += "\n";
704                 shaders_header += "#define PARALLAX_OCCLUSION_SCALE ";
705                 shaders_header += ftos(scale);
706                 shaders_header += "\n";
707                 shaders_header += "#define PARALLAX_OCCLUSION_BIAS ";
708                 shaders_header += ftos(bias);
709                 shaders_header += "\n";
710                 shaders_header += "#define PARALLAX_OCCLUSION_ITERATIONS ";
711                 shaders_header += itos(iterations);
712                 shaders_header += "\n";
713         }
714
715         shaders_header += "#define USE_NORMALMAPS ";
716         if (g_settings->getBool("enable_bumpmapping") || g_settings->getBool("enable_parallax_occlusion"))
717                 shaders_header += "1\n";
718         else
719                 shaders_header += "0\n";
720
721         if (g_settings->getBool("enable_waving_water")){
722                 shaders_header += "#define ENABLE_WAVING_WATER 1\n";
723                 shaders_header += "#define WATER_WAVE_HEIGHT ";
724                 shaders_header += ftos(g_settings->getFloat("water_wave_height"));
725                 shaders_header += "\n";
726                 shaders_header += "#define WATER_WAVE_LENGTH ";
727                 shaders_header += ftos(g_settings->getFloat("water_wave_length"));
728                 shaders_header += "\n";
729                 shaders_header += "#define WATER_WAVE_SPEED ";
730                 shaders_header += ftos(g_settings->getFloat("water_wave_speed"));
731                 shaders_header += "\n";
732         } else{
733                 shaders_header += "#define ENABLE_WAVING_WATER 0\n";
734         }
735
736         shaders_header += "#define ENABLE_WAVING_LEAVES ";
737         if (g_settings->getBool("enable_waving_leaves"))
738                 shaders_header += "1\n";
739         else
740                 shaders_header += "0\n";
741
742         shaders_header += "#define ENABLE_WAVING_PLANTS ";
743         if (g_settings->getBool("enable_waving_plants"))
744                 shaders_header += "1\n";
745         else
746                 shaders_header += "0\n";
747
748         if (g_settings->getBool("tone_mapping"))
749                 shaders_header += "#define ENABLE_TONE_MAPPING\n";
750
751         shaders_header += "#define FOG_START ";
752         shaders_header += ftos(rangelim(g_settings->getFloat("fog_start"), 0.0f, 0.99f));
753         shaders_header += "\n";
754
755         // Call addHighLevelShaderMaterial() or addShaderMaterial()
756         const c8* vertex_program_ptr = 0;
757         const c8* pixel_program_ptr = 0;
758         const c8* geometry_program_ptr = 0;
759         if (!vertex_program.empty()) {
760                 vertex_program = shaders_header + vertex_program;
761                 vertex_program_ptr = vertex_program.c_str();
762         }
763         if (!pixel_program.empty()) {
764                 pixel_program = shaders_header + pixel_program;
765                 pixel_program_ptr = pixel_program.c_str();
766         }
767         if (!geometry_program.empty()) {
768                 geometry_program = shaders_header + geometry_program;
769                 geometry_program_ptr = geometry_program.c_str();
770         }
771         ShaderCallback *cb = new ShaderCallback(setter_factories);
772         s32 shadermat = -1;
773         if(is_highlevel){
774                 infostream<<"Compiling high level shaders for "<<name<<std::endl;
775                 shadermat = gpu->addHighLevelShaderMaterial(
776                         vertex_program_ptr,   // Vertex shader program
777                         "vertexMain",         // Vertex shader entry point
778                         video::EVST_VS_1_1,   // Vertex shader version
779                         pixel_program_ptr,    // Pixel shader program
780                         "pixelMain",          // Pixel shader entry point
781                         video::EPST_PS_1_2,   // Pixel shader version
782                         geometry_program_ptr, // Geometry shader program
783                         "geometryMain",       // Geometry shader entry point
784                         video::EGST_GS_4_0,   // Geometry shader version
785                         scene::EPT_TRIANGLES,      // Geometry shader input
786                         scene::EPT_TRIANGLE_STRIP, // Geometry shader output
787                         0,                         // Support maximum number of vertices
788                         cb, // Set-constant callback
789                         shaderinfo.base_material,  // Base material
790                         1                          // Userdata passed to callback
791                         );
792                 if(shadermat == -1){
793                         errorstream<<"generate_shader(): "
794                                         "failed to generate \""<<name<<"\", "
795                                         "addHighLevelShaderMaterial failed."
796                                         <<std::endl;
797                         dumpShaderProgram(warningstream, "Vertex", vertex_program);
798                         dumpShaderProgram(warningstream, "Pixel", pixel_program);
799                         dumpShaderProgram(warningstream, "Geometry", geometry_program);
800                         delete cb;
801                         return shaderinfo;
802                 }
803         }
804         else{
805                 infostream<<"Compiling assembly shaders for "<<name<<std::endl;
806                 shadermat = gpu->addShaderMaterial(
807                         vertex_program_ptr,   // Vertex shader program
808                         pixel_program_ptr,    // Pixel shader program
809                         cb, // Set-constant callback
810                         shaderinfo.base_material,  // Base material
811                         0                     // Userdata passed to callback
812                         );
813
814                 if(shadermat == -1){
815                         errorstream<<"generate_shader(): "
816                                         "failed to generate \""<<name<<"\", "
817                                         "addShaderMaterial failed."
818                                         <<std::endl;
819                         dumpShaderProgram(warningstream, "Vertex", vertex_program);
820                         dumpShaderProgram(warningstream,"Pixel", pixel_program);
821                         delete cb;
822                         return shaderinfo;
823                 }
824         }
825         callbacks.push_back(cb);
826
827         // HACK, TODO: investigate this better
828         // Grab the material renderer once more so minetest doesn't crash on exit
829         driver->getMaterialRenderer(shadermat)->grab();
830
831         // Apply the newly created material type
832         shaderinfo.material = (video::E_MATERIAL_TYPE) shadermat;
833         return shaderinfo;
834 }
835
836 void load_shaders(const std::string &name, SourceShaderCache *sourcecache,
837                 video::E_DRIVER_TYPE drivertype, bool enable_shaders,
838                 std::string &vertex_program, std::string &pixel_program,
839                 std::string &geometry_program, bool &is_highlevel)
840 {
841         vertex_program = "";
842         pixel_program = "";
843         geometry_program = "";
844         is_highlevel = false;
845
846         if(enable_shaders){
847                 // Look for high level shaders
848                 if(drivertype == video::EDT_DIRECT3D9){
849                         // Direct3D 9: HLSL
850                         // (All shaders in one file)
851                         vertex_program = sourcecache->getOrLoad(name, "d3d9.hlsl");
852                         pixel_program = vertex_program;
853                         geometry_program = vertex_program;
854                 }
855                 else if(drivertype == video::EDT_OPENGL){
856                         // OpenGL: GLSL
857                         vertex_program = sourcecache->getOrLoad(name, "opengl_vertex.glsl");
858                         pixel_program = sourcecache->getOrLoad(name, "opengl_fragment.glsl");
859                         geometry_program = sourcecache->getOrLoad(name, "opengl_geometry.glsl");
860                 }
861                 if (!vertex_program.empty() || !pixel_program.empty() || !geometry_program.empty()){
862                         is_highlevel = true;
863                         return;
864                 }
865         }
866
867 }
868
869 void dumpShaderProgram(std::ostream &output_stream,
870                 const std::string &program_type, const std::string &program)
871 {
872         output_stream << program_type << " shader program:" << std::endl <<
873                 "----------------------------------" << std::endl;
874         size_t pos = 0;
875         size_t prev = 0;
876         s16 line = 1;
877         while ((pos = program.find('\n', prev)) != std::string::npos) {
878                 output_stream << line++ << ": "<< program.substr(prev, pos - prev) <<
879                         std::endl;
880                 prev = pos + 1;
881         }
882         output_stream << line << ": " << program.substr(prev) << std::endl <<
883                 "End of " << program_type << " shader program." << std::endl <<
884                 " " << std::endl;
885 }