Explorar o código

+ added support for reading multiple images from a texture
first steps to fix #79

Signed-off-by: Alexis Maiquez <almamu@almamu.com>

Alexis Maiquez %!s(int64=4) %!d(string=hai) anos
pai
achega
64d2f77d41

+ 257 - 133
src/WallpaperEngine/Assets/CTexture.cpp

@@ -9,20 +9,36 @@ using namespace WallpaperEngine::Assets;
 CTexture::CTexture (void* fileData)
 {
     // ensure the header is parsed
-    this->parseHeader (static_cast <char*> (fileData));
+    this->m_header = this->parseHeader (static_cast <char*> (fileData));
 
     GLint internalFormat;
 
+    if (this->isAnimated () == true)
+    {
+        this->m_resolution = {
+            this->m_header->textureWidth, this->m_header->textureHeight,
+            this->m_header->gifWidth, this->m_header->gifHeight
+        };
+    }
+    else
+    {
+        // set the texture resolution
+        this->m_resolution = {
+                this->m_header->textureWidth, this->m_header->textureHeight,
+                this->m_header->width, this->m_header->height
+        };
+    }
+
     if (this->m_header->freeImageFormat != FREE_IMAGE_FORMAT::FIF_UNKNOWN)
     {
         internalFormat = GL_RGBA8;
         // set some extra information too as it's used for image sizing
         // this ensures that a_TexCoord uses the full image instead of just part of it
-        this->m_header->width = this->m_header->mipmaps [0]->width;
+        // TODO: MAYBE IT'S BETTER TO CREATE A TEXTURE OF THE GIVEN SIZE AND COPY OVER WHAT WE READ FROM THE FILE?
+        /*this->m_header->width = this->m_header->mipmaps [0]->width;
         this->m_header->height = this->m_header->mipmaps [0]->height;
         this->m_header->textureWidth = this->m_header->mipmaps [0]->width;
-        this->m_header->textureHeight = this->m_header->mipmaps [0]->height;
-        // TODO: MAYBE IT'S BETTER TO CREATE A TEXTURE OF THE GIVEN SIZE AND COPY OVER WHAT WE READ FROM THE FILE?
+        this->m_header->textureHeight = this->m_header->mipmaps [0]->height;*/
     }
     else
     {
@@ -53,114 +69,115 @@ CTexture::CTexture (void* fileData)
         }
     }
 
-    // set the texture resolution
-    // TODO: SUPPORT SPRITES
-    this->m_resolution = {
-        this->m_header->textureWidth, this->m_header->textureHeight,
-        this->m_header->width, this->m_header->height
-    };
-
-    // reserve a texture
-    glGenTextures (1, &this->m_textureID);
-
-    // bind the texture to assign information to it
-    glBindTexture (GL_TEXTURE_2D, this->m_textureID);
-    // set mipmap levels
-    glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
-    glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, this->m_header->mipmapCount - 1);
-
-    // TODO: ADD SUPPORT FOR .tex-json FILES AS THEY ALSO HAVE FLAGS LIKE THESE ONES
-    // setup texture wrapping and filtering
-    if (this->m_header->flags & TextureFlags::ClampUVs)
-    {
-        glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-        glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-    }
-    else
-    {
-        glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
-        glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
-    }
-
-    if (this->m_header->flags & TextureFlags::NoInterpolation)
-    {
-        glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-        glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
-    }
-    else
-    {
-        glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-        glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
-    }
-
-    glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY, 8.0f);
+    // allocate texture ids list
+    this->m_textureID = new GLuint [this->m_header->imageCount];
+    // ask opengl for the correct amount of textures
+    glGenTextures (this->m_header->imageCount, this->m_textureID);
 
-    // TODO: USE THIS ONE
-    // uint32_t blockSize = (internalFormat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) ? 8 : 16;
+    auto imgCur = this->m_header->images.begin ();
+    auto imgEnd = this->m_header->images.end ();
 
