From d2efbd8a32efa2a3ee8542efc846277af19d63e0 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Thu, 27 Oct 2016 10:48:32 +0300 Subject: [PATCH] Implement loading functionality for texture classes that were missing it --- source/resources.cpp | 3 ++ source/texture.cpp | 19 +++++++++++++ source/texture.h | 13 +++++++++ source/texture1d.cpp | 46 ++++++++++++++++++++++++++++++ source/texture1d.h | 14 +++++++++ source/texture2d.cpp | 19 ------------- source/texture2d.h | 6 +--- source/texture3d.cpp | 64 ++++++++++++++++++++++++++++++++++++++++++ source/texture3d.h | 28 +++++++++++++++++- source/texturecube.cpp | 24 ++++++++++++++++ source/texturecube.h | 2 ++ 11 files changed, 213 insertions(+), 25 deletions(-) diff --git a/source/resources.cpp b/source/resources.cpp index 61d05c9b..c3042663 100644 --- a/source/resources.cpp +++ b/source/resources.cpp @@ -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().keyword("pose"); add_type().keyword("shader"); add_type().suffix(".tech").keyword("technique"); + add_type().base().suffix(".tex1d").keyword("texture1d"); add_type().base().suffix(".tex2d").suffix(".png").suffix(".jpg").keyword("texture2d").creator(&Resources::create_texture2d); + add_type().base().suffix(".tex3d").keyword("texture3d"); add_type().base().suffix(".texcb").keyword("texture_cube"); } diff --git a/source/texture.cpp b/source/texture.cpp index 8d43143c..bda29f05 100644 --- a/source/texture.cpp +++ b/source/texture.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #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); diff --git a/source/texture.h b/source/texture.h index 4cd5481e..3e050db5 100644 --- a/source/texture.h +++ b/source/texture.h @@ -2,6 +2,7 @@ #define MSP_GL_TEXTURE_H_ #include +#include #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; } diff --git a/source/texture1d.cpp b/source/texture1d.cpp index 046fca6f..043e0c0e 100644 --- a/source/texture1d.cpp +++ b/source/texture1d.cpp @@ -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(t) +{ + init(); +} + +Texture1D::Loader::Loader(Texture1D &t, Collection &c): + DataFile::DerivedObjectLoader(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 diff --git a/source/texture1d.h b/source/texture1d.h index 20b1d35c..ee930a87 100644 --- a/source/texture1d.h +++ b/source/texture1d.h @@ -8,6 +8,19 @@ namespace GL { class Texture1D: public Texture { +public: + class Loader: public DataFile::DerivedObjectLoader + { + 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: diff --git a/source/texture2d.cpp b/source/texture2d.cpp index d435a356..2189fa83 100644 --- a/source/texture2d.cpp +++ b/source/texture2d.cpp @@ -1,4 +1,3 @@ -#include #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()); diff --git a/source/texture2d.h b/source/texture2d.h index 030fe408..674c778f 100644 --- a/source/texture2d.h +++ b/source/texture2d.h @@ -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); diff --git a/source/texture3d.cpp b/source/texture3d.cpp index d5badc72..8b014aee 100644 --- a/source/texture3d.cpp +++ b/source/texture3d.cpp @@ -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(t) +{ + init(); +} + +Texture3D::Loader::Loader(Texture3D &t, Collection &c): + DataFile::DerivedObjectLoader(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 diff --git a/source/texture3d.h b/source/texture3d.h index 93cae7e8..75ae0fe9 100644 --- a/source/texture3d.h +++ b/source/texture3d.h @@ -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 + { + 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; } diff --git a/source/texturecube.cpp b/source/texturecube.cpp index 576f1c71..743eb986 100644 --- a/source/texturecube.cpp +++ b/source/texturecube.cpp @@ -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(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; diff --git a/source/texturecube.h b/source/texturecube.h index f65ec059..9adf0697 100644 --- a/source/texturecube.h +++ b/source/texturecube.h @@ -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); -- 2.43.0