root/trunk/dglut/opengl.d

Revision 172, 26.8 kB (checked in by FeepingCreature, 4 years ago)
  • Went back to the simple blob
Line 
1 module dglut.opengl;
2 import dglut.vector;
3 import std.stdio;
4
5 extern(System) {
6   typedef uint GLenum;
7   typedef uint GLbitfield;
8   typedef uint GLuint; // different on 64-bit?
9   typedef GLenum glPrimitive;
10   const glPrimitive GL_POINTS=0, GL_LINES=1, GL_LINE_LOOP=2, GL_LINE_STRIP=3, GL_TRIANGLES=4,
11     GL_TRIANGLE_STRIP=5, GL_TRIANGLE_FAN=6, GL_QUADS=7, GL_QUAD_STRIP=8, GL_POLYGON=9;
12   void glBegin(glPrimitive mode);
13   void glEnd();
14 }
15
16 template Prepend (string S, T...) {
17   static if (!T.length) alias Tuple!() Prepend;
18   else {
19     static if (is(typeof(T[0]): string)) alias Tuple!(S~T[0], Prepend!(S, T[1..$])) Prepend;
20     else alias Tuple!(T[0], Prepend!(S, T[1..$])) Prepend;
21   }
22 }
23
24 template Append(string S, T...) {
25   static if (!T.length) alias Tuple!() Append;
26   else {
27     static if (is(typeof(T[0]): string)) alias Tuple!(T[0]~S, Append!(S, T[1..$])) Append;
28     else alias Tuple!(T[0], Append!(S, T[1..$])) Append;
29   }
30 }
31
32 template Find(string S, string T) {
33   static if(S.length<T.length) { const size_t Find=size_t.max; }
34   else {
35     static if (S[0..T.length] == T) const size_t Find=0;
36     else static if (Find!(S[1..$], T)==size_t.max) const size_t Find=size_t.max;
37     else const size_t Find=Find!(S[1..$], T) + 1;
38   }
39 }
40
41 template Split(string S, string SEP) {
42   static if (Find!(S, SEP)==size_t.max) alias Tuple!(S) Split;
43   else alias Tuple!(S[0..Find!(S, SEP)], Split!(S[Find!(S, SEP)+SEP.length .. $], SEP)) Split;
44 }
45
46 template StringCross(T, U) {
47   static if (T.Tuple.length==1) alias Prepend!(T.Tuple[0], U.Tuple) StringCross;
48   else alias Tuple!(Prepend!(T.Tuple[0], U.Tuple), StringCross!(TupleWrapper!(T.Tuple[1..$]), U)) StringCross;
49 }
50
51 template Expand(string E) {
52   static if (!E.length) alias Tuple!("") Expand;
53   else {
54     static if (E[0]=='{') {
55       static if(Find!(E, "}")==size_t.max) {
56         pragma(msg, "You forgot a closing bracket in \""~E~"\"");
57         static assert(false);
58       }
59       alias StringCross!(TupleWrapper!(Split!(E[1..Find!(E, "}")], "|")), TupleWrapper!(Expand!(E[Find!(E, "}")+1 .. $]))) Expand;
60     } else {
61       alias Prepend!(""~E[0], Expand!(E[1..$])) Expand;
62     }
63   }
64 }
65
66 template ConstEnum(T, string MOD, SYMBOLS...) {
67   static assert(SYMBOLS.length>1);
68   static assert(is(typeof(SYMBOLS[0]): long));
69   static if (SYMBOLS.length>1) {
70     static if (is(typeof(SYMBOLS[1]): long)) {
71       static if (SYMBOLS.length>2) mixin ConstEnum!(T, MOD, SYMBOLS[1..$]);
72     } else {
73       mixin("T "~SYMBOLS[1]~"=SYMBOLS[0]; ");
74       static if (SYMBOLS.length>2) mixin ConstEnum!(T, MOD, mixin("SYMBOLS[0]"~MOD), SYMBOLS[2..$]);
75     }
76   }
77 }
78
79 template PrimitiveScope(string NAME, string WHICH) {
80   mixin("void "~NAME~"(void delegate()[] dgs...) {
81     glBegin("~WHICH~"); scope(exit) glEnd();
82     foreach (dg; dgs) dg();
83   }");
84 }
85
86 template MultiMixin(alias T, int count, U...) {
87   mixin T!(U[0..count]);
88   static if (U.length>count) mixin MultiMixin!(T, count, U[count..$]);
89 }
90
91 mixin MultiMixin!(PrimitiveScope, 2,
92   "Points", "GL_POINTS", "Lines", "GL_LINES",
93   "LineLoop", "GL_LINE_LOOP", "LineStrip", "GL_LINE_STRIP",
94   "Triangles", "GL_TRIANGLES", "TriangleStrip", "GL_TRIANGLE_STRIP",
95   "TriangleFan", "GL_TRIANGLE_FAN", "Quads", "GL_QUADS",
96   "QuadStrip", "GL_QUAD_STRIP", "Polygon", "GL_POLYGON"
97 );
98
99 string glTypeDecode(string s) {
100   if (s=="b") return "byte";
101   if (s=="d") return "double";
102   if (s=="f") return "float";
103   if (s=="i") return "int";
104   if (s=="s") return "short";
105   if (s=="ub") return "ubyte";
106   if (s=="ui") return "uint";
107   if (s=="us") return "ushort";
108   assert(false);
109 }
110
111 string glTypeEncode(string s) {
112   if (s[0]=='u') return s[0..2];
113   return s[0..1];
114 }
115
116 template Repeat(int count, T) {
117   static if (!count) alias Tuple!() Repeat;
118   else alias Tuple!(T, Repeat!(count-1, T)) Repeat;
119 }
120
121 size_t find(string where, string what) {
122   size_t counter=0;
123   while (where.length>=what.length) {
124     if (where[0..what.length]==what) return counter;
125     where=where[1..$];
126     ++counter;
127   }
128   return size_t.max;
129 }
130
131 string glFunctions(string name, string params, string types) {
132   string res;
133   while (types.length) {
134     string type;
135     if (find(types, "|")==size_t.max) { type=types; types=""; }
136     else { type=types[0..find(types, "|")]; types=types[find(types, "|")+1..$]; }
137     foreach (param; params) {
138      
139       res~="extern(System) void "~name~param~type~"(Repeat!("~param~", "~glTypeDecode(type)~")); ";
140       res~="extern(System) void "~name~param~type~"v("~glTypeDecode(type)~" *); ";
141       res~="void "~name~"(Repeat!("~param~", "~glTypeDecode(type)~") par) {
142         "~name~param~type~"(par);
143       }";
144       res~="void "~name~"("~glTypeDecode(type)~"["~param~"] par) {
145         "~name~param~type~"v(par.ptr);
146       }";
147     }
148   }
149   return res;
150 }
151
152 mixin(glFunctions("glVertex", "234", "d|f|i|s"));
153 mixin(glFunctions("glNormal", "3", "b|d|f|i|s"));
154 mixin(glFunctions("glTexCoord", "1234", "d|f|i|s"));
155 mixin(glFunctions("glColor", "34", "b|d|f|i|s|ub|ui|us"));
156 mixin(glFunctions("glRasterPos", "234", "d|f|i|s"));
157
158 void Vertex(T...)(T t) { static if (T.length==1) glVertex(t[0].parts); else glVertex(t); }
159 void Normal(T...)(T t) { static if (T.length==1) glNormal(t[0].parts); else glNormal(t); }
160 void TexCoord(T...)(T t) { static if (T.length==1) glTexCoord(t[0].parts); else glTexCoord(t); }
161 void Color(T...)(T t) { static if (T.length==1) glColor(t[0].parts); else glColor(t); }
162 void RasterPos(T...)(T t) { static if (T.length==1) glRasterPos(t[0].parts); else glRasterPos(t); }
163
164 extern(System) {
165   void glPushMatrix();
166   void glPopMatrix();
167 }
168
169 void MatrixScope(void delegate()[] dgs...) {
170   glPushMatrix();
171   scope(exit) glPopMatrix;
172   foreach (dg; dgs) dg();
173 }
174
175 extern(System) {
176   void glMatrixMode(MatrixModeType);
177   typedef GLenum MatrixModeType;
178   const MatrixModeType GL_MODELVIEW=0x1700, GL_PROJECTION=0x1701, GL_TEXTURE=0x1702;
179 }
180
181 // so as to prevent conflicts between Texture and class Texture later on
182 struct MatrixMode {
183   static void Modelview() { glMatrixMode(GL_MODELVIEW); }
184   static void Projection() { glMatrixMode(GL_PROJECTION); }
185   static void Texture() { glMatrixMode(GL_TEXTURE); }
186 }
187
188 extern(System) {
189   const GLenum GL_NONE=0;
190   mixin ConstEnum!(GLenum, "+1", 0x0400,
191     Expand!("GL_{FRONT|BACK}_{LEFT|RIGHT}"),
192     Expand!("GL_{FRONT|BACK|LEFT|RIGHT}"),
193     "GL_FRONT_AND_BACK",
194     Expand!("GL_AUX{0|1|2|3}")
195   );
196   typedef GLenum LightParameter;
197   mixin ConstEnum!(LightParameter, "+1", 0x1200,
198     Prepend!("GL_",
199       Tuple!(
200         "AMBIENT", "DIFFUSE", "SPECULAR", "POSITION",
201         Expand!("SPOT_{DIRECTION|EXPONENT|CUTOFF}"),
202         Expand!("{CONSTANT|LINEAR|QUADRATIC}_ATTENUATION")
203       )
204     )
205   );
206   typedef GLenum MaterialParameter;
207   mixin ConstEnum!(MaterialParameter, "+1", 0x1600,
208     Prepend!("GL_", Tuple!("EMISSION", "SHININESS", "AMBIENT_AND_DIFFUSE", "COLOR_INDEXES"))
209   );
210   void glMaterialf(GLenum face, GLenum pname, float param);
211   void glMaterialfv(GLenum face, GLenum pname, float *param);
212   void glMateriali(GLenum face, GLenum pname, int param);
213   void glMaterialiv(GLenum face, GLenum pname, int *param);
214 }
215
216 template MaterialNestedStruct(string NAME, string GLNAME) {
217   mixin("struct "~NAME~" {
218     static void ambient(float[4] col) { glMaterialfv("~GLNAME~", GL_AMBIENT, col.ptr); }
219     static void diffuse(float[4] col) { glMaterialfv("~GLNAME~", GL_DIFFUSE, col.ptr); }
220     static void ambient_and_diffuse(float[4] col) { glMaterialfv("~GLNAME~", GL_AMBIENT_AND_DIFFUSE, col.ptr); }
221     static void specular(float[4] col) { glMaterialfv("~GLNAME~", GL_SPECULAR, col.ptr); }
222     static void shininess(float s) { glMaterialf("~GLNAME~", GL_SHININESS, s); }
223     static void emission(float[4] e) { glMaterialfv("~GLNAME~", GL_EMISSION, e.ptr); }
224     static void emission(int[4] i) { glMaterialiv("~GLNAME~", GL_COLOR_INDEXES, i.ptr); }
225   }");
226 }
227
228 struct Material {
229   mixin MultiMixin!(MaterialNestedStruct, 2,  "Front", "GL_FRONT", "Back", "GL_BACK", "FrontAndBack", "GL_FRONT_AND_BACK");
230 }
231
232 extern(System) {
233   void glTranslated(Repeat!(3, double) xyz);
234   void glTranslatef(Repeat!(3, float) xyz);
235 }
236 void Translate(T...)(T what) {
237   static if (is(T[0]==double) || is(T[0]==real)) glTranslated(what);
238   else glTranslatef(what);
239 }
240
241 extern(System) {
242   void glRotated(double angle, Repeat!(3, double) xyz);
243   void glRotatef(float angle, Repeat!(3, float) xyz);
244 }
245
246 void Rotate(T...)(T what) {
247   static if (is(T[0]==double) || is(T[0]==real)) glRotated(what);
248   else glRotatef(what);
249 }
250
251 extern(System) {
252   void glClear(GLbitfield mask);
253   typedef GLbitfield AttribMask;
254   mixin ConstEnum!(AttribMask, "*2", 1, Prepend!("GL_",
255     Append!("_BIT",
256       Expand!("{CURRENT|POINT|LINE|POLYGON|POLYGON_STIPPLE|PIXEL_MODE|LIGHTING|FOG|DEPTH_BUFFER|ACCUM_BUFFER|STENCIL_BUFFER"~
257         "|VIEWPORT|TRANSFORM|ENABLE|COLOR_BUFFER|HINT|EVAL|LIST|TEXTURE|SCISSOR}"
258       )
259     )
260   ));
261   const AttribMask GL_ALL_ATTRIB_BITS=0xFFFFFFFF;
262   void glClearColor(Repeat!(4, float) rgb);
263   void glFlush();
264   void glPushAttrib(GLbitfield);
265   void glPopAttrib();
266 }
267
268 extern(System) {
269   void glEnable(GLenum);
270   void glDisable(GLenum);
271   // sorry, but using templates would have been too much to ask from the compiler
272   // (I tried; the resulting binary was 40M big)
273   // yay for sed!
274   // cat gl.h |sed -e "s@#define@const GLenum@" -e "s@ *0x\(.*\)@ = 0x\1;@" |less
275   const GLenum GL_CURRENT_COLOR = 0x0B00;
276   const GLenum GL_CURRENT_INDEX = 0x0B01;
277   const GLenum GL_CURRENT_NORMAL = 0x0B02;
278   const GLenum GL_CURRENT_TEXTURE_COORDS = 0x0B03;
279   const GLenum GL_CURRENT_RASTER_COLOR = 0x0B04;
280   const GLenum GL_CURRENT_RASTER_INDEX = 0x0B05;
281   const GLenum GL_CURRENT_RASTER_TEXTURE_COORDS = 0x0B06;
282   const GLenum GL_CURRENT_RASTER_POSITION = 0x0B07;
283   const GLenum GL_CURRENT_RASTER_POSITION_VALID = 0x0B08;
284   const GLenum GL_CURRENT_RASTER_DISTANCE = 0x0B09;
285   const GLenum GL_POINT_SMOOTH = 0x0B10;
286   const GLenum GL_POINT_SIZE = 0x0B11;
287   const GLenum GL_SMOOTH_POINT_SIZE_RANGE = 0x0B12;
288   const GLenum GL_SMOOTH_POINT_SIZE_GRANULARITY = 0x0B13;
289   const GLenum GL_POINT_SIZE_RANGE = GL_SMOOTH_POINT_SIZE_RANGE;
290   const GLenum GL_POINT_SIZE_GRANULARITY = GL_SMOOTH_POINT_SIZE_GRANULARITY;
291   const GLenum GL_LINE_SMOOTH = 0x0B20;
292   const GLenum GL_LINE_WIDTH = 0x0B21;
293   const GLenum GL_SMOOTH_LINE_WIDTH_RANGE = 0x0B22;
294   const GLenum GL_SMOOTH_LINE_WIDTH_GRANULARITY = 0x0B23;
295   const GLenum GL_LINE_WIDTH_RANGE = GL_SMOOTH_LINE_WIDTH_RANGE;
296   const GLenum GL_LINE_WIDTH_GRANULARITY = GL_SMOOTH_LINE_WIDTH_GRANULARITY;
297   const GLenum GL_LINE_STIPPLE = 0x0B24;
298   const GLenum GL_LINE_STIPPLE_PATTERN = 0x0B25;
299   const GLenum GL_LINE_STIPPLE_REPEAT = 0x0B26;
300   const GLenum GL_LIST_MODE = 0x0B30;
301   const GLenum GL_MAX_LIST_NESTING = 0x0B31;
302   const GLenum GL_LIST_BASE = 0x0B32;
303   const GLenum GL_LIST_INDEX = 0x0B33;
304   const GLenum GL_POLYGON_MODE = 0x0B40;
305   const GLenum GL_POLYGON_SMOOTH = 0x0B41;
306   const GLenum GL_POLYGON_STIPPLE = 0x0B42;
307   const GLenum GL_EDGE_FLAG = 0x0B43;
308   const GLenum GL_CULL_FACE = 0x0B44;
309   const GLenum GL_CULL_FACE_MODE = 0x0B45;
310   const GLenum GL_FRONT_FACE = 0x0B46;
311   const GLenum GL_LIGHTING = 0x0B50;
312   const GLenum GL_LIGHT_MODEL_LOCAL_VIEWER = 0x0B51;
313   const GLenum GL_LIGHT_MODEL_TWO_SIDE = 0x0B52;
314   const GLenum GL_LIGHT_MODEL_AMBIENT = 0x0B53;
315   const GLenum GL_SHADE_MODEL = 0x0B54;
316   const GLenum GL_COLOR_MATERIAL_FACE = 0x0B55;
317   const GLenum GL_COLOR_MATERIAL_PARAMETER = 0x0B56;
318   const GLenum GL_COLOR_MATERIAL = 0x0B57;
319   const GLenum GL_FOG = 0x0B60;
320   const GLenum GL_FOG_INDEX = 0x0B61;
321   const GLenum GL_FOG_DENSITY = 0x0B62;
322   const GLenum GL_FOG_START = 0x0B63;
323   const GLenum GL_FOG_END = 0x0B64;
324   const GLenum GL_FOG_MODE = 0x0B65;
325   const GLenum GL_FOG_COLOR = 0x0B66;
326   const GLenum GL_DEPTH_RANGE = 0x0B70;
327   const GLenum GL_DEPTH_TEST = 0x0B71;
328   const GLenum GL_DEPTH_WRITEMASK = 0x0B72;
329   const GLenum GL_DEPTH_CLEAR_VALUE = 0x0B73;
330   const GLenum GL_DEPTH_FUNC = 0x0B74;
331   const GLenum GL_ACCUM_CLEAR_VALUE = 0x0B80;
332   const GLenum GL_STENCIL_TEST = 0x0B90;
333   const GLenum GL_STENCIL_CLEAR_VALUE = 0x0B91;
334   const GLenum GL_STENCIL_FUNC = 0x0B92;
335   const GLenum GL_STENCIL_VALUE_MASK = 0x0B93;
336   const GLenum GL_STENCIL_FAIL = 0x0B94;
337   const GLenum GL_STENCIL_PASS_DEPTH_FAIL = 0x0B95;
338   const GLenum GL_STENCIL_PASS_DEPTH_PASS = 0x0B96;
339   const GLenum GL_STENCIL_REF = 0x0B97;
340   const GLenum GL_STENCIL_WRITEMASK = 0x0B98;
341   const GLenum GL_MATRIX_MODE = 0x0BA0;
342   const GLenum GL_NORMALIZE = 0x0BA1;
343   const GLenum GL_VIEWPORT = 0x0BA2;
344   const GLenum GL_MODELVIEW_STACK_DEPTH = 0x0BA3;
345   const GLenum GL_PROJECTION_STACK_DEPTH = 0x0BA4;
346   const GLenum GL_TEXTURE_STACK_DEPTH = 0x0BA5;
347   const GLenum GL_MODELVIEW_MATRIX = 0x0BA6;
348   const GLenum GL_PROJECTION_MATRIX = 0x0BA7;
349   const GLenum GL_TEXTURE_MATRIX = 0x0BA8;
350   const GLenum GL_ATTRIB_STACK_DEPTH = 0x0BB0;
351   const GLenum GL_CLIENT_ATTRIB_STACK_DEPTH = 0x0BB1;
352   const GLenum GL_ALPHA_TEST = 0x0BC0;
353   const GLenum GL_ALPHA_TEST_FUNC = 0x0BC1;
354   const GLenum GL_ALPHA_TEST_REF = 0x0BC2;
355   const GLenum GL_DITHER = 0x0BD0;
356   const GLenum GL_BLEND_DST = 0x0BE0;
357   const GLenum GL_BLEND_SRC = 0x0BE1;
358   const GLenum GL_BLEND = 0x0BE2;
359   const GLenum GL_LOGIC_OP_MODE = 0x0BF0;
360   const GLenum GL_INDEX_LOGIC_OP = 0x0BF1;
361   const GLenum GL_LOGIC_OP = GL_INDEX_LOGIC_OP;
362   const GLenum GL_COLOR_LOGIC_OP = 0x0BF2;
363   const GLenum GL_AUX_BUFFERS = 0x0C00;
364   const GLenum GL_DRAW_BUFFER = 0x0C01;
365   const GLenum GL_READ_BUFFER = 0x0C02;
366   const GLenum GL_SCISSOR_BOX = 0x0C10;
367   const GLenum GL_SCISSOR_TEST = 0x0C11;
368   const GLenum GL_INDEX_CLEAR_VALUE = 0x0C20;
369   const GLenum GL_INDEX_WRITEMASK = 0x0C21;
370   const GLenum GL_COLOR_CLEAR_VALUE = 0x0C22;
371   const GLenum GL_COLOR_WRITEMASK = 0x0C23;
372   const GLenum GL_INDEX_MODE = 0x0C30;
373   const GLenum GL_RGBA_MODE = 0x0C31;
374   const GLenum GL_DOUBLEBUFFER = 0x0C32;
375   const GLenum GL_STEREO = 0x0C33;
376   const GLenum GL_RENDER_MODE = 0x0C40;
377   const GLenum GL_PERSPECTIVE_CORRECTION_HINT = 0x0C50;
378   const GLenum GL_POINT_SMOOTH_HINT = 0x0C51;
379   const GLenum GL_LINE_SMOOTH_HINT = 0x0C52;
380   const GLenum GL_POLYGON_SMOOTH_HINT = 0x0C53;
381   const GLenum GL_FOG_HINT = 0x0C54;
382   const GLenum GL_TEXTURE_GEN_S = 0x0C60;
383   const GLenum GL_TEXTURE_GEN_T = 0x0C61;
384   const GLenum GL_TEXTURE_GEN_R = 0x0C62;
385   const GLenum GL_TEXTURE_GEN_Q = 0x0C63;
386   const GLenum GL_PIXEL_MAP_I_TO_I_SIZE = 0x0CB0;
387   const GLenum GL_PIXEL_MAP_S_TO_S_SIZE = 0x0CB1;
388   const GLenum GL_PIXEL_MAP_I_TO_R_SIZE = 0x0CB2;
389   const GLenum GL_PIXEL_MAP_I_TO_G_SIZE = 0x0CB3;
390   const GLenum GL_PIXEL_MAP_I_TO_B_SIZE = 0x0CB4;
391   const GLenum GL_PIXEL_MAP_I_TO_A_SIZE = 0x0CB5;
392   const GLenum GL_PIXEL_MAP_R_TO_R_SIZE = 0x0CB6;
393   const GLenum GL_PIXEL_MAP_G_TO_G_SIZE = 0x0CB7;
394   const GLenum GL_PIXEL_MAP_B_TO_B_SIZE = 0x0CB8;
395   const GLenum GL_PIXEL_MAP_A_TO_A_SIZE = 0x0CB9;
396   const GLenum GL_UNPACK_SWAP_BYTES = 0x0CF0;
397   const GLenum GL_UNPACK_LSB_FIRST = 0x0CF1;
398   const GLenum GL_UNPACK_ROW_LENGTH = 0x0CF2;
399   const GLenum GL_UNPACK_SKIP_ROWS = 0x0CF3;
400   const GLenum GL_UNPACK_SKIP_PIXELS = 0x0CF4;
401   const GLenum GL_UNPACK_ALIGNMENT = 0x0CF5;
402   const GLenum GL_PACK_SWAP_BYTES = 0x0D00;
403   const GLenum GL_PACK_LSB_FIRST = 0x0D01;
404   const GLenum GL_PACK_ROW_LENGTH = 0x0D02;
405   const GLenum GL_PACK_SKIP_ROWS = 0x0D03;
406   const GLenum GL_PACK_SKIP_PIXELS = 0x0D04;
407   const GLenum GL_PACK_ALIGNMENT = 0x0D05;
408   const GLenum GL_MAP_COLOR = 0x0D10;
409   const GLenum GL_MAP_STENCIL = 0x0D11;
410   const GLenum GL_INDEX_SHIFT = 0x0D12;
411   const GLenum GL_INDEX_OFFSET = 0x0D13;
412   const GLenum GL_RED_SCALE = 0x0D14;
413   const GLenum GL_RED_BIAS = 0x0D15;
414   const GLenum GL_ZOOM_X = 0x0D16;
415   const GLenum GL_ZOOM_Y = 0x0D17;
416   const GLenum GL_GREEN_SCALE = 0x0D18;
417   const GLenum GL_GREEN_BIAS = 0x0D19;
418   const GLenum GL_BLUE_SCALE = 0x0D1A;
419   const GLenum GL_BLUE_BIAS = 0x0D1B;
420   const GLenum GL_ALPHA_SCALE = 0x0D1C;
421   const GLenum GL_ALPHA_BIAS = 0x0D1D;
422   const GLenum GL_DEPTH_SCALE = 0x0D1E;
423   const GLenum GL_DEPTH_BIAS = 0x0D1F;
424   const GLenum GL_MAX_EVAL_ORDER = 0x0D30;
425   const GLenum GL_MAX_LIGHTS = 0x0D31;
426   const GLenum GL_MAX_CLIP_PLANES = 0x0D32;
427   const GLenum GL_MAX_TEXTURE_SIZE = 0x0D33;
428   const GLenum GL_MAX_PIXEL_MAP_TABLE = 0x0D34;
429   const GLenum GL_MAX_ATTRIB_STACK_DEPTH = 0x0D35;
430   const GLenum GL_MAX_MODELVIEW_STACK_DEPTH = 0x0D36;
431   const GLenum GL_MAX_NAME_STACK_DEPTH = 0x0D37;
432   const GLenum GL_MAX_PROJECTION_STACK_DEPTH = 0x0D38;
433   const GLenum GL_MAX_TEXTURE_STACK_DEPTH = 0x0D39;
434   const GLenum GL_MAX_VIEWPORT_DIMS = 0x0D3A;
435   const GLenum GL_MAX_CLIENT_ATTRIB_STACK_DEPTH = 0x0D3B;
436   const GLenum GL_SUBPIXEL_BITS = 0x0D50;
437   const GLenum GL_INDEX_BITS = 0x0D51;
438   const GLenum GL_RED_BITS = 0x0D52;
439   const GLenum GL_GREEN_BITS = 0x0D53;
440   const GLenum GL_BLUE_BITS = 0x0D54;
441   const GLenum GL_ALPHA_BITS = 0x0D55;
442   const GLenum GL_DEPTH_BITS = 0x0D56;
443   const GLenum GL_STENCIL_BITS = 0x0D57;
444   const GLenum GL_ACCUM_RED_BITS = 0x0D58;
445   const GLenum GL_ACCUM_GREEN_BITS = 0x0D59;
446   const GLenum GL_ACCUM_BLUE_BITS = 0x0D5A;
447   const GLenum GL_ACCUM_ALPHA_BITS = 0x0D5B;
448   const GLenum GL_NAME_STACK_DEPTH = 0x0D70;
449   const GLenum GL_AUTO_NORMAL = 0x0D80;
450   const GLenum GL_MAP1_COLOR_4 = 0x0D90;
451   const GLenum GL_MAP1_INDEX = 0x0D91;
452   const GLenum GL_MAP1_NORMAL = 0x0D92;
453   const GLenum GL_MAP1_TEXTURE_COORD_1 = 0x0D93;
454   const GLenum GL_MAP1_TEXTURE_COORD_2 = 0x0D94;
455   const GLenum GL_MAP1_TEXTURE_COORD_3 = 0x0D95;
456   const GLenum GL_MAP1_TEXTURE_COORD_4 = 0x0D96;
457   const GLenum GL_MAP1_VERTEX_3 = 0x0D97;
458   const GLenum GL_MAP1_VERTEX_4 = 0x0D98;
459   const GLenum GL_MAP2_COLOR_4 = 0x0DB0;
460   const GLenum GL_MAP2_INDEX = 0x0DB1;
461   const GLenum GL_MAP2_NORMAL = 0x0DB2;
462   const GLenum GL_MAP2_TEXTURE_COORD_1 = 0x0DB3;
463   const GLenum GL_MAP2_TEXTURE_COORD_2 = 0x0DB4;
464   const GLenum GL_MAP2_TEXTURE_COORD_3 = 0x0DB5;
465   const GLenum GL_MAP2_TEXTURE_COORD_4 = 0x0DB6;
466   const GLenum GL_MAP2_VERTEX_3 = 0x0DB7;
467   const GLenum GL_MAP2_VERTEX_4 = 0x0DB8;
468   const GLenum GL_MAP1_GRID_DOMAIN = 0x0DD0;
469   const GLenum GL_MAP1_GRID_SEGMENTS = 0x0DD1;
470   const GLenum GL_MAP2_GRID_DOMAIN = 0x0DD2;
471   const GLenum GL_MAP2_GRID_SEGMENTS = 0x0DD3;
472   const GLenum GL_TEXTURE_1D = 0x0DE0;
473   const GLenum GL_TEXTURE_2D = 0x0DE1;
474   const GLenum GL_FEEDBACK_BUFFER_POINTER = 0x0DF0;
475   const GLenum GL_FEEDBACK_BUFFER_SIZE = 0x0DF1;
476   const GLenum GL_FEEDBACK_BUFFER_TYPE = 0x0DF2;
477   const GLenum GL_SELECTION_BUFFER_POINTER = 0x0DF3;
478   const GLenum GL_SELECTION_BUFFER_SIZE = 0x0DF4;
479   const GLenum GL_POLYGON_OFFSET_UNITS = 0x2A00;
480   const GLenum GL_POLYGON_OFFSET_POINT = 0x2A01;
481   const GLenum GL_POLYGON_OFFSET_LINE = 0x2A02;
482   const GLenum GL_POLYGON_OFFSET_FILL = 0x8037;
483   const GLenum GL_POLYGON_OFFSET_FACTOR = 0x8038;
484   const GLenum GL_TEXTURE_BINDING_1D = 0x8068;
485   const GLenum GL_TEXTURE_BINDING_2D = 0x8069;
486   const GLenum GL_TEXTURE_BINDING_3D = 0x806A;
487   const GLenum GL_VERTEX_ARRAY = 0x8074;
488   const GLenum GL_NORMAL_ARRAY = 0x8075;
489   const GLenum GL_COLOR_ARRAY = 0x8076;
490   const GLenum GL_INDEX_ARRAY = 0x8077;
491   const GLenum GL_TEXTURE_COORD_ARRAY = 0x8078;
492   const GLenum GL_EDGE_FLAG_ARRAY = 0x8079;
493   const GLenum GL_VERTEX_ARRAY_SIZE = 0x807A;
494   const GLenum GL_VERTEX_ARRAY_TYPE = 0x807B;
495   const GLenum GL_VERTEX_ARRAY_STRIDE = 0x807C;
496   const GLenum GL_NORMAL_ARRAY_TYPE = 0x807E;
497   const GLenum GL_NORMAL_ARRAY_STRIDE = 0x807F;
498   const GLenum GL_COLOR_ARRAY_SIZE = 0x8081;
499   const GLenum GL_COLOR_ARRAY_TYPE = 0x8082;
500   const GLenum GL_COLOR_ARRAY_STRIDE = 0x8083;
501   const GLenum GL_INDEX_ARRAY_TYPE = 0x8085;
502   const GLenum GL_INDEX_ARRAY_STRIDE = 0x8086;
503   const GLenum GL_TEXTURE_COORD_ARRAY_SIZE = 0x8088;
504   const GLenum GL_TEXTURE_COORD_ARRAY_TYPE = 0x8089;
505   const GLenum GL_TEXTURE_COORD_ARRAY_STRIDE = 0x808A;
506   const GLenum GL_EDGE_FLAG_ARRAY_STRIDE = 0x808C;
507   const GLenum GL_TEXTURE_WIDTH = 0x1000;
508   const GLenum GL_TEXTURE_HEIGHT = 0x1001;
509   const GLenum GL_TEXTURE_INTERNAL_FORMAT = 0x1003;
510   const GLenum GL_TEXTURE_COMPONENTS = GL_TEXTURE_INTERNAL_FORMAT;
511   const GLenum GL_TEXTURE_BORDER_COLOR = 0x1004;
512   const GLenum GL_TEXTURE_BORDER = 0x1005;
513   const GLenum GL_TEXTURE_RED_SIZE = 0x805C;
514   const GLenum GL_TEXTURE_GREEN_SIZE = 0x805D;
515   const GLenum GL_TEXTURE_BLUE_SIZE = 0x805E;
516   const GLenum GL_TEXTURE_ALPHA_SIZE = 0x805F;
517   const GLenum GL_TEXTURE_LUMINANCE_SIZE = 0x8060;
518   const GLenum GL_TEXTURE_INTENSITY_SIZE = 0x8061;
519   const GLenum GL_TEXTURE_PRIORITY = 0x8066;
520   const GLenum GL_TEXTURE_RESIDENT = 0x8067;
521   const GLenum GL_DONT_CARE = 0x1100;
522   const GLenum GL_FASTEST = 0x1101;
523   const GLenum GL_NICEST = 0x1102;
524   typedef GLenum LightSource;
525   const LightSource GL_LIGHT0=0x4000,
526     GL_LIGHT1=GL_LIGHT0+1, GL_LIGHT2=GL_LIGHT1+1,
527     GL_LIGHT3=GL_LIGHT2+1, GL_LIGHT4=GL_LIGHT3+1,
528     GL_LIGHT5=GL_LIGHT4+1, GL_LIGHT6=GL_LIGHT5+1,
529     GL_LIGHT7=GL_LIGHT6+1;
530 }
531
532 extern(System) {
533   void glLightf(LightSource, GLenum pname, float);
534   void glLightfv(LightSource, GLenum pname, float *);
535   void glLighti(LightSource, GLenum pname, int);
536   void glLightiv(LightSource, GLenum pname, int *);
537 }
538 template LightProperty(string name, GLenum GL, int params) {
539   mixin("void "~name~"("~(params?"float["~params.stringof~"]":"float")~" par) {
540     glLightf"~(params?"v":"")~"(index, GL, par"~(params?".ptr":"")~");
541   }");
542 }
543 struct Light {
544   LightSource index;
545   void position(float[3] par, bool point=true) {
546     float[4] fullpar; fullpar[0..3]=par;
547     if (point) fullpar[3]=1f; else fullpar[3]=0f;
548     glLightfv(index, GL_POSITION, fullpar.ptr);
549   }
550   void enable() { glEnable(index); }
551   mixin MultiMixin!(LightProperty, 3,
552     "ambient", GL_AMBIENT, 4,             "diffuse", GL_DIFFUSE, 4,
553     "specular", GL_SPECULAR, 4,           "spot_direction", GL_SPOT_DIRECTION, 3,
554     "spot_exponent", GL_SPOT_EXPONENT, 0, "spot_cutoff", GL_SPOT_CUTOFF, 0,
555     "constant_attenuation", GL_CONSTANT_ATTENUATION, 0,
556     "linear_attenuation", GL_LINEAR_ATTENUATION, 0,
557     "quadratic_attenuation", GL_QUADRATIC_ATTENUATION, 0
558   );
559   static Light opIndex(size_t which) {
560     assert(which<8, "Allowed number of light sources exceeded!");
561     return Light(cast(LightSource)(GL_LIGHT0+which));
562   }
563 }
564
565 extern(System) {
566   typedef GLenum ErrorCode;
567   mixin ConstEnum!(ErrorCode, "+1", Prepend!(
568       "GL_", 0, "NO_ERROR", 0x0500, Expand!("INVALID_{ENUM|VALUE|OPERATION}"),
569       Expand!("STACK_{OVER|UNDER}FLOW"), "OUT_OF_MEMORY",
570       0x8031, "TABLE_TOO_LARGE"
571     )
572   );
573   char *gluErrorString(ErrorCode);
574   ErrorCode glGetError();
575 }
576
577 string glErrorToString(ErrorCode err) {
578   auto res=gluErrorString(err), cur=res;
579   while (*cur) cur++;
580   return res[0..(cur-res)];
581 }
582
583 import std.string: toString;
584 void glChecked(string label, void delegate()[] dgs...) {
585   foreach (idx, dg; dgs) {
586     if (auto err=glGetError())
587       if (!idx) throw new Exception("OpenGL error before checked section"~(label.length?" \""~label~"\"":"")~": "~glErrorToString(err));
588       else throw new Exception("OpenGL error in "~(label.length?"\""~label~"\", ":"")~"command "~toString(idx)~": "~glErrorToString(err));
589     dg();
590   }
591   if (auto err=glGetError()) {
592     if (label.length) throw new Exception("OpenGL error in \""~label~"\""~(dgs.length>1?", last command":"")~": "~glErrorToString(err));
593     else throw new Exception("OpenGL error in"~(dgs.length>1?" last":"")~" command: "~glErrorToString(err));
594   }
595 }
596
597 extern(System) {
598   void glGenTextures(int n, uint *textures);
599   bool glIsTexture(uint texture);
600   void glBindTexture(GLenum target, uint texture);
601   void glDeleteTextures(int n, uint *textures);
602  
603   void glTexImage2D(GLenum target, int level, PixelFormat internalFormat, int width, int height, int border, PixelFormat, DataType, void *pixels);
604   void gluBuild2DMipmaps(GLenum target, PixelFormat internalFormat, int width, int height, PixelFormat, DataType, void *pixels);
605   void glTexParameterf(GLenum target, GLenum pname, float param);
606   void glTexParameterfv(GLenum target, GLenum pname, float *param);
607   void glTexParameteri(GLenum target, GLenum pname, int param);
608   void glTexParameteriv(GLenum target, GLenum pname, int *param);
609   typedef GLenum PixelFormat;
610   mixin ConstEnum!(PixelFormat, "+1", 0x1900, Prepend!("GL_",
611       "COLOR_INDEX", "STENCIL_INDEX", "DEPTH_COMPONENT",
612       "RED", "GREEN", "BLUE", "ALPHA",
613       "RGB", "RGBA", "LUMINANCE", "LUMINANCE_ALPHA"
614     )
615   );
616   typedef GLenum DataType;
617   mixin ConstEnum!(DataType, "+1", 0x1400, Prepend!("GL_",
618       "BYTE", "UNSIGNED_BYTE", "SHORT", "UNSIGNED_SHORT",
619       "INT", "UNSIGNED_INT", "FLOAT", Expand!("{2|3|4}_BYTES"),
620       "DOUBLE"
621     )
622   );
623   typedef GLenum TextureParameterName;
624   mixin ConstEnum!(TextureParameterName, "+1", 0x2800, Prepend!("GL_TEXTURE_", "MAG_FILTER", "MIN_FILTER", "WRAP_S", "WRAP_T"));
625   const GLenum GL_NEAREST=0x2600, GL_LINEAR=0x2601, GL_CLAMP=0x2900, GL_REPEAT=0x2901;
626   mixin ConstEnum!(GLenum, "+1", 0x2700, Prepend!("GL_",
627     Append!("_NEAREST", Expand!("{NEAREST|LINEAR}_MIPMAP")),
628     Append!("_LINEAR", Expand!("{NEAREST|LINEAR}_MIPMAP"))
629   ));
630
631 }
632
633 extern(System) {
634   typedef GLenum StringName;
635   void glGetDoublev(GLenum, double *);
636   char *glGetString(StringName);
637   void glGetFloatv(GLenum, float *);
638   void glGetIntegerv(GLenum, int *);
639  
640   const StringName GL_VENDOR=0x1F00, GL_RENDERER=0x1F01, GL_VERSION=0x1F02, GL_EXTENSIONS=0x1F03;
641 }
642
643 class Texture  {
644   uint me;
645   int width, height;
646   this(size_t w, size_t h, bool mipmap, ubyte[] data) {
647     width=w; height=h;
648     glChecked("GenTextures", glGenTextures(1, &me));
649     bind;
650     if (mipmap) glChecked("TexMinFilterMipmap", glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST));
651     else glChecked("TexMinFilter", glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
652     glChecked("TexParams", glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR),
653       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT),
654       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
655     );
656     if (mipmap) {
657       glChecked("TexBuildMipmaps", gluBuild2DMipmaps(GL_TEXTURE_2D, 4, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data.length?data.ptr:null));
658     } else {
659       glChecked("TexGenImage", glTexImage2D(GL_TEXTURE_2D, 0, 4, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data.length?data.ptr:null));
660     }
661   }
662   this(size_t w, size_t h, bool mipmap=false) { ubyte[] empty; this(w, h, mipmap, empty); }
663   this(size_t w, size_t h, bool mipmap, vec3f delegate(float u, float v) dg) {
664     width=w; height=h;
665     ubyte[] data;
666     if (dg) {
667       data=new ubyte[width*height*4];
668       size_t idx=0;
669       for (int y=0; y<height; ++y) {
670         for (int x=0; x<width; ++x) {
671           auto col=dg(x/(1f*width), y/(1f/height));
672           data[idx+0]=cast(ubyte)(col.x*255);
673           data[idx+1]=cast(ubyte)(col.y*255);
674           data[idx+2]=cast(ubyte)(col.z*255);
675           data[idx+3]=0;
676           idx += 4;
677         }
678       }
679     }
680     this(width, height, mipmap, data);
681   }
682   static void enable() {  glEnable(GL_TEXTURE_2D); }
683   static void disable() { glDisable(GL_TEXTURE_2D); }
684   void free() { glDeleteTextures(1, &me); me=0; }
685   ~this() { free; }
686  
687   static void bind(uint what) { glBindTexture(GL_TEXTURE_2D, what); }
688   static uint bound() { uint res; glGetIntegerv(GL_TEXTURE_BINDING_2D, cast(int*)&res); return res; }
689   void bind() { bind(me); }
690   void With(void delegate()[] dgs...) {
691     auto old=bound(); scope(exit) bind(old);
692     bind;
693     foreach (dg; dgs) dg();
694   }
695 }
696
697 extern(System) {
698   void glViewport(int x, int y, int width, int height);
699 }
Note: See TracBrowser for help on using the browser.