-
Notifications
You must be signed in to change notification settings - Fork 60
/
cyGL.h
1790 lines (1569 loc) · 113 KB
/
cyGL.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
// cyCodeBase by Cem Yuksel
// [www.cemyuksel.com]
//-------------------------------------------------------------------------------
//! \file cyGL.h
//! \author Cem Yuksel
//!
//! \brief OpenGL helper classes
//!
//! The classes in this file are designed to provide convenient interfaces for
//! some OpenGL features. They are not intended to provide the full flexibility
//! of the underlying OpenGL functions, but they greatly simplify the
//! implementation of some general OpenGL operations.
//!
//-------------------------------------------------------------------------------
//
// Copyright (c) 2017, Cem Yuksel <[email protected]>
// All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
//-------------------------------------------------------------------------------
#ifndef _CY_GL_H_INCLUDED_
#define _CY_GL_H_INCLUDED_
//-------------------------------------------------------------------------------
#if !defined(__gl_h_) && !defined(__GL_H__) && !defined(_GL_H) && !defined(__X_GL_H)
#error gl.h not included before cyGL.h
#endif
#ifndef GL_VERSION_2_0
#error OpenGL 2.0 extensions are required for cyGL.h. You must include an OpenGL extensions header before including cyGL.h.
#endif
#ifndef GL_VERSION_3_0
# define _CY_GL_VERSION_3_0_WARNING "OpenGL version 3 is required for using geometry and tessellation shaders, but the OpenGL extensions header included before cyGL.h does not include OpenGL version 3.0 definitions."
# if _MSC_VER
# pragma message ("Warning: " _CY_GL_VERSION_3_0_WARNING)
# elif __GNUC__
# warning (_CY_GL_VERSION_3_0_WARNING)
# endif
#endif
//-------------------------------------------------------------------------------
#ifndef GL_GEOMETRY_SHADER
#define GL_GEOMETRY_SHADER 0x8DD9
#endif
#ifndef GL_TESS_EVALUATION_SHADER
#define GL_TESS_EVALUATION_SHADER 0x8E87
#endif
#ifndef GL_TESS_CONTROL_SHADER
#define GL_TESS_CONTROL_SHADER 0x8E88
#endif
#ifdef APIENTRY
# define _CY_APIENTRY APIENTRY
#else
# if defined(__MINGW32__) || defined(__CYGWIN__) || (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED) || defined(__BORLANDC__)
# define _CY_APIENTRY __stdcall
# else
# define _CY_APIENTRY
# endif
#endif
//-------------------------------------------------------------------------------
#include <vector>
#include <string>
#include <iostream>
#include <fstream>
#include <sstream>
#include <cassert>
//-------------------------------------------------------------------------------
// These includes are needed for checking the OpenGL context.
// If CY_GL_DONT_CHECK_CONTEXT is defined before including this file,
// checking the OpenGL context is disabled and these includes are skipped.
#ifndef CY_GL_DONT_CHECK_CONTEXT
# ifdef _WIN32
# include <wtypes.h>
# include <Wingdi.h>
# define _CY_GL_GET_CONTEXT wglGetCurrentContext()
# elif defined(__APPLE__)
# include <OpenGL/OpenGL.h>
# define _CY_GL_GET_CONTEXT CGLGetCurrentContext()
# elif defined(__unix__)
# include <GL/glx.h>
# define _CY_GL_GET_CONTEXT glXGetCurrentContext()
# else
# define _CY_GL_GET_CONTEXT 1
# endif
#else
# define _CY_GL_GET_CONTEXT 1
#endif
//-------------------------------------------------------------------------------
namespace cy {
//-------------------------------------------------------------------------------
#define CY_GL_INVALID_ID 0xFFFFFFFF //!< Invalid ID value
//-------------------------------------------------------------------------------
//! General OpenGL queries
//!
//! This class includes static functions for general OpenGL queries
//! and types used by the other classes in this file.
class GL
{
public:
//! OpenGL types
enum Type {
TYPE_UBYTE = 0,
TYPE_USHORT,
TYPE_HALF,
TYPE_FLOAT,
TYPE_INT8,
TYPE_UINT8,
TYPE_INT16,
TYPE_UINT16,
TYPE_INT32,
TYPE_UINT32,
};
static GLenum GetGLType( GLubyte const * ) { return GL_UNSIGNED_BYTE ; } //!< Returns the OpenGL type identifier that corresponds to unsigned byte.
static GLenum GetGLType( GLushort const * ) { return GL_UNSIGNED_SHORT; } //!< Returns the OpenGL type identifier that corresponds to unsigned short.
static GLenum GetGLType( GLfloat const * ) { return GL_FLOAT ; } //!< Returns the OpenGL type identifier that corresponds to float.
static GLenum GetGLType( GLbyte const * ) { return GL_BYTE ; } //!< Returns the OpenGL type identifier that corresponds to byte.
static GLenum GetGLType( GLshort const * ) { return GL_SHORT ; } //!< Returns the OpenGL type identifier that corresponds to short.
static GLenum GetGLType( GLint const * ) { return GL_INT ; } //!< Returns the OpenGL type identifier that corresponds to int.
static GLenum GetGLType( GLuint const * ) { return GL_UNSIGNED_INT ; } //!< Returns the OpenGL type identifier that corresponds to unsigned int.
static Type GetType( GLubyte const * ) { return TYPE_UBYTE ; } //!< Returns the Type that corresponds to unsigned byte.
static Type GetType( GLushort const * ) { return TYPE_USHORT; } //!< Returns the Type that corresponds to unsigned short.
static Type GetType( GLfloat const * ) { return TYPE_FLOAT ; } //!< Returns the Type that corresponds to float.
static Type GetType( GLbyte const * ) { return TYPE_INT8 ; } //!< Returns the Type that corresponds to byte.
static Type GetType( GLshort const * ) { return TYPE_INT16 ; } //!< Returns the Type that corresponds to short.
static Type GetType( GLint const * ) { return TYPE_INT32 ; } //!< Returns the Type that corresponds to int.
static Type GetType( GLuint const * ) { return TYPE_UINT32; } //!< Returns the Type that corresponds to unsigned int.
static GLenum TextureFormat ( Type type, int numChannels ); //!< Returns the internal OpenGL texture type identifier for the given Type and the number of channels.
static GLenum TextureDataFormat( Type type, int numChannels ); //!< Returns the OpenGL texture data format identifier for the given Type and the number of channels.
//! Prints the OpenGL version to the given stream.
static void PrintVersion(std::ostream *outStream=&std::cout);
//! Checks all previously triggered OpenGL errors and prints them to the given output stream.
static void CheckError( char const *sourcefile, int line, char const *call=nullptr, std::ostream *outStream=&std::cout );
//! Checks if an OpenGL context exists. Returns false if a valid OpenGL context cannot be retrieved.
//! This is mostly useful for safely deleting previously allocated OpenGL objects.
static bool CheckContext() { return _CY_GL_GET_CONTEXT ? true : false; }
};
//-------------------------------------------------------------------------------
//! Checks and prints OpenGL error messages to the default output stream.
#define CY_GL_ERROR _CY_GL_ERROR
#define _CY_GL_ERROR cy::GL::CheckError(__FILE__,__LINE__)
//! Checks OpenGL errors before calling the given function,
//! calls the function, and then checks OpenGL errors again.
//! If an error is found, it is printed to the default output stream.
#define CY_GL_ERR(gl_function_call) _CY_GL_ERR(gl_function_call)
#define _CY_GL_ERR(f) cy::GL::CheckError(__FILE__,__LINE__,"a prior call"); f; cy::GL::CheckError(__FILE__,__LINE__,#f)
#ifdef _DEBUG
# define CY_GL_ERROR_D CY_GL_ERROR //!< Checks and prints OpenGL error messages using CY_GL_ERROR in code compiled in debug mode only (with _DEBUG defined).
# define CY_GL_ERR_D CY_GL_ERR //!< Checks and prints OpenGL error messages using CY_GL_ERR in code compiled in debug mode only (with _DEBUG defined).
#else
# define CY_GL_ERROR_D //!< Checks and prints OpenGL error messages using CY_GL_ERROR in code compiled in debug mode only (with _DEBUG defined).
# define CY_GL_ERR_D //!< Checks and prints OpenGL error messages using CY_GL_ERR in code compiled in debug mode only (with _DEBUG defined).
#endif
//-------------------------------------------------------------------------------
#ifdef GL_KHR_debug
#define _CY_GLDebugCallback
//! OpenGL debug callback class.
//!
//! For this class to work, you may need to initialize the OpenGL context in debug mode.
//! This class registers an OpenGL debug callback function, which is called when
//! there is an OpenGL generates a debug message.
//! The class has no local storage, so it can be safely deleted.
//! Deleting an object of this class, however, does not automatically disable the debug callbacks.
class GLDebugCallback
{
public:
//! Constructor can register the callback, but only if the OpenGL context is created
//! before the constructor is called. If the regsiterCallback argument is false,
//! the other arguments are ignored.
GLDebugCallback(bool registerCallback=false, bool ignoreNotifications=false, std::ostream *outStream=&std::cout)
{ if ( registerCallback ) { Register(outStream); IgnoreNotifications(ignoreNotifications); } }
//! Registers the debug callback function.
//! The callback function outputs the debug data to the given stream.
//! Note that if the OpenGL context is not created in debug mode,
//! OpenGL may not call the callback function.
//! If there is a previously registered callback function,
//! calling this function overwrites the previous callback registration.
void Register(std::ostream *outStream=&std::cout) { glEnable(GL_DEBUG_OUTPUT); glDebugMessageCallback((GLDEBUGPROC)Callback,outStream); }
//! Unregisters the OpenGL debug callback function.
void Unregister() { glDisable(GL_DEBUG_OUTPUT); glDebugMessageCallback(0,0); }
//! Sets which type of non-critical debug messages should be ignored.
//! By default, no debug message type is ignored.
void SetIgnoredTypes( bool deprecated_behavior, bool portability, bool performance, bool other )
{
glDebugMessageControl( GL_DONT_CARE, GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR, GL_DONT_CARE, 0, 0, deprecated_behavior );
glDebugMessageControl( GL_DONT_CARE, GL_DEBUG_TYPE_PORTABILITY, GL_DONT_CARE, 0, 0, portability );
glDebugMessageControl( GL_DONT_CARE, GL_DEBUG_TYPE_PERFORMANCE, GL_DONT_CARE, 0, 0, performance );
glDebugMessageControl( GL_DONT_CARE, GL_DEBUG_TYPE_OTHER, GL_DONT_CARE, 0, 0, other );
}
//! Sets weather notification messages should be ignored.
void IgnoreNotifications(bool ignore=true) { glDebugMessageControl( GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_NOTIFICATION, 0, 0, !ignore ); }
protected:
//! This callback function that is called by OpenGL whenever there is a debug message.
//! See the OpenGL documentation for glDebugMessageCallback for details.
//! Placing the break point in this function allows easily identifying the
//! OpenGL call that triggered the debug message (using the call stack).
static void _CY_APIENTRY Callback( GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, GLchar const *message, void const *userParam );
};
//! Registers the OpenGL callback by ignoring notifications.
//! After this macro is called, the debug messages get printed to the default output stream.
//! The OpenGL context must be created before using this macro.
//! Note that OpenGL may not generate debug messages if it is not created in debug mode.
#define CY_GL_REGISTER_DEBUG_CALLBACK _CY_GL_REGISTER_DEBUG_CALLBACK
#define _CY_GL_REGISTER_DEBUG_CALLBACK { cy::GLDebugCallback callback(true,true); }
#endif // GL_KHR_debug
//-------------------------------------------------------------------------------
//! OpenGL texture base class.
//!
//! This class provides a convenient interface for handling basic texture
//! operations with OpenGL. The template argument TEXTURE_TYPE should be a
//! texture type supported by OpenGL, such as GL_TEXTURE_1D, GL_TEXTURE_2D,
//! GL_TEXTURE_3D, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_RECTANGLE,
//! GL_TEXTURE_1D_ARRAY, GL_TEXTURE_2D_ARRAY, GL_TEXTURE_CUBE_MAP_ARRAY,
//! GL_TEXTURE_BUFFER, GL_TEXTURE_2D_MULTISAMPLE, or
//! GL_TEXTURE_2D_MULTISAMPLE_ARRAY. This class merely stores the texture id.
//! Note that deleting an object of this class does not automatically delete
//! the texture from the GPU memory. You must explicitly call the Delete()
//! method to free the texture storage on the GPU.
template <GLenum TEXTURE_TYPE>
class GLTexture
{
private:
GLuint textureID; //!< The texture ID
public:
GLTexture() : textureID(CY_GL_INVALID_ID) {} //!< Constructor.
//!@name General Methods
void Delete() { if ( textureID != CY_GL_INVALID_ID ) glDeleteTextures(1,&textureID); textureID = CY_GL_INVALID_ID; } //!< Deletes the texture.
GLuint GetID () const { return textureID; } //!< Returns the texture ID.
bool IsNull() const { return textureID == CY_GL_INVALID_ID; } //!< Returns true if the OpenGL texture object is not generated, i.e. the texture id is invalid.
void Bind () const { glBindTexture(TEXTURE_TYPE, textureID); } //!< Binds the texture to the current texture unit.
void Bind (int textureUnit) const { glActiveTexture(GL_TEXTURE0+textureUnit); Bind(); } //!< Binds the texture to the given texture unit.
GLenum Type () const { return TEXTURE_TYPE; }
//!@name Texture Creation and Initialization
//! Generates the texture, only if the texture has not been previously generated.
//! Initializes the texture sampling parameters
void Initialize();
#ifdef GL_VERSION_3_0
//! Builds mipmap levels for the texture. The texture image must be set first.
void BuildMipmaps() { Bind(); glGenerateMipmap(TEXTURE_TYPE); }
#endif
//! Sets the texture filtering mode.
//! The acceptable values are GL_NEAREST and GL_LINEAR.
//! The minification filter values can also be GL_NEAREST_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR, or GL_LINEAR_MIPMAP_LINEAR.
//! If the filter argument is zero, the corresponding filter parameter is not changed.
void SetFilteringMode(GLenum magnificationFilter, GLenum minificationFilter);
#ifdef GL_EXT_texture_filter_anisotropic
//! Sets the anisotropy level of the texture.
//! The anisotropy value of 1 disables anisotropic filtering.
//! Larger values provide provide better anisotropic filtering.
void SetAnisotropy(float anisotropy) { Bind(); glTexParameterf(TEXTURE_TYPE, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy ); }
//! Sets anisotropic filtering to the maximum permissible value.
void SetMaxAnisotropy() { float largest; glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &largest); SetAnisotropy(largest); }
//! Turns off anisotropic filtering.
void SetNoAnisotropy() { SetAnisotropy(1.0f); }
#endif
};
//-------------------------------------------------------------------------------
//! OpenGL 1D texture class.
//!
//! This class provides a convenient interface for handling 1D texture
//! operations with OpenGL. The template argument TEXTURE_TYPE should be a
//! 1D texture type supported by OpenGL, such as GL_TEXTURE_1D.
//! This class merely stores the texture id.
//! Note that deleting an object of this class does not automatically delete
//! the texture from the GPU memory. You must explicitly call the Delete()
//! method to free the texture storage on the GPU.
template <GLenum TEXTURE_TYPE>
class GLTexture1 : public GLTexture<TEXTURE_TYPE>
{
public:
//! Sets the texture image using the given texture format, data format, and data type.
void SetImage( GLenum textureFormat, GLenum dataFormat, GLenum dataType, void const *data, GLsizei width, int level=0 ) { GLTexture<TEXTURE_TYPE>::Bind(); glTexImage1D(TEXTURE_TYPE,level,textureFormat,width,0,dataFormat,dataType,data); }
//! Sets the texture image using the given texture format and data format. The data type is determined by the data pointer type.
template <typename T> void SetImage( GLenum textureFormat, GLenum dataFormat, T const *data, GLsizei width, int level=0 ) { SetImage(textureFormat,dataFormat,GL::GetGLType(data),data,width,level); }
//! Sets the texture image using the given texture type. The data format and type are determined by the data pointer type and the number of channels.
//! The texture format is determined by the texture type and the number of channels.
template <typename T> void SetImage( GL::Type textureType, T const *data, int numChannels, GLsizei width, int level=0 ) { SetImage(GL::TextureFormat(textureType,numChannels),GL::TextureDataFormat(GL::GetType(data),numChannels),data,width,level); }
//! Sets the texture image. The texture format uses the matching data pointer type.
//! If unsigned char is used, the texture uses 8-bit normalized values.
//! If unsigned short is used, the texture uses 16-bit normalized values.
//! If float is used, the texture uses non-normalized 32-bit float values.
//! If char, short, or int is used, the texture uses non-normalized 8-bit, 16-bit, or 32-bit integer values.
template <typename T> void SetImage( T const *data, int numChannels, GLsizei width, int level=0 ) { SetImage(GL::GetType(data),data,numChannels,width,level); }
template <typename T> void SetImageRGBA( GL::Type textureType, T const *data, GLsizei width, int level=0 ) { SetImage(textureType,data,4,width,level); } //!< Sets the texture image with 4 channels.
template <typename T> void SetImageRGB ( GL::Type textureType, T const *data, GLsizei width, int level=0 ) { SetImage(textureType,data,3,width,level); } //!< Sets the texture image with 3 channels.
template <typename T> void SetImageRG ( GL::Type textureType, T const *data, GLsizei width, int level=0 ) { SetImage(textureType,data,2,width,level); } //!< Sets the texture image with 2 channels.
template <typename T> void SetImageR ( GL::Type textureType, T const *data, GLsizei width, int level=0 ) { SetImage(textureType,data,1,width,level); } //!< Sets the texture image with 1 channel.
template <typename T> void SetImageRGBA( T const *data, GLsizei width, int level=0 ) { SetImage(data,4,width,level); } //!< Sets the texture image with 4 channels.
template <typename T> void SetImageRGB ( T const *data, GLsizei width, int level=0 ) { SetImage(data,3,width,level); } //!< Sets the texture image with 3 channels.
template <typename T> void SetImageRG ( T const *data, GLsizei width, int level=0 ) { SetImage(data,2,width,level); } //!< Sets the texture image with 2 channels.
template <typename T> void SetImageR ( T const *data, GLsizei width, int level=0 ) { SetImage(data,1,width,level); } //!< Sets the texture image with 1 channel.
//! Sets the texture wrapping parameter.
//! The acceptable values are GL_REPEAT, GL_MIRRORED_REPEAT, GL_CLAMP, and GL_CLAMP_TO_BORDER.
void SetWrappingMode(GLenum wrapS) { GLTexture<TEXTURE_TYPE>::Bind(); glTexParameteri(TEXTURE_TYPE, GL_TEXTURE_WRAP_S, wrapS); }
};
//-------------------------------------------------------------------------------
//! OpenGL 2D texture class.
//!
//! This class provides a convenient interface for handling 2D texture
//! operations with OpenGL. The template argument TEXTURE_TYPE should be a
//! 2D texture type supported by OpenGL, such as GL_TEXTURE_2D,
//! GL_TEXTURE_RECTANGLE, or GL_TEXTURE_1D_ARRAY. This class merely stores the texture id.
//! Note that deleting an object of this class does not automatically delete
//! the texture from the GPU memory. You must explicitly call the Delete()
//! method to free the texture storage on the GPU.
template <GLenum TEXTURE_TYPE>
class GLTexture2 : public GLTexture<TEXTURE_TYPE>
{
public:
//! Sets the texture image using the given texture format, data format, and data type.
void SetImage( GLenum textureFormat, GLenum dataFormat, GLenum dataType, void const *data, GLsizei width, GLsizei height, int level=0 ) { GLTexture<TEXTURE_TYPE>::Bind(); glTexImage2D(TEXTURE_TYPE,level,textureFormat,width,height,0,dataFormat,dataType,data); }
//! Sets the texture image using the given texture format and data format. The data type is determined by the data pointer type.
template <typename T> void SetImage( GLenum textureFormat, GLenum dataFormat, T const *data, GLsizei width, GLsizei height, int level=0 ) { SetImage(textureFormat,dataFormat,GL::GetGLType(data),data,width,height,level); }
//! Sets the texture image using the given texture type. The data format and type are determined by the data pointer type and the number of channels.
//! The texture format is determined by the texture type and the number of channels.
template <typename T> void SetImage( GL::Type textureType, T const *data, int numChannels, GLsizei width, GLsizei height, int level=0 ) { SetImage(GL::TextureFormat(textureType,numChannels),GL::TextureDataFormat(GL::GetType(data),numChannels),data,width,height,level); }
//! Sets the texture image. The texture format uses the matching data pointer type.
//! If GLubyte (unsigned char) is used, the texture uses 8-bit normalized values.
//! If GLushort (unsigned short) is used, the texture uses 16-bit normalized values.
//! If GLfloat (float) is used, the texture uses non-normalized 32-bit float values.
//! If GLbyte, GLshort, GLint, or GLuint is used, the texture uses non-normalized 8-bit, 16-bit, or 32-bit integer values.
template <typename T> void SetImage( T const *data, int numChannels, GLsizei width, GLsizei height, int level=0 ) { SetImage(GL::GetType(data),data,numChannels,width,height,level); }
template <typename T> void SetImageRGBA( GL::Type textureType, T const *data, GLsizei width, GLsizei height, int level=0 ) { SetImage(textureType,data,4,width,height,level); } //!< Sets the texture image with 4 channels.
template <typename T> void SetImageRGB ( GL::Type textureType, T const *data, GLsizei width, GLsizei height, int level=0 ) { SetImage(textureType,data,3,width,height,level); } //!< Sets the texture image with 3 channels.
template <typename T> void SetImageRG ( GL::Type textureType, T const *data, GLsizei width, GLsizei height, int level=0 ) { SetImage(textureType,data,2,width,height,level); } //!< Sets the texture image with 2 channels.
template <typename T> void SetImageR ( GL::Type textureType, T const *data, GLsizei width, GLsizei height, int level=0 ) { SetImage(textureType,data,1,width,height,level); } //!< Sets the texture image with 1 channel.
template <typename T> void SetImageRGBA( T const *data, GLsizei width, GLsizei height, int level=0 ) { SetImage(data,4,width,height,level); } //!< Sets the texture image with 4 channels.
template <typename T> void SetImageRGB ( T const *data, GLsizei width, GLsizei height, int level=0 ) { SetImage(data,3,width,height,level); } //!< Sets the texture image with 3 channels.
template <typename T> void SetImageRG ( T const *data, GLsizei width, GLsizei height, int level=0 ) { SetImage(data,2,width,height,level); } //!< Sets the texture image with 2 channels.
template <typename T> void SetImageR ( T const *data, GLsizei width, GLsizei height, int level=0 ) { SetImage(data,1,width,height,level); } //!< Sets the texture image with 1 channel.
//! Sets the texture wrapping parameter.
//! The acceptable values are GL_REPEAT, GL_MIRRORED_REPEAT, GL_CLAMP, and GL_CLAMP_TO_BORDER.
//! If the wrap argument is zero, the corresponding wrapping parameter is not changed.
void SetWrappingMode(GLenum wrapS, GLenum wrapT)
{
GLTexture<TEXTURE_TYPE>::Bind();
if ( wrapS != 0 ) glTexParameteri(TEXTURE_TYPE, GL_TEXTURE_WRAP_S, wrapS);
if ( wrapT != 0 ) glTexParameteri(TEXTURE_TYPE, GL_TEXTURE_WRAP_T, wrapT);
}
};
//-------------------------------------------------------------------------------
//! OpenGL 3D texture class.
//!
//! This class provides a convenient interface for handling 3D texture
//! operations with OpenGL. The template argument TEXTURE_TYPE should be a
//! 3D texture type supported by OpenGL, such as GL_TEXTURE_3D or
//! GL_TEXTURE_2D_ARRAY. This class merely stores the texture id.
//! Note that deleting an object of this class does not automatically delete
//! the texture from the GPU memory. You must explicitly call the Delete()
//! method to free the texture storage on the GPU.
template <GLenum TEXTURE_TYPE>
class GLTexture3 : public GLTexture<TEXTURE_TYPE>
{
public:
//! Sets the texture image using the given texture format, data format, and data type.
void SetImage( GLenum textureFormat, GLenum dataFormat, GLenum dataType, void const *data, GLsizei width, GLsizei height, GLsizei depth, int level=0 ) { GLTexture<TEXTURE_TYPE>::Bind(); glTexImage3D(TEXTURE_TYPE,level,textureFormat,width,height,depth,0,dataFormat,dataType,data); }
//! Sets the texture image using the given texture format and data format. The data type is determined by the data pointer type.
template <typename T> void SetImage( GLenum textureFormat, GLenum dataFormat, T const *data, GLsizei width, GLsizei height, GLsizei depth, int level=0 ) { SetImage(textureFormat,dataFormat,GL::GetGLType(data),data,width,height,depth,level); }
//! Sets the texture image using the given texture type. The data format and type are determined by the data pointer type and the number of channels.
//! The texture format is determined by the texture type and the number of channels.
template <typename T> void SetImage( GL::Type textureType, T const *data, int numChannels, GLsizei width, GLsizei height, GLsizei depth, int level=0 ) { SetImage(GL::TextureFormat(textureType,numChannels),GL::TextureDataFormat(GL::GetType(data),numChannels),data,width,height,depth,level); }
//! Sets the texture image. The texture format uses the matching data pointer type.
//! If unsigned char is used, the texture uses 8-bit normalized values.
//! If unsigned short is used, the texture uses 16-bit normalized values.
//! If float is used, the texture uses non-normalized 32-bit float values.
//! If char, short, or int is used, the texture uses non-normalized 8-bit, 16-bit, or 32-bit integer values.
template <typename T> void SetImage( T const *data, int numChannels, GLsizei width, GLsizei height, GLsizei depth, int level=0 ) { SetImage(GL::GetType(data),data,numChannels,width,height,depth,level); }
template <typename T> void SetImageRGBA( GL::Type textureType, T const *data, GLsizei width, GLsizei height, GLsizei depth, int level=0 ) { SetImage(textureType,data,4,width,height,depth,level); } //!< Sets the texture image with 4 channels.
template <typename T> void SetImageRGB ( GL::Type textureType, T const *data, GLsizei width, GLsizei height, GLsizei depth, int level=0 ) { SetImage(textureType,data,3,width,height,depth,level); } //!< Sets the texture image with 3 channels.
template <typename T> void SetImageRG ( GL::Type textureType, T const *data, GLsizei width, GLsizei height, GLsizei depth, int level=0 ) { SetImage(textureType,data,2,width,height,depth,level); } //!< Sets the texture image with 2 channels.
template <typename T> void SetImageR ( GL::Type textureType, T const *data, GLsizei width, GLsizei height, GLsizei depth, int level=0 ) { SetImage(textureType,data,1,width,height,depth,level); } //!< Sets the texture image with 1 channel.
template <typename T> void SetImageRGBA( T const *data, GLsizei width, GLsizei height, GLsizei depth, int level=0 ) { SetImage(data,4,width,height,depth,level); } //!< Sets the texture image with 4 channels.
template <typename T> void SetImageRGB ( T const *data, GLsizei width, GLsizei height, GLsizei depth, int level=0 ) { SetImage(data,3,width,height,depth,level); } //!< Sets the texture image with 3 channels.
template <typename T> void SetImageRG ( T const *data, GLsizei width, GLsizei height, GLsizei depth, int level=0 ) { SetImage(data,2,width,height,depth,level); } //!< Sets the texture image with 2 channels.
template <typename T> void SetImageR ( T const *data, GLsizei width, GLsizei height, GLsizei depth, int level=0 ) { SetImage(data,1,width,height,depth,level); } //!< Sets the texture image with 1 channel.
//! Sets the texture wrapping parameter.
//! The acceptable values are GL_REPEAT, GL_MIRRORED_REPEAT, GL_CLAMP, and GL_CLAMP_TO_BORDER.
//! If the wrap argument is zero, the corresponding wrapping parameter is not changed.
void SetWrappingMode(GLenum wrapS, GLenum wrapT, GLenum wrapR)
{
GLTexture<TEXTURE_TYPE>::Bind();
if ( wrapS != 0 ) glTexParameteri(TEXTURE_TYPE, GL_TEXTURE_WRAP_S, wrapS);
if ( wrapT != 0 ) glTexParameteri(TEXTURE_TYPE, GL_TEXTURE_WRAP_T, wrapT);
if ( wrapR != 0 ) glTexParameteri(TEXTURE_TYPE, GL_TEXTURE_WRAP_R, wrapR);
}
};
//-------------------------------------------------------------------------------
//! Sides of a cube map
enum GLTextureCubeMapSide {
POSITIVE_X=0,
NEGATIVE_X,
POSITIVE_Y,
NEGATIVE_Y,
POSITIVE_Z,
NEGATIVE_Z
};
//-------------------------------------------------------------------------------
//! OpenGL cube map texture class.
//!
//! This class provides a convenient interface for handling cube map texture
//! operations with OpenGL. This class merely stores the texture id.
//! Note that deleting an object of this class does not automatically delete
//! the texture from the GPU memory. You must explicitly call the Delete()
//! method to free the texture storage on the GPU.
class GLTextureCubeMap : public GLTexture<GL_TEXTURE_CUBE_MAP>
{
public:
typedef GLTextureCubeMapSide Side; //!< Sides of the cube map
//! Sets the texture image using the given texture format, data format, and data type.
void SetImage( Side side, GLenum textureFormat, GLenum dataFormat, GLenum dataType, void const *data, GLsizei width, GLsizei height, int level=0 ) { GLTexture<GL_TEXTURE_CUBE_MAP>::Bind(); glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+side,level,textureFormat,width,height,0,dataFormat,dataType,data); }
//! Sets the texture image using the given texture format and data format. The data type is determined by the data pointer type.
template <typename T> void SetImage( Side side, GLenum textureFormat, GLenum dataFormat, T const *data, GLsizei width, GLsizei height, int level=0 ) { SetImage(side,textureFormat,dataFormat,GL::GetGLType(data),data,width,height,level); }
//! Sets the texture image using the given texture type. The data format and type are determined by the data pointer type and the number of channels.
//! The texture format is determined by the texture type and the number of channels.
template <typename T> void SetImage( Side side, GL::Type textureType, T const *data, int numChannels, GLsizei width, GLsizei height, int level=0 ) { SetImage(side,GL::TextureFormat(textureType,numChannels),GL::TextureDataFormat(GL::GetType(data),numChannels),data,width,height,level); }
//! Sets the texture image. The texture format uses the matching data pointer type.
//! If unsigned char is used, the texture uses 8-bit normalized values.
//! If unsigned short is used, the texture uses 16-bit normalized values.
//! If float is used, the texture uses non-normalized 32-bit float values.
//! If char, short, or int is used, the texture uses non-normalized 8-bit, 16-bit, or 32-bit integer values.
template <typename T> void SetImage( Side side, T const *data, int numChannels, GLsizei width, GLsizei height, int level=0 ) { SetImage(side,GL::GetType(data),data,numChannels,width,height,level); }
template <typename T> void SetImageRGBA( Side side, GL::Type textureType, T const *data, GLsizei width, GLsizei height, int level=0 ) { SetImage(side,textureType,data,4,width,height,level); } //!< Sets the texture image with 4 channels.
template <typename T> void SetImageRGB ( Side side, GL::Type textureType, T const *data, GLsizei width, GLsizei height, int level=0 ) { SetImage(side,textureType,data,3,width,height,level); } //!< Sets the texture image with 3 channels.
template <typename T> void SetImageRG ( Side side, GL::Type textureType, T const *data, GLsizei width, GLsizei height, int level=0 ) { SetImage(side,textureType,data,2,width,height,level); } //!< Sets the texture image with 2 channels.
template <typename T> void SetImageR ( Side side, GL::Type textureType, T const *data, GLsizei width, GLsizei height, int level=0 ) { SetImage(side,textureType,data,1,width,height,level); } //!< Sets the texture image with 1 channel.
template <typename T> void SetImageRGBA( Side side, T const *data, GLsizei width, GLsizei height, int level=0 ) { SetImage(side,data,4,width,height,level); } //!< Sets the texture image with 4 channels.
template <typename T> void SetImageRGB ( Side side, T const *data, GLsizei width, GLsizei height, int level=0 ) { SetImage(side,data,3,width,height,level); } //!< Sets the texture image with 3 channels.
template <typename T> void SetImageRG ( Side side, T const *data, GLsizei width, GLsizei height, int level=0 ) { SetImage(side,data,2,width,height,level); } //!< Sets the texture image with 2 channels.
template <typename T> void SetImageR ( Side side, T const *data, GLsizei width, GLsizei height, int level=0 ) { SetImage(side,data,1,width,height,level); } //!< Sets the texture image with 1 channel.
#ifdef GL_TEXTURE_CUBE_MAP_SEAMLESS
//! Sets the global seamless cube mapping flag, if supported by the hardware.
static void SetSeamless(bool enable=true) { if (enable) glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); else glDisable(GL_TEXTURE_CUBE_MAP_SEAMLESS); }
#endif
};
//-------------------------------------------------------------------------------
#ifdef GL_VERSION_3_0
#define _CY_GLRenderBuffer
//-------------------------------------------------------------------------------
//! OpenGL render buffer
//!
//! This is the base class for helper classes for render to texture in OpenGL.
template <GLenum TEXTURE_TYPE>
class GLRenderBuffer
{
protected:
GLuint framebufferID; //!< The frame-buffer ID
GLuint depthbufferID; //!< The depth-buffer ID
GLTexture2<TEXTURE_TYPE> texture; //!< The buffer texture
GLsizei bufferWidth; //!< The width of the frame buffer
GLsizei bufferHeight; //!< The height of the frame buffer
mutable GLint prevBufferID; //!< Temporary storage for previous frame-buffer used before binding this buffer
mutable GLint prevViewport[4]; //!< Temporary storage for the size and position of the previous frame-buffer used before binding this buffer
public:
GLRenderBuffer() : framebufferID(CY_GL_INVALID_ID), depthbufferID(CY_GL_INVALID_ID), prevBufferID(0) {} //!< Constructor.
~GLRenderBuffer() { if ( GL::CheckContext() ) Delete(); } //!< Destructor.
//!@name General Methods
void Delete (); //!< Deletes the render buffer.
GLuint GetID () const { return framebufferID; } //!< Returns the frame buffer ID.
bool IsNull () const { return framebufferID == CY_GL_INVALID_ID; } //!< Returns true if the render buffer is not initialized, i.e. the render buffer id is invalid.
void Bind () const; //!< Binds the frame buffer for rendering and adjusts the viewport accordingly.
void Unbind () const; //!< Binds the frame buffer that was used before this frame buffer was bound and reverts the viewport.
bool IsReady () const { return glIsFramebuffer(framebufferID) > 0; } //!< Returns true if the frame buffer is ready. This method can be called after initialization.
bool IsComplete() const; //!< Returns true if the render buffer is complete.
//!@name Texture Methods
GLuint GetTextureID() const { return texture.GetID(); } //!< Returns the texture ID.
void BindTexture () const { texture.Bind(); } //!< Binds the texture to the current texture unit.
void BindTexture (int textureUnit) const { texture.Bind(textureUnit); } //!< Binds the texture to the given texture unit.
void BuildTextureMipmaps() { texture.BuildMipmaps(); } //!< Builds mipmap levels for the texture.
//! Sets the wrapping parameter for the texture.
//! The acceptable values are GL_REPEAT, GL_MIRRORED_REPEAT, GL_CLAMP, and GL_CLAMP_TO_BORDER.
//! If the wrap argument is zero, the corresponding wrapping parameter is not changed.
void SetTextureWrappingMode(GLenum wrapS, GLenum wrapT) { texture.SetWrappingMode(wrapS,wrapT); }
//! Sets the filtering mode for the texture.
//! The acceptable values are GL_NEAREST and GL_LINEAR.
//! The minification filter values can also be GL_NEAREST_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR, or GL_LINEAR_MIPMAP_LINEAR.
//! If the filter argument is zero, the corresponding filter parameter is not changed.
void SetTextureFilteringMode(GLenum magnificationFilter=0, GLenum minificationFilter=0) { texture.SetFilteringMode(magnificationFilter,minificationFilter); }
#ifdef GL_EXT_texture_filter_anisotropic
void SetTextureAnisotropy(float anisotropy) { texture.SetAnisotropy(anisotropy); } //!< Sets the anisotropy level of the texture.
void SetTextureMaxAnisotropy() { texture.SetMaxAnisotropy(); } //!< Sets anisotropic filtering to the maximum permissible value.
void SetTextureNoAnisotropy () { texture.SetNoAnisotropy(); } //!< Turns off anisotropic filtering.
#endif
protected:
void GenerateBuffer(); //!< Generates the frame buffer and initializes the texture
void SetSize(GLsizei width, GLsizei height) { bufferWidth = width; bufferHeight = height; } //!< Sets the size of the frame buffer
};
//-------------------------------------------------------------------------------
//! OpenGL render color buffer
//!
//! This class provides a convenient interface for texture rendering in OpenGL with a color texture buffer.
template <GLenum TEXTURE_TYPE>
class GLRenderTexture : public GLRenderBuffer<TEXTURE_TYPE>
{
public:
//!@name Render Buffer Creation and Initialization
//! Generates the render buffer.
//! Returns true if the render buffer is ready.
bool Initialize( bool useDepthBuffer );
//! Generates the render buffer and sets its size.
//! Returns true if the render buffer is ready and complete.
bool Initialize( bool useDepthBuffer, int numChannels, GLsizei width, GLsizei height, GL::Type type=GL::TYPE_UBYTE ) { return Initialize(useDepthBuffer) ? Resize(numChannels,width,height,type) : false; }
//! Initializes or changes the size of the render buffer.
//! Returns true if the buffer is complete.
bool Resize( int numChannels, GLsizei width, GLsizei height, GL::Type type=GL::TYPE_UBYTE );
};
//-------------------------------------------------------------------------------
//! OpenGL render depth buffer
//!
//! This class provides a convenient interface for texture rendering in OpenGL with a depth texture buffer.
template <GLenum TEXTURE_TYPE>
class GLRenderDepth : public GLRenderBuffer<TEXTURE_TYPE>
{
public:
//!@name Render Buffer Creation and Initialization
//! Generates the render buffer.
//! Returns true if the render buffer is ready.
//! If depthComparisonTexture is true, initializes the texture for depth comparison.
bool Initialize( bool depthComparisonTexture=true );
//! Generates the render buffer and sets its size.
//! Returns true if the render buffer is ready and complete.
//! If depthComparisonTexture is true, initializes the texture for depth comparison.
bool Initialize( bool depthComparisonTexture, GLsizei width, GLsizei height, GLenum depthFormat=GL_DEPTH_COMPONENT ) { return Initialize(depthComparisonTexture) ? Resize(width,height,depthFormat) : false; }
//! Initializes or changes the size of the render buffer.
//! Returns true if the buffer is complete.
bool Resize( GLsizei width, GLsizei height, GLenum depthFormat=GL_DEPTH_COMPONENT );
};
//-------------------------------------------------------------------------------
//! OpenGL render buffer with a cube map texture
//!
//! This class provides a convenient interface for texture rendering in OpenGL with a cube map texture buffer.
template <GLenum ATTACHMENT_TYPE, typename BASE>
class GLRenderTextureCubeBase : public BASE
{
public:
//! Set the render target to the given side.
//! Should be called after binding the render texture.
void SetTarget( GLTextureCubeMapSide side )
{
glFramebufferTexture2D( GL_FRAMEBUFFER, ATTACHMENT_TYPE, GL_TEXTURE_CUBE_MAP_POSITIVE_X + side, GLRenderBuffer<GL_TEXTURE_CUBE_MAP>::GetTextureID(), 0 );
}
#ifdef _CY_MATRIX_H_INCLUDED_
//! Returns the rotation matrix for the given side.
static Matrix3f GetRotation( GLTextureCubeMapSide side )
{
static Matrix3f m[] = {
Matrix3f( 0, 0,-1, 0,-1, 0, -1, 0, 0 ),
Matrix3f( 0, 0, 1, 0,-1, 0, 1, 0, 0 ),
Matrix3f( 1, 0, 0, 0, 0, 1, 0,-1, 0 ),
Matrix3f( 1, 0, 0, 0, 0,-1, 0, 1, 0 ),
Matrix3f( 1, 0, 0, 0,-1, 0, 0, 0,-1 ),
Matrix3f( -1, 0, 0, 0,-1, 0, 0, 0, 1 )
};
return m[side];
}
//! Returns the perspective projection matrix to be used by all sides.
static Matrix4f GetProjection( float znear, float zfar ) { return Matrix4f::Perspective( Pi<float>()/2, 1, znear, zfar ); }
#endif
};
//-------------------------------------------------------------------------------
#endif // GL_VERSION_3_0
//-------------------------------------------------------------------------------
//! GLSL shader class.
//!
//! This class provides basic functionality for compiling GLSL shaders
//! either from a given source string or a given file.
//! It only stores the shader ID and it can be safely deleted after
//! the shader is used for building (linking) a GLSL program.
class GLSLShader
{
private:
GLuint shaderID; //!< The shader ID
public:
GLSLShader() : shaderID(CY_GL_INVALID_ID) {} //!< Constructor.
virtual ~GLSLShader() { if ( GL::CheckContext() ) Delete(); } //!< Destructor that deletes the shader.
//!@name General Methods
void Delete() { if (shaderID!=CY_GL_INVALID_ID) { glDeleteShader(shaderID); shaderID=CY_GL_INVALID_ID; } } //!< Deletes the shader.
GLuint GetID () const { return shaderID; } //!< Returns the shader ID.
bool IsNull() const { return shaderID == CY_GL_INVALID_ID; } //!< Returns true if the OpenGL shader object is not generated, i.e. the shader id is invalid.
//!@name Compilation Methods
//! Compiles the shader using the given file.
//! If the shader was previously compiled, it is deleted.
bool CompileFile( char const *filename, GLenum shaderType, std::ostream *outStream=&std::cout ) { return CompileFile(filename,shaderType,0,nullptr,outStream); }
//! Compiles the shader using the given file.
//! If the shader was previously compiled, it is deleted.
//! The prependSource string is added to the beginning of the shader code, so it must begin with the "#version" statement.
bool CompileFile( char const *filename, GLenum shaderType, char const *prependSource, std::ostream *outStream=&std::cout ) { return CompileFile(filename,shaderType,1,&prependSource,outStream); }
//! Compiles the shader using the given file.
//! If the shader was previously compiled, it is deleted.
//! The prependSources strings are added to the beginning of the shader code, so the first string must begin with "#version" statement.
bool CompileFile( char const *filename, GLenum shaderType, int prependSourceCount, char const **prependSources, std::ostream *outStream=&std::cout );
//! Compiles the shader using the given source code.
//! If the shader was previously compiled, it is deleted.
bool Compile( char const *shaderSourceCode, GLenum shaderType, std::ostream *outStream=&std::cout ) { return Compile(shaderSourceCode,shaderType,0,nullptr,outStream); }
//! Compiles the shader using the given source code.
//! If the shader was previously compiled, it is deleted.
//! The prependSource string is added to the beginning of the shader code, so it must begin with the "#version" statement.
bool Compile( char const *shaderSourceCode, GLenum shaderType, char const *prependSource, std::ostream *outStream=&std::cout ) { return Compile(shaderSourceCode,shaderType,1,&prependSource,outStream); }
//! Compiles the shader using the given source code.
//! If the shader was previously compiled, it is deleted.
//! The prependSources strings are added to the beginning of the shader code, so the first string must begin with "#version" statement.
bool Compile( char const *shaderSourceCode, GLenum shaderType, int prependSourceCount, char const **prependSources, std::ostream *outStream=&std::cout );
};
//-------------------------------------------------------------------------------
//! GLSL program class.
//!
//! This class provides basic functionality for building GLSL programs
//! using vertex and fragment shaders, along with optionally geometry and tessellation shaders.
//! The shader sources can be provides as GLSLShader class objects, source strings, or file names.
//! This class also stores a vector of registered uniform parameter IDs.
class GLSLProgram
{
private:
GLuint programID; //!< The program ID
std::vector<GLint> params; //!< A list of registered uniform parameter IDs
public:
GLSLProgram() : programID(CY_GL_INVALID_ID) {} //!< Constructor
virtual ~GLSLProgram() { if ( GL::CheckContext() ) Delete(); } //!< Destructor that deletes the program
//!@name General Methods
void Delete() { if (programID!=CY_GL_INVALID_ID) { glDeleteProgram(programID); programID=CY_GL_INVALID_ID; } } //!< Deletes the program.
GLuint GetID () const { return programID; } //!< Returns the program ID
bool IsNull() const { return programID == CY_GL_INVALID_ID; } //!< Returns true if the OpenGL program object is not generated, i.e. the program id is invalid.
void Bind () const { glUseProgram(programID); } //!< Binds the program for rendering
//! Attaches the given shader to the program.
//! This function must be called before calling Link.
void CreateProgram() { Delete(); programID = glCreateProgram(); }
//! Attaches the given shader to the program.
//! This function must be called before calling Link.
void AttachShader( GLSLShader const &shader ) { AttachShader(shader.GetID()); }
//! Attaches the given shader to the program.
//! This function must be called before calling Link.
void AttachShader( GLuint shaderID ) { glAttachShader(programID,shaderID); }
//! Links the program.
//! The shaders must be attached before calling this function.
//! Returns true if the link operation is successful.
//! Writes any error or warning messages to the given output stream.
bool Link( std::ostream *outStream=&std::cout );
//!@name Build Methods
//! Creates a program, compiles the given shaders, and links them.
//! Returns true if all compilation and link operations are successful.
//! Writes any error or warning messages to the given output stream.
bool Build( GLSLShader const *vertexShader,
GLSLShader const *fragmentShader,
GLSLShader const *geometryShader=nullptr,
GLSLShader const *tessControlShader=nullptr,
GLSLShader const *tessEvaluationShader=nullptr,
std::ostream *outStream=&std::cout );
//! Creates a program, compiles the given shaders, and links them.
//! Returns true if all compilation and link operations are successful.
//! Writes any error or warning messages to the given output stream.
bool BuildFiles( char const *vertexShaderFile,
char const *fragmentShaderFile,
char const *geometryShaderFile=nullptr,
char const *tessControlShaderFile=nullptr,
char const *tessEvaluationShaderFile=nullptr,
std::ostream *outStream=&std::cout )
{ return BuildFiles(vertexShaderFile,fragmentShaderFile,geometryShaderFile,tessControlShaderFile,tessEvaluationShaderFile,0,nullptr,outStream); }
//! Creates a program, compiles the given shaders, and links them.
//! Returns true if all compilation and link operations are successful.
//! Writes any error or warning messages to the given output stream.
//! The prependSource string is added to the beginning of each shader code, so it must begin with the "#version" statement.
bool BuildFiles( char const *vertexShaderFile,
char const *fragmentShaderFile,
char const *geometryShaderFile,
char const *tessControlShaderFile,
char const *tessEvaluationShaderFile,
char const *prependSource,
std::ostream *outStream=&std::cout )
{ return BuildFiles(vertexShaderFile,fragmentShaderFile,geometryShaderFile,tessControlShaderFile,tessEvaluationShaderFile,1,&prependSource,outStream); }
//! Creates a program, compiles the given shaders, and links them.
//! Returns true if all compilation and link operations are successful.
//! Writes any error or warning messages to the given output stream.
//! The prependSources strings are added to the beginning of each shader code, so the first string must begin with "#version" statement.
bool BuildFiles( char const *vertexShaderFile,
char const *fragmentShaderFile,
char const *geometryShaderFile,
char const *tessControlShaderFile,
char const *tessEvaluationShaderFile,
int prependSourceCount,
char const **prependSource,
std::ostream *outStream=&std::cout );
//! Creates a program, compiles the given shaders, and links them.
//! Returns true if all compilation and link operations are successful.
//! Writes any error or warning messages to the given output stream.
bool BuildSources( char const *vertexShaderSourceCode,
char const *fragmentShaderSourceCode,
char const *geometryShaderSourceCode=nullptr,
char const *tessControlShaderSourceCode=nullptr,
char const *tessEvaluationShaderSourceCode=nullptr,
std::ostream *outStream=&std::cout )
{ return BuildSources(vertexShaderSourceCode,fragmentShaderSourceCode,geometryShaderSourceCode,tessControlShaderSourceCode,tessEvaluationShaderSourceCode,0,nullptr,outStream); }
//! Creates a program, compiles the given shaders, and links them.
//! Returns true if all compilation and link operations are successful.
//! Writes any error or warning messages to the given output stream.
//! The prependSource string is added to the beginning of each shader code, so it must begin with the "#version" statement.
bool BuildSources( char const *vertexShaderSourceCode,
char const *fragmentShaderSourceCode,
char const *geometryShaderSourceCode,
char const *tessControlShaderSourceCode,
char const *tessEvaluationShaderSourceCode,
char const *prependSource,
std::ostream *outStream=&std::cout )
{ return BuildSources(vertexShaderSourceCode,fragmentShaderSourceCode,geometryShaderSourceCode,tessControlShaderSourceCode,tessEvaluationShaderSourceCode,1,&prependSource,outStream); }
//! Creates a program, compiles the given shaders, and links them.
//! Returns true if all compilation and link operations are successful.
//! Writes any error or warning messages to the given output stream.
//! The prependSources strings are added to the beginning of each shader code, so the first string must begin with "#version" statement.
bool BuildSources( char const *vertexShaderSourceCode,
char const *fragmentShaderSourceCode,
char const *geometryShaderSourceCode,
char const *tessControlShaderSourceCode,
char const *tessEvaluationShaderSourceCode,
int prependSourceCount,
char const **prependSource,
std::ostream *outStream=&std::cout );
//!@name Uniform Parameter Methods
//! Registers a single uniform parameter.
//! The index must be unique and the name should match a uniform parameter name in one of the shaders.
//! The index values for different parameters don't have to be consecutive, but unused index values waste memory.
void RegisterUniform( unsigned int index, char const *name, std::ostream *outStream=&std::cout );
//! Registers multiple parameters.
//! The names should be separated by a space character.
void RegisterUniforms( char const *names, unsigned int startingIndex=0, std::ostream *outStream=&std::cout );
//!@{
//! Sets the value of the uniform parameter with the given index.
//! The uniform parameter must be registered before using RegisterUniform() or RegisterUniforms().
//! The program must be bind by calling Bind() before calling this method.
void SetUniform (int index, float x) { glUniform1f (params[index],x); }
void SetUniform (int index, float x, float y) { glUniform2f (params[index],x,y); }
void SetUniform (int index, float x, float y, float z) { glUniform3f (params[index],x,y,z); }
void SetUniform (int index, float x, float y, float z, float w) { glUniform4f (params[index],x,y,z,w); }
void SetUniform1(int index, float const *data, int count=1) { glUniform1fv (params[index],count,data); }
void SetUniform2(int index, float const *data, int count=1) { glUniform2fv (params[index],count,data); }
void SetUniform3(int index, float const *data, int count=1) { glUniform3fv (params[index],count,data); }
void SetUniform4(int index, float const *data, int count=1) { glUniform4fv (params[index],count,data); }
void SetUniform (int index, int x) { glUniform1i (params[index],x); }
void SetUniform (int index, int x, int y) { glUniform2i (params[index],x,y); }
void SetUniform (int index, int x, int y, int z) { glUniform3i (params[index],x,y,z); }
void SetUniform (int index, int x, int y, int z, int w) { glUniform4i (params[index],x,y,z,w); }
void SetUniform1(int index, int const *data, int count=1) { glUniform1iv (params[index],count,data); }
void SetUniform2(int index, int const *data, int count=1) { glUniform2iv (params[index],count,data); }
void SetUniform3(int index, int const *data, int count=1) { glUniform3iv (params[index],count,data); }
void SetUniform4(int index, int const *data, int count=1) { glUniform4iv (params[index],count,data); }
#ifdef GL_VERSION_3_0
void SetUniform (int index, GLuint x) { glUniform1ui (params[index],x); }
void SetUniform (int index, GLuint x, GLuint y) { glUniform2ui (params[index],x,y); }
void SetUniform (int index, GLuint x, GLuint y, GLuint z) { glUniform3ui (params[index],x,y,z); }
void SetUniform (int index, GLuint x, GLuint y, GLuint z, GLuint w) { glUniform4ui (params[index],x,y,z,w); }
void SetUniform1(int index, GLuint const *data, int count=1) { glUniform1uiv(params[index],count,data); }
void SetUniform2(int index, GLuint const *data, int count=1) { glUniform2uiv(params[index],count,data); }
void SetUniform3(int index, GLuint const *data, int count=1) { glUniform3uiv(params[index],count,data); }
void SetUniform4(int index, GLuint const *data, int count=1) { glUniform4uiv(params[index],count,data); }
#endif
#ifdef GL_VERSION_4_0
void SetUniform (int index, double x) { glUniform1d (params[index],x); }
void SetUniform (int index, double x, double y) { glUniform2d (params[index],x,y); }
void SetUniform (int index, double x, double y, double z) { glUniform3d (params[index],x,y,z); }
void SetUniform (int index, double x, double y, double z, double w) { glUniform4d (params[index],x,y,z,w); }
void SetUniform1(int index, double const *data, int count=1) { glUniform1dv (params[index],count,data); }
void SetUniform2(int index, double const *data, int count=1) { glUniform2dv (params[index],count,data); }
void SetUniform3(int index, double const *data, int count=1) { glUniform3dv (params[index],count,data); }
void SetUniform4(int index, double const *data, int count=1) { glUniform4dv (params[index],count,data); }
#endif
void SetUniformMatrix2 (int index, float const *m, int count=1, bool transpose=false) { glUniformMatrix2fv (params[index],count,transpose,m); }
void SetUniformMatrix3 (int index, float const *m, int count=1, bool transpose=false) { glUniformMatrix3fv (params[index],count,transpose,m); }
void SetUniformMatrix4 (int index, float const *m, int count=1, bool transpose=false) { glUniformMatrix4fv (params[index],count,transpose,m); }
#ifdef GL_VERSION_2_1
void SetUniformMatrix2x3(int index, float const *m, int count=1, bool transpose=false) { glUniformMatrix2x3fv(params[index],count,transpose,m); }
void SetUniformMatrix2x4(int index, float const *m, int count=1, bool transpose=false) { glUniformMatrix2x4fv(params[index],count,transpose,m); }
void SetUniformMatrix3x2(int index, float const *m, int count=1, bool transpose=false) { glUniformMatrix3x2fv(params[index],count,transpose,m); }
void SetUniformMatrix3x4(int index, float const *m, int count=1, bool transpose=false) { glUniformMatrix3x4fv(params[index],count,transpose,m); }
void SetUniformMatrix4x2(int index, float const *m, int count=1, bool transpose=false) { glUniformMatrix4x2fv(params[index],count,transpose,m); }
void SetUniformMatrix4x3(int index, float const *m, int count=1, bool transpose=false) { glUniformMatrix4x3fv(params[index],count,transpose,m); }
#endif
#ifdef GL_VERSION_4_0
void SetUniformMatrix2 (int index, double const *m, int count=1, bool transpose=false) { glUniformMatrix2dv (params[index],count,transpose,m); }
void SetUniformMatrix3 (int index, double const *m, int count=1, bool transpose=false) { glUniformMatrix3dv (params[index],count,transpose,m); }
void SetUniformMatrix4 (int index, double const *m, int count=1, bool transpose=false) { glUniformMatrix4dv (params[index],count,transpose,m); }
void SetUniformMatrix2x3(int index, double const *m, int count=1, bool transpose=false) { glUniformMatrix2x3dv(params[index],count,transpose,m); }
void SetUniformMatrix2x4(int index, double const *m, int count=1, bool transpose=false) { glUniformMatrix2x4dv(params[index],count,transpose,m); }
void SetUniformMatrix3x2(int index, double const *m, int count=1, bool transpose=false) { glUniformMatrix3x2dv(params[index],count,transpose,m); }
void SetUniformMatrix3x4(int index, double const *m, int count=1, bool transpose=false) { glUniformMatrix3x4dv(params[index],count,transpose,m); }
void SetUniformMatrix4x2(int index, double const *m, int count=1, bool transpose=false) { glUniformMatrix4x2dv(params[index],count,transpose,m); }
void SetUniformMatrix4x3(int index, double const *m, int count=1, bool transpose=false) { glUniformMatrix4x3dv(params[index],count,transpose,m); }
#endif
#ifdef _CY_VECTOR_H_INCLUDED_
void SetUniform(int index, Vec2<float> const &p) { glUniform2fv (params[index],1, &p.x ); }
void SetUniform(int index, Vec3<float> const &p) { glUniform3fv (params[index],1, &p.x ); }
void SetUniform(int index, Vec4<float> const &p) { glUniform4fv (params[index],1, &p.x ); }
void SetUniform(int index, Vec2<int> const &p) { glUniform2iv (params[index],1, &p.x ); }
void SetUniform(int index, Vec3<int> const &p) { glUniform3iv (params[index],1, &p.x ); }
void SetUniform(int index, Vec4<int> const &p) { glUniform4iv (params[index],1, &p.x ); }
void SetUniform(int index, Vec2<float> const *p, int count=1) { glUniform2fv (params[index],count,&p->x); }
void SetUniform(int index, Vec3<float> const *p, int count=1) { glUniform3fv (params[index],count,&p->x); }
void SetUniform(int index, Vec4<float> const *p, int count=1) { glUniform4fv (params[index],count,&p->x); }
void SetUniform(int index, Vec2<int> const *p, int count=1) { glUniform2iv (params[index],count,&p->x); }
void SetUniform(int index, Vec3<int> const *p, int count=1) { glUniform3iv (params[index],count,&p->x); }
void SetUniform(int index, Vec4<int> const *p, int count=1) { glUniform4iv (params[index],count,&p->x); }
# ifdef GL_VERSION_3_0
void SetUniform(int index, Vec2<GLuint> const &p) { glUniform2uiv(params[index],1, &p.x ); }
void SetUniform(int index, Vec3<GLuint> const &p) { glUniform3uiv(params[index],1, &p.x ); }
void SetUniform(int index, Vec4<GLuint> const &p) { glUniform4uiv(params[index],1, &p.x ); }
void SetUniform(int index, Vec2<GLuint> const *p, int count=1) { glUniform2uiv(params[index],count,&p->x); }
void SetUniform(int index, Vec3<GLuint> const *p, int count=1) { glUniform3uiv(params[index],count,&p->x); }
void SetUniform(int index, Vec4<GLuint> const *p, int count=1) { glUniform4uiv(params[index],count,&p->x); }
# endif
# ifdef GL_VERSION_4_0
void SetUniform(int index, Vec2<double> const &p) { glUniform2dv (params[index],1, &p.x ); }
void SetUniform(int index, Vec3<double> const &p) { glUniform3dv (params[index],1, &p.x ); }
void SetUniform(int index, Vec4<double> const &p) { glUniform4dv (params[index],1, &p.x ); }
void SetUniform(int index, Vec2<double> const *p, int count=1) { glUniform2dv (params[index],count,&p->x); }
void SetUniform(int index, Vec3<double> const *p, int count=1) { glUniform3dv (params[index],count,&p->x); }
void SetUniform(int index, Vec4<double> const *p, int count=1) { glUniform4dv (params[index],count,&p->x); }
# endif
#endif
#ifdef _CY_IVECTOR_H_INCLUDED_
void SetUniform(int index, IVec2<int> const &p) { glUniform2iv (params[index],1, &p.x ); }
void SetUniform(int index, IVec3<int> const &p) { glUniform3iv (params[index],1, &p.x ); }
void SetUniform(int index, IVec4<int> const &p) { glUniform4iv (params[index],1, &p.x ); }
void SetUniform(int index, IVec2<int> const *p, int count=1) { glUniform2iv (params[index],count,&p->x); }
void SetUniform(int index, IVec3<int> const *p, int count=1) { glUniform3iv (params[index],count,&p->x); }
void SetUniform(int index, IVec4<int> const *p, int count=1) { glUniform4iv (params[index],count,&p->x); }
# ifdef GL_VERSION_3_0
void SetUniform(int index, IVec2<GLuint> const &p) { glUniform2uiv(params[index],1, &p.x ); }
void SetUniform(int index, IVec3<GLuint> const &p) { glUniform3uiv(params[index],1, &p.x ); }
void SetUniform(int index, IVec4<GLuint> const &p) { glUniform4uiv(params[index],1, &p.x ); }
void SetUniform(int index, IVec2<GLuint> const *p, int count=1) { glUniform2uiv(params[index],count,&p->x); }
void SetUniform(int index, IVec3<GLuint> const *p, int count=1) { glUniform3uiv(params[index],count,&p->x); }
void SetUniform(int index, IVec4<GLuint> const *p, int count=1) { glUniform4uiv(params[index],count,&p->x); }
# endif
#endif
#ifdef _CY_MATRIX_H_INCLUDED_
void SetUniform(int index, Matrix2 <float> const &m) { glUniformMatrix2fv (params[index],1, GL_FALSE,m.cell ); }
void SetUniform(int index, Matrix3 <float> const &m) { glUniformMatrix3fv (params[index],1, GL_FALSE,m.cell ); }
void SetUniform(int index, Matrix4 <float> const &m) { glUniformMatrix4fv (params[index],1, GL_FALSE,m.cell ); }
void SetUniform(int index, Matrix2 <float> const *m, int count=1) { glUniformMatrix2fv (params[index],count,GL_FALSE,m->cell); }
void SetUniform(int index, Matrix3 <float> const *m, int count=1) { glUniformMatrix3fv (params[index],count,GL_FALSE,m->cell); }
void SetUniform(int index, Matrix4 <float> const *m, int count=1) { glUniformMatrix4fv (params[index],count,GL_FALSE,m->cell); }
# ifdef GL_VERSION_2_1
void SetUniform(int index, Matrix34<float> const &m) { glUniformMatrix3x4fv(params[index],1, GL_FALSE,m.cell ); }