HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
IMG_DeepShadow.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: IMG_DeepShadow.h ( IMG Library, C++)
7  *
8  * COMMENTS: Deep shadow API
9  */
10 
11 #pragma once
12 
13 #ifndef __IMG_DeepShadow__
14 #define __IMG_DeepShadow__
15 
16 #include "IMG_API.h"
17 #include "IMG_DeepStat.h"
18 #include "IMG_FileTypes.h"
19 
20 #include <PXL/PXL_Forward.h>
21 #include <UT/UT_NonCopyable.h>
22 #include <UT/UT_Rect.h>
23 #include <UT/UT_SharedPtr.h>
24 #include <UT/UT_StringHolder.h>
25 #include <UT/UT_UniquePtr.h>
26 #include <UT/UT_ValArray.h>
27 #include <UT/UT_VectorTypes.h>
28 
29 class PXL_DeepPixel;
30 class img_DeepShadow;
31 class IMG_DeepShadow;
33 class IMG_FileParms;
34 class IMG_Format;
35 class IMG_Stat;
36 class UT_WorkBuffer;
37 class UT_Options;
38 
39 /// @brief Thread-safe convenience class to make reading DSM pixels easy
40 ///
41 /// This is a thread-safe convenience class to wrap around reading pixels
42 /// which ensures that the pixel is closed properly.
43 ///
44 /// @warning Beware when declaring an IMG_DeepPixelReader in the same scope
45 /// as an IMG_DeepShadow. Since the pixel reader keeps a reference to the
46 /// file, the destruction order is important -- though calling close()
47 /// should avoid any problems.
48 ///
49 /// The class should be used as follows: @code
50 ///
51 /// IMG_DeepPixelReader pixel(dsm);
52 /// for (x, y) in raster {
53 /// if (pixel.open(x, y)) {
54 /// for (int i = 0; i < pixel.getDepth(); i++)
55 /// data = pixel.getData(chp, i);
56 /// }
57 /// }
58 /// @endcode
59 ///
62 {
63 public:
65  {
66  }
68  : myHandle(nullptr)
69  {
70  init(dsm);
71  }
73  {
74  clear();
75  }
76 
78 
79  // Check to see if the deep pixel reader is valid
80  bool isValid() const { return myHandle != nullptr; }
81 
82  // Initialize given a DSM
83  void init(const IMG_DeepShadow &dsm);
84 
85  // Clear the reader handle
86  void clear();
87 
88  /// Open a pixel for reading
89  bool open(int x, int y);
90  /// Close the pixel. This is called automatically on destruction.
91  /// However, if an IMG_DeepPixelReader and IMG_DeepShadow are created in
92  /// the same scope, the IMG_DeepPixelReader may hold onto references (and
93  /// cause crashing errors). Calling close() manually is a safe thing to
94  /// do.
95  void close();
96  /// Returns the number of z-records
97  int getDepth() const;
98  /// Return the data for the channel at the given depth index.
99  const float *getData(const IMG_DeepShadowChannel &chp,
100  int depth_index);
101 
102  /// Alternately, just fill a PXL_DeepSampleList with the appropriate
103  /// data. This manages zback, coverage, flags and other special deep
104  /// channels.
105  bool readPixel(int x, int y, PXL_DeepSampleList &pixel) const;
106 
107 
108  /// After opening, you can call either of these methods to ensure that the
109  /// data is in the correct form for your application. "composited" pixels
110  /// will have the data accumulated over from front to back. "uncomposited"
111  /// pixels will have the raw data for each z-record.
112  ///
113  /// If the force flag is false, then the state of the file will be used
114  /// to determine whether the deep records need to be processed or not.
115  ///
116  /// These methods should be called after the pixel has been opened.
117  void composite(const IMG_DeepShadowChannel &pz,
118  const IMG_DeepShadowChannel &of,
119  bool force = false);
120  void uncomposite(const IMG_DeepShadowChannel &pz,
121  const IMG_DeepShadowChannel &of,
122  bool force = false);
123 
124 private:
125  class DeepShadowPixel; // Forward declaration
126  DeepShadowPixel *myHandle;
127 };
128 
129 /// @brief Thread-safe convenience class to make writing DSM pixels easy
130 ///
131 /// This is a thread-safe convenience class to wrap around writing pixels
132 /// which ensures that the pixel is closed properly.
133 ///
134 /// @warning Beware when declaring an IMG_DeepPixelReader in the same scope
135 /// as an IMG_DeepShadow. Since the pixel reader keeps a reference to the
136 /// file, the destruction order is important -- though calling close()
137 /// should avoid any problems.
138 ///
139 /// The class should be used as follows for sequential samples: @code
140 ///
141 /// IMG_DeepPixelWriter pixel(dsm);
142 /// for (x, y) in raster {
143 /// if (pixel.open(x, y)) {
144 /// for (int i = 0; i < depth; i++)
145 /// data = pixel.writeOrdered(z, data, vsize);
146 /// pixel.close();
147 /// }
148 /// }
149 /// @endcode
150 ///
153 {
154 public:
157 
159 
160  /// Ignore the desired sample compositing state in IMG_DeepShadow.
161  /// The default is to assume the incoming samples are pre-composited.
162  /// Writing raw samples will ignore compression levels, since the
163  /// compressors assume pre-composited samples.
164  void writeRawSamples(bool enable);
165 
166  /// Open a pixel for writing
167  bool open(int x, int y);
168 
169  /// Close the pixel. This is called automatically on destruction.
170  /// However, if an IMG_DeepPixelWriter and IMG_DeepShadow are created in
171  /// the same scope, the IMG_DeepPixelReader may hold onto references (and
172  /// cause crashing errors). Calling close() manually is a safe thing to
173  /// do.
174  bool close();
175 
176  /// Write data to the currently open pixel. This method inserts an
177  /// unordered data record with the given z-value and data into the
178  /// current pixel. vsize is the number of floats that are contained
179  /// in the data array.
180  ///
181  /// The first 3 floats of the data array must be the opacity (RGB). Any
182  /// extra channel data follows this according to the float_offset
183  /// associated with the channel. This data may be quantized to a single
184  /// float depending on the options.
185  ///
186  /// If @c vsize doesn't contain a full record, then this method will fail.
187  /// vsize must be greater or equal to 3 (depending on extra channels)
188  ///
189  /// Currently, mantra will always interpret the data as a rgb opacity
190  /// triple.
191  ///
192  /// The @c flags parameter is used to pass information to the
193  /// @c PXL_DeepSampleList interface. Possible values are:
194  /// - 0x00: No special meaning
195  /// - 0x01: Sample represents a volume
196  /// - 0x02: Sample is a matte surface
197  /// These values are found in the @c PXL_DeepSampleList::SampleFlag enum.
198  ///
199  /// The @c sampleid parameter specifies which pixel sample is associated
200  /// with these values (see @c sxres and @c syres on the create() method).
201  ///
202  /// The @c z value represents the "z-front" value for the depth sample.
203  /// For hard surfaces @c dz should be 0. For volumes @c dz should be set
204  /// to the extent of the volume sample so that the "z-back" data can be set
205  /// appropriately.
206  bool write(float z,
207  const float *chdata, int chsize,
208  int flags,
209  int sampleid,
210  float dz=0);
211 
212  /// Perform the same operation as write() except assume that data
213  /// is pre-sorted by increasing z-value. This method will perform
214  /// slightly better than write() as data does not need to be sorted.
215  bool writeOrdered(float z,
216  const float *chdata, int chsize,
217  int flags,
218  int sampleid,
219  float dz=0)
220  {
221  return write(z, chdata, chsize, flags, sampleid, dz);
222  }
223 
224  /// Alternatively, you can do something like: @code
225  /// PXL_DeepPixel pixel;
226  /// pixel.startPixel(x, y);
227  /// for (rec : records) pixel.store(rec);
228  /// write(pixel.closePixel(writer.compressor()));
229  /// @endcode
230  bool writePixel(int pixel_x, int pixel_y,
231  const PXL_DeepSampleListPtr &pixel);
232 
233  /// Access to the pixel compressor.
234  const PXL_DeepCompressorPtr &compressor() const { return myDeepCompressor; }
235 
236 private:
237  img_DeepShadow *myFile;
238  int myPixelX, myPixelY;
239  UT_UniquePtr<PXL_DeepPixel> myDeepPixel;
240  PXL_DeepCompressorPtr myDeepCompressor;
241  bool myWriteRaw;
242 };
243 
244 /// @brief Single channel of a Houdini DSM image
245 ///
246 /// A Houdini deep shadow/camera file can have any number of image channels
247 /// (planes). A DSM image contains a single channel for opacity. A deep
248 /// camera image has the opacity channel along with any number of extra image
249 /// channels.
251 {
252 public:
253  /// @param name The unique name of the DSM channel
254  /// @param float_offset
255  /// When data is read or written in deep shadow files, the pixel
256  /// data is interleaved. That is, the data for a single pixel can
257  /// be represented as an array of floats. Each channel has a
258  /// unique offset into the array. The user should @b not assume
259  /// that the offsets are contiguous. For example, the pixel data
260  /// might look like: @code
261  /// [ Of.r, // Opacity red
262  /// Of.g, // Opacity green
263  /// Of.b, // Opacity blue
264  /// Cf.r, // Color (red)
265  /// Cf.g, // Color (green)
266  /// Cf.b, // Color (blue)
267  /// s, // s coordinate
268  /// t, // t coordinate
269  /// N.x, // Normal x
270  /// N.y, // Normal y
271  /// N.z, // Normal z
272  /// ]
273  /// @endcode
274  /// Where the channels would be defined by: @code
275  /// IMG_DeepShadowChannel("Of", 0, 3);
276  /// IMG_DeepShadowChannel("Cf", 3, 3);
277  /// IMG_DeepShadowChannel("s", 6, 1);
278  /// IMG_DeepShadowChannel("t", 7, 1);
279  /// IMG_DeepShadowChannel("N", 8, 3);
280  /// @endcode
281  /// @param tuple_size Number of floats
282  /// @param storage
283  /// Storage type. This may be one of { "real16", "real32",
284  /// "real64" }. This value represents the storage of the channel
285  /// in the file.
286  /// @see IMG_DeepShadow::addExtraChannel()
287  IMG_DeepShadowChannel(const char *name,
288  int float_offset,
289  int tuple_size,
290  const char *storage="real32");
291 
292  bool operator==(const IMG_DeepShadowChannel &s) const;
293 
294  /// @{
295  /// Data acceess function
296  const char *getName() const { return myName.c_str(); }
297  const char *getStorage() const { return myStorage.c_str(); }
298  int getOffset() const { return myOffset; }
299  int getTupleSize() const { return myTupleSize; }
300  /// @}
301 
302 private:
303  UT_StringHolder myName;
304  UT_StringHolder myStorage;
305  int myOffset;
306  int myTupleSize;
307 };
308 
309 /// @brief Class to read or write deep shadow/camera images
310 ///
311 /// This class provides a creation interface for deep shadow maps.
312 /// The class can be used as follows: @code
313 /// setOption(...);
314 /// setOption(...);
315 /// ...
316 /// open(fname, xres, yres);
317 /// IMG_DeepPixelWriter writer;
318 /// foreach pixel loop
319 /// writer.open(pixel);
320 /// foreach record
321 /// writer.write(record);
322 /// end loop
323 /// writer.close();
324 /// end loop
325 /// close();
326 /// @endcode
327 ///
328 /// To read from an existing deep shadow map, the class can be used as
329 /// follows: @code
330 /// IMG_DeepShadow dsm;
331 /// IMG_DeepPixelReader pixel;
332 /// dsm.open(fname);
333 /// foreach (x,y) in raster:
334 /// pixel.open(x, y)
335 /// for (i = 0; i < pixel.getDepth(); i++)
336 /// pixel.getData(chp, i);
337 /// close();
338 /// @endcode
339 ///
340 /// @see
341 /// - TIL_TextureMap - for filtered evaluation of DSM/DCM's)
342 /// - IMG_DeepPixelReader - For thread-safe reading of DSM pixels
343 /// - IMG_DeepShadowChannel
345 {
346 public:
347  IMG_DeepShadow();
348  virtual ~IMG_DeepShadow();
349 
351 
352  /// Certain channel names are reserved as "special" channels. These
353  /// channels have special interpretations for deep images (i.e. "Z",
354  /// "ZBack", etc.). Each format registers their special channel names
355  static void addSpecialChannel(const UT_StringHolder &channel_name,
357  static IMG_DeepPlaneMask isSpecialChannel(const char *name);
358 
359  /// Set a file creation option. Options must be set before the
360  /// file is opened with open() below.
361  ///
362  /// Currently (and this list may be out of date), the options are:
363  /// - "ofstorage" = one of { "int8", "int16", "int32", "int64",
364  /// "uint8", "uint16", "uint32", "uint64",
365  /// "real16", "real32", "real64" }
366  /// - "pzstorage" = one of { "int8" ... "real64" }
367  /// - "ofsize" = one of { "1", "3" }
368  /// - "compression = a value between "0" and "9" (lossyness)
369  /// - "zbias" = minimum delta between z-values (float value)
370  /// - "depth_mode" = one of { "nearest", "midpoint", "farthest" }
371  /// - "depth_interp" = one of { "discrete", "continuous" }
372  /// - "compositing" = "0" will turn off pre-compositing of the z-records
373  /// This is recommended when dealing with deep camera maps (i.e. if
374  /// there are extra channels)
375  void setOption(const char *option, const UT_StringHolder &value);
376  void setOption(const char *option, fpreal value);
377  void setOption(const char *option, int64 value);
378  void setOption(const char *option, int value)
379  { setOption(option, (int64)value); }
380 
381  /// Set options based on the "texture:*" options defined in the UT_Options.
382  /// The UT_Options will be checked for options:
383  /// - @c texture:ofstorage
384  /// - @c texture:pzstorage
385  /// - @c texture:ofsize
386  /// - @c etc.
387  void setOptions(const UT_Options &options);
388 
389  /// Print the current values of the file options into the work buffer
390  void printArgs(UT_WorkBuffer &wbuf, bool json);
391 
392  /// Get a description of the available options that can be provided in
393  /// setOption()
394  const char *getDescription();
395 
396  /// Add an extra channel to be stored along with Of and Pz. Any number of
397  /// channels may be added (though the file size will increase accordingly).
398  /// - The name must be unique among (and not Of or Pz)
399  /// - The float_offset is the offset into the "data" in the
400  /// IMG_DeepPixelWriter::write() method. Note that the opacity
401  /// must occupy the first 3
402  /// floats of the data array. So, the float_offset @b must be at least 3.
403  /// - The tuple_size is the number of elements in the channel
404  /// Currently, this must be 1, 3 or 4.
405  /// - The storage specifies the storage type (and uses the same
406  /// tokens as the "ofstorage" option (i.e. int8, int16, int32, int64,
407  /// uint8, uint16, uint32, uint64, real16, real32 or real64.
408  /// The extra channels must be added @b before open() is called.
409  bool addExtraChannel(const IMG_DeepShadowChannel &def,
410  const UT_Options *options=0);
411 
412  /// Open a deep shadow map for writing. This method will return false
413  /// if there were errors opening the texture.
414  /// The resolution of the image is specified by @c xres and @c yres, while
415  /// the @c sxres and @c syres parameters specify the samples per pixel
416  /// (i.e. 3x3 sampling). The pixel_aspect is typically 1.0, while the crop
417  /// can be a NULL ptr.
418  ///
419  /// If the sample resolution is unknown, you can set @c sxres and @c syres
420  /// to 1 (the @c sampleid should be set to 0).
421  /// @{
422  bool create(const char *name, int xres, int yres,
423  int sxres, int syres,
424  float pixel_aspect = 1.0,
425  const UT_DimRect *crop = NULL);
426  bool create(
427  const char *name,
428  const IMG_Stat &stat,
429  const IMG_FileParms *options = NULL,
430  const IMG_Format *fmt = NULL);
431  ///@}
432 
433  /// Open a deep shadow map for reading.
434  bool open(const char *name);
435 
436 
437  /// These methods are now deprecated in favor of the
438  /// IMG_DeepPixelWriter class, which allows thread-safe writes to
439  /// deep images.
440  /// {
441  SYS_DEPRECATED(13.0)
442  bool pixelStart(int x, int y);
443  SYS_DEPRECATED(13.0)
444  bool pixelWrite(float z, const float *data, int vsize);
445  SYS_DEPRECATED(13.0)
446  bool pixelWriteOrdered(float z, const float *data,
447  int vsize);
448  SYS_DEPRECATED(13.0)
449  bool pixelClose();
450  /// }
451 
452  /// Close the deep shadow map and write it to disk.
453  bool close();
454 
455 public:
456 
457  /// Get the resolution of the deep shadow map.
458  void resolution(int &xres, int &yres) const;
459 
460  /// Get the number of channels in the DSM
461  int getChannelCount() const;
462 
463  /// Get a channel definition
464  const IMG_DeepShadowChannel *getChannel(int i) const;
465 
466  /// Get UT_Option structure from the file. These options are stored with
467  /// the file and may be queried in VEX using teximport().
468  UT_SharedPtr<UT_Options> getTextureOptions() const;
469 
470  /// Store the UT_Options structure in the file. These options are stored with
471  /// the file and may be queried in VEX using teximport() on load.
472  bool setTextureOptions(const UT_Options &opts);
473 
474  /// @{
475  /// Extract the worldToCamera transform from a UT_Options. Returns false
476  /// if there was no matrix available.
477  ///
478  /// This extracts the "space:world" matrix from the UT_Options.
479  static bool getWorldToCamera(const UT_Options *options,
480  UT_Matrix4F &xform);
481  static bool getWorldToCamera(const UT_Options *options,
482  UT_Matrix4D &xform);
483  template <typename T>
484  bool getWorldToCamera(UT_Matrix4T<T> &xform) const
485  { return getWorldToCamera(getTextureOptions().get(),
486  xform); }
487  /// @}
488 
489  /// @{
490  /// Get the camera's projection transform from the file options. Returns
491  /// false if there was no matrix available.
492  /// If @c fit_z is true, the projection will attempt to fit the z
493  /// coordinates to the NDC near/far to the range (0,1). If the camera:clip
494  /// option is not saved, this will not be possible (z coordinates will
495  /// remain unchanged). The method will @b not fail if there is no
496  /// camera:clip saved, but the z coordinates will have unexpected values
497  ///
498  /// The method gets the values for the projection matrix from the following
499  /// options:
500  /// - float camera:zoom
501  /// - int camera:projection (optional, defaults to 0)
502  /// - float image:pixelaspect (optional, defaults to 1)
503  /// - vector4 image:window (optional, defaults to [0, 1, 0, 1])
504  /// - vector2 camera:clip (used iff @c fit_z is true, defaults to (0,1))
505  /// - float camera:orthowidth (required iff @c projection != 0)
506  static bool getCameraToNDC(const UT_Options *options,
507  UT_Matrix4F &xform,
508  int xres, int yres,
509  bool fit_z=true);
510  static bool getCameraToNDC(const UT_Options *options,
511  UT_Matrix4D &xform,
512  int xres, int yres,
513  bool fit_z=true);
514  template <typename T>
516  bool fit_z=true) const
517  {
518  int xres, yres;
519  resolution(xres, yres);
520  return getCameraToNDC(getTextureOptions().get(),
521  xform, xres, yres, fit_z);
522  }
523  /// @}
524 
525  /// @{
526  /// Get the world to camera NDC space transform using the file options.
527  /// Returns false if there is no matrix available.
528  /// If @c fit_z is true, the projection will attempt to fit the z
529  /// coordinates to the NDC near/far to the range (0,1). If the camera:clip
530  /// option is not saved, this will not be possible (z coordinates will
531  /// remain unchanged).
532  /// @note This simply returns getWorldToCamera()*getCameraToNDC()
533  static bool getWorldToNDC(const UT_Options *options,
534  UT_Matrix4F &xform,
535  int xres, int yres, bool fit_z);
536  static bool getWorldToNDC(const UT_Options *options,
537  UT_Matrix4D &xform,
538  int xres, int yres, bool fit_z);
539  template <typename T>
541  bool fit_z) const
542  {
543  int xres, yres;
544  resolution(xres, yres);
545  return getWorldToNDC(getTextureOptions().get(),
546  xform, xres, yres, fit_z);
547  }
548  /// @}
549 
550  /// Return deep stats
551  UT_SharedPtr<IMG_DeepStat> getDeepStat() const;
552 
553  float ofBias() const;
554  float zBias() const;
555 
556  /// Return the PXL_DeepChannelList being written to the DSM
557  const PXL_DeepChannelListPtr &deepChannels() const;
558 
559  /// Return the number of samples per pixel
560  int deepSampleListsPerPixel() const;
561 
562  /// Metadata to send to deep image file
563  void setWriteTag(
564  const char *tag,
565  int datasize,
566  const char *const *data);
567 
568  bool copyImageTextureOptions(const IMG_DeepShadow &src, bool clear_existing);
569 
570 protected:
571  /// Perform all computation for creating an image, but don't actually open
572  /// the IMG_File. This can be done when you want to make sure all the deep
573  /// information is set up properly, but don't actually want to create the
574  /// image. One example of this might be when doing distributed rendering.
575  ///
576  /// This takes the same arguments as @c create().
577  bool createStat(IMG_Stat &stat,
578  const char *name, int xres, int yres,
579  int sxres, int syres,
580  float pixel_aspect,
581  const UT_DimRect *crop);
582 
583 private:
584  friend class IMG_DeepPixelReader;
585  friend class IMG_DeepPixelWriter;
586 
587  bool openPixelRead(IMG_DeepPixelReader &h, int x, int y);
588  void closePixelRead(IMG_DeepPixelReader &h);
589 
590 private:
591  friend class img_DeepShadow;
592 
593 private:
595  img_DeepShadow *myFile;
596 };
597 
598 #endif
GLbitfield flags
Definition: glcorearb.h:1596
PXL_API const char * getDescription(const ColorSpace *space)
Return the description of the color space.
#define SYS_DEPRECATED(__V__)
Thread-safe convenience class to make reading DSM pixels easy.
getFileOption("OpenEXR:storage") storage
Definition: HDK_Image.dox:276
GLdouble GLdouble GLdouble z
Definition: glcorearb.h:848
Single channel of a Houdini DSM image.
const PXL_DeepCompressorPtr & compressor() const
Access to the pixel compressor.
Thread-safe convenience class to make writing DSM pixels easy.
GLdouble s
Definition: glad.h:3009
GLint y
Definition: glcorearb.h:103
Class to read or write deep shadow/camera images.
void close() override
std::unique_ptr< T, Deleter > UT_UniquePtr
A smart pointer for unique ownership of dynamically allocated objects.
Definition: UT_UniquePtr.h:39
void setOption(const char *option, int value)
bool operator==(const BaseDimensions< T > &a, const BaseDimensions< Y > &b)
Definition: Dimensions.h:137
#define IMG_API
Definition: IMG_API.h:10
const char * getName() const
IMG_DeepPixelReader(const IMG_DeepShadow &dsm)
int open(float queuesize) override
bool getCameraToNDC(UT_Matrix4T< T > &xform, bool fit_z=true) const
std::shared_ptr< T > UT_SharedPtr
Wrapper around std::shared_ptr.
Definition: UT_SharedPtr.h:36
int getTupleSize() const
#define UT_NON_COPYABLE(CLASS)
Define deleted copy constructor and assignment operator inside a class.
IMG_DeepPlaneMask
Definition: IMG_DeepStat.h:35
long long int64
Definition: SYS_Types.h:116
HUSD_API const char * resolution()
GLuint const GLchar * name
Definition: glcorearb.h:786
GLint GLenum GLint x
Definition: glcorearb.h:409
GLfloat GLfloat GLfloat GLfloat h
Definition: glcorearb.h:2002
A map of string to various well defined value types.
Definition: UT_Options.h:84
SIM_API const UT_StringHolder force
fpreal64 fpreal
Definition: SYS_Types.h:277
bool getWorldToNDC(UT_Matrix4T< T > &xform, bool fit_z) const
File options for manipulating image data on load or save. This class allows you to modify the incomin...
Definition: IMG_FileParms.h:38
Contains the details of a specific image file, used by IMG_File. This class contains all the high-lev...
Definition: IMG_Stat.h:38
Definition: core.h:1131
UT_SharedPtr< PXL_DeepCompressor > PXL_DeepCompressorPtr
Definition: PXL_Forward.h:26
const char * getStorage() const
ImageBuf OIIO_API crop(const ImageBuf &src, ROI roi={}, int nthreads=0)
type
Definition: core.h:1059
bool writeOrdered(float z, const float *chdata, int chsize, int flags, int sampleid, float dz=0)
Definition: format.h:895
GLenum src
Definition: glcorearb.h:1793