]> git.tdb.fi Git - libs/gl.git/commitdiff
Implement loading functionality for texture classes that were missing it
authorMikko Rasa <tdb@tdb.fi>
Thu, 27 Oct 2016 07:48:32 +0000 (10:48 +0300)
committerMikko Rasa <tdb@tdb.fi>
Thu, 27 Oct 2016 07:49:42 +0000 (10:49 +0300)
source/resources.cpp
source/texture.cpp
source/texture.h
source/texture1d.cpp
source/texture1d.h
source/texture2d.cpp
source/texture2d.h
source/texture3d.cpp
source/texture3d.h
source/texturecube.cpp
source/texturecube.h

index 61d05c9b3d831867e8b36af2f1f8cb70bb916c58..c30426633e60746756428951c8e907e82829c690 100644 (file)
@@ -12,6 +12,7 @@
 #include "resourcemanager.h"
 #include "resources.h"
 #include "technique.h"
+#include "texture1d.h"
 #include "texture2d.h"
 #include "texturecube.h"
 
@@ -35,7 +36,9 @@ Resources::Resources():
        add_type<Pose>().keyword("pose");
        add_type<Program>().keyword("shader");
        add_type<Technique>().suffix(".tech").keyword("technique");
+       add_type<Texture1D>().base<Texture>().suffix(".tex1d").keyword("texture1d");
        add_type<Texture2D>().base<Texture>().suffix(".tex2d").suffix(".png").suffix(".jpg").keyword("texture2d").creator(&Resources::create_texture2d);
+       add_type<Texture3D>().base<Texture>().suffix(".tex3d").keyword("texture3d");
        add_type<TextureCube>().base<Texture>().suffix(".texcb").keyword("texture_cube");
 }
 
index 8d43143c9d734c218211d070890bf4cd080b42ed..bda29f05cdd5a2c63f93f8cc334503c1c8e1ef97 100644 (file)
@@ -3,6 +3,7 @@
 #include <msp/gl/extensions/ext_texture3d.h>
 #include <msp/gl/extensions/ext_texture_filter_anisotropic.h>
 #include <msp/gl/extensions/sgis_generate_mipmap.h>
+#include <msp/io/memory.h>
 #include <msp/strings/format.h>
 #include "error.h"
 #include "resourcemanager.h"
@@ -203,6 +204,14 @@ void Texture::set_compare_func(Predicate f)
        update_parameter(COMPARE_FUNC);
 }
 
+void Texture::load_image(const string &fn, bool srgb)
+{
+       Graphics::Image img;
+       img.load_file(fn);
+
+       image(img, srgb);
+}
+
 void Texture::bind_to(unsigned i) const
 {
        if(!id)
@@ -282,6 +291,7 @@ void Texture::Loader::init()
        add("filter", &Loader::filter);
        add("max_anisotropy", &Loader::max_anisotropy);
        add("generate_mipmap", &Loader::generate_mipmap);
+       add("image_data", &Loader::image_data);
        add("mag_filter", &Loader::mag_filter);
        add("min_filter", &Loader::min_filter);
        add("wrap",       &Loader::wrap);
@@ -300,6 +310,15 @@ void Texture::Loader::generate_mipmap(bool gm)
        obj.set_generate_mipmap(gm);
 }
 
