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