-    auto cur = this->m_header->mipmaps.begin ();
-    auto end = this->m_header->mipmaps.end ();
-
-    for (int32_t level = 0; cur != end; cur ++, level ++)
+    for (int index = 0; imgCur != imgEnd; imgCur ++, index ++)
     {
-        FIBITMAP* bitmap = nullptr;
-        FIBITMAP* converted = nullptr;
-        FIMEMORY* memory = nullptr;
-        void* dataptr = (*cur)->uncompressedData;
-        uint32_t width = (*cur)->width;
-        uint32_t height = (*cur)->height;
-        GLenum textureFormat = GL_RGBA;
-
-        if (this->m_header->freeImageFormat != FREE_IMAGE_FORMAT::FIF_UNKNOWN)
+        // bind the texture to assign information to it
+        glBindTexture (GL_TEXTURE_2D, this->m_textureID [index]);
+        // set mipmap levels
+        glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
+        glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, this->m_header->mipmapCount - 1);
+
+        // TODO: ADD SUPPORT FOR .tex-json FILES AS THEY ALSO HAVE FLAGS LIKE THESE ONES
+        // setup texture wrapping and filtering
+        if (this->m_header->flags & TextureFlags::ClampUVs)
         {
-            memory = FreeImage_OpenMemory (reinterpret_cast <BYTE *> ((*cur)->uncompressedData), (*cur)->uncompressedSize);
-
-            // load the image and setup pointers so they can be used
-            bitmap = FreeImage_LoadFromMemory (this->m_header->freeImageFormat, memory);
-            // flip the image vertically
-            FreeImage_FlipVertical (bitmap);
-            // convert to a 32bits bytearray
-            converted = FreeImage_ConvertTo32Bits (bitmap);
-
-            dataptr = FreeImage_GetBits (converted);
-            width = FreeImage_GetWidth (converted);
-            height = FreeImage_GetHeight (converted);
-            textureFormat = GL_BGRA;
+            glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+            glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
         }
         else
         {
-            if (this->m_header->format == TextureFormat::RG88)
-                textureFormat = GL_RG;
-            else if (this->m_header->format == TextureFormat::R8)
-                textureFormat = GL_R;
+            glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+            glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
         }
 
-        switch (internalFormat)
+        if (this->m_header->flags & TextureFlags::NoInterpolation)
         {
-            case GL_RGBA8:
-                glTexImage2D (GL_TEXTURE_2D, level, internalFormat,
-                    width, height, 0,
-                    textureFormat, GL_UNSIGNED_BYTE,
-                    dataptr
-                );
-                break;
-            case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
-            case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
-            case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
-                glCompressedTexImage2D (
-                        GL_TEXTURE_2D, level, internalFormat,
-                        (*cur)->width, (*cur)->height, 0,
-                        (*cur)->uncompressedSize, dataptr
-                );
-                break;
+            glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+            glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
+        }
+        else
+        {
+            glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+            glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
         }
 
-        // freeimage buffer won't be used anymore, so free memory
-        if (this->m_header->freeImageFormat != FREE_IMAGE_FORMAT::FIF_UNKNOWN)
+        glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY, 8.0f);
+
+        // TODO: USE THIS ONE
+        // uint32_t blockSize = (internalFormat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) ? 8 : 16;
+
+        auto cur = (*imgCur).second.begin ();
+        auto end = (*imgCur).second.end ();
+
+        for (int32_t level = 0; cur != end; cur ++, level ++)
         {
-            FreeImage_Unload (bitmap);
-            FreeImage_Unload (converted);
-            FreeImage_CloseMemory (memory);
+            FIBITMAP* bitmap = nullptr;
+            FIBITMAP* converted = nullptr;
+            FIMEMORY* memory = nullptr;
+            void* dataptr = (*cur)->uncompressedData;
+            uint32_t width = (*cur)->width;
+            uint32_t height = (*cur)->height;
+            GLenum textureFormat = GL_RGBA;
+
+            if (this->m_header->freeImageFormat != FREE_IMAGE_FORMAT::FIF_UNKNOWN)
+            {
+                memory = FreeImage_OpenMemory (reinterpret_cast <BYTE *> ((*cur)->uncompressedData), (*cur)->uncompressedSize);
+
+                // load the image and setup pointers so they can be used
+                bitmap = FreeImage_LoadFromMemory (this->m_header->freeImageFormat, memory);
+                // flip the image vertically
+                FreeImage_FlipVertical (bitmap);
+                // convert to a 32bits bytearray
+                converted = FreeImage_ConvertTo32Bits (bitmap);
+
+                dataptr = FreeImage_GetBits (converted);
+                width = FreeImage_GetWidth (converted);
+                height = FreeImage_GetHeight (converted);
+                textureFormat = GL_BGRA;
+            }
+            else
+            {
+                if (this->m_header->format == TextureFormat::RG88)
+                    textureFormat = GL_RG;
+                else if (this->m_header->format == TextureFormat::R8)
+                    textureFormat = GL_R;
+            }
+
+            switch (internalFormat)
+            {
+                case GL_RGBA8:
+                    glTexImage2D (GL_TEXTURE_2D, level, internalFormat,
+                                  width, height, 0,
+                                  textureFormat, GL_UNSIGNED_BYTE,
+                                  dataptr
+                    );
+                    break;
+                case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+                case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+                case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+                    glCompressedTexImage2D (
+                            GL_TEXTURE_2D, level, internalFormat,
+                            (*cur)->width, (*cur)->height, 0,
+                            (*cur)->uncompressedSize, dataptr
+                    );
+                    break;
+            }
+
+            // freeimage buffer won't be used anymore, so free memory
+            if (this->m_header->freeImageFormat != FREE_IMAGE_FORMAT::FIF_UNKNOWN)
+            {
+                FreeImage_Unload (bitmap);
+                FreeImage_Unload (converted);
+                FreeImage_CloseMemory (memory);
+            }
         }
     }
 }
