1
1

shader.d 4.1 KB

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