CScene.cpp 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. #include "common.h"
  2. #include "WallpaperEngine/Core/Objects/CImage.h"
  3. #include "WallpaperEngine/Core/Objects/CSound.h"
  4. #include "WallpaperEngine/Render/Objects/CImage.h"
  5. #include "WallpaperEngine/Render/Objects/CSound.h"
  6. #include "CScene.h"
  7. extern float g_Time;
  8. extern float g_TimeLast;
  9. using namespace WallpaperEngine;
  10. using namespace WallpaperEngine::Render;
  11. CScene::CScene (Core::CScene* scene, CRenderContext& context, CAudioContext& audioContext) :
  12. CWallpaper (scene, Type, context, audioContext),
  13. m_mousePosition (),
  14. m_mousePositionLast (),
  15. m_parallaxDisplacement ()
  16. {
  17. // setup the scene camera
  18. this->m_camera = new CCamera (this, scene->getCamera ());
  19. // detect size if the orthogonal project is auto
  20. if (scene->getOrthogonalProjection ()->isAuto ())
  21. {
  22. // calculate the size of the projection based on the size of everything
  23. for (const auto& cur : scene->getObjects ())
  24. {
  25. if (!cur.second->is <Core::Objects::CImage> ())
  26. continue;
  27. glm::vec2 size = cur.second->as <Core::Objects::CImage> ()->getSize ();
  28. scene->getOrthogonalProjection ()->setWidth (size.x);
  29. scene->getOrthogonalProjection ()->setHeight (size.y);
  30. }
  31. }
  32. this->m_parallaxDisplacement = {0, 0};
  33. this->m_camera->setOrthogonalProjection (
  34. scene->getOrthogonalProjection ()->getWidth (),
  35. scene->getOrthogonalProjection ()->getHeight ()
  36. );
  37. // setup framebuffers here as they're required for the scene setup
  38. this->setupFramebuffers();
  39. // set clear color
  40. glm::vec3 clearColor = this->getScene ()->getClearColor ();
  41. glClearColor (clearColor.r, clearColor.g, clearColor.b, 1.0f);
  42. // create all objects based off their dependencies
  43. for (const auto& cur : scene->getObjects ())
  44. this->createObject (cur.second);
  45. // copy over objects by render order
  46. for (const auto& cur : scene->getObjectsByRenderOrder ())
  47. {
  48. auto obj = this->m_objects.find (cur->getId ());
  49. // ignores not created objects like particle systems
  50. if (obj == this->m_objects.end ())
  51. continue;
  52. this->m_objectsByRenderOrder.emplace_back ((*obj).second);
  53. }
  54. uint32_t sceneWidth = scene->getOrthogonalProjection ()->getWidth ();
  55. uint32_t sceneHeight = scene->getOrthogonalProjection ()->getHeight ();
  56. // create extra framebuffers for the bloom effect
  57. this->_rt_4FrameBuffer = this->createFBO (
  58. "_rt_4FrameBuffer",
  59. ITexture::TextureFormat::ARGB8888,
  60. ITexture::TextureFlags::ClampUVs,
  61. 1.0,
  62. sceneWidth / 4, sceneHeight / 4,
  63. sceneWidth / 4, sceneHeight / 4
  64. );
  65. this->_rt_8FrameBuffer = this->createFBO (
  66. "_rt_8FrameBuffer",
  67. ITexture::TextureFormat::ARGB8888,
  68. ITexture::TextureFlags::ClampUVs,
  69. 1.0,
  70. sceneWidth / 8, sceneHeight / 8,
  71. sceneWidth / 8, sceneHeight / 8
  72. );
  73. this->_rt_Bloom = this->createFBO (
  74. "_rt_Bloom",
  75. ITexture::TextureFormat::ARGB8888,
  76. ITexture::TextureFlags::ClampUVs,
  77. 1.0,
  78. sceneWidth / 8, sceneHeight / 8,
  79. sceneWidth / 8, sceneHeight / 8
  80. );
  81. //
  82. // Had to get a little creative with the effects to achieve the same bloom effect without any custom code
  83. // this custom image loads some effect files from the virtual container to achieve the same bloom effect
  84. // this approach requires of two extra draw calls due to the way the effect works in official WPE
  85. // (it renders directly to the screen, whereas here we never do that from a scene)
  86. //
  87. std::string imagejson =
  88. "{"
  89. "\t\"image\": \"models/wpenginelinux.json\","
  90. "\t\"name\": \"bloomimagewpenginelinux\","
  91. "\t\"visible\": true,"
  92. "\t\"scale\": \"1.0 1.0 1.0\","
  93. "\t\"angles\": \"0.0 0.0 0.0\","
  94. "\t\"origin\": \"" + std::to_string (sceneWidth / 2) + " " + std::to_string (sceneHeight / 2) + " 0.0\","
  95. "\t\"id\": " + std::to_string (0xFFFFFFFF) + ","
  96. "\t\"effects\":"
  97. "\t["
  98. "\t\t{"
  99. "\t\t\t\"file\": \"effects/wpenginelinux/bloomeffect.json\","
  100. "\t\t\t\"id\": 15242000,"
  101. "\t\t\t\"name\": \"\","
  102. "\t\t\t\"passes\":"
  103. "\t\t\t["
  104. "\t\t\t\t{"
  105. "\t\t\t\t\t\"constantshadervalues\":"
  106. "\t\t\t\t\t{"
  107. "\t\t\t\t\t\t\"bloomstrength\": " + std::to_string (this->getScene ()->getBloomStrength ()) + ","
  108. "\t\t\t\t\t\t\"bloomthreshold\": " + std::to_string (this->getScene ()->getBloomThreshold ()) +
  109. "\t\t\t\t\t}"
  110. "\t\t\t\t},"
  111. "\t\t\t\t{"
  112. "\t\t\t\t\t\"constantshadervalues\":"
  113. "\t\t\t\t\t{"
  114. "\t\t\t\t\t\t\"bloomstrength\": " + std::to_string (this->getScene ()->getBloomStrength ()) + ","
  115. "\t\t\t\t\t\t\"bloomthreshold\": " + std::to_string (this->getScene ()->getBloomThreshold ()) +
  116. "\t\t\t\t\t}"
  117. "\t\t\t\t},"
  118. "\t\t\t\t{"
  119. "\t\t\t\t\t\"constantshadervalues\":"
  120. "\t\t\t\t\t{"
  121. "\t\t\t\t\t\t\"bloomstrength\": " + std::to_string (this->getScene ()->getBloomStrength ()) + ","
  122. "\t\t\t\t\t\t\"bloomthreshold\": " + std::to_string (this->getScene ()->getBloomThreshold ()) +
  123. "\t\t\t\t\t}"
  124. "\t\t\t\t}"
  125. "\t\t\t]"
  126. "\t\t}"
  127. "\t],"
  128. "\t\"size\": \"" + std::to_string (sceneWidth) + " " + std::to_string (sceneHeight) + "\""
  129. "}";
  130. auto json = nlohmann::json::parse (imagejson);
  131. // create image for bloom passes
  132. if (this->getScene ()->isBloom ())
  133. {
  134. this->m_bloomObject = this->createObject (
  135. WallpaperEngine::Core::CObject::fromJSON (
  136. json, this->getScene (), this->getContainer ()
  137. )
  138. );
  139. this->m_objectsByRenderOrder.push_back (this->m_bloomObject);
  140. }
  141. }
  142. Render::CObject* CScene::createObject (Core::CObject* object)
  143. {
  144. Render::CObject* renderObject = nullptr;
  145. // ensure the item is not loaded already
  146. auto current = this->m_objects.find (object->getId ());
  147. if (current != this->m_objects.end ())
  148. return (*current).second;
  149. // check dependencies too!
  150. for (const auto& cur : object->getDependencies ())
  151. {
  152. // self-dependency is a possibility...
  153. if (cur == object->getId ())
  154. continue;
  155. auto dep = this->getScene ()->getObjects ().find (cur);
  156. if (dep != this->getScene ()->getObjects ().end ())
  157. this->createObject ((*dep).second);
  158. }
  159. if (object->is <Core::Objects::CImage> ())
  160. {
  161. auto* image = new Objects::CImage (this, object->as<Core::Objects::CImage>());
  162. try
  163. {
  164. image->setup ();
  165. }
  166. catch (std::runtime_error& ex)
  167. {
  168. // this error message is already printed, so just show extra info about it
  169. sLog.error ("Cannot setup image ", image->getImage ()->getName ());
  170. }
  171. renderObject = image;
  172. }
  173. else if (object->is <Core::Objects::CSound> ())
  174. {
  175. renderObject = new Objects::CSound (this, object->as<Core::Objects::CSound>());
  176. }
  177. if (renderObject != nullptr)
  178. this->m_objects.insert (std::make_pair (renderObject->getId (), renderObject));
  179. return renderObject;
  180. }
  181. CCamera* CScene::getCamera () const
  182. {
  183. return this->m_camera;
  184. }
  185. void CScene::renderFrame (glm::ivec4 viewport)
  186. {
  187. // ensure the virtual mouse position is up to date
  188. this->updateMouse (viewport);
  189. // update the parallax position if required
  190. if (this->getScene ()->isCameraParallax ())
  191. {
  192. float influence = this->getScene ()->getCameraParallaxMouseInfluence ();
  193. float amount = this->getScene ()->getCameraParallaxAmount ();
  194. float delay = glm::min ((float) this->getScene ()->getCameraParallaxDelay (), g_Time - g_TimeLast);
  195. this->m_parallaxDisplacement = glm::mix (this->m_parallaxDisplacement, (this->m_mousePosition * amount) * influence, delay);
  196. }
  197. // use the scene's framebuffer by default
  198. glBindFramebuffer (GL_FRAMEBUFFER, this->getWallpaperFramebuffer());
  199. // ensure we render over the whole framebuffer
  200. glViewport (0, 0, this->m_sceneFBO->getRealWidth (), this->m_sceneFBO->getRealHeight ());
  201. glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  202. for (const auto& cur : this->m_objectsByRenderOrder)
  203. cur->render ();
  204. }
  205. void CScene::updateMouse (glm::ivec4 viewport)
  206. {
  207. // update virtual mouse position first
  208. glm::dvec2 position = this->getContext ().getInputContext ().getMouseInput ().position;
  209. // TODO: PROPERLY TRANSLATE THESE TO WHAT'S VISIBLE ON SCREEN (FOR BACKGROUNDS THAT DO NOT EXACTLY FIT ON SCREEN)
  210. // rollover the position to the last
  211. this->m_mousePositionLast = this->m_mousePosition;
  212. // calculate the current position of the mouse
  213. this->m_mousePosition.x = glm::clamp ((position.x - viewport.x) / viewport.z, 0.0, 1.0);
  214. this->m_mousePosition.y = glm::clamp ((position.y - viewport.y) / viewport.w, 0.0, 1.0);
  215. // screen-space positions have to be transposed to what the screen will actually show
  216. }
  217. Core::CScene* CScene::getScene () const
  218. {
  219. return this->getWallpaperData ()->as<Core::CScene> ();
  220. }
  221. uint32_t CScene::getWidth () const
  222. {
  223. return this->getScene ()->getOrthogonalProjection()->getWidth ();
  224. }
  225. uint32_t CScene::getHeight () const
  226. {
  227. return this->getScene ()->getOrthogonalProjection()->getHeight ();
  228. }
  229. glm::vec2* CScene::getMousePosition ()
  230. {
  231. return &this->m_mousePosition;
  232. }
  233. glm::vec2* CScene::getMousePositionLast ()
  234. {
  235. return &this->m_mousePositionLast;
  236. }
  237. glm::vec2* CScene::getParallaxDisplacement ()
  238. {
  239. return &this->m_parallaxDisplacement;
  240. }
  241. const std::string CScene::Type = "scene";