@@ -174,9 +191,13 @@ CTexture::~CTexture ()
     delete this->getHeader ();
 }
 
-const GLuint CTexture::getTextureID () const
+const GLuint CTexture::getTextureID (int imageIndex) const
 {
-    return this->m_textureID;
+    // ensure we do not go out of bounds
+    if (imageIndex > this->m_header->imageCount)
+        return this->m_textureID [0];
+
+    return this->m_textureID [imageIndex];
 }
 
 const uint32_t CTexture::getTextureWidth () const
@@ -214,6 +235,11 @@ const glm::vec4* CTexture::getResolution () const
     return &this->m_resolution;
 }
 
+const bool CTexture::isAnimated () const
+{
+    return this->getHeader ()->isAnimated ();
+}
+
 CTexture::TextureMipmap::TextureMipmap ()
 {
 }
@@ -242,20 +268,34 @@ void CTexture::TextureMipmap::decompressData ()
     }
 }
 
+CTexture::TextureFrame::TextureFrame ()
+{
+}
+
+CTexture::TextureFrame::~TextureFrame ()
+{
+}
+
 CTexture::TextureHeader::TextureHeader ()
 {
 }
 
 CTexture::TextureHeader::~TextureHeader ()
 {
-    auto cur = this->mipmaps.begin ();
-    auto end = this->mipmaps.end ();
+    auto imgCur = this->images.begin ();
+    auto imgEnd = this->images.end ();
 
-    for (; cur != end; cur ++)
-        delete *cur;
+    for (; imgCur != imgEnd; imgCur ++)
+    {
+        auto cur = (*imgCur).second.begin ();
+        auto end = (*imgCur).second.end ();
+
+        for (; cur != end; cur ++)
+            delete *cur;
+    }
 }
 
