| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353 |
- #include "CWallpaper.h"
- #include "CScene.h"
- #include "CVideo.h"
- #include <utility>
- #include <glm/glm.hpp>
- #include <glm/gtc/type_ptr.hpp>
- using namespace WallpaperEngine::Render;
- CWallpaper::CWallpaper (Core::CWallpaper* wallpaperData, std::string type, CContainer* container) :
- m_container (container),
- m_wallpaperData (wallpaperData),
- m_type (std::move(type))
- {
- this->setupShaders ();
- GLfloat texCoords [] = {
- 0.0f, 0.0f,
- 1.0f, 0.0f,
- 0.0f, 1.0f,
- 0.0f, 1.0f,
- 1.0f, 0.0f,
- 1.0f, 1.0f
- };
- // inverted positions so the final texture is rendered properly
- GLfloat position [] = {
- -1.0f, 1.0f, 0.0f,
- 1.0, 1.0f, 0.0f,
- -1.0f, -1.0f, 0.0f,
- -1.0f, -1.0f, 0.0f,
- 1.0f, 1.0f, 0.0f,
- 1.0f, -1.0f, 0.0f
- };
- glGenBuffers (1, &this->m_texCoordBuffer);
- glBindBuffer (GL_ARRAY_BUFFER, this->m_texCoordBuffer);
- glBufferData (GL_ARRAY_BUFFER, sizeof (texCoords), texCoords, GL_STATIC_DRAW);
- glGenBuffers (1, &this->m_positionBuffer);
- glBindBuffer (GL_ARRAY_BUFFER, this->m_positionBuffer);
- glBufferData (GL_ARRAY_BUFFER, sizeof (position), position, GL_STATIC_DRAW);
- }
- CWallpaper::~CWallpaper ()
- {
- }
- CContainer* CWallpaper::getContainer () const
- {
- return this->m_container;
- }
- WallpaperEngine::Core::CWallpaper* CWallpaper::getWallpaperData ()
- {
- return this->m_wallpaperData;
- }
- GLuint CWallpaper::getWallpaperFramebuffer () const
- {
- return this->m_sceneFBO->getFramebuffer ();
- }
- GLuint CWallpaper::getWallpaperTexture () const
- {
- return this->m_sceneFBO->getTextureID();
- }
- void CWallpaper::setupShaders ()
- {
- // reserve shaders in OpenGL
- GLuint vertexShaderID = glCreateShader (GL_VERTEX_SHADER);
- // give shader's source code to OpenGL to be compiled
- const char* sourcePointer = "#version 120\n"
- "attribute vec3 a_Position;\n"
- "attribute vec2 a_TexCoord;\n"
- "varying vec2 v_TexCoord;\n"
- "void main () {\n"
- "gl_Position = vec4 (a_Position, 1.0);\n"
- "v_TexCoord = a_TexCoord;\n"
- "}";
- glShaderSource (vertexShaderID, 1, &sourcePointer, nullptr);
- glCompileShader (vertexShaderID);
- GLint result = GL_FALSE;
- int infoLogLength = 0;
- // ensure the vertex shader was correctly compiled
- glGetShaderiv (vertexShaderID, GL_COMPILE_STATUS, &result);
- glGetShaderiv (vertexShaderID, GL_INFO_LOG_LENGTH, &infoLogLength);
- if (infoLogLength > 0)
- {
- char* logBuffer = new char [infoLogLength + 1];
- // ensure logBuffer ends with a \0
- memset (logBuffer, 0, infoLogLength + 1);
- // get information about the error
- glGetShaderInfoLog (vertexShaderID, infoLogLength, nullptr, logBuffer);
- // throw an exception about the issue
- std::string message = logBuffer;
- // free the buffer
- delete[] logBuffer;
- // throw an exception
- throw std::runtime_error (message);
- }
- // reserve shaders in OpenGL
- GLuint fragmentShaderID = glCreateShader (GL_FRAGMENT_SHADER);
- // give shader's source code to OpenGL to be compiled
- sourcePointer = "#version 120\n"
- "uniform sampler2D g_Texture0;\n"
- "varying vec2 v_TexCoord;\n"
- "void main () {\n"
- "gl_FragColor = texture2D (g_Texture0, v_TexCoord);\n"
- "}";
- glShaderSource (fragmentShaderID, 1, &sourcePointer, nullptr);
- glCompileShader (fragmentShaderID);
- result = GL_FALSE;
- infoLogLength = 0;
- // ensure the vertex shader was correctly compiled
- glGetShaderiv (fragmentShaderID, GL_COMPILE_STATUS, &result);
- glGetShaderiv (fragmentShaderID, GL_INFO_LOG_LENGTH, &infoLogLength);
- if (infoLogLength > 0)
- {
- char* logBuffer = new char [infoLogLength + 1];
- // ensure logBuffer ends with a \0
- memset (logBuffer, 0, infoLogLength + 1);
- // get information about the error
- glGetShaderInfoLog (fragmentShaderID, infoLogLength, nullptr, logBuffer);
- // throw an exception about the issue
- std::string message = logBuffer;
- // free the buffer
- delete[] logBuffer;
- // throw an exception
- throw std::runtime_error (message);
- }
- // create the final program
- this->m_shader = glCreateProgram ();
- // link the shaders together
- glAttachShader (this->m_shader, vertexShaderID);
- glAttachShader (this->m_shader, fragmentShaderID);
- glLinkProgram (this->m_shader);
- // check that the shader was properly linked
- result = GL_FALSE;
- infoLogLength = 0;
- glGetProgramiv (this->m_shader, GL_LINK_STATUS, &result);
- glGetProgramiv (this->m_shader, GL_INFO_LOG_LENGTH, &infoLogLength);
- if (infoLogLength > 0)
- {
- char* logBuffer = new char [infoLogLength + 1];
- // ensure logBuffer ends with a \0
- memset (logBuffer, 0, infoLogLength + 1);
- // get information about the error
- glGetProgramInfoLog (this->m_shader, infoLogLength, nullptr, logBuffer);
- // throw an exception about the issue
- std::string message = logBuffer;
- // free the buffer
- delete[] logBuffer;
- // throw an exception
- throw std::runtime_error (message);
- }
- // after being liked shaders can be dettached and deleted
- glDetachShader (this->m_shader, vertexShaderID);
- glDetachShader (this->m_shader, fragmentShaderID);
- glDeleteShader (vertexShaderID);
- glDeleteShader (fragmentShaderID);
- // get textures
- this->g_Texture0 = glGetUniformLocation (this->m_shader, "g_Texture0");
- this->a_Position = glGetAttribLocation (this->m_shader, "a_Position");
- this->a_TexCoord = glGetAttribLocation (this->m_shader, "a_TexCoord");
- }
- void CWallpaper::render (glm::vec4 viewport, bool newFrame)
- {
- if (newFrame == true)
- this->renderFrame ();
- int windowWidth = 1920;
- int windowHeight = 1080;
- if (this->getWallpaperData ()->is <WallpaperEngine::Core::CScene> ())
- {
- auto projection = this->getWallpaperData ()->as <WallpaperEngine::Core::CScene> ()->getOrthogonalProjection ();
- windowWidth = projection->getWidth ();
- windowHeight = projection->getHeight ();
- }
- else if (this->is <WallpaperEngine::Render::CVideo> ())
- {
- auto video = this->as <WallpaperEngine::Render::CVideo> ();
- windowWidth = video->getWidth ();
- windowHeight = video->getHeight ();
- }
- float widthRatio = windowWidth / viewport.z;
- float heightRatio = windowHeight / viewport.w;
- if (widthRatio > 1.0f)
- {
- float diff = widthRatio - 1.0f;
- widthRatio -= diff;
- heightRatio -= diff;
- }
- if (heightRatio > 1.0f)
- {
- float diff = heightRatio - 1.0f;
- widthRatio -= diff;
- heightRatio -= diff;
- }
- if (widthRatio < 1.0f)
- {
- float diff = 1.0f - widthRatio;
- widthRatio += diff;
- heightRatio += diff;
- }
- if (heightRatio < 1.0f)
- {
- float diff = 1.0f - heightRatio;
- widthRatio += diff;
- heightRatio += diff;
- }
- if (widthRatio < 0.0f) widthRatio = -widthRatio;
- if (heightRatio < 0.0f) heightRatio = -heightRatio;
- GLfloat position [] = {
- widthRatio * -1.0f, heightRatio * 1.0f, 0.0f,
- widthRatio * 1.0f, heightRatio * 1.0f, 0.0f,
- widthRatio * -1.0f, heightRatio * -1.0f, 0.0f,
- widthRatio * -1.0f, heightRatio * -1.0f, 0.0f,
- widthRatio * 1.0f, heightRatio * 1.0f, 0.0f,
- widthRatio * 1.0f, heightRatio * -1.0f, 0.0f
- };
- glBindBuffer (GL_ARRAY_BUFFER, this->m_positionBuffer);
- glBufferData (GL_ARRAY_BUFFER, sizeof (position), position, GL_STATIC_DRAW);
- glViewport (viewport.x, viewport.y, viewport.z, viewport.w);
- // write to default's framebuffer
- glBindFramebuffer (GL_FRAMEBUFFER, GL_NONE);
- glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- glDisable (GL_BLEND);
- glDisable (GL_DEPTH_TEST);
- // do not use any shader
- glUseProgram (this->m_shader);
- // activate scene texture
- glActiveTexture (GL_TEXTURE0);
- glBindTexture (GL_TEXTURE_2D, this->getWallpaperTexture ());
- // set uniforms and attribs
- glEnableVertexAttribArray (this->a_TexCoord);
- glBindBuffer (GL_ARRAY_BUFFER, this->m_texCoordBuffer);
- glVertexAttribPointer (this->a_TexCoord, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
- glEnableVertexAttribArray (this->a_Position);
- glBindBuffer (GL_ARRAY_BUFFER, this->m_positionBuffer);
- glVertexAttribPointer (this->a_Position, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
- glUniform1i (this->g_Texture0, 0);
- // write the framebuffer as is to the screen
- glBindBuffer (GL_ARRAY_BUFFER, this->m_texCoordBuffer);
- glDrawArrays (GL_TRIANGLES, 0, 6);
- }
- void CWallpaper::pinpongFramebuffer (GLuint* drawTo, GLuint* inputTexture)
- {
- // temporarily store FBOs used
- CFBO* currentMainFBO = this->m_mainFBO;
- CFBO* currentSubFBO = this->m_subFBO;
- if (drawTo != nullptr)
- *drawTo = currentSubFBO->getFramebuffer ();
- if (inputTexture != nullptr)
- *inputTexture = currentMainFBO->getTextureID();
- // swap the FBOs
- this->m_mainFBO = currentSubFBO;
- this->m_subFBO = currentMainFBO;
- }
- void CWallpaper::setupFramebuffers ()
- {
- int windowWidth = 1920;
- int windowHeight = 1080;
- if (this->getWallpaperData ()->is <WallpaperEngine::Core::CScene> ())
- {
- auto projection = this->getWallpaperData ()->as <WallpaperEngine::Core::CScene> ()->getOrthogonalProjection ();
- windowWidth = projection->getWidth ();
- windowHeight = projection->getHeight ();
- }
- else if (this->is <WallpaperEngine::Render::CVideo> ())
- {
- auto video = this->as <WallpaperEngine::Render::CVideo> ();
- windowWidth = video->getWidth ();
- windowHeight = video->getHeight ();
- }
- this->m_mainFBO = this->createFBO ("_rt_FullFrameBuffera", ITexture::TextureFormat::ARGB8888, 1.0, windowWidth, windowHeight, windowWidth, windowHeight);
- this->m_subFBO = this->createFBO ("_rt_FullFrameBuffera", ITexture::TextureFormat::ARGB8888, 1.0, windowWidth, windowHeight, windowWidth, windowHeight);
- // create framebuffer for the scene
- this->m_sceneFBO = this->createFBO ("_rt_FullFrameBuffer", ITexture::TextureFormat::ARGB8888, 1.0, windowWidth, windowHeight, windowWidth, windowHeight);
- }
- CFBO* CWallpaper::createFBO (const std::string& name, ITexture::TextureFormat format, float scale, uint32_t realWidth, uint32_t realHeight, uint32_t textureWidth, uint32_t textureHeight)
- {
- CFBO* fbo = new CFBO (name, format, scale, realWidth, realHeight, textureWidth, textureHeight);
- this->m_fbos.insert (std::make_pair (name, fbo));
- return fbo;
- }
- const std::map<std::string, CFBO*>& CWallpaper::getFBOs () const
- {
- return this->m_fbos;
- }
- const CFBO* CWallpaper::findFBO (const std::string& name) const
- {
- auto it = this->m_fbos.find (name);
- if (it == this->m_fbos.end ())
- throw std::runtime_error ("Cannot find given FBO");
- return it->second;
- }
|