+void Texture::Loader::image_data(const string &data)
+{
+       Graphics::Image img;
+       IO::Memory mem(data.data(), data.size());
+       img.load_io(mem);
+
+       obj.image(img, srgb);
+}
+
 void Texture::Loader::mag_filter(TextureFilter f)
 {
        obj.set_mag_filter(f);
index 4cd5481e2e18f570377c3f13d86b8b4dbf984cb8..3e050db57f359cc0d3a9f514d828491c6a81cce0 100644 (file)
@@ -2,6 +2,7 @@
 #define MSP_GL_TEXTURE_H_
 
 #include <msp/datafile/objectloader.h>
+#include <msp/graphics/image.h>
 #include "datatype.h"
 #include "gl.h"
 #include "pixelformat.h"
@@ -82,6 +83,7 @@ protected:
 
                void filter(TextureFilter);
                void generate_mipmap(bool);
+               void image_data(const std::string &);
                void mag_filter(TextureFilter);
                void max_anisotropy(float);
                void min_filter(TextureFilter);
@@ -161,6 +163,17 @@ public:
        /** Sets the function to use for depth comparison. */
        void set_compare_func(Predicate);
 
+       /// Loads a Graphics::Image from a file and uploads it to the texture.
+       virtual void load_image(const std::string &, bool srgb = false);
+
+       /** Uploads an image to the texture.  If storage has not been defined, it
+       will be set to match the image.  Otherwise the image must be compatible
+       with the defined storage.  Semantics depend on the type of texture.
+
+       If srgb is true and storage is determined by this call, then an sRGB pixel
+       format will be used. */
+       virtual void image(const Graphics::Image &, bool srgb = false) = 0;
+
        GLenum get_target() const { return target; }
        unsigned get_id() const { return id; }
 
index 046fca6fa4eccbe49a5a5174ba498adefc1b892c..043e0c0e1008bcc4346cc6852b42ad19d9f99e4a 100644 (file)
@@ -57,6 +57,21 @@ void Texture1D::image(unsigned level, PixelFormat fmt, DataType type, const void
        }
 }
 
+void Texture1D::image(const Graphics::Image &img, bool srgb)
+{
+       if(img.get_height()!=1)
+               throw incompatible_data("Texture1D::image");
+
+       unsigned w = img.get_width();
+       PixelFormat fmt = pixelformat_from_graphics(img.get_format());
+       if(width==0)
+               storage(storage_pixelformat_from_graphics(img.get_format(), srgb), w);
+       else if(w!=width)
+               throw incompatible_data("Texture1D::image");
+
+       image(0, fmt, UNSIGNED_BYTE, img.get_data());
+}
+
 unsigned Texture1D::get_level_size(unsigned level)
 {
        return width>>level;
@@ -67,5 +82,36 @@ UInt64 Texture1D::get_data_size() const
        return id ? width*get_pixel_size(ifmt) : 0;
 }
 
+
+Texture1D::Loader::Loader(Texture1D &t):
+       DataFile::DerivedObjectLoader<Texture1D, Texture::Loader>(t)
+{
+       init();
+}
+
+Texture1D::Loader::Loader(Texture1D &t, Collection &c):
+       DataFile::DerivedObjectLoader<Texture1D, Texture::Loader>(t, c)
+{
+       init();
+}
+
+void Texture1D::Loader::init()
+{
+       add("raw_data", &Loader::raw_data);
+       add("storage", &Loader::storage);
+}
+
+void Texture1D::Loader::raw_data(const string &data)
+{
+       obj.image(0, get_base_pixelformat(obj.ifmt), UNSIGNED_BYTE, data.data());
+}
+
+void Texture1D::Loader::storage(PixelFormat fmt, unsigned w)
+{
+       if(srgb)
+               fmt = get_srgb_pixelformat(fmt);
+       obj.storage(fmt, w);
+}
+
 } // namespace GL
 } // namespace Msp
