util.d 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  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.util;
  8. import std.algorithm;
  9. import std.stdio;
  10. import std.stdio : stderr;
  11. import std.array : join;
  12. import std.range : repeat;
  13. import std.string : format;
  14. import std.traits : ReturnType;
  15. import derelict.opengl3.gl3;
  16. //==============================================================================
  17. ///
  18. enum BlendMode {
  19. Replace,
  20. Blend,
  21. Add,
  22. AddBlended,
  23. Mult
  24. }
  25. //==============================================================================
  26. ///
  27. enum DepthTestMode {
  28. None,
  29. Always,
  30. Equal,
  31. Less,
  32. Greater,
  33. LessEqual,
  34. GreaterEqual
  35. }
  36. //==============================================================================
  37. ///
  38. enum CullMode {
  39. None,
  40. Back,
  41. Front
  42. }
  43. //==============================================================================
  44. ///
  45. void setCullMode(CullMode cm) {
  46. final switch(cm) {
  47. case CullMode.Back:
  48. check!glEnable(GL_CULL_FACE);
  49. check!glCullFace(GL_BACK);
  50. break;
  51. case CullMode.Front:
  52. check!glEnable(GL_CULL_FACE);
  53. check!glCullFace(GL_FRONT);
  54. break;
  55. case CullMode.None:
  56. check!glDisable(GL_CULL_FACE);
  57. break;
  58. }
  59. }
  60. //==============================================================================
  61. ///
  62. void setBlendMode(BlendMode bm) {
  63. final switch(bm) {
  64. case BlendMode.Replace:
  65. glDisable(GL_BLEND);
  66. break;
  67. case BlendMode.Blend:
  68. glEnable(GL_BLEND);
  69. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  70. break;
  71. case BlendMode.Add:
  72. glEnable(GL_BLEND);
  73. glBlendFunc(GL_ONE, GL_ONE);
  74. break;
  75. case BlendMode.AddBlended:
  76. glEnable(GL_BLEND);
  77. glBlendFunc(GL_SRC_ALPHA, GL_ONE);
  78. break;
  79. case BlendMode.Mult:
  80. glEnable(GL_BLEND);
  81. glBlendFunc(GL_DST_COLOR, GL_ZERO);
  82. break;
  83. }
  84. }
  85. //==============================================================================
  86. ///
  87. void setDepthTestMode(DepthTestMode dt) {
  88. glDepthMask(dt == DepthTestMode.None ? GL_FALSE : GL_TRUE);
  89. final switch(dt) {
  90. case DepthTestMode.None:
  91. glDisable(GL_DEPTH_TEST);
  92. break;
  93. case DepthTestMode.Always:
  94. glEnable(GL_DEPTH_TEST);
  95. glDepthFunc(GL_ALWAYS);
  96. break;
  97. case DepthTestMode.Equal:
  98. glEnable(GL_DEPTH_TEST);
  99. glDepthFunc(GL_EQUAL);
  100. break;
  101. case DepthTestMode.Less:
  102. glEnable(GL_DEPTH_TEST);
  103. glDepthFunc(GL_LESS);
  104. break;
  105. case DepthTestMode.Greater:
  106. glEnable(GL_DEPTH_TEST);
  107. glDepthFunc(GL_GREATER);
  108. break;
  109. case DepthTestMode.LessEqual:
  110. glEnable(GL_DEPTH_TEST);
  111. glDepthFunc(GL_LEQUAL);
  112. break;
  113. case DepthTestMode.GreaterEqual:
  114. glEnable(GL_DEPTH_TEST);
  115. glDepthFunc(GL_GEQUAL);
  116. break;
  117. }
  118. }
  119. //==============================================================================
  120. ///
  121. int maxDrawBuffers() {
  122. int maxDrawBuffers;
  123. glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
  124. return maxDrawBuffers;
  125. }
  126. //==============================================================================
  127. ///
  128. int maxColorBuffers() {
  129. int maxColorBuffers;
  130. glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxColorBuffers);
  131. return maxColorBuffers;
  132. }
  133. //==============================================================================
  134. ///
  135. int maxTextureImageUnits() {
  136. int maxTextureImageUnits;
  137. glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
  138. return maxTextureImageUnits;
  139. }
  140. //==============================================================================
  141. ///
  142. ReturnType!func check(alias func, Args...)(Args args) {
  143. try{
  144. debug scope(exit) {
  145. GLenum err = glGetError();
  146. if(err != GL_NO_ERROR) {
  147. stderr.writefln(`OpenGL function "%s(%s)" failed: "%s."`,
  148. func.stringof, format("%s".repeat(Args.length).join(", "), args), gl_error_string(err));
  149. assert(false);
  150. }
  151. }
  152. }
  153. catch(Exception e){
  154. }
  155. debug if(func is null) {
  156. try{
  157. stderr.writefln("%s is null! OpenGL loaded? Required OpenGL version not supported?".format(func.stringof));
  158. }
  159. catch(Exception e){
  160. assert(false);
  161. }
  162. assert(false);
  163. }
  164. return func(args);
  165. }
  166. //==============================================================================
  167. ///
  168. string gl_error_string(GLenum error) {
  169. final switch(error) {
  170. case GL_NO_ERROR: return "no error";
  171. case GL_INVALID_ENUM: return "invalid enum";
  172. case GL_INVALID_VALUE: return "invalid value";
  173. case GL_INVALID_OPERATION: return "invalid operation";
  174. //case GL_STACK_OVERFLOW: return "stack overflow";
  175. //case GL_STACK_UNDERFLOW: return "stack underflow";
  176. case GL_INVALID_FRAMEBUFFER_OPERATION: return "invalid framebuffer operation";
  177. case GL_OUT_OF_MEMORY: return "out of memory";
  178. }
  179. assert(false, "invalid enum");
  180. }
  181. //~ bool glCheck(string file = __FILE__, int line = __LINE__) @trusted
  182. //~ {
  183. //~ debug{
  184. //~ try{
  185. //~ int error = glGetError();
  186. //~ if (error == GL_NO_ERROR) return true;
  187. //~ "[[ %s:%s ]]".writef(file, line);
  188. //~ while(error != GL_NO_ERROR) {
  189. //~ switch (error) {
  190. //~ case GL_INVALID_ENUM:
  191. //~ writeln("GL_INVALID_ENUM: an unacceptable value has been specified for an enumerated argument");
  192. //~ break;
  193. //~ case GL_INVALID_VALUE:
  194. //~ writeln("GL_INVALID_VALUE: a numeric argument is out of range");
  195. //~ break;
  196. //~ case GL_INVALID_OPERATION:
  197. //~ writeln("GL_INVALID_OPERATION: the specified operation is not allowed in the current state");
  198. //~ break;
  199. //~ case GL_OUT_OF_MEMORY:
  200. //~ writeln("GL_OUT_OF_MEMORY: there is not enough memory left to execute the command");
  201. //~ break;
  202. //~ case GL_INVALID_FRAMEBUFFER_OPERATION:
  203. //~ writeln("GL_INVALID_FRAMEBUFFER_OPERATION_EXT: the object bound to FRAMEBUFFER_BINDING_EXT is not \"framebuffer complete\"");
  204. //~ break;
  205. //~ default:
  206. //~ writeln("Error not listed. Value: ", error);
  207. //~ break;
  208. //~ }
  209. //~ error = glGetError();
  210. //~ }
  211. //~ }catch(Exception e)
  212. //~ {}
  213. //~ return false;
  214. //~ }
  215. //~ return true;
  216. //~ }
  217. //==============================================================================
  218. ///
  219. template toGlType(T) {
  220. static if(is(T == byte)) {
  221. enum toGlType = GL_BYTE;
  222. } else static if(is(T == ubyte)) {
  223. enum toGlType = GL_UNSIGNED_BYTE;
  224. } else static if(is(T == short)) {
  225. enum toGlType = GL_SHORT;
  226. } else static if(is(T == ushort)) {
  227. enum toGlType = GL_UNSIGNED_SHORT;
  228. } else static if(is(T == int)) {
  229. enum toGlType = GL_INT;
  230. } else static if(is(T == uint)) {
  231. enum toGlType = GL_UNSIGNED_INT;
  232. } else static if(is(T == float)) {
  233. enum toGlType = GL_FLOAT;
  234. } else static if(is(T == double)) {
  235. enum toGlType = GL_DOUBLE;
  236. } else {
  237. static assert(false, T.stringof ~ " cannot be represented as GLenum");
  238. }
  239. }
  240. //==============================================================================
  241. ///
  242. template sizeofGlType(GLenum t) {
  243. static if(t == GL_BYTE) {
  244. enum sizeofGlType = byte.sizeof;
  245. } else static if(t == GL_UNSIGNED_BYTE) {
  246. enum sizeofGlType = ubyte.sizeof;
  247. } else static if(t == GL_SHORT) {
  248. enum sizeofGlType = short.sizeof;
  249. } else static if(t == GL_UNSIGNED_SHORT) {
  250. enum sizeofGlType = ushort.sizeof;
  251. } else static if(t == GL_INT) {
  252. enum sizeofGlType = int.sizeof;
  253. } else static if(t == GL_UNSIGNED_INT) {
  254. enum sizeofGlType = uint.sizeof;
  255. } else static if(t == GL_FLOAT) {
  256. enum sizeofGlType = float.sizeof;
  257. } else static if(t == GL_DOUBLE) {
  258. enum sizeofGlType = double.sizeof;
  259. } else {
  260. static assert(false, T.stringof ~ " cannot be represented as D-Type");
  261. }
  262. }