Panda3D
 All Classes Functions Variables Enumerations
samplerState.cxx
1 // Filename: samplerState.cxx
2 // Created by: rdb (09Dec14)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "samplerState.h"
16 #include "indent.h"
17 #include "datagram.h"
18 #include "datagramIterator.h"
19 #include "bamReader.h"
20 #include "bamWriter.h"
21 #include "samplerContext.h"
22 #include "preparedGraphicsObjects.h"
23 
24 TypeHandle SamplerState::_type_handle;
25 SamplerState SamplerState::_default;
26 
28 ("texture-minfilter", SamplerState::FT_linear,
29  PRC_DESC("This specifies the default minfilter that is applied to a texture "
30  "in the absence of a specific minfilter setting. Normally this "
31  "is either 'linear' to disable mipmapping by default, or "
32  "'mipmap', to enable trilinear mipmapping by default. This "
33  "does not apply to depth textures. Note if this variable is "
34  "changed at runtime, you may need to reload textures explicitly "
35  "in order to change their visible properties."));
36 
38 ("texture-magfilter", SamplerState::FT_linear,
39  PRC_DESC("This specifies the default magfilter that is applied to a texture "
40  "in the absence of a specific magfilter setting. Normally this "
41  "is 'linear' (since mipmapping does not apply to magfilters). This "
42  "does not apply to depth textures. Note if this variable is "
43  "changed at runtime, you may need to reload textures explicitly "
44  "in order to change their visible properties."));
45 
46 ConfigVariableInt texture_anisotropic_degree
47 ("texture-anisotropic-degree", 1,
48  PRC_DESC("This specifies the default anisotropic degree that is applied "
49  "to a texture in the absence of a particular anisotropic degree "
50  "setting (that is, a texture for which the anisotropic degree "
51  "is 0, meaning the default setting). It should be 1 to disable "
52  "anisotropic filtering, or a higher number to enable it. "
53  "Note if this variable is "
54  "changed at runtime, you may need to reload textures explicitly "
55  "in order to change their visible properties."));
56 
57 ////////////////////////////////////////////////////////////////////
58 // Function: SamplerState::get_effective_minfilter
59 // Access: Published
60 // Description: Returns the filter mode of the texture for
61 // minification, with special treatment for FT_default.
62 // This will normally not return FT_default, unless
63 // there is an error in the config file.
64 ////////////////////////////////////////////////////////////////////
65 SamplerState::FilterType SamplerState::
67  if (_minfilter != FT_default) {
68  return _minfilter;
69  }
70  return texture_minfilter;
71 }
72 
73 ////////////////////////////////////////////////////////////////////
74 // Function: SamplerState::get_effective_magfilter
75 // Access: Published
76 // Description: Returns the filter mode of the texture for
77 // magnification, with special treatment for FT_default.
78 // This will normally not return FT_default, unless
79 // there is an error in the config file.
80 ////////////////////////////////////////////////////////////////////
81 SamplerState::FilterType SamplerState::
83  if (_magfilter != FT_default) {
84  return _magfilter;
85  }
86  return texture_magfilter;
87 }
88 
89 ////////////////////////////////////////////////////////////////////
90 // Function: SamplerState::format_filter_type
91 // Access: Published, Static
92 // Description: Returns the indicated FilterType converted to a
93 // string word.
94 ////////////////////////////////////////////////////////////////////
95 string SamplerState::
96 format_filter_type(FilterType ft) {
97  switch (ft) {
98  case FT_nearest:
99  return "nearest";
100  case FT_linear:
101  return "linear";
102 
103  case FT_nearest_mipmap_nearest:
104  return "nearest_mipmap_nearest";
105  case FT_linear_mipmap_nearest:
106  return "linear_mipmap_nearest";
107  case FT_nearest_mipmap_linear:
108  return "nearest_mipmap_linear";
109  case FT_linear_mipmap_linear:
110  return "linear_mipmap_linear";
111 
112  case FT_shadow:
113  return "shadow";
114 
115  case FT_default:
116  return "default";
117 
118  case FT_invalid:
119  return "invalid";
120  }
121  return "**invalid**";
122 }
123 
124 ////////////////////////////////////////////////////////////////////
125 // Function: SamplerState::string_filter_type
126 // Access: Public
127 // Description: Returns the FilterType value associated with the given
128 // string representation, or FT_invalid if the string
129 // does not match any known FilterType value.
130 ////////////////////////////////////////////////////////////////////
131 SamplerState::FilterType SamplerState::
132 string_filter_type(const string &string) {
133  if (cmp_nocase_uh(string, "nearest") == 0) {
134  return FT_nearest;
135  } else if (cmp_nocase_uh(string, "linear") == 0) {
136  return FT_linear;
137  } else if (cmp_nocase_uh(string, "nearest_mipmap_nearest") == 0) {
138  return FT_nearest_mipmap_nearest;
139  } else if (cmp_nocase_uh(string, "linear_mipmap_nearest") == 0) {
140  return FT_linear_mipmap_nearest;
141  } else if (cmp_nocase_uh(string, "nearest_mipmap_linear") == 0) {
142  return FT_nearest_mipmap_linear;
143  } else if (cmp_nocase_uh(string, "linear_mipmap_linear") == 0) {
144  return FT_linear_mipmap_linear;
145  } else if (cmp_nocase_uh(string, "mipmap") == 0) {
146  return FT_linear_mipmap_linear;
147  } else if (cmp_nocase_uh(string, "shadow") == 0) {
148  return FT_shadow;
149  } else if (cmp_nocase_uh(string, "default") == 0) {
150  return FT_default;
151  } else {
152  return FT_invalid;
153  }
154 }
155 
156 ////////////////////////////////////////////////////////////////////
157 // Function: SamplerState::format_wrap_mode
158 // Access: Published, Static
159 // Description: Returns the indicated WrapMode converted to a
160 // string word.
161 ////////////////////////////////////////////////////////////////////
162 string SamplerState::
163 format_wrap_mode(WrapMode wm) {
164  switch (wm) {
165  case WM_clamp:
166  return "clamp";
167  case WM_repeat:
168  return "repeat";
169  case WM_mirror:
170  return "mirror";
171  case WM_mirror_once:
172  return "mirror_once";
173  case WM_border_color:
174  return "border_color";
175 
176  case WM_invalid:
177  return "invalid";
178  }
179 
180  return "**invalid**";
181 }
182 
183 ////////////////////////////////////////////////////////////////////
184 // Function: SamplerState::string_wrap_mode
185 // Access: Public
186 // Description: Returns the WrapMode value associated with the given
187 // string representation, or WM_invalid if the string
188 // does not match any known WrapMode value.
189 ////////////////////////////////////////////////////////////////////
190 SamplerState::WrapMode SamplerState::
191 string_wrap_mode(const string &string) {
192  if (cmp_nocase_uh(string, "repeat") == 0 ||
193  cmp_nocase_uh(string, "wrap") == 0) {
194  return WM_repeat;
195  } else if (cmp_nocase_uh(string, "clamp") == 0) {
196  return WM_clamp;
197  } else if (cmp_nocase_uh(string, "mirror") == 0 ||
198  cmp_nocase_uh(string, "mirrored_repeat") == 0) {
199  return WM_mirror;
200  } else if (cmp_nocase_uh(string, "mirror_once") == 0) {
201  return WM_mirror_once;
202  } else if (cmp_nocase_uh(string, "border_color") == 0 ||
203  cmp_nocase_uh(string, "border") == 0) {
204  return WM_border_color;
205  } else {
206  return WM_invalid;
207  }
208 }
209 
210 ////////////////////////////////////////////////////////////////////
211 // Function: SamplerState::prepare
212 // Access: Published
213 // Description: Indicates that the sampler should be enqueued to be
214 // prepared in the indicated prepared_objects at the
215 // beginning of the next frame.
216 //
217 // Use this function instead of prepare_now() to preload
218 // samplers from a user interface standpoint.
219 ////////////////////////////////////////////////////////////////////
220 void SamplerState::
221 prepare(PreparedGraphicsObjects *prepared_objects) const {
222  prepared_objects->enqueue_sampler(*this);
223 }
224 
225 ////////////////////////////////////////////////////////////////////
226 // Function: SamplerState::is_prepared
227 // Access: Published
228 // Description: Returns true if the sampler has already been prepared
229 // or enqueued for preparation on the indicated GSG,
230 // false otherwise.
231 ////////////////////////////////////////////////////////////////////
232 bool SamplerState::
233 is_prepared(PreparedGraphicsObjects *prepared_objects) const {
234  return prepared_objects->is_sampler_queued(*this)
235  || prepared_objects->is_sampler_prepared(*this);
236 }
237 
238 ////////////////////////////////////////////////////////////////////
239 // Function: SamplerState::release
240 // Access: Published
241 // Description: Frees the texture context only on the indicated object,
242 // if it exists there. Returns true if it was released,
243 // false if it had not been prepared.
244 ////////////////////////////////////////////////////////////////////
245 void SamplerState::
246 release(PreparedGraphicsObjects *prepared_objects) const {
247  prepared_objects->release_sampler(*this);
248 }
249 
250 ////////////////////////////////////////////////////////////////////
251 // Function: SamplerState::prepare_now
252 // Access: Published
253 // Description: Creates a context for the sampler on the particular
254 // GSG, if it does not already exist. Returns the new
255 // (or old) SamplerContext. This assumes that the
256 // GraphicsStateGuardian is the currently active
257 // rendering context and that it is ready to accept new
258 // textures. If this is not necessarily the case, you
259 // should use prepare() instead.
260 //
261 // Normally, this is not called directly except by the
262 // GraphicsStateGuardian; a sampler does not need to be
263 // explicitly prepared by the user before it may be
264 // rendered.
265 ////////////////////////////////////////////////////////////////////
268  GraphicsStateGuardianBase *gsg) const {
269  return prepared_objects->prepare_sampler_now(*this, gsg);
270 }
271 
272 ////////////////////////////////////////////////////////////////////
273 // Function: SamplerState::compare_to
274 // Access: Public
275 // Description: Returns a number less than zero if this sampler
276 // sorts before the other one, greater than zero if it
277 // sorts after, or zero if they are equivalent. The
278 // sorting order is arbitrary and largely meaningless,
279 // except to differentiate different sampler states.
280 ////////////////////////////////////////////////////////////////////
281 int SamplerState::
282 compare_to(const SamplerState &other) const {
283  if (_wrap_u != other._wrap_u) {
284  return (_wrap_u < other._wrap_u) ? -1 : 1;
285  }
286  if (_wrap_v != other._wrap_v) {
287  return (_wrap_v < other._wrap_v) ? -1 : 1;
288  }
289  if (_wrap_w != other._wrap_w) {
290  return (_wrap_w < other._wrap_w) ? -1 : 1;
291  }
292  if (_minfilter != other._minfilter) {
293  return (_minfilter < other._minfilter) ? -1 : 1;
294  }
295  if (_magfilter != other._magfilter) {
296  return (_magfilter < other._magfilter) ? -1 : 1;
297  }
298  if (_anisotropic_degree != other._anisotropic_degree) {
299  return (_anisotropic_degree < other._anisotropic_degree) ? -1 : 1;
300  }
301  if (_border_color != other._border_color) {
302  return (_border_color < other._border_color) ? -1 : 1;
303  }
304  if (_min_lod != other._min_lod) {
305  return (_min_lod < other._min_lod) ? -1 : 1;
306  }
307  if (_max_lod != other._max_lod) {
308  return (_max_lod < other._max_lod) ? -1 : 1;
309  }
310  if (_lod_bias != other._lod_bias) {
311  return (_lod_bias < other._lod_bias) ? -1 : 1;
312  }
313 
314  return 0;
315 }
316 
317 ////////////////////////////////////////////////////////////////////
318 // Function: SamplerState::output
319 // Access: Public
320 // Description:
321 ////////////////////////////////////////////////////////////////////
322 void SamplerState::
323 output(ostream &out) const {
324  out
325  << "sampler"
326  << " wrap(u=" << _wrap_u << ", v=" << _wrap_v << ", w=" << _wrap_w
327  << ", border=" << _border_color << ")"
328  << " filter(min=" << _minfilter << ", mag=" << _magfilter
329  << ", aniso=" << _anisotropic_degree << ")"
330  << " lod(min=" << _min_lod << ", max=" << _max_lod
331  << ", bias=" << _lod_bias << ")";
332 }
333 
334 ////////////////////////////////////////////////////////////////////
335 // Function: SamplerState::write
336 // Access: Public
337 // Description:
338 ////////////////////////////////////////////////////////////////////
339 void SamplerState::
340 write(ostream &out, int indent_level) const {
341  indent(out, indent_level) << "SamplerState\n";
342  indent(out, indent_level) << " wrap_u = " << _wrap_u << "\n";
343  indent(out, indent_level) << " wrap_v = " << _wrap_v << "\n";
344  indent(out, indent_level) << " wrap_w = " << _wrap_w << "\n";
345  indent(out, indent_level) << " minfilter = " << _minfilter << "\n";
346  indent(out, indent_level) << " magfilter = " << _magfilter << "\n";
347  indent(out, indent_level) << " anisotropic_degree = " << _anisotropic_degree << "\n";
348  indent(out, indent_level) << " border_color = " << _border_color << "\n";
349  indent(out, indent_level) << " min_lod = " << _min_lod << "\n";
350  indent(out, indent_level) << " max_lod = " << _max_lod << "\n";
351  indent(out, indent_level) << " lod_bias = " << _lod_bias << "\n";
352 }
353 
354 ////////////////////////////////////////////////////////////////////
355 // Function: SamplerState::write_datagram
356 // Access: Public
357 // Description: Encodes the sampler state into a datagram.
358 ////////////////////////////////////////////////////////////////////
359 void SamplerState::
361  me.add_uint8(_wrap_u);
362  me.add_uint8(_wrap_v);
363  me.add_uint8(_wrap_w);
364  me.add_uint8(_minfilter);
365  me.add_uint8(_magfilter);
366  me.add_int16(_anisotropic_degree);
367  _border_color.write_datagram(me);
368  me.add_stdfloat(_min_lod);
369  me.add_stdfloat(_max_lod);
370  me.add_stdfloat(_lod_bias);
371 }
372 
373 ////////////////////////////////////////////////////////////////////
374 // Function: SamplerState::read_datagram
375 // Access: Protected
376 // Description: Reads the sampler state from the datagram that has
377 // been previously written using write_datagram.
378 ////////////////////////////////////////////////////////////////////
379 void SamplerState::
381  _wrap_u = (WrapMode)scan.get_uint8();
382  _wrap_v = (WrapMode)scan.get_uint8();
383  _wrap_w = (WrapMode)scan.get_uint8();
384  _minfilter = (FilterType)scan.get_uint8();
385  _magfilter = (FilterType)scan.get_uint8();
386  _anisotropic_degree = scan.get_int16();
387  _border_color.read_datagram(scan);
388 
389  if (manager->get_file_minor_ver() >= 36) {
390  // These were added with the introduction of SamplerState.
391  // Since Texture::do_fillin_body calls this, we still have to
392  // preserve backward compatibility here.
393  _min_lod = scan.get_stdfloat();
394  _max_lod = scan.get_stdfloat();
395  _lod_bias = scan.get_stdfloat();
396  } else {
397  _min_lod = -1000;
398  _max_lod = 1000;
399  _lod_bias = 0;
400  }
401 }
bool is_sampler_queued(const SamplerState &sampler) const
Returns true if the sampler has been queued on this GSG, false otherwise.
FilterType get_effective_magfilter() const
Returns the filter mode of the texture for magnification, with special treatment for FT_default...
void add_uint8(PN_uint8 value)
Adds an unsigned 8-bit integer to the datagram.
Definition: datagram.I:138
PN_stdfloat get_stdfloat()
Extracts either a 32-bit or a 64-bit floating-point number, according to Datagram::set_stdfloat_doubl...
int compare_to(const SamplerState &other) const
Returns a number less than zero if this sampler sorts before the other one, greater than zero if it s...
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:122
void prepare(PreparedGraphicsObjects *prepared_objects) const
Indicates that the sampler should be enqueued to be prepared in the indicated prepared_objects at the...
void write_datagram(Datagram &destination) const
Encodes the sampler state into a datagram.
static string format_wrap_mode(WrapMode wm)
Returns the indicated WrapMode converted to a string word.
void read_datagram(DatagramIterator &source, BamReader *manager)
Reads the sampler state from the datagram that has been previously written using write_datagram.
static string format_filter_type(FilterType ft)
Returns the indicated FilterType converted to a string word.
void enqueue_sampler(const SamplerState &sampler)
Indicates that a sampler would like to be put on the list to be prepared when the GSG is next ready t...
PN_uint8 get_uint8()
Extracts an unsigned 8-bit integer.
SamplerContext * prepare_now(PreparedGraphicsObjects *prepared_objects, GraphicsStateGuardianBase *gsg) const
Creates a context for the sampler on the particular GSG, if it does not already exist.
A table of objects that are saved within the graphics context for reference by handle later...
void release(PreparedGraphicsObjects *prepared_objects) const
Frees the texture context only on the indicated object, if it exists there.
PN_int16 get_int16()
Extracts a signed 16-bit integer.
static FilterType string_filter_type(const string &str)
Returns the FilterType value associated with the given string representation, or FT_invalid if the st...
void add_stdfloat(PN_stdfloat value)
Adds either a 32-bit or a 64-bit floating-point number, according to set_stdfloat_double().
Definition: datagram.I:240
void add_int16(PN_int16 value)
Adds a signed 16-bit integer to the datagram.
Definition: datagram.I:148
void read_datagram(DatagramIterator &source)
Reads the vector from the Datagram using get_stdfloat().
Definition: lvecBase4.h:1442
SamplerContext * prepare_sampler_now(const SamplerState &sampler, GraphicsStateGuardianBase *gsg)
Immediately creates a new SamplerContext for the indicated sampler and returns it.
This class specializes ConfigVariable as an enumerated type.
Represents a set of settings that indicate how a texture is sampled.
Definition: samplerState.h:39
This is a special class object that holds a handle to the sampler state object given by the graphics ...
bool is_sampler_prepared(const SamplerState &sampler) const
Returns true if the sampler has been prepared on this GSG, false otherwise.
void write_datagram(Datagram &destination) const
Writes the vector to the Datagram using add_stdfloat().
Definition: lvecBase4.h:1422
This is a base class for the GraphicsStateGuardian class, which is itself a base class for the variou...
This is a convenience class to specialize ConfigVariable as an integer type.
FilterType get_effective_minfilter() const
Returns the filter mode of the texture for minification, with special treatment for FT_default...
A class to retrieve the individual data elements previously stored in a Datagram. ...
void release_sampler(SamplerContext *sc)
Indicates that a sampler context, created by a previous call to prepare_sampler(), is no longer needed.
int get_file_minor_ver() const
Returns the minor version number of the Bam file currently being read.
Definition: bamReader.I:105
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
bool is_prepared(PreparedGraphicsObjects *prepared_objects) const
Returns true if the sampler has already been prepared or enqueued for preparation on the indicated GS...
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:43
static WrapMode string_wrap_mode(const string &str)
Returns the WrapMode value associated with the given string representation, or WM_invalid if the stri...