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     );