1 module gbaid.render.gl;
2 
3 import std.regex : ctRegex, matchAll;
4 import std.file : readText;
5 import std..string : splitLines, toUpper;
6 import std.conv : to;
7 
8 import derelict.opengl3.gl3 : glGetError;
9 
10 /**
11  * Represents an object that has an OpenGL version associated to it.
12  */
13 public interface GLVersioned {
14     /**
15      * Returns the lowest OpenGL version required by this object's implementation.
16      *
17      * @return The lowest required OpenGL version
18      */
19     public GLVersion getGLVersion();
20 }
21 
22 public enum : GLVersion {
23     GL11 = new GLVersion(1, 1, false, 0, 0),
24     GL12 = new GLVersion(1, 2, false, 0, 0),
25     GL13 = new GLVersion(1, 3, false, 0, 0),
26     GL14 = new GLVersion(1, 4, false, 0, 0),
27     GL15 = new GLVersion(1, 5, false, 0, 0),
28     GL20 = new GLVersion(2, 0, false, 1, 1),
29     GL21 = new GLVersion(2, 1, false, 1, 2),
30     GL30 = new GLVersion(3, 0, false, 1, 3),
31     GL31 = new GLVersion(3, 1, false, 1, 4),
32     GL32 = new GLVersion(3, 2, false, 1, 5),
33     GL33 = new GLVersion(3, 3, false, 3, 3),
34     GL40 = new GLVersion(4, 0, false, 4, 0),
35     GL41 = new GLVersion(4, 1, false, 4, 1),
36     GL42 = new GLVersion(4, 2, false, 4, 2),
37     GL43 = new GLVersion(4, 3, false, 4, 3),
38     GL44 = new GLVersion(4, 4, false, 4, 4),
39     GLES10 = new GLVersion(1, 0, true, 1, 0),
40     GLES11 = new GLVersion(1, 1, true, 1, 0),
41     GLES20 = new GLVersion(2, 0, true, 1, 0),
42     GLES30 = new GLVersion(3, 0, true, 3, 0),
43     GLES31 = new GLVersion(3, 1, true, 3, 0),
44     SOFTWARE = new GLVersion(0, 0, false, 0, 0),
45     OTHER = new GLVersion(0, 0, false, 0, 0)
46 }
47 
48 /**
49  * An enum of the existing OpenGL versions. Use this class to generate rendering objects compatible with the version.
50  */
51 public final class GLVersion {
52     private immutable uint major;
53     private immutable uint minor;
54     private immutable bool es;
55     private immutable uint glslMajor;
56     private immutable uint glslMinor;
57 
58     private this(uint major, uint minor, bool es, uint glslMajor, uint glslMinor) {
59         this.major = major;
60         this.minor = minor;
61         this.es = es;
62         this.glslMajor = glslMajor;
63         this.glslMinor = glslMinor;
64     }
65 
66     /**
67      * Returns the full version number of the version.
68      *
69      * @return The full version number
70      */
71     public uint getFull() {
72         return major * 10 + minor;
73     }
74 
75     /**
76      * Returns the major version number of the version.
77      *
78      * @return The major version number
79      */
80     public uint getMajor() {
81         return major;
82     }
83 
84     /**
85      * Returns the minor version number of the version.
86      *
87      * @return The minor version number
88      */
89     public uint getMinor() {
90         return minor;
91     }
92 
93     /**
94      * Returns true if the version is ES compatible, false if not.
95      *
96      * @return Whether or not this is an ES compatible version
97      */
98     public bool isES() {
99         return es;
100     }
101 
102     /**
103      * Returns the full GLSL version available with the OpenGL version.
104      *
105      * @return The GLSL version
106      */
107     public uint getGLSLFull() {
108         return glslMajor * 100 + glslMinor * 10;
109     }
110 
111     /**
112      * Returns the GLSL major version available with the OpenGL version. This version number is 0 if GLSL isn't supported.
113      *
114      * @return The GLSL major version, or 0 for unsupported
115      */
116     public uint getGLSLMajor() {
117         return glslMajor;
118     }
119 
120     /**
121      * Returns the GLSL minor version available with the OpenGL version.
122      *
123      * @return The GLSL minor version
124      */
125     public uint getGLSLMinor() {
126         return glslMinor;
127     }
128 
129     /**
130      * Returns true if this version supports GLSL, false if not.
131      *
132      * @return Whether or not this version supports GLSL
133      */
134     public bool supportsGLSL() {
135         return glslMajor != 0;
136     }
137 }
138 
139 /**
140  * Represents a resource that can be created and destroyed.
141  */
142 public abstract class Creatable {
143     private bool created = false;
144 
145     /**
146      * Creates the resources. It can now be used.
147      */
148     public void create() {
149         created = true;
150     }
151 
152     /**
153      * Releases the resource. It can not longer be used.
154      */
155     public void destroy() {
156         created = false;
157     }
158 
159     /**
160      * Returns true if the resource was created and is ready for use, false if otherwise.
161      *
162      * @return Whether or not the resource has been created
163      */
164     public bool isCreated() {
165         return created;
166     }
167 
168     /**
169      * Throws an exception if the resource hasn't been created yet.
170      *
171      * @throws IllegalStateException if the resource hasn't been created
172      */
173     public void checkCreated() {
174         if (!isCreated()) {
175             throw new Exception("Resource has not been created yet");
176         }
177     }
178 
179     /**
180      * Throws an exception if the resource has been created already.
181      *
182      * @throws IllegalStateException if the resource has been created
183      */
184     public void checkNotCreated() {
185         if (isCreated()) {
186             throw new Exception("Resource has been created already");
187         }
188     }
189 }
190 
191 /**
192  * Represents an OpenGL context. Creating context must be done before any other OpenGL object.
193  */
194 public abstract class Context : Creatable, GLVersioned {
195     public override void destroy() {
196         super.destroy();
197     }
198 
199     /**
200      * Creates a new frame buffer.
201      *
202      * @return A new frame buffer
203      */
204     public abstract FrameBuffer newFrameBuffer();
205 
206     /**
207      * Creates a new program.
208      *
209      * @return A new program
210      */
211     public abstract Program newProgram();
212 
213     /**
214      * Creates a new render buffer.
215      *
216      * @return A new render buffer
217      */
218     public abstract RenderBuffer newRenderBuffer();
219 
220     /**
221      * Creates a new shader.
222      *
223      * @return A new shader
224      */
225     public abstract Shader newShader();
226 
227     /**
228      * Creates a new texture.
229      *
230      * @return A new texture
231      */
232     public abstract Texture newTexture();
233 
234     /**
235      * Creates a new vertex array.
236      *
237      * @return A new vertex array
238      */
239     public abstract VertexArray newVertexArray();
240 
241     /**
242      * Returns the window title.
243      *
244      * @return The window title
245      */
246     public abstract string getWindowTitle();
247 
248     /**
249      * Sets the window title to the desired one.
250      *
251      * @param title The window title
252      */
253     public abstract void setWindowTitle(string title);
254 
255     /**
256      * Sets the window size. Will be limited to the desktop size.
257      *
258      * @param width The width
259      * @param height The height
260      */
261     public abstract void setWindowSize(uint width, uint height);
262 
263     /**
264      * Sets the user resizability of this window. This doesn't do anything if
265      * the window is in full screen mode.
266      *
267      * @param resizable Whether or not the window is resizable
268      */
269     public abstract void setResizable(bool resizable);
270 
271     /**
272      * Enable or disable full screen mode. The window size will be changed
273      * to the desktop size when enabled, and back to the original size when
274      * disabled.
275      *
276      * @param full Whether or not the window is in full screen mode
277      */
278     public abstract void setFullScreen(bool fullscreen);
279 
280     /**
281      * Enable or disable VSYNC. If enabled, updating the display will cause the
282      * calling thread to hang until a new frame starts. In other words, it will lock
283      * the updating rate to the display refresh rate.
284      *
285      * @param enable Whether or not to use VSYNC
286      */
287     public abstract void enableVsync(bool enable);
288 
289     /**
290      * Gets the window size.
291      *
292      * @param width Where to store the width, may be null
293      * @param height Where to store the height, may be null
294      */
295     public abstract void getWindowSize(int* width, int *height);
296 
297     /**
298      * Gets the window size actually being used. This can be different from the one
299      * that was set when running in full screen mode, or if it was bigger than the
300      * display.
301      *
302      * @param width Where to store the width, may be null
303      * @param height Where to store the height, may be null
304      */
305     public abstract void getActualWindowSize(int* width, int* height);
306 
307     /**
308      * Returns the window width.
309      *
310      * @return The window width
311      */
312     public abstract uint getWindowWidth();
313 
314     /**
315      * Returns the window height.
316      *
317      * @return The window height
318      */
319     public abstract uint getWindowHeight();
320 
321     /**
322      * Updates the display with the current front (screen) buffer.
323      */
324     public abstract void updateDisplay();
325 
326     /**
327      * Sets the renderer buffer clear color. This can be interpreted as the background color.
328      *
329      * @param color The clear color
330      */
331     public abstract void setClearColor(float red, float green, float blue, float alpha);
332 
333     /**
334      * Clears the currently bound buffer (either a frame buffer, or the front (screen) buffer if none are bound).
335      */
336     public abstract void clearCurrentBuffer();
337 
338     /**
339      * Disables the capability.
340      *
341      * @param capability The capability to disable
342      */
343     public abstract void disableCapability(Capability capability);
344 
345     /**
346      * Enables the capability.
347      *
348      * @param capability The capability to enable
349      */
350     public abstract void enableCapability(Capability capability);
351 
352     /**
353      * Enables or disables writing into the depth buffer.
354      *
355      * @param enabled Whether or not to write into the depth buffer.
356      */
357     public abstract void setDepthMask(bool enabled);
358 
359     /**
360      * Sets the blending functions for the source and destination buffers, for all buffers. Blending must be enabled with {@link #enableCapability(org.spout.renderer.api.gl.Context.Capability)}.
361      *
362      * @param source The source function
363      * @param destination The destination function
364      */
365     public void setBlendingFunctions(BlendFunction source, BlendFunction destination) {
366         setBlendingFunctions(-1, source, destination);
367     }
368 
369     /**
370      * Sets the blending functions for the source and destination buffer at the index. Blending must be enabled with {@link #enableCapability(org.spout.renderer.api.gl.Context.Capability)}.
371      * <p/>
372      * Support for specifying the buffer index is only available in GL40.
373      *
374      * @param bufferIndex The index of the target buffer
375      * @param source The source function
376      * @param destination The destination function
377      */
378     public abstract void setBlendingFunctions(int bufferIndex, BlendFunction source, BlendFunction destination);
379 
380     /**
381      * Sets the render view port, which is the dimensions and position of the frame inside the window.
382      *
383      * @param x The x coordinate
384      * @param y The y coordinate
385      * @param width The width
386      * @param height The height
387      */
388     public abstract void setViewPort(uint x, uint y, uint width, uint height);
389 
390     /**
391      * Reads the current frame pixels and returns it as a byte buffer of the desired format. The size of the returned image data is the same as the current window dimensions.
392      *
393      * @param x The x coordinate
394      * @param y The y coordinate
395      * @param width The width
396      * @param height The height
397      * @param format The image format to return
398      * @return The byte array containing the pixel data, according to the provided format
399      */
400     public abstract ubyte[] readFrame(uint x, uint y, uint width, uint height, InternalFormat format);
401 
402     /**
403      * Returns true if an external process (such as the user) is requesting for the window to be closed. This value is reset once this method has been called.
404      *
405      * @return Whether or not the window is being requested to close
406      */
407     public abstract bool isWindowCloseRequested();
408 }
409 
410 public enum : Capability {
411     BLEND = new Capability(0xBE2), // GL11.GL_BLEND
412     CULL_FACE = new Capability(0xB44), // GL11.GL_CULL_FACE
413     DEPTH_CLAMP = new Capability(0x864F), // GL32.GL_DEPTH_CLAMP
414     DEPTH_TEST = new Capability(0xB71) // GL11.GL_DEPTH_TEST
415 }
416 
417 /**
418  * An enum of the renderer capabilities.
419  */
420 public final class Capability {
421     private immutable uint glConstant;
422 
423     private this(uint glConstant) {
424         this.glConstant = glConstant;
425     }
426 
427     /**
428      * Returns the OpenGL constant associated to the capability.
429      *
430      * @return The OpenGL constant
431      */
432     public uint getGLConstant() {
433         return glConstant;
434     }
435 }
436 
437 public enum : BlendFunction {
438     GL_ZERO = new BlendFunction(0x0), // GL11.GL_ZERO
439     GL_ONE = new BlendFunction(0x1), // GL11.GL_ONE
440     GL_SRC_COLOR = new BlendFunction(0x300), // GL11.GL_SRC_COLOR
441     GL_ONE_MINUS_SRC_COLOR = new BlendFunction(0x301), // GL11.GL_ONE_MINUS_SRC_COLOR
442     GL_DST_COLOR = new BlendFunction(0x306), // GL11.GL_DST_COLOR
443     GL_ONE_MINUS_DST_COLOR = new BlendFunction(0x307), // GL11.GL_ONE_MINUS_DST_COLOR
444     GL_SRC_ALPHA = new BlendFunction(0x302), // GL11.GL_SRC_ALPHA
445     GL_ONE_MINUS_SRC_ALPHA = new BlendFunction(0x303), // GL11.GL_ONE_MINUS_SRC_ALPHA
446     GL_DST_ALPHA = new BlendFunction(0x304), // GL11.GL_DST_ALPHA
447     GL_ONE_MINUS_DST_ALPHA = new BlendFunction(0x305), // GL11.GL_ONE_MINUS_DST_ALPHA
448     GL_CONSTANT_COLOR = new BlendFunction(0x8001), // GL11.GL_CONSTANT_COLOR
449     GL_ONE_MINUS_CONSTANT_COLOR = new BlendFunction(0x8002), // GL11.GL_ONE_MINUS_CONSTANT_COLOR
450     GL_CONSTANT_ALPHA = new BlendFunction(0x8003), // GL11.GL_CONSTANT_ALPHA
451     GL_ONE_MINUS_CONSTANT_ALPHA = new BlendFunction(0x8004), // GL11.GL_ONE_MINUS_CONSTANT_ALPHA
452     GL_SRC_ALPHA_SATURATE = new BlendFunction(0x308), // GL11.GL_SRC_ALPHA_SATURATE
453     GL_SRC1_COLOR = new BlendFunction(0x88F9), // GL33.GL_SRC1_COLOR
454     GL_ONE_MINUS_SRC1_COLOR = new BlendFunction(0x88FA), // GL33.GL_ONE_MINUS_SRC1_COLOR
455     GL_SRC1_ALPHA = new BlendFunction(0x8589), // GL33.GL_SRC1_ALPHA
456     GL_ONE_MINUS_SRC1_ALPHA = new BlendFunction(0x88FB) // GL33.GL_ONE_MINUS_SRC1_ALPHA
457 }
458 
459 /**
460  * An enum of the blending functions.
461  */
462 public final class BlendFunction {
463     private immutable uint glConstant;
464 
465     private this(uint glConstant) {
466         this.glConstant = glConstant;
467     }
468 
469     /**
470      * Returns the OpenGL constant associated to the blending function.
471      *
472      * @return The OpenGL constant
473      */
474     public uint getGLConstant() {
475         return glConstant;
476     }
477 }
478 
479 /**
480  * Represents an OpenGL frame buffer. A frame buffer can be bound before rendering to redirect the output to textures instead of the screen. This is meant for advanced rendering techniques such as
481  * shadow mapping and screen space ambient occlusion (SSAO).
482  */
483 public abstract class FrameBuffer : Creatable, GLVersioned {
484     protected uint id;
485 
486     public override void destroy() {
487         id = 0;
488         super.destroy();
489     }
490 
491     /**
492      * Binds the frame buffer to the OpenGL context.
493      */
494     public abstract void bind();
495 
496     /**
497      * Unbinds the frame buffer from the OpenGL context.
498      */
499     public abstract void unbind();
500 
501     /**
502      * Attaches the texture to the frame buffer attachment point.
503      *
504      * @param point The attachment point
505      * @param texture The texture to attach
506      */
507     public abstract void attach(AttachmentPoint point, Texture texture);
508 
509     /**
510      * Attaches the render buffer to the attachment point
511      *
512      * @param point The attachment point
513      * @param buffer The render buffer
514      */
515     public abstract void attach(AttachmentPoint point, RenderBuffer buffer);
516 
517     /**
518      * Detaches the texture or render buffer from the attachment point
519      *
520      * @param point The attachment point
521      */
522     public abstract void detach(AttachmentPoint point);
523 
524     /**
525      * Returns true if the frame buffer is complete, false if otherwise.
526      *
527      * @return Whether or not the frame buffer is complete
528      */
529     public abstract bool isComplete();
530 
531     /**
532      * Gets the ID for this frame buffer as assigned by OpenGL.
533      *
534      * @return The ID
535      */
536     public uint getId() {
537         return id;
538     }
539 }
540 
541 public enum : AttachmentPoint {
542     COLOR_ATTACHMENT0 = new AttachmentPoint(0x8CE0, true), // GL30.GL_COLOR_ATTACHMENT0
543     COLOR_ATTACHMENT1 = new AttachmentPoint(0x8CE1, true), // GL30.GL_COLOR_ATTACHMENT1
544     COLOR_ATTACHMENT2 = new AttachmentPoint(0x8CE2, true), // GL30.GL_COLOR_ATTACHMENT2
545     COLOR_ATTACHMENT3 = new AttachmentPoint(0x8CE3, true), // GL30.GL_COLOR_ATTACHMENT3
546     COLOR_ATTACHMENT4 = new AttachmentPoint(0x8CE4, true), // GL30.GL_COLOR_ATTACHMENT4
547     DEPTH_ATTACHMENT = new AttachmentPoint(0x8D00, false), // GL30.GL_DEPTH_ATTACHMENT
548     STENCIL_ATTACHMENT = new AttachmentPoint(0x8D20, false), // GL30.GL_STENCIL_ATTACHMENT
549     DEPTH_STENCIL_ATTACHMENT = new AttachmentPoint(0x821A, false) // GL30.GL_DEPTH_STENCIL_ATTACHMENT
550 }
551 
552 /**
553  * An enum of the possible frame buffer attachment points.
554  */
555 public final class AttachmentPoint {
556     private immutable uint glConstant;
557     private immutable bool color;
558 
559     private this(uint glConstant, bool color) {
560         this.glConstant = glConstant;
561         this.color = color;
562     }
563 
564     /**
565      * Gets the OpenGL constant for this attachment point.
566      *
567      * @return The OpenGL Constant
568      */
569     public uint getGLConstant() {
570         return glConstant;
571     }
572 
573     /**
574      * Returns true if the attachment point is a color attachment.
575      *
576      * @return Whether or not the attachment is a color attachment
577      */
578     public bool isColor() {
579         return color;
580     }
581 }
582 
583 /**
584  * Represents an OpenGL program. A program holds the necessary shaders for the rendering pipeline. When using GL20, it is strongly recommended to set the attribute layout in the {@link
585  * org.spout.renderer.api.gl.Shader}s with {@link org.spout.renderer.api.gl.Shader#setAttributeLayout(String, int)}}, which must be done before attaching it. The layout allows for association between
586  * the attribute index in the vertex data and the name in the shaders. For GL30, it is recommended to do so in the shaders instead, using the "layout" keyword. Failing to do so might result in
587  * partial, wrong or missing rendering, and affects models using multiple attributes. The texture layout should also be setup using {@link Shader#setTextureLayout(int, String)} in the same way.
588  */
589 public abstract class Program : Creatable, GLVersioned {
590     protected uint id;
591 
592     public override void destroy() {
593         id = 0;
594         super.destroy();
595     }
596 
597     /**
598      * Attaches a shader to the program.
599      *
600      * @param shader The shader to attach
601      */
602     public abstract void attachShader(Shader shader);
603 
604     /**
605      * Detaches a shader from the shader.
606      *
607      * @param shader The shader to detach
608      */
609     public abstract void detachShader(Shader shader);
610 
611     /**
612      * Links the shaders together in the program. This makes it usable.
613      */
614     public abstract void link();
615 
616     /**
617      * Binds this program to the OpenGL context.
618      */
619     public abstract void use();
620 
621     /**
622      * Binds the sampler to the texture unit. The binding is done according to the texture layout, which must be set in the program for the textures that will be used before any binding can be done.
623      *
624      * @param unit The unit to bind
625      */
626     public abstract void bindSampler(uint unit);
627 
628     /**
629      * Sets a uniform boolean in the shader to the desired value.
630      *
631      * @param name The name of the uniform to set
632      * @param b The boolean value
633      */
634     public abstract void setUniform(string name, bool b);
635 
636     /**
637      * Sets a uniform integer in the shader to the desired value.
638      *
639      * @param name The name of the uniform to set
640      * @param i The integer value
641      */
642     public abstract void setUniform(string name, int i);
643 
644     /**
645      * Sets a uniform float in the shader to the desired value.
646      *
647      * @param name The name of the uniform to set
648      * @param f The float value
649      */
650     public abstract void setUniform(string name, float f);
651 
652     /**
653      * Sets a uniform float array in the shader to the desired value.
654      *
655      * @param name The name of the uniform to set
656      * @param fs The float array value
657      */
658     public abstract void setUniform(string name, float[] fs);
659 
660     /**
661      * Sets a uniform {@link com.flowpowered.math.vector.Vector2f} in the shader to the desired value.
662      *
663      * @param name The name of the uniform to set
664      * @param v The vector value
665      */
666     public abstract void setUniform(string name, float x, float y);
667 
668     /**
669      * Sets a uniform {@link com.flowpowered.math.vector.Vector3f} in the shader to the desired value.
670      *
671      * @param name The name of the uniform to set
672      * @param v The vector value
673      */
674     public abstract void setUniform(string name, float x, float y, float z);
675 
676     /**
677      * Sets a uniform {@link com.flowpowered.math.vector.Vector4f} in the shader to the desired value.
678      *
679      * @param name The name of the uniform to set
680      * @param v The vector value
681      */
682     public abstract void setUniform(string name, float x, float y, float z, float w);
683 
684     /**
685      * Sets a uniform {@link com.flowpowered.math.matrix.Matrix4f} in the shader to the desired value.
686      *
687      * @param name The name of the uniform to set
688      * @param m The matrix value
689      */
690     public abstract void setUniform(string name, ref float[4] m);
691 
692     /**
693      * Sets a uniform {@link com.flowpowered.math.matrix.Matrix4f} in the shader to the desired value.
694      *
695      * @param name The name of the uniform to set
696      * @param m The matrix value
697      */
698     public abstract void setUniform(string name, ref float[9] m);
699 
700     /**
701      * Sets a uniform {@link com.flowpowered.math.matrix.Matrix4f} in the shader to the desired value.
702      *
703      * @param name The name of the uniform to set
704      * @param m The matrix value
705      */
706     public abstract void setUniform(string name, ref float[16] m);
707 
708     /**
709      * Returns the shaders that have been attached to this program.
710      *
711      * @return The attached shaders
712      */
713     public abstract Shader[] getShaders();
714 
715     /**
716      * Returns an set containing all of the uniform names for this program.
717      *
718      * @return A set of all the uniform names
719      */
720     public abstract string[] getUniformNames();
721 
722     /**
723      * Gets the ID for this program as assigned by OpenGL.
724      *
725      * @return The ID
726      */
727     public uint getID() {
728         return id;
729     }
730 }
731 
732 /**
733  * Represents an OpenGL render buffer. A render buffer can be used as a faster alternative to a texture in a frame buffer when its rendering output doesn't need to be read. The storage format, width
734  * and height dimensions need to be set with {@link #setStorage(org.spout.renderer.api.gl.Texture.InternalFormat, int, int)}, before the render buffer can be used.
735  */
736 public abstract class RenderBuffer : Creatable, GLVersioned {
737     protected uint id;
738 
739     public override void destroy() {
740         id = 0;
741         super.destroy();
742     }
743 
744     /**
745      * Sets the render buffer storage.
746      *
747      * @param format The format
748      * @param width The width
749      * @param height The height
750      */
751     public abstract void setStorage(InternalFormat format, uint width, uint height);
752 
753     /**
754      * Returns the render buffer format.
755      *
756      * @return The format
757      */
758     public abstract InternalFormat getFormat();
759 
760     /**
761      * Returns the render buffer width.
762      *
763      * @return The width
764      */
765     public abstract uint getWidth();
766 
767     /**
768      * Returns the render buffer height.
769      *
770      * @return The height
771      */
772     public abstract uint getHeight();
773 
774     /**
775      * Binds the render buffer to the OpenGL context.
776      */
777     public abstract void bind();
778 
779     /**
780      * Unbinds the render buffer from the OpenGL context.
781      */
782     public abstract void unbind();
783 
784     /**
785      * Gets the ID for this render buffer as assigned by OpenGL.
786      *
787      * @return The ID
788      */
789     public uint getID() {
790         return id;
791     }
792 }
793 
794 /**
795  * Represents an OpenGL shader. The shader source and type must be set with {@link #setSource(ShaderSource)}.
796  */
797 public abstract class Shader : Creatable, GLVersioned {
798     protected uint id;
799 
800     public override void destroy() {
801         id = 0;
802         // Update the state
803         super.destroy();
804     }
805 
806     /**
807      * Sets the shader source.
808      *
809      * @param source The shader source
810      */
811     public abstract void setSource(ShaderSource source);
812 
813     /**
814      * Compiles the shader.
815      */
816     public abstract void compile();
817 
818     /**
819      * Gets the shader type.
820      *
821      * @return The shader type
822      */
823     public abstract ShaderType getType();
824 
825     /**
826      * Returns the attribute layouts parsed from the tokens in the shader source.
827      *
828      * @return A map of the attribute name to the layout index.
829      */
830     public abstract uint[string] getAttributeLayouts();
831 
832     /**
833      * Returns the texture layouts parsed from the tokens in the shader source.
834      *
835      * @return A map of the texture name to the layout index.
836      */
837     public abstract string[uint] getTextureLayouts();
838 
839     /**
840      * Sets an attribute layout.
841      *
842      * @param attribute The name of the attribute
843      * @param layout The layout for the attribute
844      */
845     public abstract void setAttributeLayout(string attribute, uint layout);
846 
847     /**
848      * Sets a texture layout.
849      *
850      * @param unit The unit for the sampler
851      * @param sampler The sampler name
852      */
853     public abstract void setTextureLayout(uint unit, string sampler);
854 
855     /**
856      * Gets the ID for this shader as assigned by OpenGL.
857      *
858      * @return The ID
859      */
860     public uint getID() {
861         return id;
862     }
863 }
864 
865 public enum : ShaderType {
866     FRAGMENT = new ShaderType(0x8B30), // GL20.GL_FRAGMENT_SHADER
867     VERTEX = new ShaderType(0x8B31), // GL20.GL_VERTEX_SHADER
868     GEOMETRY = new ShaderType(0x8DD9), // GL32.GL_GEOMETRY_SHADER
869     TESS_EVALUATION = new ShaderType(0x8E87), // GL40.GL_TESS_EVALUATION_SHADER
870     TESS_CONTROL = new ShaderType(0x8E88), // GL40.GL_TESS_CONTROL_SHADER
871     COMPUTE = new ShaderType(0x91B9) // GL43.GL_COMPUTE_SHADER
872 }
873 
874 /**
875  * Represents a shader type.
876  */
877 public final class ShaderType {
878     private static ShaderType[string] NAME_TO_ENUM_MAP;
879     private immutable uint glConstant;
880 
881     static this() {
882         NAME_TO_ENUM_MAP["FRAGMENT"] = FRAGMENT;
883         NAME_TO_ENUM_MAP["VERTEX"] = VERTEX;
884         NAME_TO_ENUM_MAP["GEOMETRY"] = GEOMETRY;
885         NAME_TO_ENUM_MAP["TESS_EVALUATION"] = TESS_EVALUATION;
886         NAME_TO_ENUM_MAP["TESS_CONTROL"] = TESS_CONTROL;
887         NAME_TO_ENUM_MAP["COMPUTE"] = COMPUTE;
888     }
889 
890     private this(uint glConstant) {
891         this.glConstant = glConstant;
892     }
893 
894     /**
895      * Returns the OpenGL constant associated to the shader type.
896      *
897      * @return The OpenGL constant
898      */
899     public uint getGLConstant() {
900         return glConstant;
901     }
902 
903     public static ShaderType valueOf(string name) {
904         return NAME_TO_ENUM_MAP.get(name, null);
905     }
906 }
907 
908 /**
909  * Represents the source of a shader. This class can be used to load a source from an input stream, and provides pre-compilation functionality such as parsing shader type, attribute layout and texture
910  * layout tokens. These tokens can be used to declare various parameters directly in the shader code instead of in the software code, which simplifies loading.
911  */
912 public class ShaderSource {
913     private static immutable string TOKEN_SYMBOL = "$";
914     private static immutable string SHADER_TYPE_TOKEN = "shader_type";
915     private static auto SHADER_TYPE_TOKEN_PATTERN = ctRegex!("\\" ~ TOKEN_SYMBOL ~ SHADER_TYPE_TOKEN ~ " *: *(\\w+)", "g");
916     private static immutable string ATTRIBUTE_LAYOUT_TOKEN = "attrib_layout";
917     private static immutable string TEXTURE_LAYOUT_TOKEN = "texture_layout";
918     private static auto LAYOUT_TOKEN_PATTERN = ctRegex!("\\" ~ TOKEN_SYMBOL ~ "(" ~ ATTRIBUTE_LAYOUT_TOKEN ~ "|" ~ TEXTURE_LAYOUT_TOKEN ~ ") *: *(\\w+) *= *(\\d+)", "g");
919     private string source;
920     private ShaderType type;
921     private uint[string] attributeLayouts;
922     private string[uint] textureLayouts;
923 
924     /**
925      * Constructs a new shader source from the input stream.
926      *
927      * @param source The source input stream
928      */
929     public this(string source, bool directSource) {
930         if (source is null) {
931             throw new Exception("Source cannot be null");
932         }
933         if (directSource) {
934             this.source = source;
935         } else {
936             this.source = readText(source);
937         }
938         parse();
939     }
940 
941     private void parse() {
942         // Look for layout tokens
943         // Used for setting the shader type automatically.
944         // Also replaces the GL30 "layout(location = x)" and GL42 "layout(binding = x) features missing from GL20 and/or GL30
945         string[] lines = splitLines(source);
946         foreach (string line; lines) {
947             foreach (match; matchAll(line, SHADER_TYPE_TOKEN_PATTERN)) {
948                 try {
949                     type = cast(ShaderType) ShaderType.valueOf(match.captures[1].toUpper());
950                 } catch (Exception ex) {
951                     throw new Exception("Unknown shader type token value", ex);
952                 }
953             }
954             foreach (match; matchAll(line, LAYOUT_TOKEN_PATTERN)) {
955                 string token = match.captures[1];
956                 final switch (token) {
957                     case "attrib_layout":
958                         attributeLayouts[match.captures[2]] = to!uint(match.captures[3]);
959                         break;
960                     case "texture_layout":
961                         textureLayouts[to!uint(match.captures[3])] = match.captures[2];
962                         break;
963                 }
964             }
965         }
966     }
967 
968     /**
969      * Returns true if the shader source is complete and ready to be used in a {@link org.spout.renderer.api.gl.Shader} object, false if otherwise. If this method returns false, than information such
970      * as the type is missing.
971      *
972      * @return Whether or not the shader source is complete
973      */
974     public bool isComplete() {
975         return type !is null;
976     }
977 
978     /**
979      * Returns the raw character sequence source of this shader source.
980      *
981      * @return The raw source
982      */
983     public string getSource() {
984         return source;
985     }
986 
987     /**
988      * Returns the type of this shader. If the type was declared in the source using a shader type token, it will have been loaded from it. Else this returns null and it must be set manually using
989      * {@link #setType(org.spout.renderer.api.gl.Shader.ShaderType)}.
990      *
991      * @return The shader type, or null if not set
992      */
993     public ShaderType getType() {
994         return cast(ShaderType) type;
995     }
996 
997     /**
998      * Sets the shader type. It's not necessary to do this manually if it was declared in the source using a shader type token.
999      *
1000      * @param type The shader type
1001      */
1002     public void setType(ShaderType type) {
1003         this.type = cast(ShaderType) type;
1004     }
1005 
1006     /**
1007      * Returns the attribute layouts, either parsed from the source or set manually using {@link #setAttributeLayout(String, int)}.
1008      *
1009      * @return The attribute layouts
1010      */
1011     public uint[string] getAttributeLayouts() {
1012         return attributeLayouts.dup;
1013     }
1014 
1015     /**
1016      * Returns the texture layouts, either parsed from the source or set manually using {@link #setTextureLayout(int, String)}.
1017      *
1018      * @return The texture layouts
1019      */
1020     public string[uint] getTextureLayouts() {
1021         return textureLayouts.dup;
1022     }
1023 
1024     /**
1025      * Sets an attribute layout.
1026      *
1027      * @param attribute The name of the attribute
1028      * @param layout The layout for the attribute
1029      */
1030     public void setAttributeLayout(string attribute, uint layout) {
1031         attributeLayouts[attribute] = layout;
1032     }
1033 
1034     /**
1035      * Sets a texture layout.
1036      *
1037      * @param unit The unit for the sampler
1038      * @param sampler The sampler name
1039      */
1040     public void setTextureLayout(uint unit, string sampler) {
1041         textureLayouts[unit] = sampler;
1042     }
1043 }
1044 
1045 /**
1046  * Represents a texture for OpenGL. Image data and various parameters can be set after creation. Image data should be set last.
1047  */
1048 public abstract class Texture : Creatable, GLVersioned {
1049     protected uint id = 0;
1050 
1051     public override void destroy() {
1052         id = 0;
1053         super.destroy();
1054     }
1055 
1056     /**
1057      * Binds the texture to the OpenGL context.
1058      *
1059      * @param unit The unit to bind the texture to, or -1 to just bind the texture
1060      */
1061     public abstract void bind(int unit);
1062 
1063     /**
1064      * Unbinds the texture from the OpenGL context.
1065      */
1066     public abstract void unbind();
1067 
1068     /**
1069      * Gets the ID for this texture as assigned by OpenGL.
1070      *
1071      * @return The ID
1072      */
1073     public uint getID() {
1074         return id;
1075     }
1076 
1077     /**
1078      * Sets the texture's format.
1079      *
1080      * @param format The format
1081      */
1082     public void setFormat(Format format) {
1083         setFormat(format, null);
1084     }
1085 
1086     /**
1087      * Sets the texture's format.
1088      *
1089      * @param format The format
1090      */
1091     public void setFormat(InternalFormat format) {
1092         setFormat(format.getFormat(), format);
1093     }
1094 
1095     /**
1096      * Sets the texture's format and internal format.
1097      *
1098      * @param format The format
1099      * @param internalFormat The internal format
1100      */
1101     public abstract void setFormat(Format format, InternalFormat internalFormat);
1102 
1103     /**
1104      * Returns the texture's format
1105      *
1106      * @return the format
1107      */
1108     public abstract Format getFormat();
1109 
1110     /**
1111      * Returns the texture's internal format.
1112      *
1113      * @return The internal format
1114      */
1115     public abstract InternalFormat getInternalFormat();
1116 
1117     /**
1118      * Sets the value for anisotropic filtering. Must be greater than zero. Note that this is EXT based and might not be supported on all hardware.
1119      *
1120      * @param value The anisotropic filtering value
1121      */
1122     public abstract void setAnisotropicFiltering(float value);
1123 
1124     /**
1125      * Sets the horizontal and vertical texture wraps.
1126      *
1127      * @param horizontalWrap The horizontal wrap
1128      * @param verticalWrap The vertical wrap
1129      */
1130     public abstract void setWraps(WrapMode horizontalWrap, WrapMode verticalWrap);
1131 
1132     /**
1133      * Sets the texture's min and mag filters. The mag filter cannot require mipmap generation.
1134      *
1135      * @param minFilter The min filter
1136      * @param magFilter The mag filter
1137      */
1138     public abstract void setFilters(FilterMode minFilter, FilterMode magFilter);
1139 
1140     /**
1141      * Sets the compare mode.
1142      *
1143      * @param compareMode The compare mode
1144      */
1145     public abstract void setCompareMode(CompareMode compareMode);
1146 
1147     /**
1148      * Sets the border color.
1149      *
1150      * @param borderColor The border color
1151      */
1152     public abstract void setBorderColor(float red, float green, float blue, float alpha);
1153 
1154     /**
1155      * Sets the texture's image data.
1156      *
1157      * @param imageData The image data
1158      * @param width The width of the image
1159      * @param height the height of the image
1160      */
1161     public abstract void setImageData(ubyte[] imageData, uint width, uint height);
1162 
1163     /**
1164      * Returns the image data in the internal format.
1165      *
1166      * @return The image data in the internal format.
1167      */
1168     public ubyte[] getImageData() {
1169         return getImageData(getInternalFormat());
1170     }
1171 
1172     /**
1173      * Returns the image data in the desired format.
1174      *
1175      * @param format The format to return the data in
1176      * @return The image data in the desired format
1177      */
1178     public abstract ubyte[] getImageData(InternalFormat format);
1179 
1180     /**
1181      * Returns the width of the image.
1182      *
1183      * @return The image width
1184      */
1185     public abstract uint getWidth();
1186 
1187     /**
1188      * Returns the height of the image.
1189      *
1190      * @return The image height
1191      */
1192     public abstract uint getHeight();
1193 }
1194 
1195 public enum : Format {
1196     RED = new Format(0x1903, 1, true, false, false, false, false, false), // GL11.GL_RED
1197     RGB = new Format(0x1907, 3, true, true, true, false, false, false), // GL11.GL_RGB
1198     RGBA = new Format(0x1908, 4, true, true, true, true, false, false), // GL11.GL_RGBA
1199     DEPTH = new Format(0x1902, 1, false, false, false, false, true, false), // GL11.GL_DEPTH_COMPONENT
1200     RG = new Format(0x8227, 2, true, true, false, false, false, false), // GL30.GL_RG
1201     DEPTH_STENCIL = new Format(0x84F9, 1, false, false, false, false, false, true) // GL30.GL_DEPTH_STENCIL
1202 }
1203 
1204 /**
1205  * An enum of texture component formats.
1206  */
1207 public final class Format {
1208     private immutable uint glConstant;
1209     private immutable uint components;
1210     private immutable bool red;
1211     private immutable bool green;
1212     private immutable bool blue;
1213     private immutable bool alpha;
1214     private immutable bool depth;
1215     private immutable bool stencil;
1216 
1217     private this(uint glConstant, uint components, bool red, bool hasGreen, bool blue, bool alpha, bool depth, bool stencil) {
1218         this.glConstant = glConstant;
1219         this.components = components;
1220         this.red = red;
1221         this.green = green;
1222         this.blue = blue;
1223         this.alpha = alpha;
1224         this.depth = depth;
1225         this.stencil = stencil;
1226     }
1227 
1228     /**
1229      * Gets the OpenGL constant for this format.
1230      *
1231      * @return The OpenGL Constant
1232      */
1233     public uint getGLConstant() {
1234         return glConstant;
1235     }
1236 
1237     /**
1238      * Returns the number of components in the format.
1239      *
1240      * @return The number of components
1241      */
1242     public uint getComponentCount() {
1243         return components;
1244     }
1245 
1246     /**
1247      * Returns true if this format has a red component.
1248      *
1249      * @return True if a red component is present
1250      */
1251     public bool hasRed() {
1252         return hasRed;
1253     }
1254 
1255     /**
1256      * Returns true if this format has a green component.
1257      *
1258      * @return True if a green component is present
1259      */
1260     public bool hasGreen() {
1261         return hasGreen;
1262     }
1263 
1264     /**
1265      * Returns true if this format has a blue component.
1266      *
1267      * @return True if a blue component is present
1268      */
1269     public bool hasBlue() {
1270         return hasBlue;
1271     }
1272 
1273     /**
1274      * Returns true if this format has an alpha component.
1275      *
1276      * @return True if an alpha component is present
1277      */
1278     public bool hasAlpha() {
1279         return hasAlpha;
1280     }
1281 
1282     /**
1283      * Returns true if this format has a depth component.
1284      *
1285      * @return True if a depth component is present
1286      */
1287     public bool hasDepth() {
1288         return hasDepth;
1289     }
1290 
1291     /**
1292      * Returns true if this format has a stencil component.
1293      *
1294      * @return True if a stencil component is present
1295      */
1296     public bool hasStencil() {
1297         return hasStencil;
1298     }
1299 }
1300 
1301 public enum : InternalFormat {
1302     RGB8 = new InternalFormat(0x8051, RGB, BYTE), // GL11.GL_RGB8
1303     RGBA8 = new InternalFormat(0x8058, RGBA, BYTE), // GL11.GL_RGBA8
1304     RGB16 = new InternalFormat(32852, RGB, UNSIGNED_SHORT), // GL11.GL_RGB16
1305     RGBA16 = new InternalFormat(0x805B, RGBA, UNSIGNED_SHORT), // GL11.GL_RGBA16
1306     DEPTH_COMPONENT16 = new InternalFormat(0x81A5, DEPTH, UNSIGNED_SHORT), // GL14.GL_DEPTH_COMPONENT16
1307     DEPTH_COMPONENT24 = new InternalFormat(0x81A6, DEPTH, UNSIGNED_INT), // GL14.GL_DEPTH_COMPONENT24
1308     DEPTH_COMPONENT32 = new InternalFormat(0x81A7, DEPTH, UNSIGNED_INT), // GL14.GL_DEPTH_COMPONENT32
1309     R8 = new InternalFormat(0x8229, RED, UNSIGNED_BYTE), // GL30.GL_R8
1310     R16 = new InternalFormat(0x822A, RED, UNSIGNED_SHORT), // GL30.GL_R16
1311     RG8 = new InternalFormat(0x822B, RG, UNSIGNED_BYTE), // GL30.GL_RG8
1312     RG16 = new InternalFormat(0x822C, RG, UNSIGNED_SHORT), // GL30.GL_RG16
1313     R16F = new InternalFormat(0x822D, RED, HALF_FLOAT), // GL30.GL_R16F
1314     R32F = new InternalFormat(0x822E, RED, FLOAT), // GL30.GL_R32F
1315     RG16F = new InternalFormat(0x822F, RG, HALF_FLOAT), // GL30.GL_RG16F
1316     RG32F = new InternalFormat(0x8230, RGB, FLOAT), // GL30.GL_RG32F
1317     RGBA32F = new InternalFormat(0x8814, RGBA, FLOAT), // GL30.GL_RGBA32F
1318     RGB32F = new InternalFormat(0x8815, RGB, FLOAT), // GL30.GL_RGB32F
1319     RGBA16F = new InternalFormat(0x881A, RGBA, HALF_FLOAT), // GL30.GL_RGBA16F
1320     RGB16F = new InternalFormat(0x881B, RGB, HALF_FLOAT), // GL30.GL_RGB16F
1321     RGB5_A1 = new InternalFormat(0x8057, RGBA, UNSIGNED_SHORT_1_5_5_5_REV) // GL11.GL_RGB5_A1
1322 }
1323 
1324 /**
1325  * An enum of sized texture component formats.
1326  */
1327 public final class InternalFormat {
1328     private immutable uint glConstant;
1329     private Format format;
1330     private immutable uint bytes;
1331     private DataType componentType;
1332 
1333     private this(uint glConstant, Format format, DataType componentType) {
1334         this.glConstant = glConstant;
1335         this.format = format;
1336         this.componentType = componentType;
1337         bytes = format.getComponentCount() * componentType.getByteSize();
1338     }
1339 
1340     /**
1341      * Gets the OpenGL constant for this internal format.
1342      *
1343      * @return The OpenGL Constant
1344      */
1345     public uint getGLConstant() {
1346         return glConstant;
1347     }
1348 
1349     /**
1350      * Returns the format associated to this internal format
1351      *
1352      * @return The associated format
1353      */
1354     public Format getFormat() {
1355         return format;
1356     }
1357 
1358     /**
1359      * Returns the number of components in the format.
1360      *
1361      * @return The number of components
1362      */
1363     public uint getComponentCount() {
1364         return format.getComponentCount();
1365     }
1366 
1367     /**
1368      * Returns the data type of the components.
1369      *
1370      * @return The component type
1371      */
1372     public DataType getComponentType() {
1373         return componentType;
1374     }
1375 
1376     /**
1377      * Returns the number of bytes used by a single pixel in the format.
1378      *
1379      * @return The number of bytes for a pixel
1380      */
1381     public uint getBytes() {
1382         return bytes;
1383     }
1384 
1385     /**
1386      * Returns the number of bytes used by a single pixel component in the format.
1387      *
1388      * @return The number of bytes for a pixel component
1389      */
1390     public uint getBytesPerComponent() {
1391         return componentType.getByteSize();
1392     }
1393 
1394     /**
1395      * Returns true if this format has a red component.
1396      *
1397      * @return True if a red component is present
1398      */
1399     public bool hasRed() {
1400         return format.hasRed();
1401     }
1402 
1403     /**
1404      * Returns true if this format has a green component.
1405      *
1406      * @return True if a green component is present
1407      */
1408     public bool hasGreen() {
1409         return format.hasGreen();
1410     }
1411 
1412     /**
1413      * Returns true if this format has a blue component.
1414      *
1415      * @return True if a blue component is present
1416      */
1417     public bool hasBlue() {
1418         return format.hasBlue();
1419     }
1420 
1421     /**
1422      * Returns true if this format has an alpha component.
1423      *
1424      * @return True if an alpha component is present
1425      */
1426     public bool hasAlpha() {
1427         return format.hasAlpha();
1428     }
1429 
1430     /**
1431      * Returns true if this format has a depth component.
1432      *
1433      * @return True if a depth component is present
1434      */
1435     public bool hasDepth() {
1436         return format.hasDepth();
1437     }
1438 }
1439 
1440 public enum : WrapMode {
1441     REPEAT = new WrapMode(0x2901), // GL11.GL_REPEAT
1442     CLAMP_TO_EDGE = new WrapMode(0x812F), // GL12.GL_CLAMP_TO_EDGE
1443     CLAMP_TO_BORDER = new WrapMode(0x812D), // GL13.GL_CLAMP_TO_BORDER
1444     MIRRORED_REPEAT = new WrapMode(0x8370) // GL14.GL_MIRRORED_REPEAT
1445 }
1446 
1447 /**
1448  * An enum for the texture wrapping modes.
1449  */
1450 public final class WrapMode {
1451     private immutable uint glConstant;
1452 
1453     private this(uint glConstant) {
1454         this.glConstant = glConstant;
1455     }
1456 
1457     /**
1458      * Gets the OpenGL constant for this texture wrap.
1459      *
1460      * @return The OpenGL Constant
1461      */
1462     public uint getGLConstant() {
1463         return glConstant;
1464     }
1465 }
1466 
1467 public enum : FilterMode {
1468     LINEAR = new FilterMode(0x2601, false), // GL11.GL_LINEAR
1469     NEAREST = new FilterMode(0x2600, false), // GL11.GL_NEAREST
1470     NEAREST_MIPMAP_NEAREST = new FilterMode(0x2700, true), // GL11.GL_NEAREST_MIPMAP_NEAREST
1471     LINEAR_MIPMAP_NEAREST = new FilterMode(0x2701, true), //GL11.GL_LINEAR_MIPMAP_NEAREST
1472     NEAREST_MIPMAP_LINEAR = new FilterMode(0x2702, true), // GL11.GL_NEAREST_MIPMAP_LINEAR
1473     LINEAR_MIPMAP_LINEAR = new FilterMode(0x2703, true) // GL11.GL_LINEAR_MIPMAP_LINEAR
1474 }
1475 
1476 /**
1477  * An enum for the texture filtering modes.
1478  */
1479 public final class FilterMode {
1480     private immutable uint glConstant;
1481     private immutable bool mimpaps;
1482 
1483     private this(uint glConstant, bool mimpaps) {
1484         this.glConstant = glConstant;
1485         this.mimpaps = mimpaps;
1486     }
1487 
1488     /**
1489      * Gets the OpenGL constant for this texture filter.
1490      *
1491      * @return The OpenGL Constant
1492      */
1493     public uint getGLConstant() {
1494         return glConstant;
1495     }
1496 
1497     /**
1498      * Returns true if the filtering mode required generation of mipmaps.
1499      *
1500      * @return Whether or not mipmaps are required
1501      */
1502     public bool needsMipMaps() {
1503         return mimpaps;
1504     }
1505 }
1506 
1507 public enum : CompareMode {
1508     LEQUAL = new CompareMode(0x203), // GL11.GL_LEQUAL
1509     GEQUAL = new CompareMode(0x206), // GL11.GL_GEQUAL
1510     LESS = new CompareMode(0x201), // GL11.GL_LESS
1511     GREATER = new CompareMode(0x204), // GL11.GL_GREATER
1512     EQUAL = new CompareMode(0x202), // GL11.GL_EQUAL
1513     NOTEQUAL = new CompareMode(0x205), // GL11.GL_NOTEQUAL
1514     ALWAYS = new CompareMode(0x206), // GL11.GL_ALWAYS
1515     NEVER = new CompareMode(0x200) // GL11.GL_NEVER
1516 }
1517 
1518 public final class CompareMode {
1519     private immutable uint glConstant;
1520 
1521     private this(uint glConstant) {
1522         this.glConstant = glConstant;
1523     }
1524 
1525     /**
1526      * Gets the OpenGL constant for this texture filter.
1527      *
1528      * @return The OpenGL Constant
1529      */
1530     public uint getGLConstant() {
1531         return glConstant;
1532     }
1533 }
1534 
1535 /**
1536  * Represent an OpenGL vertex array. The vertex data must be set with {@link #setData(org.spout.renderer.api.data.VertexData)} before it can be created.
1537  */
1538 public abstract class VertexArray : Creatable, GLVersioned {
1539     protected uint id = 0;
1540 
1541     public override void destroy() {
1542         id = 0;
1543         super.destroy();
1544     }
1545 
1546     /**
1547      * Sets the vertex data source to use. The indices offset is kept but maybe reduced if it doesn't fit inside the new data. The count is set to the size from the offset to the end of the data.
1548      *
1549      * @param vertexData The vertex data source
1550      */
1551     public abstract void setData(VertexData vertexData);
1552 
1553     /**
1554      * Sets the vertex array's drawing mode.
1555      *
1556      * @param mode The drawing mode to use
1557      */
1558     public abstract void setDrawingMode(DrawingMode mode);
1559 
1560     /**
1561      * Sets the vertex array's polygon mode. This describes how to rasterize each primitive. The default is {@link org.spout.renderer.api.gl.VertexArray.PolygonMode#FILL}. This can be used to draw
1562      * only the wireframes of the polygons.
1563      *
1564      * @param mode The polygon mode
1565      */
1566     public abstract void setPolygonMode(PolygonMode mode);
1567 
1568     /**
1569      * Sets the starting offset in the indices buffer. Defaults to 0.
1570      *
1571      * @param offset The offset in the indices buffer
1572      */
1573     public abstract void setIndicesOffset(uint offset);
1574 
1575     /**
1576      * Sets the number of indices to render during each draw call, starting at the offset set by {@link #setIndicesOffset(int)}. Setting this to a value smaller than zero results in rendering of the
1577      * whole list. If the value is larger than the list (starting at the offset), it will be maxed to that value.
1578      *
1579      * @param count The number of indices
1580      */
1581     public abstract void setIndicesCount(uint count);
1582 
1583     /**
1584      * Draws the primitives defined by the vertex data.
1585      */
1586     public abstract void draw();
1587 
1588     /**
1589      * Gets the ID for this vertex array as assigned by OpenGL.
1590      *
1591      * @return The ID
1592      */
1593     public uint getID() {
1594         return id;
1595     }
1596 }
1597 
1598 public enum : DrawingMode {
1599     POINTS = new DrawingMode(0x0), // GL11.GL_POINTS
1600     LINES = new DrawingMode(0x1), // GL11.GL_LINES
1601     LINE_LOOP = new DrawingMode(0x2), // GL11.GL_LINE_LOOP
1602     LINE_STRIP = new DrawingMode(0x3), // GL11.GL_LINE_STRIP
1603     TRIANGLES = new DrawingMode(0x4), // GL11.GL_TRIANGLES
1604     TRIANGLES_STRIP = new DrawingMode(0x5), // GL11.GL_TRIANGLE_STRIP
1605     TRIANGLE_FAN = new DrawingMode(0x7), // GL11.GL_TRIANGLE_FAN
1606     LINES_ADJACENCY = new DrawingMode(0xA), // GL32.GL_LINES_ADJACENCY
1607     LINE_STRIP_ADJACENCY = new DrawingMode(0xB), // GL32.GL_LINE_STRIP_ADJACENCY
1608     TRIANGLES_ADJACENCY = new DrawingMode(0xC), // GL32.GL_TRIANGLES_ADJACENCY
1609     TRIANGLE_STRIP_ADJACENCY = new DrawingMode(0xD), // GL32.GL_TRIANGLE_STRIP_ADJACENCY
1610     PATCHES = new DrawingMode(0xE) // GL40.GL_PATCHES
1611 }
1612 
1613 /**
1614  * Represents the different drawing modes for the vertex array
1615  */
1616 public final class DrawingMode {
1617     private immutable uint glConstant;
1618 
1619     private this(uint glConstant) {
1620         this.glConstant = glConstant;
1621     }
1622 
1623     /**
1624      * Returns the OpenGL constant associated to the drawing mode
1625      *
1626      * @return The OpenGL constant
1627      */
1628     public uint getGLConstant() {
1629         return glConstant;
1630     }
1631 }
1632 
1633 public enum : PolygonMode {
1634     POINT = new PolygonMode(0x1B00), // GL11.GL_POINT
1635     LINE = new PolygonMode(0x1B01), // GL11.GL_LINE
1636     FILL = new PolygonMode(0x1B02) // GL11.GL_FILL
1637 }
1638 
1639 /**
1640  * Represents the different polygon modes for the vertex array
1641  */
1642 public final class PolygonMode {
1643     private immutable uint glConstant;
1644 
1645     private this(uint glConstant) {
1646         this.glConstant = glConstant;
1647     }
1648 
1649     /**
1650      * Returns the OpenGL constant associated to the polygon mode
1651      *
1652      * @return The OpenGL constant
1653      */
1654     public uint getGLConstant() {
1655         return glConstant;
1656     }
1657 }
1658 
1659 /**
1660  * Represents a vertex attribute. It has a name, a data type, a size (the number of components) and data.
1661  */
1662 public class VertexAttribute {
1663     protected string name;
1664     protected DataType type;
1665     protected uint size;
1666     protected UploadMode uploadMode;
1667     private ubyte[] buffer;
1668 
1669     /**
1670      * Creates a new vertex attribute from the name, the data type and the size. The upload mode will be {@link UploadMode#TO_FLOAT}.
1671      *
1672      * @param name The name
1673      * @param type The type
1674      * @param size The size
1675      */
1676     public this(string name, DataType type, uint size) {
1677         this(name, type, size, TO_FLOAT);
1678     }
1679 
1680     /**
1681      * Creates a new vertex attribute from the name, the data type, the size and the upload mode.
1682      *
1683      * @param name The name
1684      * @param type The type
1685      * @param size The size
1686      * @param uploadMode the upload mode
1687      */
1688     public this(string name, DataType type, uint size, UploadMode uploadMode) {
1689         this.name = name;
1690         this.type = type;
1691         this.size = size;
1692         this.uploadMode = uploadMode;
1693     }
1694 
1695     /**
1696      * Returns the name of the attribute.
1697      *
1698      * @return The name
1699      */
1700     public string getName() {
1701         return name;
1702     }
1703 
1704     /**
1705      * Returns the data type of the attribute.
1706      *
1707      * @return The data type
1708      */
1709     public DataType getType() {
1710         return type;
1711     }
1712 
1713     /**
1714      * Return the size of the attribute.
1715      *
1716      * @return The size
1717      */
1718     public uint getSize() {
1719         return size;
1720     }
1721 
1722     /**
1723      * Returns the upload mode for this attribute.
1724      *
1725      * @return The upload mode
1726      */
1727     public UploadMode getUploadMode() {
1728         return uploadMode;
1729     }
1730 
1731     /**
1732      * Returns a new byte buffer filled and ready to read, containing the attribute data. This method will {@link java.nio.ByteBuffer#flip()} the buffer before returning it.
1733      *
1734      * @return The buffer
1735      */
1736     public ubyte[] getData() {
1737         if (buffer is null) {
1738             throw new Exception("ByteBuffer must have data before it is ready for use.");
1739         }
1740         return buffer.dup;
1741     }
1742 
1743     /**
1744      * Replaces the current buffer data with a copy of the given {@link java.nio.ByteBuffer} This method arbitrarily creates data for the ByteBuffer regardless of the data type of the vertex
1745      * attribute.
1746      *
1747      * @param buffer to set
1748      */
1749     public void setData(ubyte[] buffer) {
1750         this.buffer = buffer.dup;
1751     }
1752 
1753     /**
1754      * Clears all of the buffer data.
1755      */
1756     public void clearData() {
1757         buffer = null;
1758     }
1759 
1760     public VertexAttribute clone() {
1761         VertexAttribute clone = new VertexAttribute(name, type, size, uploadMode);
1762         clone.setData(this.buffer);
1763         return clone;
1764     }
1765 }
1766 
1767 public enum : DataType {
1768     BYTE = new DataType(0x1400, 1, true, true), // GL11.GL_BYTE
1769     UNSIGNED_BYTE = new DataType(0x1401, 1, true, false), // GL11.GL_UNSIGNED_BYTE
1770     SHORT = new DataType(0x1402, 2, true, true), // GL11.GL_SHORT
1771     UNSIGNED_SHORT = new DataType(0x1403, 2, true, false), // GL11.GL_UNSIGNED_SHORT
1772     UNSIGNED_SHORT_1_5_5_5_REV = new DataType(0x8366, 2, true, false), // GL12.GL_UNSIGNED_SHORT_1_5_5_5_REV
1773     INT = new DataType(0x1404, 4, true, true), // GL11.GL_INT
1774     UNSIGNED_INT = new DataType(0x1405, 4, true, false), // GL11.GL_UNSIGNED_INT
1775     HALF_FLOAT = new DataType(0x140B, 2, false, true), // GL30.GL_HALF_FLOAT
1776     FLOAT = new DataType(0x1406, 4, false, true), // GL11.GL_FLOAT
1777     DOUBLE = new DataType(0x140A, 8, false, true) // GL11.GL_DOUBLE
1778 }
1779 
1780 /**
1781  * Represents an attribute data type.
1782  */
1783 public final class DataType {
1784     private immutable uint glConstant;
1785     private immutable uint byteSize;
1786     private immutable bool integer;
1787     private immutable bool signed;
1788     private immutable uint multiplyShift;
1789 
1790     private this(uint glConstant, uint byteSize, bool integer, bool signed) {
1791         this.glConstant = glConstant;
1792         this.byteSize = byteSize;
1793         this.integer = integer;
1794         this.signed = signed;
1795         uint result = 0;
1796         while (byteSize >>= 1) {
1797             result++;
1798         }
1799         multiplyShift = result;
1800     }
1801 
1802     /**
1803      * Returns the OpenGL constant for the data type.
1804      *
1805      * @return The OpenGL constant
1806      */
1807     public uint getGLConstant() {
1808         return glConstant;
1809     }
1810 
1811     /**
1812      * Returns the size in bytes of the data type.
1813      *
1814      * @return The size in bytes
1815      */
1816     public uint getByteSize() {
1817         return byteSize;
1818     }
1819 
1820     /**
1821      * Returns true if the data type is an integer number ({@link DataType#BYTE}, {@link DataType#SHORT} or {@link DataType#INT}).
1822      *
1823      * @return Whether or not the data type is an integer
1824      */
1825     public bool isInteger() {
1826         return integer;
1827     }
1828 
1829     /**
1830      * Returns true if this data type supports signed numbers, false if not.
1831      *
1832      * @return Whether or not this data type supports signed numbers
1833      */
1834     public bool isSigned() {
1835         return signed;
1836     }
1837 
1838     /**
1839      * Returns the shift amount equivalent to multiplying by the number of bytes in this data type.
1840      *
1841      * @return The shift amount corresponding to the multiplication by the byte size
1842      */
1843     public uint getMultiplyShift() {
1844         return multiplyShift;
1845     }
1846 }
1847 
1848 public enum : UploadMode {
1849     TO_FLOAT = new UploadMode(),
1850     TO_FLOAT_NORMALIZE = new UploadMode(),
1851     /**
1852      * Only supported in OpenGL 3.0 and after.
1853      */
1854     KEEP_INT = new UploadMode()
1855 }
1856 
1857 /**
1858  * The uploading mode. When uploading attribute data to OpenGL, integer data can be either converted to float or not (the later is only possible with version 3.0+). When converting to float, the
1859  * data can be normalized or not. By default, {@link UploadMode#TO_FLOAT} is used as it provides the best compatibility.
1860  */
1861 public final class UploadMode {
1862     /**
1863      * Returns true if this upload mode converts integer data to normalized floats.
1864      *
1865      * @return Whether or not this upload mode converts integer data to normalized floats
1866      */
1867     public bool normalize() {
1868         return this == TO_FLOAT_NORMALIZE;
1869     }
1870 
1871     /**
1872      * Returns true if this upload mode converts the data to floats.
1873      *
1874      * @return Whether or not this upload mode converts the data to floats
1875      */
1876     public bool toFloat() {
1877         return this == TO_FLOAT || this == TO_FLOAT_NORMALIZE;
1878     }
1879 }
1880 
1881 /**
1882  * Represents a vertex data. A vertex is a collection of attributes, most often attached to a point in space. This class is a data structure which groups together collections of primitives to
1883  * represent a list of vertices.
1884  */
1885 public class VertexData {
1886     // Rendering indices
1887     private uint[] indices;
1888     // Attributes by index
1889     private VertexAttribute[uint] attributes;
1890     // Index from name lookup
1891     private uint[string] nameToIndex;
1892 
1893     /**
1894      * Returns the list of indices used by OpenGL to pick the vertices to draw the object with in the correct order.
1895      *
1896      * @return The indices list
1897      */
1898     public uint[] getIndices() {
1899         return indices.dup;
1900     }
1901 
1902     /**
1903      * Sets the list of indices used by OpenGL to pick the vertices to draw the object with in the correct order.
1904      *
1905      * @param indices The indices list
1906      */
1907     public void setIndices(uint[] indices) {
1908         this.indices = indices.dup;
1909     }
1910 
1911     /**
1912      * Returns the index count.
1913      *
1914      * @return The number of indices
1915      */
1916     public uint getIndicesCount() {
1917         return cast(uint) indices.length;
1918     }
1919 
1920     /**
1921      * Returns a byte buffer containing all the current indices.
1922      *
1923      * @return A buffer of the indices
1924      */
1925     public ubyte[] getIndicesBuffer() {
1926         return cast(ubyte[]) indices.dup;
1927     }
1928 
1929     /**
1930      * Adds an attribute.
1931      *
1932      * @param index The attribute index
1933      * @param attribute The attribute to add
1934      */
1935     public void addAttribute(uint index, VertexAttribute attribute) {
1936         attributes[index] = attribute;
1937         nameToIndex[attribute.getName()] = index;
1938     }
1939 
1940     /**
1941      * Returns the {@link VertexAttribute} associated to the name, or null if none can be found.
1942      *
1943      * @param name The name to lookup
1944      * @return The attribute, or null if none is associated to the index.
1945      */
1946     public VertexAttribute getAttribute(string name) {
1947         return getAttribute(getAttributeIndex(name));
1948     }
1949 
1950     /**
1951      * Returns the {@link VertexAttribute} at the desired index, or null if none is associated to the index.
1952      *
1953      * @param index The index to lookup
1954      * @return The attribute, or null if none is associated to the index.
1955      */
1956     public VertexAttribute getAttribute(uint index) {
1957         return attributes.get(index, null);
1958     }
1959 
1960     /**
1961      * Returns the index associated to the attribute name, or -1 if no attribute has the name.
1962      *
1963      * @param name The name to lookup
1964      * @return The index, or -1 if no attribute has the name
1965      */
1966     public int getAttributeIndex(string name) {
1967         return nameToIndex.get(name, -1);
1968     }
1969 
1970     /**
1971      * Returns true if an attribute has the provided name.
1972      *
1973      * @param name The name to lookup
1974      * @return Whether or not an attribute possesses the name
1975      */
1976     public bool hasAttribute(string name) {
1977         return cast(bool) (name in nameToIndex);
1978     }
1979 
1980     /**
1981      * Returns true in an attribute can be found at the provided index.
1982      *
1983      * @param index The index to lookup
1984      * @return Whether or not an attribute is at the index
1985      */
1986     public bool hasAttribute(uint index) {
1987         return cast(bool) (index in attributes);
1988     }
1989 
1990     /**
1991      * Removes the attribute associated to the provided name. If no attribute is found, nothing will be removed.
1992      *
1993      * @param name The name of the attribute to remove
1994      */
1995     public void removeAttribute(string name) {
1996         removeAttribute(getAttributeIndex(name));
1997     }
1998 
1999     /**
2000      * Removes the attribute at the provided index. If no attribute is found, nothing will be removed.
2001      *
2002      * @param index The index of the attribute to remove
2003      */
2004     public void removeAttribute(uint index) {
2005         attributes.remove(index);
2006         nameToIndex.remove(getAttributeName(index));
2007     }
2008 
2009     /**
2010      * Returns the size of the attribute associated to the provided name.
2011      *
2012      * @param name The name to lookup
2013      * @return The size of the attribute
2014      */
2015     public int getAttributeSize(string name) {
2016         return getAttributeSize(getAttributeIndex(name));
2017     }
2018 
2019     /**
2020      * Returns the size of the attribute at the provided index, or -1 if none can be found.
2021      *
2022      * @param index The index to lookup
2023      * @return The size of the attribute, or -1 if none can be found
2024      */
2025     public int getAttributeSize(uint index) {
2026         VertexAttribute attribute = getAttribute(index);
2027         if (attribute is null) {
2028             return -1;
2029         }
2030         return attribute.getSize();
2031     }
2032 
2033     /**
2034      * Returns the type of the attribute associated to the provided name, or null if none can be found.
2035      *
2036      * @param name The name to lookup
2037      * @return The type of the attribute, or null if none can be found
2038      */
2039     public DataType getAttributeType(string name) {
2040         return getAttributeType(getAttributeIndex(name));
2041     }
2042 
2043     /**
2044      * Returns the type of the attribute at the provided index, or null if none can be found.
2045      *
2046      * @param index The index to lookup
2047      * @return The type of the attribute, or null if none can be found
2048      */
2049     public DataType getAttributeType(uint index) {
2050         VertexAttribute attribute = getAttribute(index);
2051         if (attribute is null) {
2052             return null;
2053         }
2054         return attribute.getType();
2055     }
2056 
2057     /**
2058      * Returns the name of the attribute at the provided index, or null if none can be found.
2059      *
2060      * @param index The index to lookup
2061      * @return The name of the attribute, or null if none can be found
2062      */
2063     public string getAttributeName(uint index) {
2064         VertexAttribute attribute = getAttribute(index);
2065         if (attribute is null) {
2066             return null;
2067         }
2068         return attribute.getName();
2069     }
2070 
2071     /**
2072      * Returns the attribute count.
2073      *
2074      * @return The number of attributes
2075      */
2076     public uint getAttributeCount() {
2077         return cast(uint) attributes.length;
2078     }
2079 
2080     /**
2081      * Returns an unmodifiable set of all the attribute names.
2082      *
2083      * @return A set of all the attribute names
2084      */
2085     public string[] getAttributeNames() {
2086         return nameToIndex.keys;
2087     }
2088 
2089     /**
2090      * Returns the buffer for the attribute associated to the provided name, or null if none can be found. The buffer is returned filled and ready for reading.
2091      *
2092      * @param name The name to lookup
2093      * @return The attribute buffer, filled and flipped
2094      */
2095     public ubyte[] getAttributeBuffer(string name) {
2096         return getAttributeBuffer(getAttributeIndex(name));
2097     }
2098 
2099     /**
2100      * Returns the buffer for the attribute at the provided index, or null if none can be found. The buffer is returned filled and ready for reading.
2101      *
2102      * @param index The index to lookup
2103      * @return The attribute buffer, filled and flipped
2104      */
2105     public ubyte[] getAttributeBuffer(uint index) {
2106         VertexAttribute attribute = getAttribute(index);
2107         if (attribute is null) {
2108             return null;
2109         }
2110         return attribute.getData();
2111     }
2112 
2113     /**
2114      * Clears all the vertex data.
2115      */
2116     public void clear() {
2117         indices = null;
2118         attributes = null;
2119         nameToIndex = null;
2120     }
2121 
2122     /**
2123      * Replaces the contents of this vertex data by the provided one. This is a deep copy. The vertex attribute are each individually cloned.
2124      *
2125      * @param data The data to copy.
2126      */
2127     public void copy(VertexData data) {
2128         indices = data.indices.dup;
2129         attributes = data.attributes.dup;
2130         nameToIndex = data.nameToIndex.dup;
2131     }
2132 }
2133 
2134 public immutable bool DEBUG_ENABLED = true;
2135 
2136 /**
2137  * Throws an exception if OpenGL reports an error.
2138  *
2139  * @throws GLException If OpenGL reports an error
2140  */
2141 public void checkForGLError() {
2142     if (DEBUG_ENABLED) {
2143         final switch (glGetError()) {
2144             case 0x0:
2145                 return;
2146             case 0x500:
2147                 throw new GLException("GL ERROR: INVALID ENUM");
2148             case 0x501:
2149                 throw new GLException("GL ERROR: INVALID VALUE");
2150             case 0x502:
2151                 throw new GLException("GL ERROR: INVALID OPERATION");
2152             case 0x503:
2153                 throw new GLException("GL ERROR: STACK OVERFLOW");
2154             case 0x504:
2155                 throw new GLException("GL ERROR: STACK UNDERFLOW");
2156             case 0x505:
2157                 throw new GLException("GL ERROR: OUT OF MEMORY");
2158             case 0x506:
2159                 throw new GLException("GL ERROR: INVALID FRAMEBUFFER OPERATION");
2160         }
2161     }
2162 }
2163 
2164 /**
2165  * An exception throw when a GL exception occurs.
2166  */
2167 public class GLException : Exception {
2168 
2169     /**
2170      * Constructs a new GL exception from the message.
2171      *
2172      * @param message The error message
2173      */
2174     public this(string message) {
2175         super(message);
2176     }
2177 }