CPass.cpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802
  1. #include <sstream>
  2. #include "CPass.h"
  3. #include "WallpaperEngine/Render/CFBO.h"
  4. #include "WallpaperEngine/Render/Shaders/Variables/CShaderVariable.h"
  5. #include "WallpaperEngine/Render/Shaders/Variables/CShaderVariableFloat.h"
  6. #include "WallpaperEngine/Render/Shaders/Variables/CShaderVariableInteger.h"
  7. #include "WallpaperEngine/Render/Shaders/Variables/CShaderVariableVector2.h"
  8. #include "WallpaperEngine/Render/Shaders/Variables/CShaderVariableVector3.h"
  9. #include "WallpaperEngine/Render/Shaders/Variables/CShaderVariableVector4.h"
  10. #include "WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstant.h"
  11. #include "WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantFloat.h"
  12. #include "WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantInteger.h"
  13. #include "WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantVector4.h"
  14. using namespace WallpaperEngine::Core::Objects::Effects::Constants;
  15. using namespace WallpaperEngine::Render::Shaders::Variables;
  16. using namespace WallpaperEngine::Render::Objects::Effects;
  17. extern float g_Time;
  18. CPass::CPass (CMaterial* material, Core::Objects::Images::Materials::CPass* pass) :
  19. m_material (material),
  20. m_pass (pass)
  21. {
  22. this->setupTextures ();
  23. this->setupShaders ();
  24. this->setupShaderVariables ();
  25. }
  26. ITexture* CPass::resolveTexture (ITexture* expected, int index, ITexture* previous)
  27. {
  28. if (expected == nullptr)
  29. {
  30. auto it = this->m_fbos.find (index);
  31. if (it != this->m_fbos.end ())
  32. expected = (*it).second;
  33. }
  34. // first check in the binds and replace it if necessary
  35. auto it = this->m_material->getMaterial ()->getTextureBinds ().find (index);
  36. if (it == this->m_material->getMaterial ()->getTextureBinds ().end ())
  37. return expected;
  38. // a bind named "previous" is just another way of telling it to use whatever texture there was already
  39. if ((*it).second->getName () == "previous")
  40. if (previous == nullptr)
  41. return expected;
  42. else
  43. return previous;
  44. // the bind actually has a name, search the FBO in the effect and return it
  45. auto fbo = this->m_material->m_effect->findFBO ((*it).second->getName ());
  46. if (fbo == nullptr)
  47. return nullptr;
  48. return fbo;
  49. }
  50. void CPass::render (CFBO* drawTo, ITexture* input, GLuint position, GLuint texcoord, glm::mat4 projection)
  51. {
  52. // set the framebuffer we're drawing to
  53. glBindFramebuffer (GL_FRAMEBUFFER, drawTo->getFramebuffer ());
  54. // set proper viewport based on what we're drawing to
  55. glViewport (0, 0, drawTo->getRealWidth (), drawTo->getRealHeight ());
  56. if (drawTo != this->m_material->getImage ()->getScene ()->getFBO())
  57. glClear (GL_COLOR_BUFFER_BIT);
  58. // set texture blending
  59. if (this->m_pass->getBlendingMode () == "translucent")
  60. {
  61. glEnable (GL_BLEND);
  62. glBlendFuncSeparate (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  63. }
  64. else if (this->m_pass->getBlendingMode () == "additive")
  65. {
  66. glEnable (GL_BLEND);
  67. glBlendFuncSeparate (GL_SRC_ALPHA, GL_ONE, GL_SRC_ALPHA, GL_ONE);
  68. }
  69. else if (this->m_pass->getBlendingMode () == "normal")
  70. {
  71. glEnable (GL_BLEND);
  72. glBlendFuncSeparate (GL_ONE, GL_ZERO, GL_ONE, GL_ZERO);
  73. }
  74. else
  75. {
  76. glDisable (GL_BLEND);
  77. }
  78. // set depth testing
  79. if (this->m_pass->getDepthTest () == "disabled")
  80. {
  81. glDisable (GL_DEPTH_TEST);
  82. }
  83. else
  84. {
  85. glEnable (GL_DEPTH_TEST);
  86. }
  87. if (this->m_pass->getCullingMode () == "nocull")
  88. {
  89. glDisable (GL_CULL_FACE);
  90. }
  91. else
  92. {
  93. glEnable (GL_CULL_FACE);
  94. }
  95. if (this->m_pass->getDepthWrite () == "disabled")
  96. {
  97. glDepthMask (false);
  98. }
  99. else
  100. {
  101. glDepthMask (true);
  102. }
  103. // update variables used in the render process (like g_ModelViewProjectionMatrix)
  104. this->m_modelViewProjectionMatrix = projection;
  105. // update a_TexCoord and a_Position based on what to draw to
  106. // this should not be required once we do some prediction on rendering things
  107. // but for now should be enough
  108. this->a_TexCoord = texcoord;
  109. this->a_Position = position;
  110. // use the shader we have registered
  111. glUseProgram (this->m_programID);
  112. ITexture* texture = this->resolveTexture (input, 0, input);
  113. uint32_t currentTexture = 0;
  114. glm::vec2 translation = {0.0f, 0.0f};
  115. glm::vec4 rotation = {0.0f, 0.0f, 0.0f, 0.0f};
  116. if (texture->isAnimated () == true)
  117. {
  118. // calculate current texture and frame
  119. double currentRenderTime = fmod (static_cast <double> (g_Time), this->m_material->getImage ()->getAnimationTime ());
  120. // find the right frame now
  121. auto frameCur = texture->getFrames ().begin ();
  122. auto frameEnd = texture->getFrames ().end ();
  123. for (; frameCur != frameEnd; frameCur ++)
  124. {
  125. currentRenderTime -= (*frameCur)->frametime;
  126. if (currentRenderTime <= 0.0f)
  127. {
  128. // frame found, store coordinates and done
  129. currentTexture = (*frameCur)->frameNumber;
  130. translation.x = (*frameCur)->x / texture->getTextureWidth (currentTexture);
  131. translation.y = (*frameCur)->y / texture->getTextureHeight (currentTexture);
  132. rotation.x = (*frameCur)->width1 / static_cast<float> (texture->getTextureWidth (currentTexture));
  133. rotation.y = (*frameCur)->width2 / static_cast<float> (texture->getTextureWidth(currentTexture));
  134. rotation.z = (*frameCur)->height2 / static_cast<float> (texture->getTextureHeight (currentTexture));
  135. rotation.w = (*frameCur)->height1 / static_cast<float> (texture->getTextureHeight (currentTexture));
  136. break;
  137. }
  138. }
  139. }
  140. glActiveTexture (GL_TEXTURE0);
  141. glBindTexture (GL_TEXTURE_2D, texture->getTextureID (currentTexture));
  142. int lastTextureIndex = 0;
  143. // first bind the textures to their sampler place
  144. {
  145. // set texture slots for the shader
  146. auto cur = this->m_textures.begin ();
  147. auto end = this->m_textures.end ();
  148. for (int index = 1; cur != end; cur ++, index ++)
  149. {
  150. texture = this->resolveTexture ((*cur), index, input);
  151. glActiveTexture (GL_TEXTURE0 + index);
  152. glBindTexture (GL_TEXTURE_2D, texture->getTextureID (0));
  153. // increase the number of textures counter
  154. lastTextureIndex ++;
  155. }
  156. }
  157. {
  158. // load the extra textures needed (if any) from the shader
  159. auto cur = this->m_fragShader->getTextures ().begin ();
  160. auto end = this->m_fragShader->getTextures ().end ();
  161. for (; cur != end; cur ++)
  162. {
  163. if ((*cur).first <= lastTextureIndex)
  164. continue;
  165. texture = this->resolveTexture ((*cur).second, (*cur).first, input);
  166. if (texture == nullptr)
  167. continue;
  168. // set the active texture index
  169. glActiveTexture (GL_TEXTURE0 + (*cur).first);
  170. // bind the correct texture here
  171. glBindTexture(GL_TEXTURE_2D, texture->getTextureID (0));
  172. }
  173. }
  174. {
  175. // load the extra textures needed (if any) from the shader
  176. auto cur = this->m_vertShader->getTextures ().begin ();
  177. auto end = this->m_vertShader->getTextures ().end ();
  178. for (; cur != end; cur ++)
  179. {
  180. if ((*cur).first <= lastTextureIndex)
  181. continue;
  182. texture = this->resolveTexture ((*cur).second, (*cur).first, input);
  183. if (texture == nullptr)
  184. continue;
  185. // set the active texture index
  186. glActiveTexture (GL_TEXTURE0 + (*cur).first);
  187. // bind the correct texture here
  188. glBindTexture(GL_TEXTURE_2D, texture->getTextureID (0));
  189. }
  190. }
  191. // add uniforms
  192. {
  193. auto cur = this->m_uniforms.begin ();
  194. auto end = this->m_uniforms.end ();
  195. for (; cur != end; cur ++)
  196. {
  197. UniformEntry* entry = (*cur).second;
  198. switch (entry->type)
  199. {
  200. case Double:
  201. glUniform1d (entry->id, *reinterpret_cast <const double*> (entry->value));
  202. break;
  203. case Float:
  204. glUniform1f (entry->id, *reinterpret_cast <const float*> (entry->value));
  205. break;
  206. case Integer:
  207. glUniform1i (entry->id, *reinterpret_cast <const int*> (entry->value));
  208. break;
  209. case Vector4:
  210. glUniform4fv (entry->id, 1, glm::value_ptr (*reinterpret_cast <const glm::vec4*> (entry->value)));
  211. break;
  212. case Vector3:
  213. glUniform3fv (entry->id, 1, glm::value_ptr (*reinterpret_cast <const glm::vec3*> (entry->value)));
  214. break;
  215. case Vector2:
  216. glUniform2fv (entry->id, 1, glm::value_ptr (*reinterpret_cast <const glm::vec2*> (entry->value)));
  217. break;
  218. case Matrix4:
  219. glUniformMatrix4fv (entry->id, 1, GL_FALSE, glm::value_ptr (*reinterpret_cast <const glm::mat4*> (entry->value)));
  220. break;
  221. }
  222. }
  223. }
  224. if (this->g_Texture0Rotation != -1)
  225. {
  226. // used in animations when one of the frames is vertical instead of horizontal
  227. // rotation with translation = origin and end of the image to display
  228. glUniform4f (this->g_Texture0Rotation, rotation.x, rotation.y, rotation.z, rotation.w);
  229. }
  230. if (this->g_Texture0Translation != -1)
  231. {
  232. // this actually picks the origin point of the image from the atlast
  233. glUniform2f (this->g_Texture0Translation, translation.x, translation.y);
  234. }
  235. {
  236. auto cur = this->m_attribs.begin ();
  237. auto end = this->m_attribs.end ();
  238. for (; cur != end; cur ++)
  239. {
  240. glEnableVertexAttribArray ((*cur)->id);
  241. glBindBuffer (GL_ARRAY_BUFFER, *(*cur)->value);
  242. glVertexAttribPointer ((*cur)->id, (*cur)->elements, (*cur)->type, GL_FALSE, 0, nullptr);
  243. }
  244. }
  245. // start actual rendering now
  246. glBindBuffer (GL_ARRAY_BUFFER, position);
  247. glDrawArrays (GL_TRIANGLES, 0, 6);
  248. // disable vertex attribs array
  249. {
  250. auto cur = this->m_attribs.begin ();
  251. auto end = this->m_attribs.end ();
  252. for (; cur != end; cur ++)
  253. glDisableVertexAttribArray ((*cur)->id);
  254. }
  255. }
  256. GLuint CPass::compileShader (Render::Shaders::Compiler* shader, GLuint type)
  257. {
  258. // reserve shaders in OpenGL
  259. GLuint shaderID = glCreateShader (type);
  260. // give shader's source code to OpenGL to be compiled
  261. const char* sourcePointer = shader->getCompiled ().c_str ();
  262. glShaderSource (shaderID, 1, &sourcePointer, nullptr);
  263. glCompileShader (shaderID);
  264. GLint result = GL_FALSE;
  265. int infoLogLength = 0;
  266. // ensure the vertex shader was correctly compiled
  267. glGetShaderiv (shaderID, GL_COMPILE_STATUS, &result);
  268. glGetShaderiv (shaderID, GL_INFO_LOG_LENGTH, &infoLogLength);
  269. if (infoLogLength > 0)
  270. {
  271. char* logBuffer = new char [infoLogLength + 1];
  272. // ensure logBuffer ends with a \0
  273. memset (logBuffer, 0, infoLogLength + 1);
  274. // get information about the error
  275. glGetShaderInfoLog (shaderID, infoLogLength, nullptr, logBuffer);
  276. // throw an exception about the issue
  277. std::stringstream buffer;
  278. buffer << logBuffer << std::endl << "Compiled source code:" << std::endl << shader->getCompiled ();
  279. // free the buffer
  280. delete[] logBuffer;
  281. // throw an exception
  282. throw std::runtime_error (buffer.str());
  283. }
  284. return shaderID;
  285. }
  286. void CPass::setupShaders ()
  287. {
  288. // ensure the constants are defined
  289. const ITexture* texture0 = this->m_material->getImage ()->getTexture ();
  290. // TODO: THE VALUES ARE THE SAME AS THE ENUMERATION, SO MAYBE IT HAS TO BE SPECIFIED FOR THE TEXTURE 0 OF ALL ELEMENTS?
  291. if (texture0 != nullptr)
  292. {
  293. if (texture0->getFormat () == ITexture::TextureFormat::RG88)
  294. {
  295. this->m_pass->insertCombo ("TEX0FORMAT", 8);
  296. }
  297. else if (texture0->getFormat () == ITexture::TextureFormat::R8)
  298. {
  299. this->m_pass->insertCombo ("TEX0FORMAT", 9);
  300. }
  301. }
  302. // prepare the shaders
  303. this->m_fragShader = new Render::Shaders::Compiler (
  304. this->m_material->getImage ()->getContainer (),
  305. this->m_pass->getShader (),
  306. Shaders::Compiler::Type_Pixel,
  307. this->m_pass->getCombos (),
  308. this->m_pass->getConstants ()
  309. );
  310. this->m_fragShader->precompile ();
  311. this->m_vertShader = new Render::Shaders::Compiler (
  312. this->m_material->getImage ()->getContainer (),
  313. this->m_pass->getShader (),
  314. Shaders::Compiler::Type_Vertex,
  315. this->m_pass->getCombos (),
  316. this->m_pass->getConstants ()
  317. );
  318. this->m_vertShader->precompile ();
  319. this->m_fragShader->precompile ();
  320. this->m_vertShader->precompile ();
  321. // compile the shaders
  322. GLuint vertexShaderID = compileShader (this->m_vertShader, GL_VERTEX_SHADER);
  323. GLuint fragmentShaderID = compileShader (this->m_fragShader, GL_FRAGMENT_SHADER);
  324. // create the final program
  325. this->m_programID = glCreateProgram ();
  326. // link the shaders together
  327. glAttachShader (this->m_programID, vertexShaderID);
  328. glAttachShader (this->m_programID, fragmentShaderID);
  329. glLinkProgram (this->m_programID);
  330. // check that the shader was properly linked
  331. GLint result = GL_FALSE;
  332. int infoLogLength = 0;
  333. glGetProgramiv (this->m_programID, GL_LINK_STATUS, &result);
  334. glGetProgramiv (this->m_programID, GL_INFO_LOG_LENGTH, &infoLogLength);
  335. if (infoLogLength > 0)
  336. {
  337. char* logBuffer = new char [infoLogLength + 1];
  338. // ensure logBuffer ends with a \0
  339. memset (logBuffer, 0, infoLogLength + 1);
  340. // get information about the error
  341. glGetProgramInfoLog (this->m_programID, infoLogLength, nullptr, logBuffer);
  342. // throw an exception about the issue
  343. std::string message = logBuffer;
  344. // free the buffer
  345. delete[] logBuffer;
  346. // throw an exception
  347. throw std::runtime_error (message);
  348. }
  349. // after being liked shaders can be dettached and deleted
  350. glDetachShader (this->m_programID, vertexShaderID);
  351. glDetachShader (this->m_programID, fragmentShaderID);
  352. glDeleteShader (vertexShaderID);
  353. glDeleteShader (fragmentShaderID);
  354. // setup uniforms
  355. this->setupUniforms ();
  356. // setup attributes too
  357. this->setupAttributes ();
  358. // get information from the program, like uniforms, etc
  359. // support three textures for now
  360. this->g_Texture0Rotation = glGetUniformLocation (this->m_programID, "g_Texture0Rotation");
  361. this->g_Texture0Translation = glGetUniformLocation (this->m_programID, "g_Texture0Translation");
  362. }
  363. void CPass::setupAttributes ()
  364. {
  365. this->addAttribute ("a_TexCoord", GL_FLOAT, 2, &this->a_TexCoord);
  366. this->addAttribute ("a_Position", GL_FLOAT, 3, &this->a_Position);
  367. }
  368. void CPass::setupUniforms ()
  369. {
  370. // resolve the main texture
  371. ITexture* texture = this->resolveTexture (this->m_material->getImage ()->getTexture (), 0);
  372. // register all the texture uniforms with correct values
  373. this->addUniform ("g_Texture0", 0);
  374. this->addUniform ("g_Texture1", 1);
  375. this->addUniform ("g_Texture2", 2);
  376. this->addUniform ("g_Texture3", 3);
  377. this->addUniform ("g_Texture4", 4);
  378. this->addUniform ("g_Texture5", 5);
  379. this->addUniform ("g_Texture6", 6);
  380. this->addUniform ("g_Texture7", 7);
  381. this->addUniform ("g_Texture0Resolution", texture->getResolution ());
  382. int lastTextureIndex = 0;
  383. // register the extra texture resolutions
  384. {
  385. auto cur = this->m_textures.begin ();
  386. auto end = this->m_textures.end ();
  387. for (int index = 1; cur != end; cur ++, index ++)
  388. {
  389. std::ostringstream namestream;
  390. namestream << "g_Texture" << index << "Resolution";
  391. texture = this->resolveTexture ((*cur), index, texture);
  392. this->addUniform (namestream.str (), texture->getResolution ());
  393. lastTextureIndex ++;
  394. }
  395. }
  396. // registers the extra texture resolutions from the shader
  397. {
  398. auto cur = this->m_fragShader->getTextures ().begin ();
  399. auto end = this->m_fragShader->getTextures ().end ();
  400. for (; cur != end; cur ++)
  401. {
  402. if ((*cur).first <= lastTextureIndex)
  403. continue;
  404. std::ostringstream namestream;
  405. namestream << "g_Texture" << (*cur).first << "Resolution";
  406. texture = this->resolveTexture ((*cur).second, (*cur).first, texture);
  407. if (texture != nullptr)
  408. this->addUniform (namestream.str (), texture->getResolution ());
  409. }
  410. }
  411. // registers the extra texture resolutions from the shader
  412. {
  413. auto cur = this->m_vertShader->getTextures ().begin ();
  414. auto end = this->m_vertShader->getTextures ().end ();
  415. for (; cur != end; cur ++)
  416. {
  417. if ((*cur).first <= lastTextureIndex)
  418. continue;
  419. std::ostringstream namestream;
  420. namestream << "g_Texture" << (*cur).first << "Resolution";
  421. texture = this->resolveTexture ((*cur).second, (*cur).first, texture);
  422. if (texture != nullptr)
  423. this->addUniform (namestream.str (), texture->getResolution ());
  424. }
  425. }
  426. // register variables like brightness and alpha with some default value
  427. this->addUniform ("g_Brightness", this->m_material->getImage ()->getImage ()->getBrightness ());
  428. this->addUniform ("g_UserAlpha", this->m_material->getImage ()->getImage ()->getAlpha ());
  429. this->addUniform ("g_Alpha", this->m_material->getImage ()->getImage ()->getAlpha ());
  430. this->addUniform ("g_Color", this->m_material->getImage ()->getImage ()->getColor ());
  431. // TODO: VALIDATE THAT G_COMPOSITECOLOR REALLY COMES FROM THIS ONE
  432. this->addUniform ("g_CompositeColor", this->m_material->getImage ()->getImage ()->getColor ());
  433. // add some external variables
  434. this->addUniform ("g_Time", &g_Time);
  435. // add model-view-projection matrix
  436. this->addUniform ("g_ModelViewProjectionMatrix", &this->m_modelViewProjectionMatrix);
  437. this->addUniform ("g_PointerPosition", this->m_material->getImage ()->getScene ()->getMousePosition ());
  438. this->addUniform ("g_EffectTextureProjectionMatrix", glm::mat4(1.0));
  439. this->addUniform ("g_EffectTextureProjectionMatrixInverse", glm::mat4(1.0));
  440. }
  441. void CPass::addAttribute (const std::string& name, GLint type, GLint elements, const GLuint* value)
  442. {
  443. GLint id = glGetAttribLocation (this->m_programID, name.c_str ());
  444. if (id == -1)
  445. return;
  446. this->m_attribs.emplace_back (
  447. new AttribEntry (id, name, type, elements, value)
  448. );
  449. }
  450. template <typename T>
  451. void CPass::addUniform (const std::string& name, UniformType type, T value)
  452. {
  453. GLint id = glGetUniformLocation (this->m_programID, name.c_str ());
  454. // parameter not found, can be ignored
  455. if (id == -1)
  456. return;
  457. // build a copy of the value and allocate it somewhere
  458. T* newValue = new T (value);
  459. // uniform found, add it to the list
  460. this->m_uniforms.insert (
  461. std::make_pair (name, new UniformEntry (id, name, type, newValue))
  462. );
  463. }
  464. template <typename T>
  465. void CPass::addUniform (const std::string& name, UniformType type, T* value)
  466. {
  467. // this version is used to reference to system variables so things like g_Time works fine
  468. GLint id = glGetUniformLocation (this->m_programID, name.c_str ());
  469. // parameter not found, can be ignored
  470. if (id == -1)
  471. return;
  472. // uniform found, add it to the list
  473. this->m_uniforms.insert (
  474. std::make_pair (name, new UniformEntry (id, name, type, value))
  475. );
  476. }
  477. void CPass::setupTextures ()
  478. {
  479. auto cur = this->m_pass->getTextures ().begin ();
  480. auto end = this->m_pass->getTextures ().end ();
  481. for (int index = 0; cur != end; cur ++, index ++)
  482. {
  483. // ignore first texture as that'll be the input of the last pass/image (unless the image is an FBO)
  484. if (index == 0)
  485. continue;
  486. if ((*cur).find ("_rt_") == 0)
  487. {
  488. CFBO* fbo = this->m_material->m_effect->findFBO ((*cur));
  489. if (fbo == nullptr)
  490. fbo = this->m_material->getImage ()->getScene ()->findFBO ((*cur));
  491. if (fbo != nullptr)
  492. {
  493. this->m_fbos.insert (std::make_pair (index, fbo));
  494. this->m_textures.emplace_back (
  495. nullptr
  496. );
  497. }
  498. // _rt_texture
  499. }
  500. else
  501. {
  502. this->m_textures.emplace_back (
  503. this->m_material->getImage ()->getContainer ()->readTexture ((*cur))
  504. );
  505. }
  506. }
  507. }
  508. void CPass::setupShaderVariables ()
  509. {
  510. {
  511. // find variables in the shaders and set the value with the constants if possible
  512. auto cur = this->m_pass->getConstants ().begin ();
  513. auto end = this->m_pass->getConstants ().end ();
  514. for (; cur != end; cur ++)
  515. {
  516. CShaderVariable* vertexVar = this->m_vertShader->findParameter ((*cur).first);
  517. CShaderVariable* pixelVar = this->m_fragShader->findParameter ((*cur).first);
  518. // variable not found, can be ignored
  519. if (vertexVar == nullptr && pixelVar == nullptr)
  520. continue;
  521. // if both can be found, ensure they're the correct type
  522. /*if (vertexVar != nullptr && pixelVar != nullptr)
  523. {
  524. if (vertexVar->getType () != pixelVar->getType ())
  525. throw std::runtime_error ("Pixel and vertex shader variable types do not match");
  526. }*/
  527. // get one instance of it
  528. CShaderVariable* var = vertexVar == nullptr ? pixelVar : vertexVar;
  529. // ensure the shader's and the constant are of the same type
  530. if ((*cur).second->getType () != var->getType ())
  531. {
  532. // there's situations where this type mismatch is actually expected
  533. // integers and floats are equivalent, this could be detected at load time
  534. // but that'd mean to compile the shader in the load, and not on the render stage
  535. // so take into account these conversions here
  536. if ((*cur).second->is <CShaderConstantFloat> () == true && var->is <CShaderVariableInteger> () == true)
  537. {
  538. // create an integer value from a float
  539. this->addUniform (var->getName (), static_cast <int> (*(*cur).second->as <CShaderConstantFloat> ()->getValue ()));
  540. }
  541. else if ((*cur).second->is <CShaderConstantInteger> () == true && var->is <CShaderVariableFloat> () == true)
  542. {
  543. // create a float value from an integer
  544. this->addUniform (var->getName (), static_cast <float> (*(*cur).second->as <CShaderConstantInteger> ()->getValue ()));
  545. }
  546. else if ((*cur).second->is <CShaderConstantVector4> () == true && var->is <CShaderVariableVector2> () == true)
  547. {
  548. CShaderConstantVector4* val = (*cur).second->as <CShaderConstantVector4> ();
  549. // create a new vector2 with the first two values
  550. this->addUniform (var->getName (), {val->getValue ()->x, val->getValue ()->y});
  551. }
  552. else if ((*cur).second->is <CShaderConstantVector4> () == true && var->is <CShaderVariableVector3> () == true)
  553. {
  554. CShaderConstantVector4* val = (*cur).second->as <CShaderConstantVector4> ();
  555. this->addUniform (var->getName (), {val->getValue ()->x, val->getValue ()->y, val->getValue ()->z});
  556. }
  557. else
  558. {
  559. throw std::runtime_error ("Constant and pixel/vertex variable are not of the same type");
  560. }
  561. }
  562. else
  563. {
  564. // now determine the constant's type and register the correct uniform for it
  565. if ((*cur).second->is <CShaderConstantFloat> ())
  566. this->addUniform (var->getName (), (*cur).second->as <CShaderConstantFloat> ()->getValue ());
  567. else if ((*cur).second->is <CShaderConstantInteger> ())
  568. this->addUniform (var->getName (), (*cur).second->as <CShaderConstantInteger> ()->getValue ());
  569. else if ((*cur).second->is <CShaderConstantVector4> ())
  570. this->addUniform (var->getName (), (*cur).second->as <CShaderConstantVector4> ()->getValue ());
  571. }
  572. }
  573. }
  574. {
  575. auto cur = this->m_vertShader->getParameters ().begin ();
  576. auto end = this->m_vertShader->getParameters ().end ();
  577. for (; cur != end; cur ++)
  578. {
  579. if (this->m_uniforms.find ((*cur)->getName ()) != this->m_uniforms.end ())
  580. continue;
  581. if ((*cur)->is <CShaderVariableFloat> ())
  582. this->addUniform ((*cur)->getName (), const_cast <float*> (reinterpret_cast <const float*> ((*cur)->as <CShaderVariableFloat> ()->getValue ())));
  583. else if ((*cur)->is <CShaderVariableInteger> ())
  584. this->addUniform ((*cur)->getName (), const_cast <int*> (reinterpret_cast <const int*> ((*cur)->as <CShaderVariableInteger> ()->getValue ())));
  585. else if ((*cur)->is <CShaderVariableVector2> ())
  586. this->addUniform ((*cur)->getName (), const_cast <glm::vec2*> (reinterpret_cast <const glm::vec2*> ((*cur)->as <CShaderVariableVector2> ()->getValue ())));
  587. else if ((*cur)->is <CShaderVariableVector3> ())
  588. this->addUniform ((*cur)->getName (), const_cast <glm::vec3*> (reinterpret_cast <const glm::vec3*> ((*cur)->as <CShaderVariableVector3> ()->getValue ())));
  589. else if ((*cur)->is <CShaderVariableVector4> ())
  590. this->addUniform ((*cur)->getName (), const_cast <glm::vec4*> (reinterpret_cast <const glm::vec4*> ((*cur)->as <CShaderVariableVector4> ()->getValue ())));
  591. }
  592. }
  593. {
  594. auto cur = this->m_fragShader->getParameters ().begin ();
  595. auto end = this->m_fragShader->getParameters ().end ();
  596. for (; cur != end; cur ++)
  597. {
  598. if (this->m_uniforms.find ((*cur)->getName ()) != this->m_uniforms.end ())
  599. continue;
  600. if ((*cur)->is <CShaderVariableFloat> ())
  601. this->addUniform ((*cur)->getName (), const_cast <float*> (reinterpret_cast <const float*> ((*cur)->as <CShaderVariableFloat> ()->getValue ())));
  602. else if ((*cur)->is <CShaderVariableInteger> ())
  603. this->addUniform ((*cur)->getName (), const_cast <int*> (reinterpret_cast <const int*> ((*cur)->as <CShaderVariableInteger> ()->getValue ())));
  604. else if ((*cur)->is <CShaderVariableVector2> ())
  605. this->addUniform ((*cur)->getName (), const_cast <glm::vec2*> (reinterpret_cast <const glm::vec2*> ((*cur)->as <CShaderVariableVector2> ()->getValue ())));
  606. else if ((*cur)->is <CShaderVariableVector3> ())
  607. this->addUniform ((*cur)->getName (), const_cast <glm::vec3*> (reinterpret_cast <const glm::vec3*> ((*cur)->as <CShaderVariableVector3> ()->getValue ())));
  608. else if ((*cur)->is <CShaderVariableVector4> ())
  609. this->addUniform ((*cur)->getName (), const_cast <glm::vec4*> (reinterpret_cast <const glm::vec4*> ((*cur)->as <CShaderVariableVector4> ()->getValue ())));
  610. }
  611. }
  612. }
  613. // define some basic methods for the template
  614. /*template double Core::jsonFindDefault (nlohmann::json& data, const char *key, double defaultValue);*/
  615. void CPass::addUniform (const std::string& name, int value)
  616. {
  617. this->addUniform (name, UniformType::Integer, value);
  618. }
  619. void CPass::addUniform (const std::string& name, const int* value)
  620. {
  621. this->addUniform (name, UniformType::Integer, value);
  622. }
  623. void CPass::addUniform (const std::string& name, double value)
  624. {
  625. this->addUniform (name, UniformType::Double, value);
  626. }
  627. void CPass::addUniform (const std::string& name, const double* value)
  628. {
  629. this->addUniform (name, UniformType::Double, value);
  630. }
  631. void CPass::addUniform (const std::string& name, float value)
  632. {
  633. this->addUniform (name, UniformType::Float, value);
  634. }
  635. void CPass::addUniform (const std::string& name, const float* value)
  636. {
  637. this->addUniform (name, UniformType::Float, value);
  638. }
  639. void CPass::addUniform (const std::string& name, glm::vec2 value)
  640. {
  641. this->addUniform (name, UniformType::Vector2, value);
  642. }
  643. void CPass::addUniform (const std::string& name, const glm::vec2* value)
  644. {
  645. this->addUniform (name, UniformType::Vector2, value);
  646. }
  647. void CPass::addUniform (const std::string& name, glm::vec3 value)
  648. {
  649. this->addUniform (name, UniformType::Vector3, value);
  650. }
  651. void CPass::addUniform (const std::string& name, const glm::vec3* value)
  652. {
  653. this->addUniform (name, UniformType::Vector3, value);
  654. }
  655. void CPass::addUniform (const std::string& name, glm::vec4 value)
  656. {
  657. this->addUniform (name, UniformType::Vector4, value);
  658. }
  659. void CPass::addUniform (const std::string& name, const glm::vec4* value)
  660. {
  661. this->addUniform (name, UniformType::Vector4, value);
  662. }
  663. void CPass::addUniform (const std::string& name, glm::mat4 value)
  664. {
  665. this->addUniform (name, UniformType::Matrix4, value);
  666. }
  667. void CPass::addUniform (const std::string& name, const glm::mat4* value)
  668. {
  669. this->addUniform (name, UniformType::Matrix4, value);
  670. }