#include "resourcemanager.h"
#include "resources.h"
#include "technique.h"
+#include "texture1d.h"
#include "texture2d.h"
#include "texturecube.h"
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");
}
#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"
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)
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);
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);
#define MSP_GL_TEXTURE_H_
#include <msp/datafile/objectloader.h>
+#include <msp/graphics/image.h>
#include "datatype.h"
#include "gl.h"
#include "pixelformat.h"
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);
/** 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; }
}
}
+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;
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
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;
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:
-#include <msp/io/memory.h>
#include "bindable.h"
#include "buffer.h"
#include "error.h"
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);
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());
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);
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);
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;
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
*/
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;
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; }
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;
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);