diff --git a/src/WallpaperEngine/Assets/CTexture.cpp b/src/WallpaperEngine/Assets/CTexture.cpp index 79cb71c..db56de4 100644 --- a/src/WallpaperEngine/Assets/CTexture.cpp +++ b/src/WallpaperEngine/Assets/CTexture.cpp @@ -191,7 +191,7 @@ CTexture::~CTexture () delete this->getHeader (); } -const GLuint CTexture::getTextureID (int imageIndex) const +const GLuint CTexture::getTextureID (uint32_t imageIndex) const { // ensure we do not go out of bounds if (imageIndex > this->m_header->imageCount) @@ -200,14 +200,20 @@ const GLuint CTexture::getTextureID (int imageIndex) const return this->m_textureID [imageIndex]; } -const uint32_t CTexture::getTextureWidth () const +const uint32_t CTexture::getTextureWidth (uint32_t imageIndex) const { - return this->getHeader ()->textureWidth; + if (imageIndex > this->m_header->imageCount) + return this->getHeader ()->textureWidth; + + return (*this->m_header->images [imageIndex].begin ())->width; } -const uint32_t CTexture::getTextureHeight () const +const uint32_t CTexture::getTextureHeight (uint32_t imageIndex) const { - return this->getHeader ()->textureHeight; + if (imageIndex > this->m_header->imageCount) + return this->getHeader ()->textureHeight; + + return (*this->m_header->images [imageIndex].begin ())->height; } const uint32_t CTexture::getRealWidth () const @@ -235,6 +241,11 @@ const glm::vec4* CTexture::getResolution () const return &this->m_resolution; } +const std::vector& CTexture::getFrames () const +{ + return this->getHeader ()->frames; +} + const bool CTexture::isAnimated () const { return this->getHeader ()->isAnimated (); @@ -408,8 +419,8 @@ CTexture::TextureHeader* CTexture::parseHeader (char* fileData) { TextureFrame* first = *header->frames.begin (); - header->gifWidth = first->width; - header->gifHeight = first->height; + header->gifWidth = first->width1; + header->gifHeight = first->height1; } } @@ -433,10 +444,10 @@ CTexture::TextureFrame* CTexture::parseAnimation (TextureHeader* header, char** frame->frametime = *fPointer ++; frame->x = *fPointer ++; frame->y = *fPointer ++; - frame->width = *fPointer ++; - frame->unk0 = *fPointer ++; - frame->unk1 = *fPointer ++; - frame->height = *fPointer ++; + frame->width1 = *fPointer ++; + frame->width2 = *fPointer ++; + frame->height2 = *fPointer ++; + frame->height1 = *fPointer ++; // get back the pointer into fileData so it can be reused later *originalFileData = reinterpret_cast (fPointer); diff --git a/src/WallpaperEngine/Assets/CTexture.h b/src/WallpaperEngine/Assets/CTexture.h index 1a0920e..cfcf6cd 100644 --- a/src/WallpaperEngine/Assets/CTexture.h +++ b/src/WallpaperEngine/Assets/CTexture.h @@ -21,13 +21,14 @@ namespace WallpaperEngine::Assets CTexture (void* fileData); ~CTexture (); - const GLuint getTextureID (int imageIndex) const override; - const uint32_t getTextureWidth () const override; - const uint32_t getTextureHeight () const override; + const GLuint getTextureID (uint32_t imageIndex = 0) const override; + const uint32_t getTextureWidth (uint32_t imageIndex = 0) const override; + const uint32_t getTextureHeight (uint32_t imageIndex = 0) const override; const uint32_t getRealWidth () const override; const uint32_t getRealHeight () const override; const TextureFormat getFormat () const override; const glm::vec4* getResolution () const override; + const std::vector& getFrames () const override; const bool isAnimated () const override; private: @@ -74,28 +75,6 @@ namespace WallpaperEngine::Assets void decompressData (); }; - class TextureFrame - { - public: - TextureFrame(); - ~TextureFrame(); - - /** The image index of this frame */ - uint32_t frameNumber; - /** The amount of time this frame spends being displayed */ - float frametime; - /** The x position of the frame in the texture */ - float x; - /** The y position of the frame in the texture */ - float y; - /** The width of the frame in the texture */ - float width; - float unk0; - float unk1; - /** The height of the frame in the texture */ - float height; - }; - /** * Configures how the texture will be handled by the background */ diff --git a/src/WallpaperEngine/Assets/ITexture.h b/src/WallpaperEngine/Assets/ITexture.h index 9ec4523..6a96aa7 100644 --- a/src/WallpaperEngine/Assets/ITexture.h +++ b/src/WallpaperEngine/Assets/ITexture.h @@ -2,12 +2,35 @@ #include #include +#include namespace WallpaperEngine::Assets { class ITexture { public: + class TextureFrame + { + public: + TextureFrame(); + ~TextureFrame(); + + /** The image index of this frame */ + uint32_t frameNumber; + /** The amount of time this frame spends being displayed */ + float frametime; + /** The x position of the frame in the texture */ + float x; + /** The y position of the frame in the texture */ + float y; + /** The width of the frame in the texture */ + float width1; + float width2; + float height2; + /** The height of the frame in the texture */ + float height1; + }; + enum TextureFormat : uint32_t { ARGB8888 = 0, @@ -18,12 +41,13 @@ namespace WallpaperEngine::Assets R8 = 9, }; - virtual const GLuint getTextureID (int imageIndex) const = 0; - virtual const uint32_t getTextureWidth () const = 0; - virtual const uint32_t getTextureHeight () const = 0; + virtual const GLuint getTextureID (uint32_t imageIndex = 0) const = 0; + virtual const uint32_t getTextureWidth (uint32_t imageIndex = 0) const = 0; + virtual const uint32_t getTextureHeight (uint32_t imageIndex = 0) const = 0; virtual const uint32_t getRealWidth () const = 0; virtual const uint32_t getRealHeight () const = 0; virtual const TextureFormat getFormat () const = 0; + virtual const std::vector& getFrames () const = 0; virtual const glm::vec4* getResolution () const = 0; virtual const bool isAnimated () const = 0; }; diff --git a/src/WallpaperEngine/Render/CFBO.cpp b/src/WallpaperEngine/Render/CFBO.cpp index beec85c..d4bac63 100644 --- a/src/WallpaperEngine/Render/CFBO.cpp +++ b/src/WallpaperEngine/Render/CFBO.cpp @@ -69,16 +69,16 @@ GLuint CFBO::getDepthbuffer () const return this->m_depthbuffer; } -const GLuint CFBO::getTextureID (int imageIndex) const +const GLuint CFBO::getTextureID (uint32_t imageIndex) const { return this->m_texture; } -const uint32_t CFBO::getTextureWidth () const +const uint32_t CFBO::getTextureWidth (uint32_t imageIndex) const { return this->m_resolution.x; } -const uint32_t CFBO::getTextureHeight () const +const uint32_t CFBO::getTextureHeight (uint32_t imageIndex) const { return this->m_resolution.y; } @@ -93,6 +93,11 @@ const uint32_t CFBO::getRealHeight () const return this->m_resolution.w; } +const std::vector& CFBO::getFrames () const +{ + return std::vector (); +} + const glm::vec4* CFBO::getResolution () const { return &this->m_resolution; diff --git a/src/WallpaperEngine/Render/CFBO.h b/src/WallpaperEngine/Render/CFBO.h index ce64ce4..753d62d 100644 --- a/src/WallpaperEngine/Render/CFBO.h +++ b/src/WallpaperEngine/Render/CFBO.h @@ -18,11 +18,12 @@ namespace WallpaperEngine::Render const ITexture::TextureFormat getFormat () const override; GLuint getFramebuffer () const; GLuint getDepthbuffer () const; - const GLuint getTextureID (int imageIndex) const override; - const uint32_t getTextureWidth () const override; - const uint32_t getTextureHeight () const override; + const GLuint getTextureID (uint32_t imageIndex = 0) const override; + const uint32_t getTextureWidth (uint32_t imageIndex = 0) const override; + const uint32_t getTextureHeight (uint32_t imageIndex = 0) const override; const uint32_t getRealWidth () const override; const uint32_t getRealHeight () const override; + const std::vector& getFrames () const override; const glm::vec4* getResolution () const override; const bool isAnimated () const override; diff --git a/src/WallpaperEngine/Render/Objects/CImage.cpp b/src/WallpaperEngine/Render/Objects/CImage.cpp index e33963c..e01a45f 100644 --- a/src/WallpaperEngine/Render/Objects/CImage.cpp +++ b/src/WallpaperEngine/Render/Objects/CImage.cpp @@ -69,8 +69,8 @@ CImage::CImage (CScene* scene, Core::Objects::CImage* image) : nameA << "_rt_imageLayerComposite_" << this->getImage ()->getId () << "_a"; nameB << "_rt_imageLayerComposite_" << this->getImage ()->getId () << "_b"; - this->m_currentMainFBO = this->m_mainFBO = scene->createFBO (nameA.str (), ITexture::TextureFormat::ARGB8888, 1, this->m_texture->getRealWidth (), this->m_texture->getRealHeight (), this->m_texture->getRealWidth (), this->m_texture->getRealHeight ()); - this->m_currentSubFBO = this->m_subFBO = scene->createFBO (nameB.str (), ITexture::TextureFormat::ARGB8888, 1, this->m_texture->getRealWidth (), this->m_texture->getRealHeight (), this->m_texture->getRealWidth (), this->m_texture->getRealHeight ()); + this->m_currentMainFBO = this->m_mainFBO = scene->createFBO (nameA.str (), ITexture::TextureFormat::ARGB8888, 1, this->m_texture->getTextureWidth (), this->m_texture->getTextureHeight (), this->m_texture->getTextureWidth (), this->m_texture->getTextureHeight ()); + this->m_currentSubFBO = this->m_subFBO = scene->createFBO (nameB.str (), ITexture::TextureFormat::ARGB8888, 1, this->m_texture->getTextureWidth (), this->m_texture->getTextureHeight (), this->m_texture->getTextureWidth (), this->m_texture->getTextureHeight ()); GLfloat realWidth = this->m_texture->getRealWidth () / 2; GLfloat realHeight = this->m_texture->getRealHeight () / 2; @@ -106,8 +106,14 @@ CImage::CImage (CScene* scene, Core::Objects::CImage* image) : float width = 1.0f; float height = 1.0f; + if (this->getTexture ()->isAnimated () == true) + { + // animated images use different coordinates as they're essentially a texture atlast + width = static_cast (this->getTexture ()->getRealWidth ()) / static_cast (this->getTexture ()->getTextureWidth ()); + height = static_cast (this->getTexture ()->getRealHeight ()) / static_cast (this->getTexture ()->getTextureHeight ()); + } // calculate the correct texCoord limits for the texture based on the texture screen size and real size - if (this->getTexture () != nullptr && + else if (this->getTexture () != nullptr && (this->getTexture ()->getTextureWidth () != this->getTexture ()->getRealWidth () || this->getTexture ()->getTextureHeight () != this->getTexture ()->getRealHeight ()) ) @@ -122,12 +128,24 @@ CImage::CImage (CScene* scene, Core::Objects::CImage* image) : height = size.y * scale.y / y; } + float x = 0.0f; + float y = 0.0f; + + if (this->getTexture ()->isAnimated () == true) + { + // animations should be copied completely + x = 0.0f; + y = 0.0f; + width = 1.0f; + height = 1.0f; + } + GLfloat texcoordCopy [] = { - 0.0f, 0.0f, - width, 0.0f, - 0.0f, height, - 0.0f, height, - width, 0.0f, + x, y, + width, y, + x, height, + x, height, + width, y, width, height }; @@ -177,18 +195,30 @@ void CImage::setup () new CEffect (this, new Core::Objects::CEffect ("", "", "", "", this->m_image)), this->m_image->getMaterial () ); + // generate the main material used to render the image this->m_material = new Effects::CMaterial ( new CEffect (this, new Core::Objects::CEffect ("", "", "", "", this->m_image)), this->m_image->getMaterial () ); - // generate the effects used by this material - auto cur = this->getImage ()->getEffects ().begin (); - auto end = this->getImage ()->getEffects ().end (); + { + // generate the effects used by this material + auto cur = this->getImage ()->getEffects ().begin (); + auto end = this->getImage ()->getEffects ().end (); + + for (; cur != end; cur ++) + this->m_effects.emplace_back (new CEffect (this, *cur)); + } + + // calculate full animation time (if any) + this->m_animationTime = 0.0f; + + auto cur = this->getTexture ()->getFrames ().begin (); + auto end = this->getTexture ()->getFrames ().end (); for (; cur != end; cur ++) - this->m_effects.emplace_back (new CEffect (this, *cur)); + this->m_animationTime += (*cur)->frametime; } void CImage::pinpongFramebuffer (CFBO** drawTo, ITexture** asInput) @@ -209,19 +239,29 @@ void CImage::pinpongFramebuffer (CFBO** drawTo, ITexture** asInput) void CImage::simpleRender () { - // first render to the composite layer - auto cur = this->m_copyMaterial->getPasses ().begin (); - auto end = this->m_copyMaterial->getPasses ().end (); + ITexture* input = this->m_mainFBO; - for (; cur != end; cur ++) - (*cur)->render (this->m_mainFBO, this->getTexture (), *this->getCopySpacePosition (), *this->getTexCoordCopy (), this->m_modelViewProjectionPass); + // FIXME: THIS IS A QUICK HACK FOR ANIMATED IMAGES, IF ANY OF THOSE HAVE ANY EFFECT ON THEM THIS WILL LIKELY BREAK + if (this->getTexture ()->isAnimated () == true) + { + input = this->getTexture (); + } + else + { + // first render to the composite layer + auto cur = this->m_copyMaterial->getPasses ().begin (); + auto end = this->m_copyMaterial->getPasses ().end (); + + for (; cur != end; cur ++) + (*cur)->render (this->m_mainFBO, this->getTexture (), *this->getCopySpacePosition (), *this->getTexCoordCopy (), this->m_modelViewProjectionPass); + } // a simple material renders directly to the screen - cur = this->m_material->getPasses ().begin (); - end = this->m_material->getPasses ().end (); + auto cur = this->m_material->getPasses ().begin (); + auto end = this->m_material->getPasses ().end (); for (; cur != end; cur ++) - (*cur)->render (this->getScene ()->getFBO (), this->m_mainFBO, *this->getSceneSpacePosition (), *this->getTexCoordPass (), this->m_modelViewProjectionScreen); + (*cur)->render (this->getScene ()->getFBO (), input, *this->getSceneSpacePosition (), *this->getTexCoordPass (), this->m_modelViewProjectionScreen); } void CImage::complexRender () @@ -319,6 +359,11 @@ ITexture* CImage::getTexture () const return this->m_texture; } +const double CImage::getAnimationTime () const +{ + return this->m_animationTime; +} + const Core::Objects::CImage* CImage::getImage () const { return this->m_image; diff --git a/src/WallpaperEngine/Render/Objects/CImage.h b/src/WallpaperEngine/Render/Objects/CImage.h index 185063a..72a1082 100644 --- a/src/WallpaperEngine/Render/Objects/CImage.h +++ b/src/WallpaperEngine/Render/Objects/CImage.h @@ -45,6 +45,7 @@ namespace WallpaperEngine::Render::Objects const GLuint* getTexCoordCopy () const; const GLuint* getTexCoordPass () const; ITexture* getTexture () const; + const double getAnimationTime () const; /** * Performs a ping-pong on the available framebuffers to be able to continue rendering things to them @@ -80,5 +81,7 @@ namespace WallpaperEngine::Render::Objects std::vector m_effects; Effects::CMaterial* m_material; Effects::CMaterial* m_copyMaterial; + + double m_animationTime; }; } diff --git a/src/WallpaperEngine/Render/Objects/Effects/CPass.cpp b/src/WallpaperEngine/Render/Objects/Effects/CPass.cpp index fcacd2f..f5a9c53 100644 --- a/src/WallpaperEngine/Render/Objects/Effects/CPass.cpp +++ b/src/WallpaperEngine/Render/Objects/Effects/CPass.cpp @@ -138,8 +138,42 @@ void CPass::render (CFBO* drawTo, ITexture* input, GLuint position, GLuint texco ITexture* texture = this->resolveTexture (input, 0, input); + uint32_t currentTexture = 0; + glm::vec2 translation = {0.0f, 0.0f}; + glm::vec4 rotation = {0.0f, 0.0f, 0.0f, 0.0f}; + + if (texture->isAnimated () == true) + { + // calculate current texture and frame + double currentRenderTime = fmod (static_cast (g_Time), this->m_material->getImage ()->getAnimationTime ()); + + // find the right frame now + auto frameCur = texture->getFrames ().begin (); + auto frameEnd = texture->getFrames ().end (); + + for (; frameCur != frameEnd; frameCur ++) + { + currentRenderTime -= (*frameCur)->frametime; + + if (currentRenderTime <= 0.0f) + { + // frame found, store coordinates and done + currentTexture = (*frameCur)->frameNumber; + + translation.x = (*frameCur)->x / texture->getTextureWidth (currentTexture); + translation.y = (*frameCur)->y / texture->getTextureHeight (currentTexture); + + rotation.x = (*frameCur)->width1 / static_cast (texture->getTextureWidth (currentTexture)); + rotation.y = (*frameCur)->width2 / static_cast (texture->getTextureWidth(currentTexture)); + rotation.z = (*frameCur)->height2 / static_cast (texture->getTextureHeight (currentTexture)); + rotation.w = (*frameCur)->height1 / static_cast (texture->getTextureHeight (currentTexture)); + break; + } + } + } + glActiveTexture (GL_TEXTURE0); - glBindTexture (GL_TEXTURE_2D, texture->getTextureID (0)); + glBindTexture (GL_TEXTURE_2D, texture->getTextureID (currentTexture)); int lastTextureIndex = 0; // first bind the textures to their sampler place @@ -233,11 +267,14 @@ void CPass::render (CFBO* drawTo, ITexture* input, GLuint position, GLuint texco if (this->g_Texture0Rotation != -1) { - glUniform4f (this->g_Texture0Rotation, 1.0f, 0.0f, 1.0f, 0.0f); + // used in animations when one of the frames is vertical instead of horizontal + // rotation with translation = origin and end of the image to display + glUniform4f (this->g_Texture0Rotation, rotation.x, rotation.y, rotation.z, rotation.w); } if (this->g_Texture0Translation != -1) { - glUniform2f (this->g_Texture0Translation, 0.0f, 0.0f); + // this actually picks the origin point of the image from the atlast + glUniform2f (this->g_Texture0Translation, translation.x, translation.y); } { auto cur = this->m_attribs.begin ();