shader.d 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. // Written in the D programming language.
  2. /**
  3. Copyright: Copyright Felix 'Zoadian' Hufnagel 2014-.
  4. License: $(WEB http://www.gnu.org/licenses/lgpl.html, LGPLv3).
  5. Authors: $(WEB zoadian.de, Felix 'Zoadian' Hufnagel)
  6. */
  7. module aurora.gl.shader;
  8. import derelict.opengl3.gl3;
  9. import aurora.gl.util;
  10. //==============================================================================
  11. ///
  12. enum ShaderType {
  13. Vertex = GL_VERTEX_SHADER,
  14. Fragment = GL_FRAGMENT_SHADER,
  15. Geometry = GL_GEOMETRY_SHADER,
  16. TesselationControl = GL_TESS_CONTROL_SHADER,
  17. TesselationEvaluation = GL_TESS_EVALUATION_SHADER
  18. }
  19. //==============================================================================
  20. ///
  21. final class Shader(ShaderType TYPE) {
  22. private:
  23. uint _id;
  24. public:
  25. ///
  26. this(string source) {
  27. auto szSource = [source.toStringz()];
  28. this._id = check!glCreateShaderProgramv(TYPE, 1, szSource.ptr);
  29. }
  30. ///
  31. ~this() {
  32. check!glDeleteProgram(this._id);
  33. }
  34. public:
  35. ///
  36. @property bool isValid() const {
  37. return (this._id > 0 && this.isLinked);
  38. }
  39. ///
  40. @property bool isLinked() const {
  41. GLint linked;
  42. check!glGetProgramiv(this._id, GL_LINK_STATUS, &linked);
  43. return linked != 0;
  44. }
  45. public:
  46. ///
  47. int getUniformLocation(string name) {
  48. int* px = (name in this._uniformLocationCache);
  49. if(px !is null) return *px;
  50. auto szName = name.toStringz();
  51. assert(this._id > 0);
  52. int x = check!glGetUniformLocation(this._id, &szName[0]);
  53. //assert(x != -1, "wrong uniform location : " ~ name);
  54. try{if(x == -1) "wrong uniform location : ".writeln(name);}catch(Exception e){}
  55. this._uniformLocationCache[name] = x;
  56. //if(x == -1) throw new Exception("uniform location "~name~" not found");
  57. return x;
  58. }
  59. ///
  60. string infoLog() {
  61. int len;
  62. check!glGetProgramiv(this._id, GL_INFO_LOG_LENGTH , &len);
  63. if (len > 1) {
  64. char[] msg = new char[len];
  65. check!glGetProgramInfoLog(this._id, len, null, cast(char*) msg);
  66. return cast(string)msg;
  67. }
  68. return "";
  69. }
  70. }
  71. //==============================================================================
  72. ///
  73. final class ShaderPipeline {
  74. private:
  75. GLuint _id;
  76. uint[ShaderType] _currentlyUsed;
  77. public:
  78. ///
  79. this() {
  80. glGenProgramPipelines(1, &this._id);
  81. }
  82. ///
  83. ~this() {
  84. glDeleteProgramPipelines(1, &this._id);
  85. }
  86. public:
  87. ///
  88. @property bool isValid() const {
  89. return (this._id > 0 && this.isValidProgramPipeline);
  90. }
  91. ///
  92. @property bool isValidProgramPipeline() const {
  93. glValidateProgramPipeline(this._id);
  94. GLint status;
  95. glGetProgramPipelineiv(this._id, GL_VALIDATE_STATUS, &status);
  96. return status != 0;
  97. }
  98. public:
  99. ///
  100. void bind() {
  101. glBindProgramPipeline(this._id);
  102. }
  103. ///
  104. static void unbind() {
  105. glBindProgramPipeline(0);
  106. }
  107. ///
  108. void activate(T)(T shaderProgram) { // TODO: add check if it is a shaderProgram
  109. glActiveShaderProgram(this._id, shaderProgram._id);
  110. }
  111. ///
  112. void use(T)(T shaderProgram) { // TODO: add check if it is a shaderProgram
  113. //check if shaderProgram is already in use by this pipeline
  114. if(_currentlyUsed.get(T.type, 0) == shaderProgram._id) return;
  115. glUseProgramStages(this._id, shaderTypeBitIdentifier!(shaderProgram.type), shaderProgram._id);
  116. }
  117. ///
  118. string infoLog() {
  119. int len;
  120. glGetProgramiv(this._id, GL_INFO_LOG_LENGTH , &len);
  121. if (len > 1) {
  122. char[] msg = new char[len];
  123. glGetProgramPipelineInfoLog(this._id, len, null, cast(char*) msg);
  124. return cast(string)msg;
  125. }
  126. return "";
  127. }
  128. }