CWallpaper.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. #include "common.h"
  2. #include "CWallpaper.h"
  3. #include "CScene.h"
  4. #include "CVideo.h"
  5. #include <utility>
  6. #include <glm/glm.hpp>
  7. #include <glm/gtc/type_ptr.hpp>
  8. using namespace WallpaperEngine::Render;
  9. CWallpaper::CWallpaper (Core::CWallpaper* wallpaperData, std::string type, CRenderContext* context, CAudioContext* audioContext) :
  10. m_wallpaperData (wallpaperData),
  11. m_type (std::move(type)),
  12. m_context (context),
  13. m_destFramebuffer (GL_NONE),
  14. m_audioContext (audioContext)
  15. {
  16. // generate the VAO to stop opengl from complaining
  17. glGenVertexArrays (1, &this->m_vaoBuffer);
  18. glBindVertexArray (this->m_vaoBuffer);
  19. this->setupShaders ();
  20. GLfloat texCoords [] = {
  21. 0.0f, 0.0f,
  22. 1.0f, 0.0f,
  23. 0.0f, 1.0f,
  24. 0.0f, 1.0f,
  25. 1.0f, 0.0f,
  26. 1.0f, 1.0f
  27. };
  28. // inverted positions so the final texture is rendered properly
  29. GLfloat position [] = {
  30. -1.0f, 1.0f, 0.0f,
  31. 1.0, 1.0f, 0.0f,
  32. -1.0f, -1.0f, 0.0f,
  33. -1.0f, -1.0f, 0.0f,
  34. 1.0f, 1.0f, 0.0f,
  35. 1.0f, -1.0f, 0.0f
  36. };
  37. glGenBuffers (1, &this->m_texCoordBuffer);
  38. glBindBuffer (GL_ARRAY_BUFFER, this->m_texCoordBuffer);
  39. glBufferData (GL_ARRAY_BUFFER, sizeof (texCoords), texCoords, GL_STATIC_DRAW);
  40. glGenBuffers (1, &this->m_positionBuffer);
  41. glBindBuffer (GL_ARRAY_BUFFER, this->m_positionBuffer);
  42. glBufferData (GL_ARRAY_BUFFER, sizeof (position), position, GL_STATIC_DRAW);
  43. }
  44. CWallpaper::~CWallpaper ()
  45. {
  46. }
  47. const CContainer* CWallpaper::getContainer () const
  48. {
  49. return this->m_context->getContainer ();
  50. }
  51. WallpaperEngine::Core::CWallpaper* CWallpaper::getWallpaperData () const
  52. {
  53. return this->m_wallpaperData;
  54. }
  55. GLuint CWallpaper::getWallpaperFramebuffer () const
  56. {
  57. return this->m_sceneFBO->getFramebuffer ();
  58. }
  59. GLuint CWallpaper::getWallpaperTexture () const
  60. {
  61. return this->m_sceneFBO->getTextureID(0);
  62. }
  63. void CWallpaper::setupShaders ()
  64. {
  65. // reserve shaders in OpenGL
  66. GLuint vertexShaderID = glCreateShader (GL_VERTEX_SHADER);
  67. // give shader's source code to OpenGL to be compiled
  68. const char* sourcePointer = "#version 120\n"
  69. "attribute vec3 a_Position;\n"
  70. "attribute vec2 a_TexCoord;\n"
  71. "varying vec2 v_TexCoord;\n"
  72. "void main () {\n"
  73. "gl_Position = vec4 (a_Position, 1.0);\n"
  74. "v_TexCoord = a_TexCoord;\n"
  75. "}";
  76. glShaderSource (vertexShaderID, 1, &sourcePointer, nullptr);
  77. glCompileShader (vertexShaderID);
  78. GLint result = GL_FALSE;
  79. int infoLogLength = 0;
  80. // ensure the vertex shader was correctly compiled
  81. glGetShaderiv (vertexShaderID, GL_COMPILE_STATUS, &result);
  82. glGetShaderiv (vertexShaderID, GL_INFO_LOG_LENGTH, &infoLogLength);
  83. if (infoLogLength > 0)
  84. {
  85. char* logBuffer = new char [infoLogLength + 1];
  86. // ensure logBuffer ends with a \0
  87. memset (logBuffer, 0, infoLogLength + 1);
  88. // get information about the error
  89. glGetShaderInfoLog (vertexShaderID, infoLogLength, nullptr, logBuffer);
  90. // throw an exception about the issue
  91. std::string message = logBuffer;
  92. // free the buffer
  93. delete[] logBuffer;
  94. // throw an exception
  95. sLog.exception (message);
  96. }
  97. // reserve shaders in OpenGL
  98. GLuint fragmentShaderID = glCreateShader (GL_FRAGMENT_SHADER);
  99. // give shader's source code to OpenGL to be compiled
  100. sourcePointer = "#version 120\n"
  101. "uniform sampler2D g_Texture0;\n"
  102. "varying vec2 v_TexCoord;\n"
  103. "void main () {\n"
  104. "gl_FragColor = texture2D (g_Texture0, v_TexCoord);\n"
  105. "}";
  106. glShaderSource (fragmentShaderID, 1, &sourcePointer, nullptr);
  107. glCompileShader (fragmentShaderID);
  108. result = GL_FALSE;
  109. infoLogLength = 0;
  110. // ensure the vertex shader was correctly compiled
  111. glGetShaderiv (fragmentShaderID, GL_COMPILE_STATUS, &result);
  112. glGetShaderiv (fragmentShaderID, GL_INFO_LOG_LENGTH, &infoLogLength);
  113. if (infoLogLength > 0)
  114. {
  115. char* logBuffer = new char [infoLogLength + 1];
  116. // ensure logBuffer ends with a \0
  117. memset (logBuffer, 0, infoLogLength + 1);
  118. // get information about the error
  119. glGetShaderInfoLog (fragmentShaderID, infoLogLength, nullptr, logBuffer);
  120. // throw an exception about the issue
  121. std::string message = logBuffer;
  122. // free the buffer
  123. delete[] logBuffer;
  124. // throw an exception
  125. sLog.exception (message);
  126. }
  127. // create the final program
  128. this->m_shader = glCreateProgram ();
  129. // link the shaders together
  130. glAttachShader (this->m_shader, vertexShaderID);
  131. glAttachShader (this->m_shader, fragmentShaderID);
  132. glLinkProgram (this->m_shader);
  133. // check that the shader was properly linked
  134. result = GL_FALSE;
  135. infoLogLength = 0;
  136. glGetProgramiv (this->m_shader, GL_LINK_STATUS, &result);
  137. glGetProgramiv (this->m_shader, GL_INFO_LOG_LENGTH, &infoLogLength);
  138. if (infoLogLength > 0)
  139. {
  140. char* logBuffer = new char [infoLogLength + 1];
  141. // ensure logBuffer ends with a \0
  142. memset (logBuffer, 0, infoLogLength + 1);
  143. // get information about the error
  144. glGetProgramInfoLog (this->m_shader, infoLogLength, nullptr, logBuffer);
  145. // throw an exception about the issue
  146. std::string message = logBuffer;
  147. // free the buffer
  148. delete[] logBuffer;
  149. // throw an exception
  150. sLog.exception (message);
  151. }
  152. // after being liked shaders can be dettached and deleted
  153. glDetachShader (this->m_shader, vertexShaderID);
  154. glDetachShader (this->m_shader, fragmentShaderID);
  155. glDeleteShader (vertexShaderID);
  156. glDeleteShader (fragmentShaderID);
  157. // get textures
  158. this->g_Texture0 = glGetUniformLocation (this->m_shader, "g_Texture0");
  159. this->a_Position = glGetAttribLocation (this->m_shader, "a_Position");
  160. this->a_TexCoord = glGetAttribLocation (this->m_shader, "a_TexCoord");
  161. }
  162. void CWallpaper::updateTexCoord (GLfloat* texCoords, GLsizeiptr size) const
  163. {
  164. glBindBuffer (GL_ARRAY_BUFFER, this->m_texCoordBuffer);
  165. glBufferData (GL_ARRAY_BUFFER, size, texCoords, GL_STATIC_DRAW);
  166. }
  167. void CWallpaper::setDestinationFramebuffer (GLuint framebuffer)
  168. {
  169. this->m_destFramebuffer = framebuffer;
  170. }
  171. void CWallpaper::render (glm::ivec4 viewport, bool vflip, bool renderFrame, bool newFrame)
  172. {
  173. if (renderFrame == true)
  174. this->renderFrame (viewport);
  175. uint32_t projectionWidth = this->getWidth ();
  176. uint32_t projectionHeight = this->getHeight ();
  177. float ustart = 0.0f;
  178. float uend = 0.0f;
  179. float vstart = 0.0f;
  180. float vend = 0.0f;
  181. if (
  182. (viewport.w > viewport.z && projectionWidth >= projectionHeight) ||
  183. (viewport.z > viewport.w && projectionHeight > projectionWidth)
  184. )
  185. {
  186. if (vflip)
  187. {
  188. vstart = 0.0f;
  189. vend = 1.0f;
  190. }
  191. else
  192. {
  193. vstart = 1.0f;
  194. vend = 0.0f;
  195. }
  196. int newWidth = viewport.w / (float) projectionHeight * projectionWidth;
  197. float newCenter = newWidth / 2.0f;
  198. float viewportCenter = viewport.z / 2.0;
  199. float left = newCenter - viewportCenter;
  200. float right = newCenter + viewportCenter;
  201. ustart = left / newWidth;
  202. uend = right / newWidth;
  203. }
  204. if (
  205. (viewport.z > viewport.w && projectionWidth >= projectionHeight) ||
  206. (viewport.w > viewport.z && projectionHeight > projectionWidth)
  207. )
  208. {
  209. ustart = 0.0f;
  210. uend = 1.0f;
  211. int newHeight = viewport.z / (float) projectionWidth * projectionHeight;
  212. float newCenter = newHeight / 2.0f;
  213. float viewportCenter = viewport.w / 2.0;
  214. float down = newCenter - viewportCenter;
  215. float up = newCenter + viewportCenter;
  216. if (vflip)
  217. {
  218. vstart = down / newHeight;
  219. vend = up / newHeight;
  220. }
  221. else
  222. {
  223. vstart = up / newHeight;
  224. vend = down / newHeight;
  225. }
  226. }
  227. GLfloat texCoords [] = {
  228. ustart, vstart,
  229. uend, vstart,
  230. ustart, vend,
  231. ustart, vend,
  232. uend, vstart,
  233. uend, vend,
  234. };
  235. glViewport (viewport.x, viewport.y, viewport.z, viewport.w);
  236. glBindFramebuffer (GL_FRAMEBUFFER, this->m_destFramebuffer);
  237. glBindVertexArray (this->m_vaoBuffer);
  238. if (newFrame)
  239. glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  240. glDisable (GL_BLEND);
  241. glDisable (GL_DEPTH_TEST);
  242. // do not use any shader
  243. glUseProgram (this->m_shader);
  244. // activate scene texture
  245. glActiveTexture (GL_TEXTURE0);
  246. glBindTexture (GL_TEXTURE_2D, this->getWallpaperTexture ());
  247. // set uniforms and attribs
  248. glEnableVertexAttribArray (this->a_TexCoord);
  249. glBindBuffer (GL_ARRAY_BUFFER, this->m_texCoordBuffer);
  250. glBufferData (GL_ARRAY_BUFFER, sizeof (texCoords), texCoords, GL_STATIC_DRAW);
  251. glVertexAttribPointer (this->a_TexCoord, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
  252. glEnableVertexAttribArray (this->a_Position);
  253. glBindBuffer (GL_ARRAY_BUFFER, this->m_positionBuffer);
  254. glVertexAttribPointer (this->a_Position, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
  255. glUniform1i (this->g_Texture0, 0);
  256. // write the framebuffer as is to the screen
  257. glBindBuffer (GL_ARRAY_BUFFER, this->m_texCoordBuffer);
  258. glDrawArrays (GL_TRIANGLES, 0, 6);
  259. }
  260. void CWallpaper::setupFramebuffers ()
  261. {
  262. uint32_t width = this->getWidth ();
  263. uint32_t height = this->getHeight ();
  264. // create framebuffer for the scene
  265. this->m_sceneFBO = this->createFBO (
  266. "_rt_FullFrameBuffer",
  267. ITexture::TextureFormat::ARGB8888,
  268. ITexture::TextureFlags::ClampUVs,
  269. 1.0,
  270. width, height,
  271. width, height
  272. );
  273. }
  274. CRenderContext* CWallpaper::getContext ()
  275. {
  276. return this->m_context;
  277. }
  278. CAudioContext* CWallpaper::getAudioContext ()
  279. {
  280. return this->m_audioContext;
  281. }
  282. CFBO* CWallpaper::createFBO (const std::string& name, ITexture::TextureFormat format, ITexture::TextureFlags flags, float scale, uint32_t realWidth, uint32_t realHeight, uint32_t textureWidth, uint32_t textureHeight)
  283. {
  284. CFBO* fbo = new CFBO (name, format, flags, scale, realWidth, realHeight, textureWidth, textureHeight);
  285. this->m_fbos.insert_or_assign (name, fbo);
  286. return fbo;
  287. }
  288. const std::map<std::string, CFBO*>& CWallpaper::getFBOs () const
  289. {
  290. return this->m_fbos;
  291. }
  292. CFBO* CWallpaper::findFBO (const std::string& name) const
  293. {
  294. auto it = this->m_fbos.find (name);
  295. if (it == this->m_fbos.end ())
  296. sLog.exception ("Cannot find FBO ", name);
  297. return it->second;
  298. }
  299. CFBO* CWallpaper::getFBO () const
  300. {
  301. return this->m_sceneFBO;
  302. }
  303. CWallpaper* CWallpaper::fromWallpaper (Core::CWallpaper* wallpaper, CRenderContext* context, CAudioContext* audioContext)
  304. {
  305. if (wallpaper->is <Core::CScene> () == true)
  306. return new WallpaperEngine::Render::CScene (wallpaper->as <Core::CScene> (), context, audioContext);
  307. else if (wallpaper->is <Core::CVideo> () == true)
  308. return new WallpaperEngine::Render::CVideo (wallpaper->as <Core::CVideo> (), context, audioContext);
  309. else
  310. sLog.exception ("Unsupported wallpaper type");
  311. }