1 2 module ws.gl.gl; 3 4 public import derelict.opengl3.gl3; 5 6 import 7 std.regex, 8 derelict.opengl3.wgl, 9 derelict.opengl3.glx, 10 ws.sys.library; 11 12 /+ 13 pragma(lib, "DerelictGL3"); 14 pragma(lib, "DerelictUtil"); 15 version(linux) pragma(lib, "dl"); 16 +/ 17 18 import std.string, ws.string, ws.exception; 19 20 import 21 ws.io, 22 std.conv, 23 ws.math.vector, 24 ws.math.matrix; 25 26 __gshared: 27 28 class gl { 29 const static int lines = GL_LINES; 30 const static int triangles = GL_TRIANGLES; 31 const static int triangleFan = GL_TRIANGLE_FAN; 32 33 const static int arrayBuffer = GL_ARRAY_BUFFER; 34 35 const static int compileStatus = GL_COMPILE_STATUS; 36 const static int linkStatus = GL_LINK_STATUS; 37 const static int shaderVertex = GL_VERTEX_SHADER; 38 const static int shaderFragment = GL_FRAGMENT_SHADER; 39 40 const static int attributeVertex = 0; 41 const static int attributeNormal = 1; 42 const static int attributeColor = 2; 43 const static int attributeTexture = 3; 44 45 static bool active(){ 46 version(Windows) 47 return wglGetCurrentContext() != null; 48 version(Posix) 49 return glXGetCurrentContext() != null; 50 } 51 52 53 /++ 54 Checks for OpenGL errors. 55 56 Resource-intensive, only call once each frame. 57 +/ 58 static void check(T = string)(T info = T.init, string file = __FILE__, size_t line = __LINE__){ 59 while(true){ 60 GLenum error = glGetError(); 61 if(!error) break; 62 exception("GL error, " ~ to!string(info) ~ ": " ~ to!string(cast(char*)gluErrorString(error)), null, file, line); 63 } 64 } 65 66 static bool matrixTranspose = false; 67 68 static class Shader { 69 70 uint shader; 71 72 this(uint type, string text){ 73 assert(gl.active()); 74 shader = glCreateShader(type); 75 char*[1] tempPtr; 76 tempPtr[0] = cast(char*)(text.toStringz()); 77 glShaderSource(shader, 1, cast(const char**)tempPtr, null); 78 glCompileShader(shader); 79 int r; 80 glGetShaderiv(shader, compileStatus, &r); 81 if(!r){ 82 string msg; 83 auto log = getLog(); 84 foreach(i, line; text.splitLines){ 85 auto m = match(log, regex(r"[0-9]\(%s\) :".format(i+1))); 86 if(m) 87 msg ~= "!\t%s\t%s\n".format(i+1, line); 88 else 89 msg ~= "\t%s\t%s\n".format(i+1, line); 90 } 91 msg ~= (log ~ '\n'); 92 exception("Failed to compile shader\n" ~ msg); 93 } 94 } 95 96 string getLog(){ 97 char[1024] log; 98 GLsizei length; 99 glGetShaderInfoLog(shader, 1024, &length, log.ptr); 100 string ret; 101 foreach(char c; log) 102 if(c != 255) 103 ret ~= c; 104 else 105 break; 106 return ret; 107 } 108 109 ~this(){ 110 //glDeleteShader(shader); 111 } 112 } 113 114 static class Program { 115 uint program; 116 117 this(){ 118 assert(gl.active()); 119 program = glCreateProgram(); 120 } 121 122 ~this(){ 123 //glDeleteProgram(program); 124 } 125 126 void attach(Shader s){ 127 glAttachShader(program, s.shader); 128 } 129 130 string getLog(){ 131 char[1024] log; 132 GLsizei length; 133 glGetProgramInfoLog(program, 1024, &length, log.ptr); 134 string ret; 135 foreach(char c; log) 136 if(c != 255) 137 ret ~= c; 138 else 139 break; 140 return ret; 141 } 142 143 void link(){ 144 glLinkProgram(program); 145 int r; 146 glGetProgramiv(program, linkStatus, &r); 147 if(!r) 148 exception("Failed to link shader: " ~ getLog()); 149 } 150 151 void use(){ 152 glUseProgram(program); 153 } 154 155 void bindAttrib(uint idx, string name){ 156 glBindAttribLocation(program, idx, name.toStringz()); 157 } 158 159 int getUniform(string n){ 160 return glGetUniformLocation(program, n.toStringz()); 161 } 162 163 void uniform(const int pos, const int i){ 164 glUniform1i(pos, i); 165 } 166 167 void uniform(const int pos, const float f){ 168 glUniform1f(pos, f); 169 } 170 171 void uniform(const int pos, const float[3] f){ 172 glUniform3fv(pos, 1, f.ptr); 173 } 174 175 void uniform(const int pos, const float[4] f){ 176 glUniform4fv(pos, 1, f.ptr); 177 } 178 179 void uniform(const int pos, const float[3][3] m){ 180 glUniformMatrix3fv(pos, 1, matrixTranspose ? GL_TRUE : GL_FALSE, m[0].ptr); 181 } 182 183 void uniform(const int pos, const float[4][4] m){ 184 glUniformMatrix4fv(pos, 1, matrixTranspose ? GL_TRUE : GL_FALSE, m[0].ptr); 185 } 186 187 void uniform(const int pos, Vector!3 v){ 188 glUniform3fv(pos, 1, v.data.ptr); 189 } 190 191 void uniform(const int pos, Matrix!(3,3) m){ 192 glUniformMatrix3fv(pos, 1, matrixTranspose ? GL_TRUE : GL_FALSE, m.data.ptr); 193 } 194 195 void uniform(const int pos, Matrix!(4,4) m){ 196 glUniformMatrix4fv(pos, 1, matrixTranspose ? GL_TRUE : GL_FALSE, m.data.ptr); 197 } 198 199 } 200 201 } 202 203 204 version(Windows) 205 const string LIB_FILE = "GLU32"; 206 version(Posix) 207 const string LIB_FILE = "GLU"; 208 209 extern(C) 210 mixin library!( 211 "OpenGL_Library", LIB_FILE, 212 "gluErrorString", const(GLubyte*) function(GLenum) 213 );