CImage.cpp 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. #include "CImage.h"
  2. using namespace WallpaperEngine;
  3. using namespace WallpaperEngine::Render::Objects;
  4. CImage::CImage (CScene* scene, Core::Objects::CImage* image) :
  5. Render::CObject (scene, Type, image),
  6. m_image (image)
  7. {
  8. // TODO: INITIALIZE NEEDED EFFECTS AND PROPERLY CALCULATE THESE?
  9. irr::f32 xsize = this->m_image->getSize ().X;
  10. irr::f32 ysize = this->m_image->getSize ().Y;
  11. irr::f32 xscale = this->m_image->getScale ().X;
  12. irr::f32 yscale = this->m_image->getScale ().Y;
  13. if (xsize == 0.0f || ysize == 0.0f)
  14. {
  15. xsize = 1920.0f;
  16. ysize = 1080.0f;
  17. this->getScene ()->getContext ()->getDevice ()->getLogger ()->log (
  18. "Initializing xsise and ysize as default values 1920 and 1080",
  19. this->getImage ()->getName ().c_str ()
  20. );
  21. }
  22. irr::core::vector3df cameraCenter = this->getScene ()->getCamera ()->getCenter ();
  23. // take the orthogonal projection into account
  24. irr::f32 scene_width = this->getScene ()->getScene ()->getOrthogonalProjection ()->getWidth ();
  25. irr::f32 scene_height = this->getScene ()->getScene ()->getOrthogonalProjection ()->getHeight ();
  26. irr::f32 xright = (-scene_width / 2.0f + this->m_image->getOrigin ().X + xsize * xscale / 2.0f) + cameraCenter.X;
  27. irr::f32 xleft = (-scene_width / 2.0f + this->m_image->getOrigin ().X - xsize * xscale / 2.0f) + cameraCenter.X;
  28. irr::f32 ytop = (-scene_height / 2.0f + this->m_image->getOrigin ().Y + ysize * yscale / 2.0f) + cameraCenter.Y;
  29. irr::f32 ybottom = (-scene_height / 2.0f + this->m_image->getOrigin ().Y - ysize * yscale / 2.0f) + cameraCenter.Y;
  30. irr::f32 z = this->m_image->getOrigin ().Z;
  31. // top left
  32. this->m_vertex [0].Pos = irr::core::vector3df (xleft, ytop, z);
  33. // top right
  34. this->m_vertex [1].Pos = irr::core::vector3df (xright, ytop, z);
  35. // bottom right
  36. this->m_vertex [2].Pos = irr::core::vector3df (xright, ybottom, z);
  37. // bottom left
  38. this->m_vertex [3].Pos = irr::core::vector3df (xleft, ybottom, z);
  39. this->m_vertex [0].TCoords = irr::core::vector2df (1.0f, 0.0f);
  40. this->m_vertex [1].TCoords = irr::core::vector2df (0.0f, 0.0f);
  41. this->m_vertex [2].TCoords = irr::core::vector2df (0.0f, 1.0f);
  42. this->m_vertex [3].TCoords = irr::core::vector2df (1.0f, 1.0f);
  43. this->m_vertex [0].Color = irr::video::SColor (255, 255, 255, 255);
  44. this->m_vertex [1].Color = irr::video::SColor (255, 255, 255, 255);
  45. this->m_vertex [2].Color = irr::video::SColor (255, 255, 255, 255);
  46. this->m_vertex [3].Color = irr::video::SColor (255, 255, 255, 255);
  47. this->setAutomaticCulling (irr::scene::EAC_OFF);
  48. this->m_boundingBox = irr::core::aabbox3d<irr::f32>(0, 0, 0, 0, 0, 0);
  49. // load the texture in the main material
  50. irr::io::path texturepath = this->getScene ()->getContext ()->resolveMaterials (
  51. (*(*this->m_image->getMaterial ()->getPasses ().begin ())->getTextures ().begin ())
  52. );
  53. irr::video::ITexture *texture = this->getScene ()->getContext ()->getDevice ()->getVideoDriver ()->getTexture (texturepath);
  54. this->m_material = new Render::Objects::Effects::CMaterial (this->getScene ()->getContext (), this, this->m_image->getMaterial (), texture);
  55. auto effectsCur = this->m_image->getEffects ().begin ();
  56. auto effectsEnd = this->m_image->getEffects ().end ();
  57. texture = this->m_material->getOutputTexture ();
  58. for (; effectsCur != effectsEnd; effectsCur ++)
  59. {
  60. CEffect* effect = new CEffect (this, *effectsCur, this->getScene ()->getContext (), texture);
  61. this->m_effects.push_back (effect);
  62. texture = effect->getOutputTexture ();
  63. }
  64. this->generateMaterial (texture);
  65. }
  66. void CImage::render()
  67. {
  68. uint16_t indices [] =
  69. {
  70. 3, 2, 1, 0
  71. };
  72. irr::video::IVideoDriver* driver = SceneManager->getVideoDriver ();
  73. // first render the base material
  74. this->m_material->render ();
  75. // now render all the effects, they should already be linked to each other
  76. auto effectCur = this->m_effects.begin ();
  77. auto effectEnd = this->m_effects.end ();
  78. size_t passes = 0;
  79. for (; effectCur != effectEnd; effectCur ++)
  80. {
  81. auto matCur = (*effectCur)->getMaterials ().begin ();
  82. auto matEnd = (*effectCur)->getMaterials ().end ();
  83. for (; matCur != matEnd; matCur ++)
  84. passes += (*matCur)->getPasses ().size ();
  85. (*effectCur)->render ();
  86. }
  87. passes ++;
  88. // depending on the number of passes we might need to flip the texture
  89. if (passes % 2 == 0)
  90. {
  91. // set render target to the screen
  92. driver->setRenderTarget (irr::video::ERT_FRAME_BUFFER, false, false);
  93. // set the material to use
  94. driver->setMaterial (this->m_irrlichtMaterialInvert);
  95. // draw it
  96. driver->drawVertexPrimitiveList (
  97. this->m_vertex, 4, indices, 1,
  98. irr::video::EVT_STANDARD, irr::scene::EPT_QUADS, irr::video::EIT_16BIT
  99. );
  100. }
  101. else
  102. {
  103. // set render target to the screen
  104. driver->setRenderTarget (irr::video::ERT_FRAME_BUFFER, false, false);
  105. // set the material to use
  106. driver->setMaterial (this->m_irrlichtMaterial);
  107. // draw it
  108. driver->drawVertexPrimitiveList (
  109. this->m_vertex, 4, indices, 1,
  110. irr::video::EVT_STANDARD, irr::scene::EPT_QUADS, irr::video::EIT_16BIT
  111. );
  112. }
  113. }
  114. void CImage::generateMaterial (irr::video::ITexture* resultTexture)
  115. {
  116. this->m_irrlichtMaterial.setTexture (0, resultTexture);
  117. this->m_irrlichtMaterial.MaterialType = irr::video::EMT_TRANSPARENT_ALPHA_CHANNEL;
  118. this->m_irrlichtMaterial.setFlag (irr::video::EMF_LIGHTING, false);
  119. this->m_irrlichtMaterial.setFlag (irr::video::EMF_BLEND_OPERATION, true);
  120. this->m_irrlichtMaterial.Wireframe = false;
  121. this->m_irrlichtMaterial.Lighting = false;
  122. /// TODO: XXXHACK: This material is used to flip textures upside down based on the amount of passes
  123. /// TODO: XXXHACK: This fixes an issue with opengl render that I had no better idea of how to solve
  124. /// TODO: XXXHACK: For the love of god, If you have a better fix, please LET ME KNOW!
  125. std::string vertex =
  126. "#define mul(x, y) (y * x)\n"
  127. "uniform mat4 g_ModelViewProjectionMatrix;\n"
  128. "// Pass to fragment shader with the same name\n"
  129. "varying vec2 v_texcoord;\n"
  130. "void main(void)\n"
  131. "{\n"
  132. " gl_Position = mul(vec4(gl_Vertex.xyz, 1.0), g_ModelViewProjectionMatrix);\n"
  133. " \n"
  134. " // The origin of the texture coordinates locates at bottom-left \n"
  135. " // corner rather than top-left corner as defined on screen quad.\n"
  136. " // Instead of using texture coordinates passed in by OpenGL, we\n"
  137. " // calculate TexCoords based on vertex position as follows.\n"
  138. " //\n"
  139. " // Vertex[0] (-1, -1) to (0, 0)\n"
  140. " // Vertex[1] (-1, 1) to (0, 1)\n"
  141. " // Vertex[2] ( 1, 1) to (1, 1)\n"
  142. " // Vertex[3] ( 1, -1) to (1, 0)\n"
  143. " // \n"
  144. " // Texture coordinate system in OpenGL operates differently from \n"
  145. " // DirectX 3D. It is not necessary to offset TexCoords to texel \n"
  146. " // center by adding 1.0 / TextureSize / 2.0\n"
  147. " \n"
  148. " v_texcoord = vec2(gl_MultiTexCoord0.x, gl_MultiTexCoord0.y);"
  149. "}";
  150. std::string fragment =
  151. "// Texture sampler\n"
  152. "uniform sampler2D TextureSampler;\n"
  153. "\n"
  154. "// TexCoords from vertex shader\n"
  155. "varying vec2 v_texcoord;\n"
  156. "\n"
  157. "void main (void)\n"
  158. "{\n"
  159. " gl_FragColor = texture2D(TextureSampler, v_texcoord);\n"
  160. "}";
  161. this->m_irrlichtMaterialInvert.setTexture (0, resultTexture);
  162. this->m_irrlichtMaterialInvert.setFlag (irr::video::EMF_LIGHTING, false);
  163. this->m_irrlichtMaterialInvert.setFlag (irr::video::EMF_BLEND_OPERATION, true);
  164. this->m_irrlichtMaterialInvert.Wireframe = false;
  165. this->m_irrlichtMaterialInvert.Lighting = false;
  166. this->m_irrlichtMaterialInvert.MaterialType = (irr::video::E_MATERIAL_TYPE)
  167. this->getScene ()->getContext ()->getDevice ()->getVideoDriver ()->getGPUProgrammingServices ()->addHighLevelShaderMaterial (
  168. vertex.c_str (), "main", irr::video::EVST_VS_2_0,
  169. fragment.c_str (), "main", irr::video::EPST_PS_2_0,
  170. this, irr::video::EMT_TRANSPARENT_ALPHA_CHANNEL, 0, irr::video::EGSL_DEFAULT
  171. );
  172. }
  173. void CImage::OnSetConstants (irr::video::IMaterialRendererServices *services, int32_t userData)
  174. {
  175. irr::s32 g_Texture0 = 0;
  176. irr::video::IVideoDriver* driver = services->getVideoDriver ();
  177. irr::core::matrix4 worldViewProj;
  178. worldViewProj = driver->getTransform (irr::video::ETS_PROJECTION);
  179. worldViewProj *= driver->getTransform (irr::video::ETS_VIEW);
  180. worldViewProj *= driver->getTransform (irr::video::ETS_WORLD);
  181. services->setPixelShaderConstant ("TextureSampler", &g_Texture0, 1);
  182. services->setVertexShaderConstant ("g_ModelViewProjectionMatrix", worldViewProj.pointer(), 16);
  183. }
  184. const irr::core::aabbox3d<irr::f32>& CImage::getBoundingBox() const
  185. {
  186. return this->m_boundingBox;
  187. }
  188. const Core::Objects::CImage* CImage::getImage () const
  189. {
  190. return this->m_image;
  191. }
  192. const std::vector<CEffect*>& CImage::getEffects () const
  193. {
  194. return this->m_effects;
  195. }
  196. const irr::video::S3DVertex* CImage::getVertex () const
  197. {
  198. return this->m_vertex;
  199. }
  200. const std::string CImage::Type = "image";