CWallpaper.cpp 11 KB

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