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 }