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