index 20b1d35cbf88b8ead6421902493e18d3d97aea19..ee930a8721a80205507deed18c73536a7584efe4 100644 (file)
@@ -8,6 +8,19 @@ namespace GL {
 
 class Texture1D: public Texture
 {
+public:
+       class Loader: public DataFile::DerivedObjectLoader<Texture1D, Texture::Loader>
+       {
+       public:
+               Loader(Texture1D &);
+               Loader(Texture1D &, Collection &);
+       private:
+               void init();
+
+               void raw_data(const std::string &);
+               void storage(PixelFormat, unsigned);
+       };
+
 private:
        PixelFormat ifmt;
        unsigned width;
@@ -19,6 +32,7 @@ public:
        void storage(PixelFormat, unsigned);
        void allocate(unsigned);
        void image(unsigned, PixelFormat, DataType, const void *);
+       virtual void image(const Graphics::Image &, bool = false);
        unsigned get_width() const { return width; }
 
 private:
index d435a356a9ef3f215c6f11d912e1c76fade17959..2189fa83360ba5ed93264f84383f249a236b7e0b 100644 (file)
@@ -1,4 +1,3 @@
-#include <msp/io/memory.h>
 #include "bindable.h"
 #include "buffer.h"
 #include "error.h"
@@ -99,14 +98,6 @@ void Texture2D::sub_image(unsigned level, int x, int y, unsigned wd, unsigned ht
        glTexSubImage2D(target, level, x, y, wd, ht, fmt, type, data);
 }
 
-void Texture2D::load_image(const string &fn, bool srgb)
-{
-       Graphics::Image img;
-       img.load_file(fn);
-
-       image(img, srgb);
-}
-
 void Texture2D::image(const Graphics::Image &img, bool srgb)
 {
        image(img, srgb, false);
@@ -175,21 +166,11 @@ Texture2D::Loader::Loader(Texture2D &t, Collection &c):
 
 void Texture2D::Loader::init()
 {
-       add("image_data", &Loader::image_data);
        add("raw_data", &Loader::raw_data);
        add("storage", &Loader::storage);
        add("storage", &Loader::storage_b);
 }
 
-void Texture2D::Loader::image_data(const string &data)
-{
-       Graphics::Image img;
-       IO::Memory mem(data.data(), data.size());
-       img.load_io(mem);
-
-       obj.image(img, srgb);
-}
-
 void Texture2D::Loader::raw_data(const string &data)
 {
        obj.image(0, get_base_pixelformat(obj.ifmt), UNSIGNED_BYTE, data.data());
index 030fe408ad0a2b08bcdc448fe1f305703c3d8dce..674c778f9782116dce94ef4c663e1dda89931953 100644 (file)
@@ -25,7 +25,6 @@ public:
        private:
                void init();
 
-               void image_data(const std::string &);
                void raw_data(const std::string &);
                void storage(PixelFormat, unsigned, unsigned);
                void storage_b(PixelFormat, unsigned, unsigned, unsigned);
@@ -62,16 +61,13 @@ public:
        void sub_image(unsigned level, int x, int y, unsigned wd, unsigned ht,
                PixelFormat fmt, DataType type, const void *data);
 
-       /// Loads a Graphics::Image from a file and uploads it to the texture.
-       void load_image(const std::string &fn, bool srgb = false);
-
        /** Uploads an image to the texture.  If storage has not been defined, it
        will be set to match the image.  Otherwise the image must be compatible with
        the defined storage.
 
        If srgb is true and storage is determined by this call, then an sRGB pixel
        format will be used. */
-       void image(const Graphics::Image &, bool srgb = false);
+       virtual void image(const Graphics::Image &, bool srgb = false);
 
 private:
        void image(const Graphics::Image &, bool, bool);
index d5badc725435fb3efb37d4c15c52bedafd40ece6..8b014aee0c262fb811444c1c44a1fba0083df21e 100644 (file)
@@ -124,6 +124,39 @@ void Texture3D::load_image(const string &fn, int dp)
        image(0, fmt, UNSIGNED_BYTE, img.get_data());
 }
 
+void Texture3D::image(const Graphics::Image &img, bool srgb)
+{
+       unsigned w = img.get_width();
+       unsigned h = img.get_height();
+       unsigned d = 1;
+
+       if(depth)
+       {
+               if(h%depth)
+                       throw incompatible_data("Texture3D::load_image");
+               h /= depth;
+               d = depth;
+       }
+       else
+       {
+               if(h%w)
+                       throw incompatible_data("Texture3D::load_image");
+               d = h/w;
+               h = w;
+       }
+
+       PixelFormat fmt = pixelformat_from_graphics(img.get_format());
+       if(width==0)
+               storage(storage_pixelformat_from_graphics(img.get_format(), srgb), w, h, d);
+       else if(w!=width || h!=height || d!=depth)
+               throw incompatible_data("Texture3D::load_image");
+
+       PixelStore pstore = PixelStore::from_image(img);
+       BindRestore _bind_ps(pstore);
+
+       image(0, fmt, UNSIGNED_BYTE, img.get_data());
+}
+
 void Texture3D::get_level_size(unsigned level, unsigned &w, unsigned &h, unsigned &d)
 {
        w >>= level;
@@ -143,5 +176,36 @@ UInt64 Texture3D::get_data_size() const
        return id ? width*height*depth*get_pixel_size(ifmt) : 0;
 }
 
+
+Texture3D::Loader::Loader(Texture3D &t):
+       DataFile::DerivedObjectLoader<Texture3D, Texture::Loader>(t)
+{
+       init();
+}
+
+Texture3D::Loader::Loader(Texture3D &t, Collection &c):
+       DataFile::DerivedObjectLoader<Texture3D, Texture::Loader>(t, c)
+{
+       init();
+}
+
+void Texture3D::Loader::init()
+{
+       add("raw_data", &Loader::raw_data);
+       add("storage", &Loader::storage);
+}
+
+void Texture3D::Loader::raw_data(const string &data)
+{
+       obj.image(0, get_base_pixelformat(obj.ifmt), UNSIGNED_BYTE, data.data());
+}
+
+void Texture3D::Loader::storage(PixelFormat fmt, unsigned w, unsigned h, unsigned d)
+{
+       if(srgb)
+               fmt = get_srgb_pixelformat(fmt);
+       obj.storage(fmt, w, h, d);
+}
+
 } // namespace GL
 } // namespace Msp
index 93cae7e84e573ff40b0e5685210a9ab6c3ca990c..75ae0fe902acb1eb8974591df86b67c9505e5fb3 100644 (file)
@@ -13,6 +13,19 @@ right cuboid.  Texture coordinates have a principal range of [0, 1].
 */
 class Texture3D: public Texture
 {
+public:
+       class Loader: public Msp::DataFile::DerivedObjectLoader<Texture3D, Texture::Loader>
+       {
+       public:
+               Loader(Texture3D &);
+               Loader(Texture3D &, Collection &);
+       private:
+               void init();
+
+               void raw_data(const std::string &);
+               void storage(PixelFormat, unsigned, unsigned, unsigned);
+       };
+
 private:
        PixelFormat ifmt;
        unsigned width;
@@ -50,9 +63,22 @@ public:
        texture's width and height are equal.  If dp is -2, the texture's height and
        depth are equal.  Otherwise, dp must be positive and determines the
        texture's depth.  In all cases, the image's height must equal the texture's
-       height times its depth. */
+       height times its depth.
+       
+       Deprecated in favor of the base class version.*/
        void load_image(const std::string &fn, int dp = -1);
 
+       using Texture::load_image;
+
+       /** Uploads an image to the texture.  If storage has not been defined, it
+       will be set to match the image.  In this case the image will be treated as
+       a stack of square layers and its height must be divisible by its width.
+       Otherwise the image must be compatible with the defined storage.
+
+       If srgb is true and storage is determined by this call, then an sRGB pixel
+       format will be used. */
+       virtual void image(const Graphics::Image &, bool = false);
+
        unsigned get_width() const { return width; }
        unsigned get_height() const { return height; }
        unsigned get_depth() const { return depth; }
index 576f1c718b3848aa043cb165b04a578f83500a70..743eb986247eb95318c98490179b3fdb95683980 100644 (file)
@@ -97,6 +97,30 @@ void TextureCube::image(TextureCubeFace face, const Graphics::Image &img, bool s
        image(face, 0, fmt, UNSIGNED_BYTE, img.get_data());
 }
 
+void TextureCube::image(const Graphics::Image &img, bool srgb)
+{
+       unsigned w = img.get_width();
+       unsigned h = img.get_height();
+
+       if(h!=w*6)
+               throw incompatible_data("TextureCube::image");
+       h /= 6;
+
+       PixelFormat fmt = pixelformat_from_graphics(img.get_format());
+       if(size==0)
+               storage(storage_pixelformat_from_graphics(img.get_format(), srgb), w);
+       else if(w!=size || h!=size)
+               throw incompatible_data("TextureCube::image");
+
+       PixelStore pstore = PixelStore::from_image(img);
+       BindRestore _bind_ps(pstore);
+
+       const char *cdata = reinterpret_cast<const char *>(img.get_data());
+       unsigned face_size = img.get_stride()*size;
+       for(unsigned i=0; i<6; ++i)
+               image(enumerate_faces(i), 0, fmt, UNSIGNED_BYTE, cdata+i*face_size);
+}
+
 unsigned TextureCube::get_level_size(unsigned level)
 {
        return size>>level;
index f65ec0592a4358b1816a59090b68f224f0c7ad78..9adf06978b4d396df7a906bcd881778d9f707ee4 100644 (file)
@@ -80,6 +80,8 @@ public:
 
        void image(TextureCubeFace, const Graphics::Image &, bool = false);
 
+       virtual void image(const Graphics::Image &, bool = false);
+
        unsigned get_size() const { return size; }
 private:
        unsigned get_level_size(unsigned);