-void CTexture::parseHeader (char* fileData)
+CTexture::TextureHeader* CTexture::parseHeader (char* fileData)
 {
     // check the magic value on the header first
     if (memcmp (fileData, "TEXV0005", 9) != 0)
@@ -268,16 +308,16 @@ void CTexture::parseHeader (char* fileData)
     // jump through the string again
     fileData += 9;
 
-    this->m_header = new TextureHeader;
+    TextureHeader* header = new TextureHeader;
 
     uint32_t* pointer = reinterpret_cast <uint32_t*> (fileData);
 
-    this->m_header->format = static_cast <TextureFormat>(*pointer ++);
-    this->m_header->flags = static_cast <TextureFlags> (*pointer ++);
-    this->m_header->textureWidth = *pointer ++;
-    this->m_header->textureHeight = *pointer ++;
-    this->m_header->width = *pointer ++;
-    this->m_header->height = *pointer ++;
+    header->format = static_cast <TextureFormat>(*pointer ++);
+    header->flags = static_cast <TextureFlags> (*pointer ++);
+    header->textureWidth = *pointer ++;
+    header->textureHeight = *pointer ++;
+    header->width = *pointer ++;
+    header->height = *pointer ++;
     pointer ++; // ignore some more bytes
 
     // now we're going to parse some more data that is string
@@ -288,42 +328,121 @@ void CTexture::parseHeader (char* fileData)
 
     if (memcmp (fileData, "TEXB0003", 9) == 0)
     {
-        this->m_header->containerVersion = ContainerVersion::TEXB0003;
-
-        // get back the pointer and use it
-        pointer ++;
-        this->m_header->freeImageFormat = static_cast <FREE_IMAGE_FORMAT> (*pointer++);
+        header->containerVersion = ContainerVersion::TEXB0003;
+        header->imageCount = *pointer ++;
+        header->freeImageFormat = static_cast <FREE_IMAGE_FORMAT> (*pointer++);
     }
     else if(memcmp (fileData, "TEXB0002", 9) == 0)
     {
-        this->m_header->containerVersion = ContainerVersion::TEXB0002;
-
-        // skip 4 bytes
-        pointer ++;
+        header->containerVersion = ContainerVersion::TEXB0002;
+        header->imageCount = *pointer ++;
     }
     else if (memcmp (fileData, "TEXB0001", 9) == 0)
     {
-        this->m_header->containerVersion = ContainerVersion::TEXB0001;
-
-        // skip 4 bytes
-        pointer ++;
+        header->containerVersion = ContainerVersion::TEXB0001;
+        header->imageCount = *pointer ++;
     }
     else
     {
-        delete this->m_header;
-        this->m_header = nullptr;
+        delete header;
         throw std::runtime_error ("unknown texture format type");
     }
 
-    // read the number of mipmaps available
-    this->m_header->mipmapCount = *pointer ++;
+    for (uint32_t image = 0; image < header->imageCount; image ++)
+    {
+        // read the number of mipmaps available for this image
+        header->mipmapCount = *pointer ++;
+        std::vector <TextureMipmap*> mipmaps;
 
-    fileData = reinterpret_cast <char*> (pointer);
+        fileData = reinterpret_cast <char*> (pointer);
+
+        for (uint32_t i = 0; i < header->mipmapCount; i ++)
+            mipmaps.emplace_back (parseMipmap (header, &fileData));
+
+        // add the pixmaps back
+        header->images.insert (std::pair <uint32_t, std::vector <TextureMipmap*>> (image, mipmaps));
+
+        pointer = reinterpret_cast <uint32_t*> (fileData);
+    }
+
+    // gifs have extra information after the mipmaps
+    if (header->isAnimated () == true)
+    {
+        if (memcmp (fileData, "TEXS0002", 9) == 0)
+        {
+            header->animatedVersion = AnimatedVersion::TEXS0002;
+        }
+        else if (memcmp (fileData, "TEXS0003", 9) == 0)
+        {
+            header->animatedVersion = AnimatedVersion::TEXS0003;
+        }
+        else
+        {
+            throw std::runtime_error ("found animation information of unknown type");
+        }
+
+        // get an integer pointer back to read the frame count
+        pointer = reinterpret_cast <uint32_t*> (fileData + 9);
+        uint32_t framecount = *pointer++;
 
-    for (uint32_t i = 0; i < this->m_header->mipmapCount; i ++)
-        this->m_header->mipmaps.emplace_back (this->parseMipmap (this->m_header, &fileData));
+        if (header->animatedVersion == AnimatedVersion::TEXS0003)
+        {
+            // ignore two extra integers as those are width and height of the git
+            header->gifWidth = *pointer ++;
+            header->gifHeight = *pointer ++;
+        }
+
+        // get back the pointer into filedata
+        fileData = reinterpret_cast <char*> (pointer);
+
+        while (framecount > 0)
+        {
+            // add the frame to the list
+            header->frames.push_back (parseAnimation (header, &fileData));
+
+            framecount --;
+        }
+
+        // ensure gif width and height is right for TEXS0002
+        if (header->animatedVersion == AnimatedVersion::TEXS0002)
+        {
+            TextureFrame* first = *header->frames.begin ();
+
+            header->gifWidth = first->width;
+            header->gifHeight = first->height;
+        }
+    }
+
+    return header;
 }
 
