]> git.lizzy.rs Git - minetest.git/blob - src/client/shader.cpp
Fix bone-attached entities (#10015)
[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_PLAIN_ALPHA:
541         case TILE_MATERIAL_LIQUID_TRANSPARENT:
542         case TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT:
543                 shaderinfo.base_material = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
544                 break;
545         case TILE_MATERIAL_BASIC:
546         case TILE_MATERIAL_PLAIN:
547         case TILE_MATERIAL_WAVING_LEAVES:
548         case TILE_MATERIAL_WAVING_PLANTS:
549         case TILE_MATERIAL_WAVING_LIQUID_BASIC:
550                 shaderinfo.base_material = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
551                 break;
552         }
553
554         bool enable_shaders = g_settings->getBool("enable_shaders");
555         if (!enable_shaders)
556                 return shaderinfo;
557
558         video::IVideoDriver *driver = RenderingEngine::get_video_driver();
559
560         video::IGPUProgrammingServices *gpu = driver->getGPUProgrammingServices();
561         if(!gpu){
562                 errorstream<<"generate_shader(): "
563                                 "failed to generate \""<<name<<"\", "
564                                 "GPU programming not supported."
565                                 <<std::endl;
566                 return shaderinfo;
567         }
568
569         // Choose shader language depending on driver type and settings
570         // Then load shaders
571         std::string vertex_program;
572         std::string pixel_program;
573         std::string geometry_program;
574         bool is_highlevel;
575         load_shaders(name, sourcecache, driver->getDriverType(),
576                         enable_shaders, vertex_program, pixel_program,
577                         geometry_program, is_highlevel);
578         // Check hardware/driver support
579         if (!vertex_program.empty() &&
580                         !driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1) &&
581                         !driver->queryFeature(video::EVDF_ARB_VERTEX_PROGRAM_1)){
582                 infostream<<"generate_shader(): vertex shaders disabled "
583                                 "because of missing driver/hardware support."
584                                 <<std::endl;
585                 vertex_program = "";
586         }
587         if (!pixel_program.empty() &&
588                         !driver->queryFeature(video::EVDF_PIXEL_SHADER_1_1) &&
589                         !driver->queryFeature(video::EVDF_ARB_FRAGMENT_PROGRAM_1)){
590                 infostream<<"generate_shader(): pixel shaders disabled "
591                                 "because of missing driver/hardware support."
592                                 <<std::endl;
593                 pixel_program = "";
594         }
595         if (!geometry_program.empty() &&
596                         !driver->queryFeature(video::EVDF_GEOMETRY_SHADER)){
597                 infostream<<"generate_shader(): geometry shaders disabled "
598                                 "because of missing driver/hardware support."
599                                 <<std::endl;
600                 geometry_program = "";
601         }
602
603         // If no shaders are used, don't make a separate material type
604         if (vertex_program.empty() && pixel_program.empty() && geometry_program.empty())
605                 return shaderinfo;
606
607         // Create shaders header
608         std::string shaders_header = "#version 120\n";
609
610         static const char* drawTypes[] = {
611                 "NDT_NORMAL",
612                 "NDT_AIRLIKE",
613                 "NDT_LIQUID",
614                 "NDT_FLOWINGLIQUID",
615                 "NDT_GLASSLIKE",
616                 "NDT_ALLFACES",
617                 "NDT_ALLFACES_OPTIONAL",
618                 "NDT_TORCHLIKE",
619                 "NDT_SIGNLIKE",
620                 "NDT_PLANTLIKE",
621                 "NDT_FENCELIKE",
622                 "NDT_RAILLIKE",
623                 "NDT_NODEBOX",
624                 "NDT_GLASSLIKE_FRAMED",
625                 "NDT_FIRELIKE",
626                 "NDT_GLASSLIKE_FRAMED_OPTIONAL",
627                 "NDT_PLANTLIKE_ROOTED",
628         };
629
630         for (int i = 0; i < 14; i++){
631                 shaders_header += "#define ";
632                 shaders_header += drawTypes[i];
633                 shaders_header += " ";
634                 shaders_header += itos(i);
635                 shaders_header += "\n";
636         }
637
638         static const char* materialTypes[] = {
639                 "TILE_MATERIAL_BASIC",
640                 "TILE_MATERIAL_ALPHA",
641                 "TILE_MATERIAL_LIQUID_TRANSPARENT",
642                 "TILE_MATERIAL_LIQUID_OPAQUE",
643                 "TILE_MATERIAL_WAVING_LEAVES",
644                 "TILE_MATERIAL_WAVING_PLANTS",
645                 "TILE_MATERIAL_OPAQUE",
646                 "TILE_MATERIAL_WAVING_LIQUID_BASIC",
647                 "TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT",
648                 "TILE_MATERIAL_WAVING_LIQUID_OPAQUE",
649                 "TILE_MATERIAL_PLAIN",
650                 "TILE_MATERIAL_PLAIN_ALPHA",
651         };
652
653         for (int i = 0; i < 12; i++){
654                 shaders_header += "#define ";
655                 shaders_header += materialTypes[i];
656                 shaders_header += " ";
657                 shaders_header += itos(i);
658                 shaders_header += "\n";
659         }
660
661         shaders_header += "#define MATERIAL_TYPE ";
662         shaders_header += itos(material_type);
663         shaders_header += "\n";
664         shaders_header += "#define DRAW_TYPE ";
665         shaders_header += itos(drawtype);
666         shaders_header += "\n";
667
668         if (g_settings->getBool("generate_normalmaps")) {
669                 shaders_header += "#define GENERATE_NORMALMAPS 1\n";
670         } else {
671                 shaders_header += "#define GENERATE_NORMALMAPS 0\n";
672         }
673         shaders_header += "#define NORMALMAPS_STRENGTH ";
674         shaders_header += ftos(g_settings->getFloat("normalmaps_strength"));
675         shaders_header += "\n";
676         float sample_step;
677         int smooth = (int)g_settings->getFloat("normalmaps_smooth");
678         switch (smooth){
679         case 0:
680                 sample_step = 0.0078125; // 1.0 / 128.0
681                 break;
682         case 1:
683                 sample_step = 0.00390625; // 1.0 / 256.0
684                 break;
685         case 2:
686                 sample_step = 0.001953125; // 1.0 / 512.0
687                 break;
688         default:
689                 sample_step = 0.0078125;
690                 break;
691         }
692         shaders_header += "#define SAMPLE_STEP ";
693         shaders_header += ftos(sample_step);
694         shaders_header += "\n";
695
696         if (g_settings->getBool("enable_bumpmapping"))
697                 shaders_header += "#define ENABLE_BUMPMAPPING\n";
698
699         if (g_settings->getBool("enable_parallax_occlusion")){
700                 int mode = g_settings->getFloat("parallax_occlusion_mode");
701                 float scale = g_settings->getFloat("parallax_occlusion_scale");
702                 float bias = g_settings->getFloat("parallax_occlusion_bias");
703                 int iterations = g_settings->getFloat("parallax_occlusion_iterations");
704                 shaders_header += "#define ENABLE_PARALLAX_OCCLUSION\n";
705                 shaders_header += "#define PARALLAX_OCCLUSION_MODE ";
706                 shaders_header += itos(mode);
707                 shaders_header += "\n";
708                 shaders_header += "#define PARALLAX_OCCLUSION_SCALE ";
709                 shaders_header += ftos(scale);
710                 shaders_header += "\n";
711                 shaders_header += "#define PARALLAX_OCCLUSION_BIAS ";
712                 shaders_header += ftos(bias);
713                 shaders_header += "\n";
714                 shaders_header += "#define PARALLAX_OCCLUSION_ITERATIONS ";
715                 shaders_header += itos(iterations);
716                 shaders_header += "\n";
717         }
718
719         shaders_header += "#define USE_NORMALMAPS ";
720         if (g_settings->getBool("enable_bumpmapping") || g_settings->getBool("enable_parallax_occlusion"))
721                 shaders_header += "1\n";
722         else
723                 shaders_header += "0\n";
724
725         if (g_settings->getBool("enable_waving_water")){
726                 shaders_header += "#define ENABLE_WAVING_WATER 1\n";
727                 shaders_header += "#define WATER_WAVE_HEIGHT ";
728                 shaders_header += ftos(g_settings->getFloat("water_wave_height"));
729                 shaders_header += "\n";
730                 shaders_header += "#define WATER_WAVE_LENGTH ";
731                 shaders_header += ftos(g_settings->getFloat("water_wave_length"));
732                 shaders_header += "\n";
733                 shaders_header += "#define WATER_WAVE_SPEED ";
734                 shaders_header += ftos(g_settings->getFloat("water_wave_speed"));
735                 shaders_header += "\n";
736         } else{
737                 shaders_header += "#define ENABLE_WAVING_WATER 0\n";
738         }
739
740         shaders_header += "#define ENABLE_WAVING_LEAVES ";
741         if (g_settings->getBool("enable_waving_leaves"))
742                 shaders_header += "1\n";
743         else
744                 shaders_header += "0\n";
745
746         shaders_header += "#define ENABLE_WAVING_PLANTS ";
747         if (g_settings->getBool("enable_waving_plants"))
748                 shaders_header += "1\n";
749         else
750                 shaders_header += "0\n";
751
752         if (g_settings->getBool("tone_mapping"))
753                 shaders_header += "#define ENABLE_TONE_MAPPING\n";
754
755         shaders_header += "#define FOG_START ";
756         shaders_header += ftos(rangelim(g_settings->getFloat("fog_start"), 0.0f, 0.99f));
757         shaders_header += "\n";
758
759         // Call addHighLevelShaderMaterial() or addShaderMaterial()
760         const c8* vertex_program_ptr = 0;
761         const c8* pixel_program_ptr = 0;
762         const c8* geometry_program_ptr = 0;
763         if (!vertex_program.empty()) {
764                 vertex_program = shaders_header + vertex_program;
765                 vertex_program_ptr = vertex_program.c_str();
766         }
767         if (!pixel_program.empty()) {
768                 pixel_program = shaders_header + pixel_program;
769                 pixel_program_ptr = pixel_program.c_str();
770         }
771         if (!geometry_program.empty()) {
772                 geometry_program = shaders_header + geometry_program;
773                 geometry_program_ptr = geometry_program.c_str();
774         }
775         ShaderCallback *cb = new ShaderCallback(setter_factories);
776         s32 shadermat = -1;
777         if(is_highlevel){
778                 infostream<<"Compiling high level shaders for "<<name<<std::endl;
779                 shadermat = gpu->addHighLevelShaderMaterial(
780                         vertex_program_ptr,   // Vertex shader program
781                         "vertexMain",         // Vertex shader entry point
782                         video::EVST_VS_1_1,   // Vertex shader version
783                         pixel_program_ptr,    // Pixel shader program
784                         "pixelMain",          // Pixel shader entry point
785                         video::EPST_PS_1_2,   // Pixel shader version
786                         geometry_program_ptr, // Geometry shader program
787                         "geometryMain",       // Geometry shader entry point
788                         video::EGST_GS_4_0,   // Geometry shader version
789                         scene::EPT_TRIANGLES,      // Geometry shader input
790                         scene::EPT_TRIANGLE_STRIP, // Geometry shader output
791                         0,                         // Support maximum number of vertices
792                         cb, // Set-constant callback
793                         shaderinfo.base_material,  // Base material
794                         1                          // Userdata passed to callback
795                         );
796                 if(shadermat == -1){
797                         errorstream<<"generate_shader(): "
798                                         "failed to generate \""<<name<<"\", "
799                                         "addHighLevelShaderMaterial failed."
800                                         <<std::endl;
801                         dumpShaderProgram(warningstream, "Vertex", vertex_program);
802                         dumpShaderProgram(warningstream, "Pixel", pixel_program);
803                         dumpShaderProgram(warningstream, "Geometry", geometry_program);
804                         delete cb;
805                         return shaderinfo;
806                 }
807         }
808         else{
809                 infostream<<"Compiling assembly shaders for "<<name<<std::endl;
810                 shadermat = gpu->addShaderMaterial(
811                         vertex_program_ptr,   // Vertex shader program
812                         pixel_program_ptr,    // Pixel shader program
813                         cb, // Set-constant callback
814                         shaderinfo.base_material,  // Base material
815                         0                     // Userdata passed to callback
816                         );
817
818                 if(shadermat == -1){
819                         errorstream<<"generate_shader(): "
820                                         "failed to generate \""<<name<<"\", "
821                                         "addShaderMaterial failed."
822                                         <<std::endl;
823                         dumpShaderProgram(warningstream, "Vertex", vertex_program);
824                         dumpShaderProgram(warningstream,"Pixel", pixel_program);
825                         delete cb;
826                         return shaderinfo;
827                 }
828         }
829         callbacks.push_back(cb);
830
831         // HACK, TODO: investigate this better
832         // Grab the material renderer once more so minetest doesn't crash on exit
833         driver->getMaterialRenderer(shadermat)->grab();
834
835         // Apply the newly created material type
836         shaderinfo.material = (video::E_MATERIAL_TYPE) shadermat;
837         return shaderinfo;
838 }
839
840 void load_shaders(const std::string &name, SourceShaderCache *sourcecache,
841                 video::E_DRIVER_TYPE drivertype, bool enable_shaders,
842                 std::string &vertex_program, std::string &pixel_program,
843                 std::string &geometry_program, bool &is_highlevel)
844 {
845         vertex_program = "";
846         pixel_program = "";
847         geometry_program = "";
848         is_highlevel = false;
849
850         if(enable_shaders){
851                 // Look for high level shaders
852                 if(drivertype == video::EDT_DIRECT3D9){
853                         // Direct3D 9: HLSL
854                         // (All shaders in one file)
855                         vertex_program = sourcecache->getOrLoad(name, "d3d9.hlsl");
856                         pixel_program = vertex_program;
857                         geometry_program = vertex_program;
858                 }
859                 else if(drivertype == video::EDT_OPENGL){
860                         // OpenGL: GLSL
861                         vertex_program = sourcecache->getOrLoad(name, "opengl_vertex.glsl");
862                         pixel_program = sourcecache->getOrLoad(name, "opengl_fragment.glsl");
863                         geometry_program = sourcecache->getOrLoad(name, "opengl_geometry.glsl");
864                 }
865                 if (!vertex_program.empty() || !pixel_program.empty() || !geometry_program.empty()){
866                         is_highlevel = true;
867                         return;
868                 }
869         }
870
871 }
872
873 void dumpShaderProgram(std::ostream &output_stream,
874                 const std::string &program_type, const std::string &program)
875 {
876         output_stream << program_type << " shader program:" << std::endl <<
877                 "----------------------------------" << std::endl;
878         size_t pos = 0;
879         size_t prev = 0;
880         s16 line = 1;
881         while ((pos = program.find('\n', prev)) != std::string::npos) {
882                 output_stream << line++ << ": "<< program.substr(prev, pos - prev) <<
883                         std::endl;
884                 prev = pos + 1;
885         }
886         output_stream << line << ": " << program.substr(prev) << std::endl <<
887                 "End of " << program_type << " shader program." << std::endl <<
888                 " " << std::endl;
889 }