CScene.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. #pragma once
  2. #include "WallpaperEngine/Render/Camera.h"
  3. #include "WallpaperEngine/Render/CWallpaper.h"
  4. #include "WallpaperEngine/Render/Volumetrics.h"
  5. #include "WallpaperEngine/Scripting/ScriptEngine.h"
  6. #include <set>
  7. namespace WallpaperEngine::Render {
  8. class Camera;
  9. class CObject;
  10. }
  11. namespace WallpaperEngine::Render::Wallpapers {
  12. using namespace WallpaperEngine::Data::Model;
  13. class CScene final : public CWallpaper {
  14. public:
  15. CScene (
  16. const Wallpaper& wallpaper, RenderContext& context, AudioContext& audioContext,
  17. const WallpaperState::TextureUVsScaling& scalingMode, const uint32_t& clampMode
  18. );
  19. ~CScene () override;
  20. /** The project's user properties (project.json "properties"), keyed by name */
  21. [[nodiscard]] const Data::Model::Properties& getUserProperties () const;
  22. [[nodiscard]] Scripting::ScriptEngine& getScriptEngine () const;
  23. [[nodiscard]] Camera& getCamera () const;
  24. [[nodiscard]] const Scene& getScene () const;
  25. [[nodiscard]] int getWidth () const override;
  26. [[nodiscard]] int getHeight () const override;
  27. [[nodiscard]] int getCanvasWidth () const override;
  28. [[nodiscard]] int getCanvasHeight () const override;
  29. // Used by CText/ScriptEngine; read from the same g_Time/g_TimeLast globals CParticle consumes via extern.
  30. [[nodiscard]] float getTime () const;
  31. [[nodiscard]] float getDeltaTime () const;
  32. [[nodiscard]] float getFps () const;
  33. /** Seconds since the scene was loaded, what wallpaper64.exe keeps in its renderer (+320) and resets past 432000 */
  34. [[nodiscard]] float getSceneClock () const;
  35. const glm::vec2* getMousePosition () const;
  36. const glm::vec2* getMousePositionLast () const;
  37. const glm::vec2* getMousePositionNormalized () const;
  38. [[nodiscard]] bool isCursorLeftDown () const { return this->m_cursorLeftDown; }
  39. /** Position fed to shaders as g_ParallaxPosition: 0.5 +- the smoothed, influence-scaled mouse offset */
  40. const glm::vec2* getParallaxPosition () const;
  41. /**
  42. * Parallax translation of an object in scene units, in the y-down space CImage/CText/CParticle position
  43. * themselves in. Like the real engine, the whole parent chain shifts as one rigid group using the topmost
  44. * ancestor's origin and parallaxDepth, a child's own depth is ignored.
  45. */
  46. [[nodiscard]] glm::vec2 getParallaxOffset (const Data::Model::Object& object) const;
  47. [[nodiscard]] const std::vector<CObject*>& getObjectsByRenderOrder () const;
  48. /** g_Fog* uniforms (sub_140186440). Height params come in two versions: WE's world (y up from the bottom) and
  49. * the space 2D objects are laid out in here (y down from the center), the same in 3D scenes */
  50. struct FogUniforms {
  51. glm::vec3 distanceColor { 0.0f };
  52. glm::vec4 distanceParams { 0.0f };
  53. glm::vec3 heightColor { 0.0f };
  54. glm::vec4 heightParamsWorld { 0.0f };
  55. glm::vec4 heightParamsLocal { 0.0f };
  56. /** g_EyePosition in WE's world, what the fog of passes drawing in world space measures from */
  57. glm::vec3 eyeWorld { 0.0f };
  58. /** The same eye in the space 2D objects are laid out in */
  59. glm::vec3 eyeLocal { 0.0f };
  60. };
  61. /** HDR scene rendering (WE's renderer flag 0x2000): float buffers, HDR define, object brightness, HDR bloom */
  62. [[nodiscard]] bool isHDR () const { return this->m_hdr; }
  63. [[nodiscard]] bool hasDistanceFog () const { return this->m_fogDistance; }
  64. [[nodiscard]] bool hasHeightFog () const { return this->m_fogHeight; }
  65. [[nodiscard]] const FogUniforms& getFog () const { return this->m_fog; }
  66. /** Size the whole scene would have at the output's scale, what WE's render targets are sized by */
  67. [[nodiscard]] glm::ivec2 getOutputResolution () const;
  68. /** WE's world (scene units, y up from the bottom left in 2D) to clip space of the scene buffer */
  69. [[nodiscard]] glm::mat4 getWorldViewProjection () const;
  70. /** Position of the active camera object in WE world units (y up, relative to the default camera), zero without one */
  71. [[nodiscard]] const glm::vec2& getCameraEye () const { return this->m_cameraEye; }
  72. [[nodiscard]] const CObject* getObject (int id) const;
  73. [[nodiscard]] CObject* getObject (int id);
  74. /** True when any group above the object (through "parent") is hidden */
  75. [[nodiscard]] bool isHiddenByAncestor (const CObject& object) const;
  76. /** The four old-style light slots as genericimage2 wants them (g_LightsPosition, g_LightsColorPremultiplied) */
  77. [[nodiscard]] const glm::vec3* getLightsPosition () const { return this->m_lightsPosition; }
  78. [[nodiscard]] const glm::vec4* getLightsColorPremultiplied () const { return this->m_lightsColorPremultiplied; }
  79. /** The same four slots unscaled, (color * intensity, radius), as the 3D shaders read them (g_LightsColorRadius) */
  80. [[nodiscard]] const glm::vec4* getLightsColorRadius () const { return this->m_lightsColorRadius; }
  81. /** The render order as scripts see it: without the synthesized bloom layer */
  82. [[nodiscard]] std::vector<CObject*> getLayers () const;
  83. [[nodiscard]] int getObjectIndex (const CObject* object) const;
  84. void setAudioPolicy (bool muted, std::optional<int> ambientVolume) override;
  85. /** Script play()/stop() request for a Sound object, remembered because scripts can ask before the CSound exists */
  86. void setSoundPlaying (int id, bool playing);
  87. [[nodiscard]] std::optional<bool> getSoundPlayRequest (int id) const;
  88. /** Creates a new image layer from a model json at runtime, appended to the render order. Backs
  89. * the scripting API's thisScene.createLayer(). Returns nullptr if the model couldn't be set up. */
  90. Render::CObject* createLayer (const std::string& imagePath);
  91. /** Moves an existing layer to the given render-order slot. Backs thisScene.sortLayer(). */
  92. void sortLayer (CObject* object, int index);
  93. protected:
  94. void appendLayer (CObject* object);
  95. void renderFrame (const glm::ivec4& viewport) override;
  96. void renderFrameSteps (const glm::ivec4& viewport);
  97. void updateMouse (const glm::ivec4& viewport);
  98. /** Hover/press tracking that turns pointer state into cursorEnter/cursorClick/... calls on scripted layers */
  99. void dispatchCursorEvents ();
  100. friend class CWallpaper;
  101. private:
  102. /**
  103. * Grows the render canvas (symmetrically around the layout center, so object positions stay valid) until
  104. * every top-level image layer with a declared size fits, see --expand-canvas
  105. */
  106. void expandCanvasToContent (
  107. const Scene& scene, float width, float height, float& canvasWidth, float& canvasHeight
  108. ) const;
  109. /** Refreshes the light slots from the light objects after scripts ran, like sub_1401D5740 + the 0x5D uniform */
  110. void updateLights ();
  111. /** Camera object view, parallax camera and perspective layer camera for this frame (sub_1401891A0) */
  112. void updateCamera ();
  113. /** Scene camera paths without a camera object, advances them by dt and writes this frame's camera */
  114. void updateCameraPath (float dt, glm::vec3& eye, glm::vec3& center, glm::vec3& up, float& zoom);
  115. /** camerafade overlay over the finished scene */
  116. void renderCameraFade ();
  117. /** WE's HDR bloom (sub_140183610) and combine_hdr_upsample into the scene buffer */
  118. void renderHDRBloom ();
  119. void releaseHDRBloom ();
  120. void updateFog (const glm::vec3& eye);
  121. /** Mouse parallax smoothing, after updateCamera () since a camera object moves the parallax camera too */
  122. void updateParallax ();
  123. /** T * Rz * Ry * Rx * S down the parent chain, WE's object world matrix (sub_1401850A0) */
  124. [[nodiscard]] glm::mat4 objectWorldMatrix (const Object& object) const;
  125. [[nodiscard]] int nextFreeLightSlot () const;
  126. Render::CObject* createObject (const Object& object);
  127. void createObjectDependencies (const Object& object);
  128. Render::CObject* dispatchObjectType (const Object& object);
  129. void addObjectToRenderOrder (const Object& object);
  130. std::unique_ptr<Scripting::ScriptEngine> m_scriptEngine;
  131. std::unique_ptr<Camera> m_camera;
  132. ObjectUniquePtr m_bloomObjectData;
  133. CObject* m_bloomObject = nullptr;
  134. std::map<int, CObject*> m_objects = {};
  135. std::set<int> m_objectsInCreation = {};
  136. std::set<int> m_objectsInRenderOrderWalk = {};
  137. std::map<int, bool> m_soundPlayRequests = {};
  138. std::vector<CObject*> m_objectsByRenderOrder = {};
  139. /** Camera objects in creation order, the last visible one wins */
  140. std::vector<CObject*> m_sceneCameras = {};
  141. /** Where the active camera object puts the eye, WE world units (y up), zero without one */
  142. glm::vec2 m_cameraEye = {};
  143. int m_pathIndex = 0;
  144. int m_pathKey = 0;
  145. float m_pathTime = 0.0f;
  146. float m_cameraFade = 0.0f;
  147. FogUniforms m_fog;
  148. std::unique_ptr<Volumetrics> m_volumetrics;
  149. bool m_fogDistance = false;
  150. bool m_fogHeight = false;
  151. bool m_hdr = false;
  152. /** HDR bloom: mip chain at half the output resolution and down, see renderHDRBloom () */
  153. struct BloomLevel {
  154. GLuint texture = GL_NONE;
  155. GLuint framebuffer = GL_NONE;
  156. glm::ivec2 size {};
  157. };
  158. std::vector<BloomLevel> m_bloomLevels;
  159. BloomLevel m_hdrCopy;
  160. glm::ivec2 m_bloomResolution {};
  161. GLuint m_bloomDownsample = GL_NONE;
  162. GLuint m_bloomDownsampleThreshold = GL_NONE;
  163. GLuint m_bloomUpsample = GL_NONE;
  164. GLuint m_bloomUpsampleCubic = GL_NONE;
  165. GLuint m_bloomCombine = GL_NONE;
  166. GLuint m_fadeProgram = GL_NONE;
  167. std::vector<DynamicValue*> m_scriptedValues = {};
  168. // owns the synthesized model data backing createLayer()'d objects; must outlive the CObject
  169. // built from it (same pattern as m_bloomObjectData)
  170. std::vector<ObjectUniquePtr> m_dynamicObjectData = {};
  171. int m_nextDynamicLayerId = 2000000000;
  172. std::map<std::string, std::string> m_createLayerAliases = {};
  173. glm::vec2 m_mousePosition = {};
  174. glm::vec2 m_mousePositionLast = {};
  175. glm::vec2 m_mousePositionNormalized = {};
  176. /** Smoothed camera offset from the scene center as a fraction of the scene size, in mouse coordinates */
  177. glm::vec2 m_cameraParallax = {};
  178. glm::vec2 m_parallaxPosition = { 0.5f, 0.5f };
  179. /** Wallpaper position offset (WallpaperState) riding through the parallax path */
  180. glm::vec2 m_parallaxBias = {};
  181. bool m_cursorLeftDown = false;
  182. float m_startTime = 0.0f;
  183. glm::vec3 m_lightsPosition[4] = {};
  184. glm::vec4 m_lightsColorPremultiplied[3] = {};
  185. glm::vec4 m_lightsColorRadius[4] = {};
  186. glm::vec2 m_cursorLastScenePosition = {};
  187. // object ids the pointer is over / that the current press started on
  188. std::set<int> m_cursorInside = {};
  189. std::set<int> m_cursorPressed = {};
  190. std::shared_ptr<const CFBO> _rt_4FrameBuffer = nullptr;
  191. std::shared_ptr<const CFBO> _rt_8FrameBuffer = nullptr;
  192. std::shared_ptr<const CFBO> _rt_Bloom = nullptr;
  193. std::shared_ptr<const CFBO> _rt_shadowAtlas = nullptr;
  194. };
  195. } // namespace WallpaperEngine::Render::Wallpaper