#include "gl.h"
#include "material.h"
+#include "resources.h"
namespace Msp {
namespace GL {
Material::Loader::Loader(Material &m):
- DataFile::ObjectLoader<Material>(m)
+ DataFile::CollectionObjectLoader<Material>(m, 0)
{
+ init();
+}
+
+Material::Loader::Loader(Material &m, Collection &c):
+ DataFile::CollectionObjectLoader<Material>(m, &c)
+{
+ init();
+}
+
+void Material::Loader::init()
+{
+ if(Resources *res = dynamic_cast<Resources *>(coll))
+ srgb = res->get_srgb_conversion();
+ else
+ srgb = false;
+
add("ambient", &Loader::ambient);
add("diffuse", &Loader::diffuse);
add("specular", &Loader::specular);
add("shininess", &Loader::shininess);
}
+Color Material::Loader::make_color(float r, float g, float b, float a)
+{
+ Color c(r, g, b, a);
+ if(srgb)
+ c = c.to_linear();
+ return c;
+}
+
void Material::Loader::ambient(float r, float g, float b, float a)
{
- obj.set_ambient(GL::Color(r, g, b, a));
+ obj.set_ambient(make_color(r, g, b, a));
}
void Material::Loader::diffuse(float r, float g, float b, float a)
{
- obj.set_diffuse(GL::Color(r, g, b, a));
+ obj.set_diffuse(make_color(r, g, b, a));
}
void Material::Loader::specular(float r, float g, float b, float a)
{
- obj.set_specular(GL::Color(r, g, b, a));
+ obj.set_specular(make_color(r, g, b, a));
}
void Material::Loader::emission(float r, float g, float b, float a)
{
- obj.set_emission(GL::Color(r, g, b, a));
+ obj.set_emission(make_color(r, g, b, a));
}
void Material::Loader::shininess(float s)
class Material: public BindableWithDefault<Material>
{
public:
- class Loader: public DataFile::ObjectLoader<Material>
+ class Loader: public DataFile::CollectionObjectLoader<Material>
{
+ private:
+ bool srgb;
+
public:
Loader(Material &);
-
+ Loader(Material &, Collection &);
private:
+ void init();
+
+ Color make_color(float, float, float, float);
void ambient(float, float, float, float);
void diffuse(float, float, float, float);
void specular(float, float, float, float);
}
}
+PixelFormat get_srgb_pixelformat(PixelFormat pf)
+{
+ switch(pf)
+ {
+ case RGB: return SRGB;
+ case RGBA: return SRGB_ALPHA;
+ case RGB8: return SRGB8;
+ case RGBA8: return SRGB8_ALPHA8;
+ case LUMINANCE: return SLUMINANCE;
+ case LUMINANCE8: return SLUMINANCE8;
+ case LUMINANCE_ALPHA: return SLUMINANCE_ALPHA;
+ case LUMINANCE_ALPHA8: return SLUMINANCE8_ALPHA8;
+ default: return pf;
+ }
+}
+
unsigned get_component_count(PixelFormat pf)
{
switch(get_base_pixelformat(pf))
PixelFormat storage_pixelformat_from_graphics(Graphics::PixelFormat);
PixelFormat get_base_pixelformat(PixelFormat);
+PixelFormat get_srgb_pixelformat(PixelFormat);
unsigned get_component_count(PixelFormat);
void require_pixelformat(PixelFormat);
void RenderPass::Loader::material_inline()
{
RefPtr<Material> mat = new Material;
- load_sub(*mat);
+ if(coll)
+ load_sub(*mat, get_collection());
+ else
+ load_sub(*mat);
obj.material = mat;
}
void RenderPass::TextureLoader::texture2d()
{
tex = new Texture2D;
- load_sub(static_cast<Texture2D &>(*tex));
+ if(coll)
+ load_sub(static_cast<Texture2D &>(*tex), get_collection());
+ else
+ load_sub(static_cast<Texture2D &>(*tex));
}
} // namespace GL
namespace GL {
Resources::Resources():
- default_tex_filter(LINEAR_MIPMAP_LINEAR)
+ default_tex_filter(LINEAR_MIPMAP_LINEAR),
+ srgb_conversion(false)
{
add_type<Animation>().suffix(".anim").keyword("animation");
add_type<Armature>().suffix(".arma").keyword("armature");
default_tex_filter = tf;
}
+void Resources::set_srgb_conversion(bool c)
+{
+ srgb_conversion = c;
+}
+
Texture2D *Resources::create_texture2d(const string &name)
{
string ext = FS::extpart(name);
{
private:
TextureFilter default_tex_filter;
+ bool srgb_conversion;
public:
Resources();
void set_default_texture_filter(TextureFilter);
+ /** Enables or disables sRGB conversion. If enabled, textures and material
+ colors are converted from sRGB to linear color space when loaded. */
+ void set_srgb_conversion(bool);
+
+ bool get_srgb_conversion() const { return srgb_conversion; }
+
protected:
Texture2D *create_texture2d(const std::string &);
};
#include <msp/gl/extensions/sgis_generate_mipmap.h>
#include <msp/strings/format.h>
#include "error.h"
+#include "resources.h"
#include "texture.h"
#include "texunit.h"
Texture::Loader::Loader(Texture &t):
- DataFile::ObjectLoader<Texture>(t)
+ DataFile::CollectionObjectLoader<Texture>(t, 0)
{
+ init();
+}
+
+Texture::Loader::Loader(Texture &t, Collection &c):
+ DataFile::CollectionObjectLoader<Texture>(t, &c)
+{
+ init();
+}
+
+void Texture::Loader::init()
+{
+ if(Resources *res = dynamic_cast<Resources *>(coll))
+ srgb = res->get_srgb_conversion();
+ else
+ srgb = false;
+
add("filter", &Loader::filter);
add("max_anisotropy", &Loader::max_anisotropy);
add("generate_mipmap", &Loader::generate_mipmap);
namespace Msp {
namespace GL {
+class Resources;
+
enum TextureFilter
{
/// No filtering
class Texture
{
protected:
- class Loader: public DataFile::ObjectLoader<Texture>
+ class Loader: public DataFile::CollectionObjectLoader<Texture>
{
+ protected:
+ bool srgb;
+
public:
Loader(Texture &);
+ Loader(Texture &, Collection &);
private:
+ void init();
+
void filter(TextureFilter);
void generate_mipmap(bool);
void mag_filter(TextureFilter);
#include "bindable.h"
#include "error.h"
#include "pixelstore.h"
+#include "resources.h"
#include "texture2d.h"
using namespace std;
glTexSubImage2D(target, level, x, y, wd, ht, fmt, type, data);
}
-void Texture2D::load_image(const string &fn)
+void Texture2D::load_image(const string &fn, bool srgb)
{
Graphics::Image img;
img.load_file(fn);
- image(img);
+ image(img, srgb);
}
-void Texture2D::image(const Graphics::Image &img)
+void Texture2D::image(const Graphics::Image &img, bool srgb)
{
unsigned w = img.get_width();
unsigned h = img.get_height();
PixelFormat fmt = pixelformat_from_graphics(img.get_format());
if(width==0)
- storage(storage_pixelformat_from_graphics(img.get_format()), w, h);
+ {
+ PixelFormat f = storage_pixelformat_from_graphics(img.get_format());
+ if(srgb)
+ f = get_srgb_pixelformat(f);
+ storage(f, w, h);
+ }
else if(w!=width || h!=height)
throw incompatible_data("Texture2D::image");
Texture2D::Loader::Loader(Texture2D &t):
DataFile::DerivedObjectLoader<Texture2D, Texture::Loader>(t)
+{
+ init();
+}
+
+Texture2D::Loader::Loader(Texture2D &t, Collection &c):
+ DataFile::DerivedObjectLoader<Texture2D, Texture::Loader>(t, c)
+{
+ init();
+}
+
+void Texture2D::Loader::init()
{
add("image_data", &Loader::image_data);
add("raw_data", &Loader::raw_data);
IO::Memory mem(data.data(), data.size());
img.load_io(mem);
- obj.image(img);
+ obj.image(img, srgb);
}
void Texture2D::Loader::raw_data(const string &data)
void Texture2D::Loader::storage(PixelFormat fmt, unsigned w, unsigned h)
{
+ if(srgb)
+ fmt = get_srgb_pixelformat(fmt);
obj.storage(fmt, w, h);
}
{
public:
Loader(Texture2D &);
+ Loader(Texture2D &, Collection &);
private:
+ void init();
+
void image_data(const std::string &);
void raw_data(const std::string &);
void storage(PixelFormat, unsigned, unsigned);
/** Loads an image from a file and uploads it to the texture. If storage
has not been defined, it will be set to match the loaded image. Otherwise
the image must be compatible with the defined storage. */
- void load_image(const std::string &fn);
+ 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. */
- void image(const Graphics::Image &);
+ void image(const Graphics::Image &, bool srgb = false);
unsigned get_width() const { return width; }
unsigned get_height() const { return height; }
}
}
-void TextureCube::image(TextureCubeFace face, const Graphics::Image &img)
+void TextureCube::image(TextureCubeFace face, const Graphics::Image &img, bool srgb)
{
unsigned w = img.get_width();
unsigned h = img.get_height();
PixelFormat fmt = pixelformat_from_graphics(img.get_format());
if(size==0)
{
- if(w==h)
- storage(storage_pixelformat_from_graphics(img.get_format()), w);
- else
+ if(w!=h)
throw incompatible_data("TextureCube::image");
+
+ PixelFormat f = storage_pixelformat_from_graphics(img.get_format());
+ if(srgb)
+ f = get_srgb_pixelformat(f);
+ storage(f, w);
}
else if(w!=size || h!=size)
throw incompatible_data("TextureCube::image");
TextureCube::Loader::Loader(TextureCube &t):
DataFile::DerivedObjectLoader<TextureCube, Texture::Loader>(t)
+{
+ init();
+}
+
+TextureCube::Loader::Loader(TextureCube &t, Collection &c):
+ DataFile::DerivedObjectLoader<TextureCube, Texture::Loader>(t, c)
+{
+ init();
+}
+
+void TextureCube::Loader::init()
{
add("image_data", &Loader::image_data);
add("raw_data", &Loader::raw_data);
IO::Memory mem(data.data(), data.size());
img.load_io(mem);
- obj.image(face, img);
+ obj.image(face, img, srgb);
}
void TextureCube::Loader::raw_data(TextureCubeFace face, const string &data)
void TextureCube::Loader::storage(PixelFormat fmt, unsigned s)
{
+ if(srgb)
+ fmt = get_srgb_pixelformat(fmt);
obj.storage(fmt, s);
}
{
public:
Loader(TextureCube &);
+ Loader(TextureCube &, Collection &);
private:
+ void init();
+
void image_data(TextureCubeFace, const std::string &);
void raw_data(TextureCubeFace, const std::string &);
void storage(PixelFormat, unsigned);
int x, int y, unsigned w, unsigned h,
PixelFormat fmt, DataType type, const void *data);
- void image(TextureCubeFace, const Graphics::Image &);
+ void image(TextureCubeFace, const Graphics::Image &, bool = false);
unsigned get_size() const { return size; }
private: