1 #include <msp/gl/extensions/arb_direct_state_access.h>
2 #include <msp/gl/extensions/arb_sampler_objects.h>
3 #include <msp/gl/extensions/arb_shadow.h>
4 #include <msp/gl/extensions/ext_texture_filter_anisotropic.h>
5 #include <msp/gl/extensions/ext_texture3d.h>
6 #include <msp/gl/extensions/khr_debug.h>
7 #include <msp/strings/format.h>
17 min_filter(NEAREST_MIPMAP_LINEAR),
23 border_color(Color(0.0f, 0.0f, 0.0f, 0.0f)),
28 Require _req(ARB_sampler_objects);
29 if(ARB_direct_state_access)
30 glCreateSamplers(1, &id);
32 glGenSamplers(1, &id);
35 void Sampler::update() const
37 if(dirty_params&MIN_FILTER)
38 glSamplerParameteri(id, GL_TEXTURE_MIN_FILTER, get_gl_filter(min_filter));
39 if(dirty_params&MAG_FILTER)
40 glSamplerParameteri(id, GL_TEXTURE_MAG_FILTER, get_gl_filter(mag_filter));
41 if(dirty_params&MAX_ANISOTROPY)
42 glSamplerParameterf(id, GL_TEXTURE_MAX_ANISOTROPY_EXT, max_anisotropy);
43 if(dirty_params&WRAP_S)
44 glSamplerParameteri(id, GL_TEXTURE_WRAP_S, get_gl_wrap(wrap_s));
45 if(dirty_params&WRAP_T)
46 glSamplerParameteri(id, GL_TEXTURE_WRAP_T, get_gl_wrap(wrap_t));
47 if(dirty_params&WRAP_R)
48 glSamplerParameteri(id, GL_TEXTURE_WRAP_R, get_gl_wrap(wrap_r));
49 if(dirty_params&BORDER_COLOR)
50 glSamplerParameterfv(id, GL_TEXTURE_BORDER_COLOR, &border_color.r);
51 if(dirty_params&COMPARE)
53 glSamplerParameteri(id, GL_TEXTURE_COMPARE_MODE, (compare ? GL_COMPARE_R_TO_TEXTURE : GL_NONE));
55 glSamplerParameteri(id, GL_TEXTURE_COMPARE_FUNC, get_gl_predicate(cmp_func));
61 void Sampler::set_min_filter(TextureFilter f)
64 dirty_params |= MIN_FILTER;
67 void Sampler::set_mag_filter(TextureFilter f)
70 dirty_params |= MAG_FILTER;
73 void Sampler::set_filter(TextureFilter f)
76 set_mag_filter(f==NEAREST ? NEAREST : LINEAR);
79 void Sampler::set_max_anisotropy(float a)
82 throw invalid_argument("Sampler::set_max_anisotropy");
84 static Require _req(EXT_texture_filter_anisotropic);
86 if(EXT_texture_filter_anisotropic)
87 dirty_params |= MAX_ANISOTROPY;
90 void Sampler::set_wrap(TextureWrap w)
98 void Sampler::set_wrap_s(TextureWrap w)
101 dirty_params |= WRAP_S;
104 void Sampler::set_wrap_t(TextureWrap w)
107 dirty_params |= WRAP_T;
110 void Sampler::set_wrap_r(TextureWrap w)
112 static Require _req(EXT_texture3D);
114 dirty_params |= WRAP_R;
117 void Sampler::set_border_color(const Color &c)
120 dirty_params |= BORDER_COLOR;
123 void Sampler::disable_compare()
126 dirty_params |= COMPARE;
129 void Sampler::set_compare(Predicate f)
131 static Require _req(ARB_shadow);
134 dirty_params |= COMPARE;
137 void Sampler::set_debug_name(const string &name)
141 glObjectLabel(GL_SAMPLER, id, name.size(), name.c_str());
148 Sampler::Loader::Loader(Sampler &s):
149 DataFile::ObjectLoader<Sampler>(s)
151 add("border_color", &Loader::border_color);
152 add("compare", &Loader::compare);
153 add("filter", &Loader::filter);
154 add("mag_filter", &Loader::mag_filter);
155 add("max_anisotropy", &Loader::max_anisotropy);
156 add("min_filter", &Loader::min_filter);
157 add("wrap", &Loader::wrap);
158 add("wrap_r", &Loader::wrap_r);
159 add("wrap_s", &Loader::wrap_s);
160 add("wrap_t", &Loader::wrap_t);
163 void Sampler::Loader::border_color(float r, float g, float b, float a)
165 obj.set_border_color(Color(r, g, b, a));
168 void Sampler::Loader::compare(Predicate c)
173 void Sampler::Loader::filter(TextureFilter f)
178 void Sampler::Loader::mag_filter(TextureFilter f)
180 obj.set_mag_filter(f);
183 void Sampler::Loader::max_anisotropy(float a)
185 obj.set_max_anisotropy(a);
188 void Sampler::Loader::min_filter(TextureFilter f)
190 obj.set_min_filter(f);
193 void Sampler::Loader::wrap(TextureWrap w)
198 void Sampler::Loader::wrap_r(TextureWrap w)
203 void Sampler::Loader::wrap_s(TextureWrap w)
208 void Sampler::Loader::wrap_t(TextureWrap w)
214 bool is_mipmapped(TextureFilter filter)
216 return (filter==NEAREST_MIPMAP_NEAREST || filter==NEAREST_MIPMAP_LINEAR ||
217 filter==LINEAR_MIPMAP_NEAREST || filter==LINEAR_MIPMAP_LINEAR);
220 unsigned get_gl_filter(TextureFilter filter)
224 case NEAREST: return GL_NEAREST;
225 case LINEAR: return GL_LINEAR;
226 case NEAREST_MIPMAP_NEAREST: return GL_NEAREST_MIPMAP_NEAREST;
227 case NEAREST_MIPMAP_LINEAR: return GL_NEAREST_MIPMAP_LINEAR;
228 case LINEAR_MIPMAP_NEAREST: return GL_LINEAR_MIPMAP_NEAREST;
229 case LINEAR_MIPMAP_LINEAR: return GL_LINEAR_MIPMAP_LINEAR;
230 default: throw invalid_argument("get_gl_filter");
234 unsigned get_gl_wrap(TextureWrap wrap)
238 case REPEAT: return GL_REPEAT;
239 case CLAMP_TO_EDGE: return GL_CLAMP_TO_EDGE;
240 case CLAMP_TO_BORDER: return GL_CLAMP_TO_BORDER;
241 case MIRRORED_REPEAT: return GL_MIRRORED_REPEAT;
242 default: throw invalid_argument("get_gl_wrap");
246 void operator>>(const LexicalConverter &c, TextureFilter &tf)
248 if(c.get()=="NEAREST")
250 else if(c.get()=="LINEAR")
252 else if(c.get()=="NEAREST_MIPMAP_NEAREST")
253 tf = NEAREST_MIPMAP_NEAREST;
254 else if(c.get()=="NEAREST_MIPMAP_LINEAR")
255 tf = NEAREST_MIPMAP_LINEAR;
256 else if(c.get()=="LINEAR_MIPMAP_NEAREST")
257 tf = LINEAR_MIPMAP_NEAREST;
258 else if(c.get()=="LINEAR_MIPMAP_LINEAR")
259 tf = LINEAR_MIPMAP_LINEAR;
261 throw lexical_error(format("conversion of '%s' to TextureFilter", c.get()));
264 void operator>>(const LexicalConverter &c, TextureWrap &tw)
266 if(c.get()=="REPEAT")
268 else if(c.get()=="CLAMP_TO_EDGE")
270 else if(c.get()=="CLAMP_TO_BORDER")
271 tw = CLAMP_TO_BORDER;
272 else if(c.get()=="MIRRORED_REPEAT")
273 tw = MIRRORED_REPEAT;
275 throw lexical_error(format("conversion of '%s' to TextureWrap", c.get()));