+CTexture::TextureFrame* CTexture::parseAnimation (TextureHeader* header, char** originalFileData)
+{
+    char* fileData = *originalFileData;
+    // get back the pointer into integer
+    uint32_t* pointer = reinterpret_cast <uint32_t*> (fileData);
+
+    // start reading frame information
+    TextureFrame* frame = new TextureFrame();
+
+    frame->frameNumber = *pointer++;
+
+    // reinterpret the pointer into float
+    float* fPointer = reinterpret_cast <float*> (pointer);
+
+    frame->frametime = *fPointer ++;
+    frame->x = *fPointer ++;
+    frame->y = *fPointer ++;
+    frame->width = *fPointer ++;
+    frame->unk0 = *fPointer ++;
+    frame->unk1 = *fPointer ++;
+    frame->height = *fPointer ++;
+
+    // get back the pointer into fileData so it can be reused later
+    *originalFileData = reinterpret_cast <char*> (fPointer);
+
+    return frame;
+}
 
 CTexture::TextureMipmap* CTexture::parseMipmap (TextureHeader* header, char** originalFileData)
 {
@@ -380,4 +499,9 @@ CTexture::TextureMipmap* CTexture::parseMipmap (TextureHeader* header, char** or
     *originalFileData = fileData;
 
     return mipmap;
+}
+
+const bool CTexture::TextureHeader::isAnimated () const
+{
+    return this->flags & TextureFlags::IsGif;
 }

+ 49 - 5
src/WallpaperEngine/Assets/CTexture.h

@@ -8,6 +8,7 @@
 #include <glm/vec4.hpp>
 
 #include <FreeImage.h>
+#include <map>
 #include "ITexture.h"
 
 namespace WallpaperEngine::Assets
@@ -20,13 +21,14 @@ namespace WallpaperEngine::Assets
         CTexture (void* fileData);
         ~CTexture ();
 
-        const GLuint getTextureID () const override;
+        const GLuint getTextureID (int imageIndex) const override;
         const uint32_t getTextureWidth () const override;
         const uint32_t getTextureHeight () 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 bool isAnimated () const override;
 
     private:
         const TextureHeader* getHeader () const;
@@ -39,6 +41,13 @@ namespace WallpaperEngine::Assets
             TEXB0001 = 1
         };
 
+        enum AnimatedVersion : int
+        {
+            TEXSUNKN = -1,
+            TEXS0002 = 0,
+            TEXS0003 = 1,
+        };
+
         class TextureMipmap
         {
         public:
@@ -65,6 +74,28 @@ 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
          */
@@ -82,8 +113,12 @@ namespace WallpaperEngine::Assets
             TextureHeader ();
             ~TextureHeader ();
 
+            const bool isAnimated () const;
+
             /** The version of the texture container */
             ContainerVersion containerVersion = ContainerVersion::UNKNOWN;
+            /** The version of the animated data */
+            AnimatedVersion animatedVersion = AnimatedVersion::TEXSUNKN;
             /** Flags with extra texture information */
             TextureFlags flags;
             /** Real width of the texture */
@@ -94,21 +129,30 @@ namespace WallpaperEngine::Assets
             uint32_t textureWidth;
             /** Texture height in memory (power of 2) */
             uint32_t textureHeight;
+            /** Gif width */
+            uint32_t gifWidth;
+            /** Gif height */
+            uint32_t gifHeight;
             /** Texture data format */
             TextureFormat format;
             /** Free Image format */
             FREE_IMAGE_FORMAT freeImageFormat = FREE_IMAGE_FORMAT::FIF_UNKNOWN;
+            /** The amount of images in the texture file */
+            uint32_t imageCount;
             /** Number of mipmap levels on the texture */
             uint32_t mipmapCount;
             /** List of mipmaps */
-            std::vector <TextureMipmap*> mipmaps;
+            std::map <uint32_t, std::vector <TextureMipmap*>> images;
+            /** List of animation frames */
+            std::vector <TextureFrame*> frames;
         };
     private:
-        void parseHeader (char* fileData);
-        TextureMipmap* parseMipmap (TextureHeader* header, char** fileData);
+        static TextureHeader* parseHeader (char* fileData);
+        static TextureFrame* parseAnimation (TextureHeader* header, char** originalFileData);
+        static TextureMipmap* parseMipmap (TextureHeader* header, char** fileData);
 
         TextureHeader* m_header;
-        GLuint m_textureID;
+        GLuint* m_textureID;
         glm::vec4 m_resolution;
     };
 }

+ 2 - 1
src/WallpaperEngine/Assets/ITexture.h

@@ -18,12 +18,13 @@ namespace WallpaperEngine::Assets
             R8 = 9,
         };
 
