CWallpaper.cpp 11 KB

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