shader.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873
  1. /*
  2. Minetest
  3. Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
  4. Copyright (C) 2013 Kahrl <kahrl@gmx.net>
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU Lesser General Public License as published by
  7. the Free Software Foundation; either version 2.1 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU Lesser General Public License for more details.
  13. You should have received a copy of the GNU Lesser General Public License along
  14. with this program; if not, write to the Free Software Foundation, Inc.,
  15. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  16. */
  17. #include <fstream>
  18. #include <iterator>
  19. #include "shader.h"
  20. #include "irrlichttypes_extrabloated.h"
  21. #include "debug.h"
  22. #include "filesys.h"
  23. #include "util/container.h"
  24. #include "util/thread.h"
  25. #include "settings.h"
  26. #include <ICameraSceneNode.h>
  27. #include <IGPUProgrammingServices.h>
  28. #include <IMaterialRenderer.h>
  29. #include <IMaterialRendererServices.h>
  30. #include <IShaderConstantSetCallBack.h>
  31. #include "client/renderingengine.h"
  32. #include "EShaderTypes.h"
  33. #include "log.h"
  34. #include "gamedef.h"
  35. #include "client/tile.h"
  36. /*
  37. A cache from shader name to shader path
  38. */
  39. MutexedMap<std::string, std::string> g_shadername_to_path_cache;
  40. /*
  41. Gets the path to a shader by first checking if the file
  42. name_of_shader/filename
  43. exists in shader_path and if not, using the data path.
  44. If not found, returns "".
  45. Utilizes a thread-safe cache.
  46. */
  47. std::string getShaderPath(const std::string &name_of_shader,
  48. const std::string &filename)
  49. {
  50. std::string combined = name_of_shader + DIR_DELIM + filename;
  51. std::string fullpath;
  52. /*
  53. Check from cache
  54. */
  55. bool incache = g_shadername_to_path_cache.get(combined, &fullpath);
  56. if(incache)
  57. return fullpath;
  58. /*
  59. Check from shader_path
  60. */
  61. std::string shader_path = g_settings->get("shader_path");
  62. if (!shader_path.empty()) {
  63. std::string testpath = shader_path + DIR_DELIM + combined;
  64. if(fs::PathExists(testpath))
  65. fullpath = testpath;
  66. }
  67. /*
  68. Check from default data directory
  69. */
  70. if (fullpath.empty()) {
  71. std::string rel_path = std::string("client") + DIR_DELIM
  72. + "shaders" + DIR_DELIM
  73. + name_of_shader + DIR_DELIM
  74. + filename;
  75. std::string testpath = porting::path_share + DIR_DELIM + rel_path;
  76. if(fs::PathExists(testpath))
  77. fullpath = testpath;
  78. }
  79. // Add to cache (also an empty result is cached)
  80. g_shadername_to_path_cache.set(combined, fullpath);
  81. // Finally return it
  82. return fullpath;
  83. }
  84. /*
  85. SourceShaderCache: A cache used for storing source shaders.
  86. */
  87. class SourceShaderCache
  88. {
  89. public:
  90. void insert(const std::string &name_of_shader, const std::string &filename,
  91. const std::string &program, bool prefer_local)
  92. {
  93. std::string combined = name_of_shader + DIR_DELIM + filename;
  94. // Try to use local shader instead if asked to
  95. if(prefer_local){
  96. std::string path = getShaderPath(name_of_shader, filename);
  97. if(!path.empty()){
  98. std::string p = readFile(path);
  99. if (!p.empty()) {
  100. m_programs[combined] = p;
  101. return;
  102. }
  103. }
  104. }
  105. m_programs[combined] = program;
  106. }
  107. std::string get(const std::string &name_of_shader,
  108. const std::string &filename)
  109. {
  110. std::string combined = name_of_shader + DIR_DELIM + filename;
  111. StringMap::iterator n = m_programs.find(combined);
  112. if (n != m_programs.end())
  113. return n->second;
  114. return "";
  115. }
  116. // Primarily fetches from cache, secondarily tries to read from filesystem
  117. std::string getOrLoad(const std::string &name_of_shader,
  118. const std::string &filename)
  119. {
  120. std::string combined = name_of_shader + DIR_DELIM + filename;
  121. StringMap::iterator n = m_programs.find(combined);
  122. if (n != m_programs.end())
  123. return n->second;
  124. std::string path = getShaderPath(name_of_shader, filename);
  125. if (path.empty()) {
  126. infostream << "SourceShaderCache::getOrLoad(): No path found for \""
  127. << combined << "\"" << std::endl;
  128. return "";
  129. }
  130. infostream << "SourceShaderCache::getOrLoad(): Loading path \""
  131. << path << "\"" << std::endl;
  132. std::string p = readFile(path);
  133. if (!p.empty()) {
  134. m_programs[combined] = p;
  135. return p;
  136. }
  137. return "";
  138. }
  139. private:
  140. StringMap m_programs;
  141. std::string readFile(const std::string &path)
  142. {
  143. std::ifstream is(path.c_str(), std::ios::binary);
  144. if(!is.is_open())
  145. return "";
  146. std::ostringstream tmp_os;
  147. tmp_os << is.rdbuf();
  148. return tmp_os.str();
  149. }
  150. };
  151. /*
  152. ShaderCallback: Sets constants that can be used in shaders
  153. */
  154. class ShaderCallback : public video::IShaderConstantSetCallBack
  155. {
  156. std::vector<IShaderConstantSetter*> m_setters;
  157. public:
  158. ShaderCallback(const std::vector<IShaderConstantSetterFactory *> &factories)
  159. {
  160. for (IShaderConstantSetterFactory *factory : factories)
  161. m_setters.push_back(factory->create());
  162. }
  163. ~ShaderCallback()
  164. {
  165. for (IShaderConstantSetter *setter : m_setters)
  166. delete setter;
  167. }
  168. virtual void OnSetConstants(video::IMaterialRendererServices *services, s32 userData)
  169. {
  170. video::IVideoDriver *driver = services->getVideoDriver();
  171. sanity_check(driver != NULL);
  172. bool is_highlevel = userData;
  173. for (IShaderConstantSetter *setter : m_setters)
  174. setter->onSetConstants(services, is_highlevel);
  175. }
  176. };
  177. /*
  178. MainShaderConstantSetter: Set basic constants required for almost everything
  179. */
  180. class MainShaderConstantSetter : public IShaderConstantSetter
  181. {
  182. CachedVertexShaderSetting<float, 16> m_world_view_proj;
  183. CachedVertexShaderSetting<float, 16> m_world;
  184. public:
  185. MainShaderConstantSetter() :
  186. m_world_view_proj("mWorldViewProj"),
  187. m_world("mWorld")
  188. {}
  189. ~MainShaderConstantSetter() = default;
  190. virtual void onSetConstants(video::IMaterialRendererServices *services,
  191. bool is_highlevel)
  192. {
  193. video::IVideoDriver *driver = services->getVideoDriver();
  194. sanity_check(driver);
  195. // Set clip matrix
  196. core::matrix4 worldViewProj;
  197. worldViewProj = driver->getTransform(video::ETS_PROJECTION);
  198. worldViewProj *= driver->getTransform(video::ETS_VIEW);
  199. worldViewProj *= driver->getTransform(video::ETS_WORLD);
  200. if (is_highlevel)
  201. m_world_view_proj.set(*reinterpret_cast<float(*)[16]>(worldViewProj.pointer()), services);
  202. else
  203. services->setVertexShaderConstant(worldViewProj.pointer(), 0, 4);
  204. // Set world matrix
  205. core::matrix4 world = driver->getTransform(video::ETS_WORLD);
  206. if (is_highlevel)
  207. m_world.set(*reinterpret_cast<float(*)[16]>(world.pointer()), services);
  208. else
  209. services->setVertexShaderConstant(world.pointer(), 4, 4);
  210. }
  211. };
  212. class MainShaderConstantSetterFactory : public IShaderConstantSetterFactory
  213. {
  214. public:
  215. virtual IShaderConstantSetter* create()
  216. { return new MainShaderConstantSetter(); }
  217. };
  218. /*
  219. ShaderSource
  220. */
  221. class ShaderSource : public IWritableShaderSource
  222. {
  223. public:
  224. ShaderSource();
  225. ~ShaderSource();
  226. /*
  227. - If shader material specified by name is found from cache,
  228. return the cached id.
  229. - Otherwise generate the shader material, add to cache and return id.
  230. The id 0 points to a null shader. Its material is EMT_SOLID.
  231. */
  232. u32 getShaderIdDirect(const std::string &name,
  233. const u8 material_type, const u8 drawtype);
  234. /*
  235. If shader specified by the name pointed by the id doesn't
  236. exist, create it, then return id.
  237. Can be called from any thread. If called from some other thread
  238. and not found in cache, the call is queued to the main thread
  239. for processing.
  240. */
  241. u32 getShader(const std::string &name,
  242. const u8 material_type, const u8 drawtype);
  243. ShaderInfo getShaderInfo(u32 id);
  244. // Processes queued shader requests from other threads.
  245. // Shall be called from the main thread.
  246. void processQueue();
  247. // Insert a shader program into the cache without touching the
  248. // filesystem. Shall be called from the main thread.
  249. void insertSourceShader(const std::string &name_of_shader,
  250. const std::string &filename, const std::string &program);
  251. // Rebuild shaders from the current set of source shaders
  252. // Shall be called from the main thread.
  253. void rebuildShaders();
  254. void addShaderConstantSetterFactory(IShaderConstantSetterFactory *setter)
  255. {
  256. m_setter_factories.push_back(setter);
  257. }
  258. private:
  259. // The id of the thread that is allowed to use irrlicht directly
  260. std::thread::id m_main_thread;
  261. // Cache of source shaders
  262. // This should be only accessed from the main thread
  263. SourceShaderCache m_sourcecache;
  264. // A shader id is index in this array.
  265. // The first position contains a dummy shader.
  266. std::vector<ShaderInfo> m_shaderinfo_cache;
  267. // The former container is behind this mutex
  268. std::mutex m_shaderinfo_cache_mutex;
  269. // Queued shader fetches (to be processed by the main thread)
  270. RequestQueue<std::string, u32, u8, u8> m_get_shader_queue;
  271. // Global constant setter factories
  272. std::vector<IShaderConstantSetterFactory *> m_setter_factories;
  273. // Shader callbacks
  274. std::vector<ShaderCallback *> m_callbacks;
  275. };
  276. IWritableShaderSource *createShaderSource()
  277. {
  278. return new ShaderSource();
  279. }
  280. /*
  281. Generate shader given the shader name.
  282. */
  283. ShaderInfo generate_shader(const std::string &name,
  284. u8 material_type, u8 drawtype, std::vector<ShaderCallback *> &callbacks,
  285. const std::vector<IShaderConstantSetterFactory *> &setter_factories,
  286. SourceShaderCache *sourcecache);
  287. /*
  288. Load shader programs
  289. */
  290. void load_shaders(const std::string &name, SourceShaderCache *sourcecache,
  291. video::E_DRIVER_TYPE drivertype, bool enable_shaders,
  292. std::string &vertex_program, std::string &pixel_program,
  293. std::string &geometry_program, bool &is_highlevel);
  294. ShaderSource::ShaderSource()
  295. {
  296. m_main_thread = std::this_thread::get_id();
  297. // Add a dummy ShaderInfo as the first index, named ""
  298. m_shaderinfo_cache.emplace_back();
  299. // Add main global constant setter
  300. addShaderConstantSetterFactory(new MainShaderConstantSetterFactory());
  301. }
  302. ShaderSource::~ShaderSource()
  303. {
  304. for (ShaderCallback *callback : m_callbacks) {
  305. delete callback;
  306. }
  307. for (IShaderConstantSetterFactory *setter_factorie : m_setter_factories) {
  308. delete setter_factorie;
  309. }
  310. }
  311. u32 ShaderSource::getShader(const std::string &name,
  312. const u8 material_type, const u8 drawtype)
  313. {
  314. /*
  315. Get shader
  316. */
  317. if (std::this_thread::get_id() == m_main_thread) {
  318. return getShaderIdDirect(name, material_type, drawtype);
  319. }
  320. /*errorstream<<"getShader(): Queued: name=\""<<name<<"\""<<std::endl;*/
  321. // We're gonna ask the result to be put into here
  322. static ResultQueue<std::string, u32, u8, u8> result_queue;
  323. // Throw a request in
  324. m_get_shader_queue.add(name, 0, 0, &result_queue);
  325. /* infostream<<"Waiting for shader from main thread, name=\""
  326. <<name<<"\""<<std::endl;*/
  327. while(true) {
  328. GetResult<std::string, u32, u8, u8>
  329. result = result_queue.pop_frontNoEx();
  330. if (result.key == name) {
  331. return result.item;
  332. }
  333. errorstream << "Got shader with invalid name: " << result.key << std::endl;
  334. }
  335. infostream << "getShader(): Failed" << std::endl;
  336. return 0;
  337. }
  338. /*
  339. This method generates all the shaders
  340. */
  341. u32 ShaderSource::getShaderIdDirect(const std::string &name,
  342. const u8 material_type, const u8 drawtype)
  343. {
  344. //infostream<<"getShaderIdDirect(): name=\""<<name<<"\""<<std::endl;
  345. // Empty name means shader 0
  346. if (name.empty()) {
  347. infostream<<"getShaderIdDirect(): name is empty"<<std::endl;
  348. return 0;
  349. }
  350. // Check if already have such instance
  351. for(u32 i=0; i<m_shaderinfo_cache.size(); i++){
  352. ShaderInfo *info = &m_shaderinfo_cache[i];
  353. if(info->name == name && info->material_type == material_type &&
  354. info->drawtype == drawtype)
  355. return i;
  356. }
  357. /*
  358. Calling only allowed from main thread
  359. */
  360. if (std::this_thread::get_id() != m_main_thread) {
  361. errorstream<<"ShaderSource::getShaderIdDirect() "
  362. "called not from main thread"<<std::endl;
  363. return 0;
  364. }
  365. ShaderInfo info = generate_shader(name, material_type, drawtype,
  366. m_callbacks, m_setter_factories, &m_sourcecache);
  367. /*
  368. Add shader to caches (add dummy shaders too)
  369. */
  370. MutexAutoLock lock(m_shaderinfo_cache_mutex);
  371. u32 id = m_shaderinfo_cache.size();
  372. m_shaderinfo_cache.push_back(info);
  373. infostream<<"getShaderIdDirect(): "
  374. <<"Returning id="<<id<<" for name \""<<name<<"\""<<std::endl;
  375. return id;
  376. }
  377. ShaderInfo ShaderSource::getShaderInfo(u32 id)
  378. {
  379. MutexAutoLock lock(m_shaderinfo_cache_mutex);
  380. if(id >= m_shaderinfo_cache.size())
  381. return ShaderInfo();
  382. return m_shaderinfo_cache[id];
  383. }
  384. void ShaderSource::processQueue()
  385. {
  386. }
  387. void ShaderSource::insertSourceShader(const std::string &name_of_shader,
  388. const std::string &filename, const std::string &program)
  389. {
  390. /*infostream<<"ShaderSource::insertSourceShader(): "
  391. "name_of_shader=\""<<name_of_shader<<"\", "
  392. "filename=\""<<filename<<"\""<<std::endl;*/
  393. sanity_check(std::this_thread::get_id() == m_main_thread);
  394. m_sourcecache.insert(name_of_shader, filename, program, true);
  395. }
  396. void ShaderSource::rebuildShaders()
  397. {
  398. MutexAutoLock lock(m_shaderinfo_cache_mutex);
  399. /*// Oh well... just clear everything, they'll load sometime.
  400. m_shaderinfo_cache.clear();
  401. m_name_to_id.clear();*/
  402. /*
  403. FIXME: Old shader materials can't be deleted in Irrlicht,
  404. or can they?
  405. (This would be nice to do in the destructor too)
  406. */
  407. // Recreate shaders
  408. for (ShaderInfo &i : m_shaderinfo_cache) {
  409. ShaderInfo *info = &i;
  410. if (!info->name.empty()) {
  411. *info = generate_shader(info->name, info->material_type,
  412. info->drawtype, m_callbacks,
  413. m_setter_factories, &m_sourcecache);
  414. }
  415. }
  416. }
  417. ShaderInfo generate_shader(const std::string &name, u8 material_type, u8 drawtype,
  418. std::vector<ShaderCallback *> &callbacks,
  419. const std::vector<IShaderConstantSetterFactory *> &setter_factories,
  420. SourceShaderCache *sourcecache)
  421. {
  422. ShaderInfo shaderinfo;
  423. shaderinfo.name = name;
  424. shaderinfo.material_type = material_type;
  425. shaderinfo.drawtype = drawtype;
  426. shaderinfo.material = video::EMT_SOLID;
  427. switch (material_type) {
  428. case TILE_MATERIAL_OPAQUE:
  429. case TILE_MATERIAL_LIQUID_OPAQUE:
  430. shaderinfo.base_material = video::EMT_SOLID;
  431. break;
  432. case TILE_MATERIAL_ALPHA:
  433. case TILE_MATERIAL_LIQUID_TRANSPARENT:
  434. shaderinfo.base_material = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
  435. break;
  436. case TILE_MATERIAL_BASIC:
  437. case TILE_MATERIAL_WAVING_LEAVES:
  438. case TILE_MATERIAL_WAVING_PLANTS:
  439. shaderinfo.base_material = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
  440. break;
  441. }
  442. bool enable_shaders = g_settings->getBool("enable_shaders");
  443. if (!enable_shaders)
  444. return shaderinfo;
  445. video::IVideoDriver *driver = RenderingEngine::get_video_driver();
  446. video::IGPUProgrammingServices *gpu = driver->getGPUProgrammingServices();
  447. if(!gpu){
  448. errorstream<<"generate_shader(): "
  449. "failed to generate \""<<name<<"\", "
  450. "GPU programming not supported."
  451. <<std::endl;
  452. return shaderinfo;
  453. }
  454. // Choose shader language depending on driver type and settings
  455. // Then load shaders
  456. std::string vertex_program;
  457. std::string pixel_program;
  458. std::string geometry_program;
  459. bool is_highlevel;
  460. load_shaders(name, sourcecache, driver->getDriverType(),
  461. enable_shaders, vertex_program, pixel_program,
  462. geometry_program, is_highlevel);
  463. // Check hardware/driver support
  464. if (!vertex_program.empty() &&
  465. !driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1) &&
  466. !driver->queryFeature(video::EVDF_ARB_VERTEX_PROGRAM_1)){
  467. infostream<<"generate_shader(): vertex shaders disabled "
  468. "because of missing driver/hardware support."
  469. <<std::endl;
  470. vertex_program = "";
  471. }
  472. if (!pixel_program.empty() &&
  473. !driver->queryFeature(video::EVDF_PIXEL_SHADER_1_1) &&
  474. !driver->queryFeature(video::EVDF_ARB_FRAGMENT_PROGRAM_1)){
  475. infostream<<"generate_shader(): pixel shaders disabled "
  476. "because of missing driver/hardware support."
  477. <<std::endl;
  478. pixel_program = "";
  479. }
  480. if (!geometry_program.empty() &&
  481. !driver->queryFeature(video::EVDF_GEOMETRY_SHADER)){
  482. infostream<<"generate_shader(): geometry shaders disabled "
  483. "because of missing driver/hardware support."
  484. <<std::endl;
  485. geometry_program = "";
  486. }
  487. // If no shaders are used, don't make a separate material type
  488. if (vertex_program.empty() && pixel_program.empty() && geometry_program.empty())
  489. return shaderinfo;
  490. // Create shaders header
  491. std::string shaders_header = "#version 120\n";
  492. static const char* drawTypes[] = {
  493. "NDT_NORMAL",
  494. "NDT_AIRLIKE",
  495. "NDT_LIQUID",
  496. "NDT_FLOWINGLIQUID",
  497. "NDT_GLASSLIKE",
  498. "NDT_ALLFACES",
  499. "NDT_ALLFACES_OPTIONAL",
  500. "NDT_TORCHLIKE",
  501. "NDT_SIGNLIKE",
  502. "NDT_PLANTLIKE",
  503. "NDT_FENCELIKE",
  504. "NDT_RAILLIKE",
  505. "NDT_NODEBOX",
  506. "NDT_GLASSLIKE_FRAMED",
  507. "NDT_FIRELIKE",
  508. "NDT_GLASSLIKE_FRAMED_OPTIONAL",
  509. "NDT_PLANTLIKE_ROOTED",
  510. };
  511. for (int i = 0; i < 14; i++){
  512. shaders_header += "#define ";
  513. shaders_header += drawTypes[i];
  514. shaders_header += " ";
  515. shaders_header += itos(i);
  516. shaders_header += "\n";
  517. }
  518. static const char* materialTypes[] = {
  519. "TILE_MATERIAL_BASIC",
  520. "TILE_MATERIAL_ALPHA",
  521. "TILE_MATERIAL_LIQUID_TRANSPARENT",
  522. "TILE_MATERIAL_LIQUID_OPAQUE",
  523. "TILE_MATERIAL_WAVING_LEAVES",
  524. "TILE_MATERIAL_WAVING_PLANTS",
  525. "TILE_MATERIAL_OPAQUE"
  526. };
  527. for (int i = 0; i < 7; i++){
  528. shaders_header += "#define ";
  529. shaders_header += materialTypes[i];
  530. shaders_header += " ";
  531. shaders_header += itos(i);
  532. shaders_header += "\n";
  533. }
  534. shaders_header += "#define MATERIAL_TYPE ";
  535. shaders_header += itos(material_type);
  536. shaders_header += "\n";
  537. shaders_header += "#define DRAW_TYPE ";
  538. shaders_header += itos(drawtype);
  539. shaders_header += "\n";
  540. if (g_settings->getBool("generate_normalmaps")) {
  541. shaders_header += "#define GENERATE_NORMALMAPS 1\n";
  542. } else {
  543. shaders_header += "#define GENERATE_NORMALMAPS 0\n";
  544. }
  545. shaders_header += "#define NORMALMAPS_STRENGTH ";
  546. shaders_header += ftos(g_settings->getFloat("normalmaps_strength"));
  547. shaders_header += "\n";
  548. float sample_step;
  549. int smooth = (int)g_settings->getFloat("normalmaps_smooth");
  550. switch (smooth){
  551. case 0:
  552. sample_step = 0.0078125; // 1.0 / 128.0
  553. break;
  554. case 1:
  555. sample_step = 0.00390625; // 1.0 / 256.0
  556. break;
  557. case 2:
  558. sample_step = 0.001953125; // 1.0 / 512.0
  559. break;
  560. default:
  561. sample_step = 0.0078125;
  562. break;
  563. }
  564. shaders_header += "#define SAMPLE_STEP ";
  565. shaders_header += ftos(sample_step);
  566. shaders_header += "\n";
  567. if (g_settings->getBool("enable_bumpmapping"))
  568. shaders_header += "#define ENABLE_BUMPMAPPING\n";
  569. if (g_settings->getBool("enable_parallax_occlusion")){
  570. int mode = g_settings->getFloat("parallax_occlusion_mode");
  571. float scale = g_settings->getFloat("parallax_occlusion_scale");
  572. float bias = g_settings->getFloat("parallax_occlusion_bias");
  573. int iterations = g_settings->getFloat("parallax_occlusion_iterations");
  574. shaders_header += "#define ENABLE_PARALLAX_OCCLUSION\n";
  575. shaders_header += "#define PARALLAX_OCCLUSION_MODE ";
  576. shaders_header += itos(mode);
  577. shaders_header += "\n";
  578. shaders_header += "#define PARALLAX_OCCLUSION_SCALE ";
  579. shaders_header += ftos(scale);
  580. shaders_header += "\n";
  581. shaders_header += "#define PARALLAX_OCCLUSION_BIAS ";
  582. shaders_header += ftos(bias);
  583. shaders_header += "\n";
  584. shaders_header += "#define PARALLAX_OCCLUSION_ITERATIONS ";
  585. shaders_header += itos(iterations);
  586. shaders_header += "\n";
  587. }
  588. shaders_header += "#define USE_NORMALMAPS ";
  589. if (g_settings->getBool("enable_bumpmapping") || g_settings->getBool("enable_parallax_occlusion"))
  590. shaders_header += "1\n";
  591. else
  592. shaders_header += "0\n";
  593. if (g_settings->getBool("enable_waving_water")){
  594. shaders_header += "#define ENABLE_WAVING_WATER 1\n";
  595. shaders_header += "#define WATER_WAVE_HEIGHT ";
  596. shaders_header += ftos(g_settings->getFloat("water_wave_height"));
  597. shaders_header += "\n";
  598. shaders_header += "#define WATER_WAVE_LENGTH ";
  599. shaders_header += ftos(g_settings->getFloat("water_wave_length"));
  600. shaders_header += "\n";
  601. shaders_header += "#define WATER_WAVE_SPEED ";
  602. shaders_header += ftos(g_settings->getFloat("water_wave_speed"));
  603. shaders_header += "\n";
  604. } else{
  605. shaders_header += "#define ENABLE_WAVING_WATER 0\n";
  606. }
  607. shaders_header += "#define ENABLE_WAVING_LEAVES ";
  608. if (g_settings->getBool("enable_waving_leaves"))
  609. shaders_header += "1\n";
  610. else
  611. shaders_header += "0\n";
  612. shaders_header += "#define ENABLE_WAVING_PLANTS ";
  613. if (g_settings->getBool("enable_waving_plants"))
  614. shaders_header += "1\n";
  615. else
  616. shaders_header += "0\n";
  617. if (g_settings->getBool("tone_mapping"))
  618. shaders_header += "#define ENABLE_TONE_MAPPING\n";
  619. shaders_header += "#define FOG_START ";
  620. shaders_header += ftos(rangelim(g_settings->getFloat("fog_start"), 0.0f, 0.99f));
  621. shaders_header += "\n";
  622. // Call addHighLevelShaderMaterial() or addShaderMaterial()
  623. const c8* vertex_program_ptr = 0;
  624. const c8* pixel_program_ptr = 0;
  625. const c8* geometry_program_ptr = 0;
  626. if (!vertex_program.empty()) {
  627. vertex_program = shaders_header + vertex_program;
  628. vertex_program_ptr = vertex_program.c_str();
  629. }
  630. if (!pixel_program.empty()) {
  631. pixel_program = shaders_header + pixel_program;
  632. pixel_program_ptr = pixel_program.c_str();
  633. }
  634. if (!geometry_program.empty()) {
  635. geometry_program = shaders_header + geometry_program;
  636. geometry_program_ptr = geometry_program.c_str();
  637. }
  638. ShaderCallback *cb = new ShaderCallback(setter_factories);
  639. s32 shadermat = -1;
  640. if(is_highlevel){
  641. infostream<<"Compiling high level shaders for "<<name<<std::endl;
  642. shadermat = gpu->addHighLevelShaderMaterial(
  643. vertex_program_ptr, // Vertex shader program
  644. "vertexMain", // Vertex shader entry point
  645. video::EVST_VS_1_1, // Vertex shader version
  646. pixel_program_ptr, // Pixel shader program
  647. "pixelMain", // Pixel shader entry point
  648. video::EPST_PS_1_2, // Pixel shader version
  649. geometry_program_ptr, // Geometry shader program
  650. "geometryMain", // Geometry shader entry point
  651. video::EGST_GS_4_0, // Geometry shader version
  652. scene::EPT_TRIANGLES, // Geometry shader input
  653. scene::EPT_TRIANGLE_STRIP, // Geometry shader output
  654. 0, // Support maximum number of vertices
  655. cb, // Set-constant callback
  656. shaderinfo.base_material, // Base material
  657. 1 // Userdata passed to callback
  658. );
  659. if(shadermat == -1){
  660. errorstream<<"generate_shader(): "
  661. "failed to generate \""<<name<<"\", "
  662. "addHighLevelShaderMaterial failed."
  663. <<std::endl;
  664. dumpShaderProgram(warningstream, "Vertex", vertex_program);
  665. dumpShaderProgram(warningstream, "Pixel", pixel_program);
  666. dumpShaderProgram(warningstream, "Geometry", geometry_program);
  667. delete cb;
  668. return shaderinfo;
  669. }
  670. }
  671. else{
  672. infostream<<"Compiling assembly shaders for "<<name<<std::endl;
  673. shadermat = gpu->addShaderMaterial(
  674. vertex_program_ptr, // Vertex shader program
  675. pixel_program_ptr, // Pixel shader program
  676. cb, // Set-constant callback
  677. shaderinfo.base_material, // Base material
  678. 0 // Userdata passed to callback
  679. );
  680. if(shadermat == -1){
  681. errorstream<<"generate_shader(): "
  682. "failed to generate \""<<name<<"\", "
  683. "addShaderMaterial failed."
  684. <<std::endl;
  685. dumpShaderProgram(warningstream, "Vertex", vertex_program);
  686. dumpShaderProgram(warningstream,"Pixel", pixel_program);
  687. delete cb;
  688. return shaderinfo;
  689. }
  690. }
  691. callbacks.push_back(cb);
  692. // HACK, TODO: investigate this better
  693. // Grab the material renderer once more so minetest doesn't crash on exit
  694. driver->getMaterialRenderer(shadermat)->grab();
  695. // Apply the newly created material type
  696. shaderinfo.material = (video::E_MATERIAL_TYPE) shadermat;
  697. return shaderinfo;
  698. }
  699. void load_shaders(const std::string &name, SourceShaderCache *sourcecache,
  700. video::E_DRIVER_TYPE drivertype, bool enable_shaders,
  701. std::string &vertex_program, std::string &pixel_program,
  702. std::string &geometry_program, bool &is_highlevel)
  703. {
  704. vertex_program = "";
  705. pixel_program = "";
  706. geometry_program = "";
  707. is_highlevel = false;
  708. if(enable_shaders){
  709. // Look for high level shaders
  710. if(drivertype == video::EDT_DIRECT3D9){
  711. // Direct3D 9: HLSL
  712. // (All shaders in one file)
  713. vertex_program = sourcecache->getOrLoad(name, "d3d9.hlsl");
  714. pixel_program = vertex_program;
  715. geometry_program = vertex_program;
  716. }
  717. else if(drivertype == video::EDT_OPENGL){
  718. // OpenGL: GLSL
  719. vertex_program = sourcecache->getOrLoad(name, "opengl_vertex.glsl");
  720. pixel_program = sourcecache->getOrLoad(name, "opengl_fragment.glsl");
  721. geometry_program = sourcecache->getOrLoad(name, "opengl_geometry.glsl");
  722. }
  723. if (!vertex_program.empty() || !pixel_program.empty() || !geometry_program.empty()){
  724. is_highlevel = true;
  725. return;
  726. }
  727. }
  728. }
  729. void dumpShaderProgram(std::ostream &output_stream,
  730. const std::string &program_type, const std::string &program)
  731. {
  732. output_stream << program_type << " shader program:" << std::endl <<
  733. "----------------------------------" << std::endl;
  734. size_t pos = 0;
  735. size_t prev = 0;
  736. s16 line = 1;
  737. while ((pos = program.find('\n', prev)) != std::string::npos) {
  738. output_stream << line++ << ": "<< program.substr(prev, pos - prev) <<
  739. std::endl;
  740. prev = pos + 1;
  741. }
  742. output_stream << line << ": " << program.substr(prev) << std::endl <<
  743. "End of " << program_type << " shader program." << std::endl <<
  744. " " << std::endl;
  745. }