CScene.cpp 9.5 KB

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