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