-        virtual const GLuint getTextureID () const = 0;
+        virtual const GLuint getTextureID (int imageIndex) const = 0;
         virtual const uint32_t getTextureWidth () const = 0;
         virtual const uint32_t getTextureHeight () const = 0;
         virtual const uint32_t getRealWidth () const = 0;
         virtual const uint32_t getRealHeight () const = 0;
         virtual const TextureFormat getFormat () const = 0;
         virtual const glm::vec4* getResolution () const = 0;
+        virtual const bool isAnimated () const = 0;
     };
 };

+ 6 - 1
src/WallpaperEngine/Render/CFBO.cpp

@@ -69,7 +69,7 @@ GLuint CFBO::getDepthbuffer () const
     return this->m_depthbuffer;
 }
 
-const GLuint CFBO::getTextureID () const
+const GLuint CFBO::getTextureID (int imageIndex) const
 {
     return this->m_texture;
 }
@@ -96,4 +96,9 @@ const uint32_t CFBO::getRealHeight () const
 const glm::vec4* CFBO::getResolution () const
 {
     return &this->m_resolution;
+}
+
+const bool CFBO::isAnimated () const
+{
+    return false;
 }

+ 2 - 1
src/WallpaperEngine/Render/CFBO.h

@@ -18,12 +18,13 @@ namespace WallpaperEngine::Render
         const ITexture::TextureFormat getFormat () const override;
         GLuint getFramebuffer () const;
         GLuint getDepthbuffer () const;
-        const GLuint getTextureID () const override;
+        const GLuint getTextureID (int imageIndex) const override;
         const uint32_t getTextureWidth () const override;
         const uint32_t getTextureHeight () const override;
         const uint32_t getRealWidth () const override;
         const uint32_t getRealHeight () const override;
         const glm::vec4* getResolution () const override;
+        const bool isAnimated () const override;
 
     private:
 

+ 1 - 1
src/WallpaperEngine/Render/CWallpaper.cpp

@@ -66,7 +66,7 @@ GLuint CWallpaper::getWallpaperFramebuffer () const
 
 GLuint CWallpaper::getWallpaperTexture () const
 {
-    return this->m_sceneFBO->getTextureID();
+    return this->m_sceneFBO->getTextureID(0);
 }
 
 void CWallpaper::setupShaders ()

+ 4 - 4
src/WallpaperEngine/Render/Objects/Effects/CPass.cpp

@@ -139,7 +139,7 @@ void CPass::render (CFBO* drawTo, ITexture* input, GLuint position, GLuint texco
     ITexture* texture = this->resolveTexture (input, 0, input);
 
     glActiveTexture (GL_TEXTURE0);
-    glBindTexture (GL_TEXTURE_2D, texture->getTextureID ());
+    glBindTexture (GL_TEXTURE_2D, texture->getTextureID (0));
     int lastTextureIndex = 0;
 
     // first bind the textures to their sampler place
@@ -153,7 +153,7 @@ void CPass::render (CFBO* drawTo, ITexture* input, GLuint position, GLuint texco
             texture = this->resolveTexture ((*cur), index, input);
 
             glActiveTexture (GL_TEXTURE0 + index);
-            glBindTexture (GL_TEXTURE_2D, texture->getTextureID ());
+            glBindTexture (GL_TEXTURE_2D, texture->getTextureID (0));
             // increase the number of textures counter
             lastTextureIndex ++;
         }
@@ -173,7 +173,7 @@ void CPass::render (CFBO* drawTo, ITexture* input, GLuint position, GLuint texco
             // set the active texture index
             glActiveTexture (GL_TEXTURE0 + (*cur).first);
             // bind the correct texture here
-            glBindTexture(GL_TEXTURE_2D, texture->getTextureID ());
+            glBindTexture(GL_TEXTURE_2D, texture->getTextureID (0));
         }
     }
 
@@ -191,7 +191,7 @@ void CPass::render (CFBO* drawTo, ITexture* input, GLuint position, GLuint texco
             // set the active texture index
             glActiveTexture (GL_TEXTURE0 + (*cur).first);
             // bind the correct texture here
-            glBindTexture(GL_TEXTURE_2D, texture->getTextureID ());
+            glBindTexture(GL_TEXTURE_2D, texture->getTextureID (0));
         }
     }