]> icculus.org git repositories - divverent/netradiant.git/blob - radiant/renderstate.cpp
new args -meta and -patchmeta to -convert with .map file argument
[divverent/netradiant.git] / radiant / renderstate.cpp
1 /*
2 Copyright (C) 2001-2006, William Joseph.
3 All Rights Reserved.
4
5 This file is part of GtkRadiant.
6
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 */
21
22 #include "renderstate.h"
23
24 #include "debugging/debugging.h"
25 #include "warnings.h"
26
27 #include "ishaders.h"
28 #include "irender.h"
29 #include "itextures.h"
30 #include "igl.h"
31 #include "iglrender.h"
32 #include "renderable.h"
33 #include "qerplugin.h"
34
35 #include <set>
36 #include <vector>
37 #include <list>
38 #include <map>
39
40 #include "math/matrix.h"
41 #include "math/aabb.h"
42 #include "generic/callback.h"
43 #include "texturelib.h"
44 #include "string/string.h"
45 #include "container/hashfunc.h"
46 #include "container/cache.h"
47 #include "generic/reference.h"
48 #include "moduleobservers.h"
49 #include "stream/filestream.h"
50 #include "stream/stringstream.h"
51 #include "os/file.h"
52 #include "preferences.h"
53
54 #include "xywindow.h"
55
56
57
58 #define DEBUG_RENDER 0
59
60 inline void debug_string(const char* string)
61 {
62 #if(DEBUG_RENDER)
63   globalOutputStream() << string << "\n";
64 #endif
65 }
66
67 inline void debug_int(const char* comment, int i)
68 {
69 #if(DEBUG_RENDER)
70   globalOutputStream() << comment << " " << i << "\n";
71 #endif
72 }
73
74 inline void debug_colour(const char* comment)
75 {
76 #if(DEBUG_RENDER)
77   Vector4 v;
78   glGetFloatv(GL_CURRENT_COLOR, reinterpret_cast<float*>(&v));
79   globalOutputStream() << comment << " colour: "
80     << v[0] << " "
81     << v[1] << " "
82     << v[2] << " "
83     << v[3];
84   if(glIsEnabled(GL_COLOR_ARRAY))
85   {
86     globalOutputStream() << " ARRAY";
87   }
88   if(glIsEnabled(GL_COLOR_MATERIAL))
89   {
90     globalOutputStream() << " MATERIAL";
91   }
92   globalOutputStream() << "\n";
93 #endif
94 }
95
96 #include "timer.h"
97
98 StringOutputStream g_renderer_stats;
99 std::size_t g_count_prims;
100 std::size_t g_count_states;
101 std::size_t g_count_transforms;
102 Timer g_timer;
103
104 inline void count_prim()
105 {
106   ++g_count_prims;
107 }
108
109 inline void count_state()
110 {
111   ++g_count_states;
112 }
113
114 inline void count_transform()
115 {
116   ++g_count_transforms;
117 }
118
119 void Renderer_ResetStats()
120 {
121   g_count_prims = 0;
122   g_count_states = 0;
123   g_count_transforms = 0;
124   g_timer.start();
125 }
126
127 const char* Renderer_GetStats()
128 {
129   g_renderer_stats.clear();
130   g_renderer_stats << "prims: " << Unsigned(g_count_prims)
131     << " | states: " << Unsigned(g_count_states)
132     << " | transforms: " << Unsigned(g_count_transforms)
133     << " | msec: " << g_timer.elapsed_msec();
134   return g_renderer_stats.c_str();
135 }
136
137
138 void printShaderLog(GLhandleARB object)
139 {
140   GLint log_length = 0;
141   glGetObjectParameterivARB(object, GL_OBJECT_INFO_LOG_LENGTH_ARB, &log_length);
142   
143   Array<char> log(log_length);
144   glGetInfoLogARB(object, log_length, &log_length, log.data());
145   
146   globalErrorStream() << StringRange(log.begin(), log.begin() + log_length) << "\n";
147 }
148
149 void createShader(GLhandleARB program, const char* filename, GLenum type)
150 {
151   GLhandleARB shader = glCreateShaderObjectARB(type);
152   GlobalOpenGL_debugAssertNoErrors();
153
154   // load shader
155   {
156     std::size_t size = file_size(filename);
157     FileInputStream file(filename);
158     ASSERT_MESSAGE(!file.failed(), "failed to open " << makeQuoted(filename));
159     Array<GLcharARB> buffer(size);
160     size = file.read(reinterpret_cast<StreamBase::byte_type*>(buffer.data()), size);
161
162     const GLcharARB* string = buffer.data();
163     GLint length = GLint(size);
164     glShaderSourceARB(shader, 1, &string, &length);
165   }
166
167   // compile shader
168   {
169     glCompileShaderARB(shader);
170     
171     GLint compiled = 0;
172     glGetObjectParameterivARB(shader, GL_OBJECT_COMPILE_STATUS_ARB, &compiled);
173
174     if(!compiled)
175     {
176       printShaderLog(shader);
177     }
178
179     ASSERT_MESSAGE(compiled, "shader compile failed: " << makeQuoted(filename));
180   }
181   
182   // attach shader
183   glAttachObjectARB(program, shader);
184   
185   glDeleteObjectARB(shader);
186
187   GlobalOpenGL_debugAssertNoErrors();
188 }
189
190 void GLSLProgram_link(GLhandleARB program)
191 {
192   glLinkProgramARB(program);
193   
194   GLint linked = false;
195   glGetObjectParameterivARB(program, GL_OBJECT_LINK_STATUS_ARB, &linked);
196
197   if(!linked)
198   {
199     printShaderLog(program);
200   }
201
202   ASSERT_MESSAGE(linked, "program link failed");
203 }
204
205 void GLSLProgram_validate(GLhandleARB program)
206 {
207   glValidateProgramARB(program);
208   
209   GLint validated = false;
210   glGetObjectParameterivARB(program, GL_OBJECT_VALIDATE_STATUS_ARB, &validated);
211
212   if(!validated)
213   {
214     printShaderLog(program);
215   }
216
217   ASSERT_MESSAGE(validated, "program validation failed");
218 }
219
220 bool g_bumpGLSLPass_enabled = false;
221 bool g_depthfillPass_enabled = false;
222
223 class GLSLBumpProgram : public GLProgram
224 {
225 public:
226   GLhandleARB m_program;
227   qtexture_t* m_light_attenuation_xy;
228   qtexture_t* m_light_attenuation_z;
229   GLint u_view_origin;
230   GLint u_light_origin;
231   GLint u_light_color;
232   GLint u_bump_scale;
233   GLint u_specular_exponent;
234
235   GLSLBumpProgram() : m_program(0), m_light_attenuation_xy(0), m_light_attenuation_z(0)
236   {
237   }
238
239   void create()
240   {
241     // create program
242     m_program = glCreateProgramObjectARB();
243     
244     // create shader
245     {
246       StringOutputStream filename(256);
247       filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_vp.glsl";
248       createShader(m_program, filename.c_str(), GL_VERTEX_SHADER_ARB);
249       filename.clear();
250       filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_fp.glsl";
251       createShader(m_program, filename.c_str(), GL_FRAGMENT_SHADER_ARB);
252     }
253
254     GLSLProgram_link(m_program);
255     GLSLProgram_validate(m_program);
256
257     glUseProgramObjectARB(m_program);
258     
259     glBindAttribLocationARB(m_program, c_attr_TexCoord0, "attr_TexCoord0");
260     glBindAttribLocationARB(m_program, c_attr_Tangent, "attr_Tangent");
261     glBindAttribLocationARB(m_program, c_attr_Binormal, "attr_Binormal");
262
263     glUniform1iARB(glGetUniformLocationARB(m_program, "u_diffusemap"), 0);
264     glUniform1iARB(glGetUniformLocationARB(m_program, "u_bumpmap"), 1);
265     glUniform1iARB(glGetUniformLocationARB(m_program, "u_specularmap"), 2);
266     glUniform1iARB(glGetUniformLocationARB(m_program, "u_attenuationmap_xy"), 3);
267     glUniform1iARB(glGetUniformLocationARB(m_program, "u_attenuationmap_z"), 4);
268     
269     u_view_origin = glGetUniformLocationARB(m_program, "u_view_origin");
270     u_light_origin = glGetUniformLocationARB(m_program, "u_light_origin");
271     u_light_color = glGetUniformLocationARB(m_program, "u_light_color");
272     u_bump_scale = glGetUniformLocationARB(m_program, "u_bump_scale");
273     u_specular_exponent = glGetUniformLocationARB(m_program, "u_specular_exponent");
274
275     glUseProgramObjectARB(0);
276
277     GlobalOpenGL_debugAssertNoErrors();
278   }
279
280   void destroy()
281   {
282     glDeleteObjectARB(m_program);
283     m_program = 0;
284   }
285
286   void enable()
287   {
288     glUseProgramObjectARB(m_program);
289
290     glEnableVertexAttribArrayARB(c_attr_TexCoord0);
291     glEnableVertexAttribArrayARB(c_attr_Tangent);
292     glEnableVertexAttribArrayARB(c_attr_Binormal);
293
294     GlobalOpenGL_debugAssertNoErrors();
295
296     debug_string("enable bump");
297     g_bumpGLSLPass_enabled = true;
298   }
299
300   void disable()
301   {
302     glUseProgramObjectARB(0);
303
304     glDisableVertexAttribArrayARB(c_attr_TexCoord0);
305     glDisableVertexAttribArrayARB(c_attr_Tangent);
306     glDisableVertexAttribArrayARB(c_attr_Binormal);
307
308     GlobalOpenGL_debugAssertNoErrors();
309
310     debug_string("disable bump");
311     g_bumpGLSLPass_enabled = false;
312   }
313
314   void setParameters(const Vector3& viewer, const Matrix4& localToWorld, const Vector3& origin, const Vector3& colour, const Matrix4& world2light)
315   {
316     Matrix4 world2local(localToWorld);
317     matrix4_affine_invert(world2local);
318
319     Vector3 localLight(origin);
320     matrix4_transform_point(world2local, localLight);
321
322     Vector3 localViewer(viewer);
323     matrix4_transform_point(world2local, localViewer);
324
325     Matrix4 local2light(world2light);
326     matrix4_multiply_by_matrix4(local2light, localToWorld); // local->world->light
327
328     glUniform3fARB(u_view_origin, localViewer.x(), localViewer.y(), localViewer.z());
329     glUniform3fARB(u_light_origin, localLight.x(), localLight.y(), localLight.z());
330     glUniform3fARB(u_light_color, colour.x(), colour.y(), colour.z());
331     glUniform1fARB(u_bump_scale, 1.0);
332     glUniform1fARB(u_specular_exponent, 32.0);
333
334     glActiveTexture(GL_TEXTURE3);
335     glClientActiveTexture(GL_TEXTURE3);
336
337     glMatrixMode(GL_TEXTURE);
338     glLoadMatrixf(reinterpret_cast<const float*>(&local2light));
339     glMatrixMode(GL_MODELVIEW);
340
341     GlobalOpenGL_debugAssertNoErrors();
342   }
343 };
344
345 GLSLBumpProgram g_bumpGLSL;
346
347
348 class GLSLDepthFillProgram : public GLProgram
349 {
350 public:
351   GLhandleARB m_program;
352
353   void create()
354   {
355     // create program
356     m_program = glCreateProgramObjectARB();
357
358     // create shader
359     {
360       StringOutputStream filename(256);
361       filename << GlobalRadiant().getAppPath() << "gl/zfill_vp.glsl";
362       createShader(m_program, filename.c_str(), GL_VERTEX_SHADER_ARB);
363       filename.clear();
364       filename << GlobalRadiant().getAppPath() << "gl/zfill_fp.glsl";
365       createShader(m_program, filename.c_str(), GL_FRAGMENT_SHADER_ARB);
366     }
367
368     GLSLProgram_link(m_program);
369     GLSLProgram_validate(m_program);
370
371     GlobalOpenGL_debugAssertNoErrors();
372   }
373
374   void destroy()
375   {
376     glDeleteObjectARB(m_program);
377     m_program = 0;
378   }
379   void enable()
380   {
381     glUseProgramObjectARB(m_program);
382     GlobalOpenGL_debugAssertNoErrors();
383     debug_string("enable depthfill");
384     g_depthfillPass_enabled = true;
385   }
386   void disable()
387   {
388     glUseProgramObjectARB(0);
389     GlobalOpenGL_debugAssertNoErrors();
390     debug_string("disable depthfill");
391     g_depthfillPass_enabled = false;
392   }
393   void setParameters(const Vector3& viewer, const Matrix4& localToWorld, const Vector3& origin, const Vector3& colour, const Matrix4& world2light)
394   {
395   }
396 };
397
398 GLSLDepthFillProgram g_depthFillGLSL;
399
400
401 // ARB path
402
403 void createProgram(const char* filename, GLenum type)
404 {
405   std::size_t size = file_size(filename);
406   FileInputStream file(filename);
407   ASSERT_MESSAGE(!file.failed(), "failed to open " << makeQuoted(filename));
408   Array<GLcharARB> buffer(size);
409   size = file.read(reinterpret_cast<StreamBase::byte_type*>(buffer.data()), size);
410
411   glProgramStringARB(type, GL_PROGRAM_FORMAT_ASCII_ARB, GLsizei(size), buffer.data());
412
413   if(GL_INVALID_OPERATION == glGetError())
414   {
415     GLint errPos;
416     glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
417     const GLubyte* errString = glGetString(GL_PROGRAM_ERROR_STRING_ARB);
418
419     globalErrorStream() << reinterpret_cast<const char*>(filename) << ":" <<  errPos << "\n" << reinterpret_cast<const char*>(errString);
420
421     ERROR_MESSAGE("error in gl program");
422   }
423 }
424
425 class ARBBumpProgram : public GLProgram
426 {
427 public:
428   GLuint m_vertex_program;
429   GLuint m_fragment_program;
430
431   void create()
432   {
433     glEnable(GL_VERTEX_PROGRAM_ARB);
434     glEnable(GL_FRAGMENT_PROGRAM_ARB);
435
436     {
437       glGenProgramsARB(1, &m_vertex_program);
438       glBindProgramARB(GL_VERTEX_PROGRAM_ARB, m_vertex_program);
439       StringOutputStream filename(256);
440       filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_vp.glp";
441       createProgram(filename.c_str(), GL_VERTEX_PROGRAM_ARB);
442
443       glGenProgramsARB(1, &m_fragment_program);
444       glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, m_fragment_program);
445       filename.clear();
446       filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_fp.glp";
447       createProgram(filename.c_str(), GL_FRAGMENT_PROGRAM_ARB);
448     }
449
450     glDisable(GL_VERTEX_PROGRAM_ARB);
451     glDisable(GL_FRAGMENT_PROGRAM_ARB);
452
453     GlobalOpenGL_debugAssertNoErrors();
454   }
455
456   void destroy()
457   {
458     glDeleteProgramsARB(1, &m_vertex_program);
459     glDeleteProgramsARB(1, &m_fragment_program);
460     GlobalOpenGL_debugAssertNoErrors();
461   }
462
463   void enable()
464   {
465     glEnable(GL_VERTEX_PROGRAM_ARB);
466     glEnable(GL_FRAGMENT_PROGRAM_ARB);
467     glBindProgramARB(GL_VERTEX_PROGRAM_ARB, m_vertex_program);
468     glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, m_fragment_program);
469
470     glEnableVertexAttribArrayARB(8);
471     glEnableVertexAttribArrayARB(9);
472     glEnableVertexAttribArrayARB(10);
473     glEnableVertexAttribArrayARB(11);
474
475     GlobalOpenGL_debugAssertNoErrors();
476   }
477
478   void disable()
479   {
480     glDisable(GL_VERTEX_PROGRAM_ARB);
481     glDisable(GL_FRAGMENT_PROGRAM_ARB);
482
483     glDisableVertexAttribArrayARB(8);
484     glDisableVertexAttribArrayARB(9);
485     glDisableVertexAttribArrayARB(10);
486     glDisableVertexAttribArrayARB(11);
487
488     GlobalOpenGL_debugAssertNoErrors();
489   }
490
491   void setParameters(const Vector3& viewer, const Matrix4& localToWorld, const Vector3& origin, const Vector3& colour, const Matrix4& world2light)
492   {
493     Matrix4 world2local(localToWorld);
494     matrix4_affine_invert(world2local);
495
496     Vector3 localLight(origin);
497     matrix4_transform_point(world2local, localLight);
498
499     Vector3 localViewer(viewer);
500     matrix4_transform_point(world2local, localViewer);
501
502     Matrix4 local2light(world2light);
503     matrix4_multiply_by_matrix4(local2light, localToWorld); // local->world->light
504
505     // view origin
506     glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 4, localViewer.x(), localViewer.y(), localViewer.z(), 0);
507
508     // light origin
509     glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 2, localLight.x(), localLight.y(), localLight.z(), 1);
510
511     // light colour
512     glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 3, colour.x(), colour.y(), colour.z(), 0);
513
514     // bump scale
515     glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, 1, 0, 0, 0);
516
517     // specular exponent
518     glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 5, 32, 0, 0, 0);
519
520
521     glActiveTexture(GL_TEXTURE3);
522     glClientActiveTexture(GL_TEXTURE3);
523
524     glMatrixMode(GL_TEXTURE);
525     glLoadMatrixf(reinterpret_cast<const float*>(&local2light));
526     glMatrixMode(GL_MODELVIEW);
527
528     GlobalOpenGL_debugAssertNoErrors();
529   }
530 };
531
532 class ARBDepthFillProgram : public GLProgram
533 {
534 public:
535   GLuint m_vertex_program;
536   GLuint m_fragment_program;
537
538   void create()
539   {
540     glEnable(GL_VERTEX_PROGRAM_ARB);
541     glEnable(GL_FRAGMENT_PROGRAM_ARB);
542
543     {
544       glGenProgramsARB(1, &m_vertex_program);
545       glBindProgramARB(GL_VERTEX_PROGRAM_ARB, m_vertex_program);
546       StringOutputStream filename(256);
547       filename << GlobalRadiant().getAppPath() << "gl/zfill_vp.glp";
548       createProgram(filename.c_str(), GL_VERTEX_PROGRAM_ARB);
549
550       glGenProgramsARB(1, &m_fragment_program);
551       glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, m_fragment_program);
552       filename.clear();
553       filename << GlobalRadiant().getAppPath() << "gl/zfill_fp.glp";
554       createProgram(filename.c_str(), GL_FRAGMENT_PROGRAM_ARB);
555     }
556
557     glDisable(GL_VERTEX_PROGRAM_ARB);
558     glDisable(GL_FRAGMENT_PROGRAM_ARB);
559
560     GlobalOpenGL_debugAssertNoErrors();
561   }
562
563   void destroy()
564   {
565     glDeleteProgramsARB(1, &m_vertex_program);
566     glDeleteProgramsARB(1, &m_fragment_program);
567     GlobalOpenGL_debugAssertNoErrors();
568   }
569
570   void enable()
571   {
572     glEnable(GL_VERTEX_PROGRAM_ARB);
573     glEnable(GL_FRAGMENT_PROGRAM_ARB);
574     glBindProgramARB(GL_VERTEX_PROGRAM_ARB, m_vertex_program);
575     glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, m_fragment_program);
576
577     GlobalOpenGL_debugAssertNoErrors();
578   }
579
580   void disable()
581   {
582     glDisable(GL_VERTEX_PROGRAM_ARB);
583     glDisable(GL_FRAGMENT_PROGRAM_ARB);
584
585     GlobalOpenGL_debugAssertNoErrors();
586   }
587
588   void setParameters(const Vector3& viewer, const Matrix4& localToWorld, const Vector3& origin, const Vector3& colour, const Matrix4& world2light)
589   {
590   }
591 };
592
593 ARBBumpProgram g_bumpARB;
594 ARBDepthFillProgram g_depthFillARB;
595
596
597 #if 0
598 // NV20 path (unfinished)
599
600 void createProgram(GLint program, const char* filename, GLenum type)
601 {
602   std::size_t size = file_size(filename);
603   FileInputStream file(filename);
604   ASSERT_MESSAGE(!file.failed(), "failed to open " << makeQuoted(filename));
605   Array<GLubyte> buffer(size);
606   size = file.read(reinterpret_cast<StreamBase::byte_type*>(buffer.data()), size);
607
608   glLoadProgramNV(type, program, GLsizei(size), buffer.data());
609
610   if(GL_INVALID_OPERATION == glGetError())
611   {
612     GLint errPos;
613     glGetIntegerv(GL_PROGRAM_ERROR_POSITION_NV, &errPos);
614     const GLubyte* errString = glGetString(GL_PROGRAM_ERROR_STRING_NV);
615
616     globalErrorStream() << filename << ":" <<  errPos << "\n" << errString;
617
618     ERROR_MESSAGE("error in gl program");
619   }
620 }
621
622 GLuint m_vertex_program;
623 GLuint m_fragment_program;
624 qtexture_t* g_cube = 0;
625 qtexture_t* g_specular_lookup = 0;
626 qtexture_t* g_attenuation_xy = 0;
627 qtexture_t* g_attenuation_z = 0;
628
629 void createVertexProgram()
630 {
631   {
632     glGenProgramsNV(1, &m_vertex_program);
633     glBindProgramNV(GL_VERTEX_PROGRAM_NV, m_vertex_program);
634     StringOutputStream filename(256);
635     filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_vp.nv30";
636     createProgram(m_vertex_program, filename.c_str(), GL_VERTEX_PROGRAM_NV);
637
638     glGenProgramsNV(1, &m_fragment_program);
639     glBindProgramNV(GL_FRAGMENT_PROGRAM_NV, m_fragment_program);
640     filename.clear();
641     filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_fp.nv30";
642     createProgram(m_fragment_program, filename.c_str(), GL_FRAGMENT_PROGRAM_NV);
643   }
644
645   g_cube = GlobalTexturesCache().capture("generated/cube");
646   g_specular_lookup = GlobalTexturesCache().capture("generated/specular");
647
648   g_attenuation_xy = GlobalTexturesCache().capture("lights/squarelight1");
649   glActiveTexture(GL_TEXTURE0);
650   glBindTexture(GL_TEXTURE_2D, g_attenuation_xy->texture_number);
651   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
652   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
653
654   g_attenuation_z = GlobalTexturesCache().capture("lights/squarelight1a");
655   glActiveTexture(GL_TEXTURE0);
656   glBindTexture(GL_TEXTURE_2D, g_attenuation_z->texture_number);
657   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
658   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
659
660   GlobalOpenGL_debugAssertNoErrors();
661 }
662
663 void destroyVertexProgram()
664 {
665   glDeleteProgramsNV(1, &m_vertex_program);
666   glDeleteProgramsNV(1, &m_fragment_program);
667   GlobalOpenGL_debugAssertNoErrors();
668
669   GlobalTexturesCache().release(g_cube);
670   GlobalTexturesCache().release(g_specular_lookup);
671   GlobalTexturesCache().release(g_attenuation_xy);
672   GlobalTexturesCache().release(g_attenuation_z);
673 }
674
675 bool g_vertexProgram_enabled = false;
676
677 void enableVertexProgram()
678 {
679         //set up the register combiners
680         //two general combiners
681         glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, 2);
682
683         //combiner 0 does tex0+tex1 -> spare0
684         glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_A_NV, GL_TEXTURE0_ARB,
685                                                 GL_UNSIGNED_IDENTITY_NV, GL_RGB);
686         glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_B_NV, GL_ZERO,
687                                                 GL_UNSIGNED_INVERT_NV, GL_RGB);
688         glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_C_NV, GL_TEXTURE1_ARB,
689                                                 GL_UNSIGNED_IDENTITY_NV, GL_RGB);
690         glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_D_NV, GL_ZERO,
691                                                 GL_UNSIGNED_INVERT_NV, GL_RGB);
692         glCombinerOutputNV(GL_COMBINER0_NV, GL_RGB, GL_DISCARD_NV, GL_DISCARD_NV, GL_SPARE0_NV,
693                                                 GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE);
694
695         //combiner 1 does tex2 dot tex3 -> spare1
696         glCombinerInputNV(GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_A_NV, GL_TEXTURE2_ARB,
697                                                 GL_EXPAND_NORMAL_NV, GL_RGB);
698         glCombinerInputNV(GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_B_NV, GL_TEXTURE3_ARB,
699                                                 GL_EXPAND_NORMAL_NV, GL_RGB);
700         glCombinerOutputNV(GL_COMBINER1_NV, GL_RGB, GL_SPARE1_NV, GL_DISCARD_NV, GL_DISCARD_NV,
701                                                 GL_NONE, GL_NONE, GL_TRUE, GL_FALSE, GL_FALSE);
702
703
704
705         //final combiner outputs (1-spare0)*constant color 0*spare1
706         //do constant color 0*spare1 in the EF multiplier
707         glFinalCombinerInputNV(GL_VARIABLE_E_NV, GL_SPARE1_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
708         glFinalCombinerInputNV(GL_VARIABLE_F_NV, GL_CONSTANT_COLOR0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
709         
710         //now do (1-spare0)*EF
711         glFinalCombinerInputNV(GL_VARIABLE_A_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
712         glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
713         glFinalCombinerInputNV(GL_VARIABLE_C_NV, GL_E_TIMES_F_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
714         glFinalCombinerInputNV(GL_VARIABLE_D_NV, GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
715
716   glEnable(GL_VERTEX_PROGRAM_NV);
717         glEnable(GL_REGISTER_COMBINERS_NV);
718   glBindProgramNV(GL_VERTEX_PROGRAM_NV, m_vertex_program);
719   glBindProgramNV(GL_FRAGMENT_PROGRAM_NV, m_fragment_program);
720
721   glActiveTexture(GL_TEXTURE0);
722   glEnable(GL_TEXTURE_2D);
723   glActiveTexture(GL_TEXTURE1);
724   glEnable(GL_TEXTURE_1D);
725   glActiveTexture(GL_TEXTURE2);
726   glEnable(GL_TEXTURE_2D);
727   glActiveTexture(GL_TEXTURE3);
728   glEnable(GL_TEXTURE_2D);
729
730   glEnableClientState(GL_VERTEX_ATTRIB_ARRAY8_NV);
731   glEnableClientState(GL_VERTEX_ATTRIB_ARRAY9_NV);
732   glEnableClientState(GL_VERTEX_ATTRIB_ARRAY10_NV);
733   glEnableClientState(GL_VERTEX_ATTRIB_ARRAY11_NV);
734
735   GlobalOpenGL_debugAssertNoErrors();
736   g_vertexProgram_enabled = true;
737 }
738
739 void disableVertexProgram()
740 {
741   glDisable(GL_VERTEX_PROGRAM_NV);
742   glDisable(GL_REGISTER_COMBINERS_NV);
743
744   glActiveTexture(GL_TEXTURE0);
745   glDisable(GL_TEXTURE_2D);
746   glActiveTexture(GL_TEXTURE1);
747   glDisable(GL_TEXTURE_1D);
748   glActiveTexture(GL_TEXTURE2);
749   glDisable(GL_TEXTURE_2D);
750   glActiveTexture(GL_TEXTURE3);
751   glDisable(GL_TEXTURE_2D);
752
753   glDisableClientState(GL_VERTEX_ATTRIB_ARRAY8_NV);
754   glDisableClientState(GL_VERTEX_ATTRIB_ARRAY9_NV);
755   glDisableClientState(GL_VERTEX_ATTRIB_ARRAY10_NV);
756   glDisableClientState(GL_VERTEX_ATTRIB_ARRAY11_NV);
757
758   GlobalOpenGL_debugAssertNoErrors();
759   g_vertexProgram_enabled = false;
760 }
761
762 class GLstringNV
763 {
764 public:
765   const GLubyte* m_string;
766   const GLint m_length;
767   GLstringNV(const char* string) : m_string(reinterpret_cast<const GLubyte*>(string)), m_length(GLint(string_length(string)))
768   {
769   }
770 };
771
772 GLstringNV g_light_origin("light_origin");
773 GLstringNV g_view_origin("view_origin");
774 GLstringNV g_light_color("light_color");
775 GLstringNV g_bumpGLSL_scale("bump_scale");
776 GLstringNV g_specular_exponent("specular_exponent");
777
778 void setVertexProgramEnvironment(const Vector3& localViewer)
779 {
780   Matrix4 local2light(g_matrix4_identity);
781   matrix4_translate_by_vec3(local2light, Vector3(0.5, 0.5, 0.5));
782   matrix4_scale_by_vec3(local2light, Vector3(0.5, 0.5, 0.5));
783   matrix4_scale_by_vec3(local2light, Vector3(1.0 / 512.0, 1.0 / 512.0, 1.0 / 512.0));
784   matrix4_translate_by_vec3(local2light, vector3_negated(localViewer));
785
786   glActiveTexture(GL_TEXTURE3);
787   glClientActiveTexture(GL_TEXTURE3);
788
789   glMatrixMode(GL_TEXTURE);
790   glLoadMatrixf(reinterpret_cast<const float*>(&local2light));
791   glMatrixMode(GL_MODELVIEW);
792
793   glTrackMatrixNV(GL_VERTEX_PROGRAM_NV, 0, GL_MODELVIEW_PROJECTION_NV, GL_IDENTITY_NV);
794   glTrackMatrixNV(GL_VERTEX_PROGRAM_NV, 4, GL_TEXTURE0_ARB, GL_IDENTITY_NV);
795
796   // view origin
797   //qglProgramNamedParameter4fNV(m_fragment_program, g_view_origin.m_length, g_view_origin.m_string, localViewer.x(), localViewer.y(), localViewer.z(), 0);
798
799   // light origin
800   glProgramParameter4fNV(GL_VERTEX_PROGRAM_NV, 8, localViewer.x(), localViewer.y(), localViewer.z(), 1.0f);
801
802   // light colour
803   glCombinerParameterfNV(GL_CONSTANT_COLOR0_NV, 1, 1, 1, 1)
804
805   // bump scale
806   //qglProgramNamedParameter4fNV(m_fragment_program, g_bumpGLSL_scale.m_length, g_bumpGLSL_scale.m_string, 1, 0, 0, 0);
807
808   // specular exponent
809   //qglProgramNamedParameter4fNV(m_fragment_program, g_specular_exponent.m_length, g_specular_exponent.m_string, 32, 0, 0, 0);
810
811   GlobalOpenGL_debugAssertNoErrors();
812 }
813
814 #endif
815
816
817 bool g_vertexArray_enabled = false;
818 bool g_normalArray_enabled = false;
819 bool g_texcoordArray_enabled = false;
820 bool g_colorArray_enabled = false;
821
822 inline bool OpenGLState_less(const OpenGLState& self, const OpenGLState& other)
823 {
824   //! Sort by sort-order override.
825   if(self.m_sort != other.m_sort)
826   {
827     return self.m_sort < other.m_sort;
828   }
829   //! Sort by texture handle.
830   if(self.m_texture != other.m_texture)
831   {
832     return self.m_texture < other.m_texture;
833   }
834   if(self.m_texture1 != other.m_texture1)
835   {
836     return self.m_texture1 < other.m_texture1;
837   }
838   if(self.m_texture2 != other.m_texture2)
839   {
840     return self.m_texture2 < other.m_texture2;
841   }
842   if(self.m_texture3 != other.m_texture3)
843   {
844     return self.m_texture3 < other.m_texture3;
845   }
846   if(self.m_texture4 != other.m_texture4)
847   {
848     return self.m_texture4 < other.m_texture4;
849   }
850   if(self.m_texture5 != other.m_texture5)
851   {
852     return self.m_texture5 < other.m_texture5;
853   }
854   if(self.m_texture6 != other.m_texture6)
855   {
856     return self.m_texture6 < other.m_texture6;
857   }
858   if(self.m_texture7 != other.m_texture7)
859   {
860     return self.m_texture7 < other.m_texture7;
861   }
862   //! Sort by state bit-vector.
863   if(self.m_state != other.m_state)
864   {
865     return self.m_state < other.m_state;
866   }
867   //! Comparing address makes sure states are never equal.
868   return &self < &other;
869 }
870
871 void OpenGLState_constructDefault(OpenGLState& state)
872 {
873   state.m_state = RENDER_DEFAULT;
874
875   state.m_texture = 0;
876   state.m_texture1 = 0;
877   state.m_texture2 = 0;
878   state.m_texture3 = 0;
879   state.m_texture4 = 0;
880   state.m_texture5 = 0;
881   state.m_texture6 = 0;
882   state.m_texture7 = 0;
883
884   state.m_colour[0] = 1;
885   state.m_colour[1] = 1;
886   state.m_colour[2] = 1;
887   state.m_colour[3] = 1;
888
889   state.m_depthfunc = GL_LESS;
890
891   state.m_blend_src = GL_SRC_ALPHA;
892   state.m_blend_dst = GL_ONE_MINUS_SRC_ALPHA;
893
894   state.m_alphafunc = GL_ALWAYS;
895   state.m_alpharef = 0;
896
897   state.m_linewidth = 1;
898   state.m_pointsize = 1;
899
900   state.m_linestipple_factor = 1;
901   state.m_linestipple_pattern = 0xaaaa;
902
903   state.m_fog = OpenGLFogState();
904 }
905
906
907
908
909 /// \brief A container of Renderable references.
910 /// May contain the same Renderable multiple times, with different transforms.
911 class OpenGLStateBucket
912 {
913 public:
914   struct RenderTransform
915   {
916     const Matrix4* m_transform;
917     const OpenGLRenderable *m_renderable;
918     const RendererLight* m_light;
919
920     RenderTransform(const OpenGLRenderable& renderable, const Matrix4& transform, const RendererLight* light)
921       : m_transform(&transform), m_renderable(&renderable), m_light(light)
922     {
923     }
924   };
925
926   typedef std::vector<RenderTransform> Renderables;
927
928 private:
929
930   OpenGLState m_state;
931   Renderables m_renderables;
932
933 public:
934   OpenGLStateBucket()
935   {
936   }
937   void addRenderable(const OpenGLRenderable& renderable, const Matrix4& modelview, const RendererLight* light = 0)
938   {
939     m_renderables.push_back(RenderTransform(renderable, modelview, light));
940   }
941
942   OpenGLState& state()
943   {
944     return m_state;
945   }
946
947   void render(OpenGLState& current, unsigned int globalstate, const Vector3& viewer);
948 };
949
950 #define LIGHT_SHADER_DEBUG 0
951
952 #if LIGHT_SHADER_DEBUG
953 typedef std::vector<Shader*> LightDebugShaders;
954 LightDebugShaders g_lightDebugShaders;
955 #endif
956
957 class OpenGLStateLess
958 {
959 public:
960   bool operator()(const OpenGLState& self, const OpenGLState& other) const
961   {
962     return OpenGLState_less(self, other);
963   }
964 };
965
966 typedef ConstReference<OpenGLState> OpenGLStateReference;
967 typedef std::map<OpenGLStateReference, OpenGLStateBucket*, OpenGLStateLess> OpenGLStates;
968 OpenGLStates g_state_sorted;
969
970 class OpenGLStateBucketAdd
971 {
972   OpenGLStateBucket& m_bucket;
973   const OpenGLRenderable& m_renderable;
974   const Matrix4& m_modelview;
975 public:
976   typedef const RendererLight& first_argument_type;
977
978   OpenGLStateBucketAdd(OpenGLStateBucket& bucket, const OpenGLRenderable& renderable, const Matrix4& modelview) :
979     m_bucket(bucket), m_renderable(renderable), m_modelview(modelview)
980   {
981   }
982   void operator()(const RendererLight& light)
983   {
984     m_bucket.addRenderable(m_renderable, m_modelview, &light);
985   }
986 };
987
988 class CountLights
989 {
990   std::size_t m_count;
991 public:
992   typedef RendererLight& first_argument_type;
993
994   CountLights() : m_count(0)
995   {
996   }
997   void operator()(const RendererLight& light)
998   {
999     ++m_count;
1000   }
1001   std::size_t count() const
1002   {
1003     return m_count;
1004   }
1005 };
1006
1007 class OpenGLShader : public Shader
1008 {
1009   typedef std::list<OpenGLStateBucket*> Passes;
1010   Passes m_passes;
1011   IShader* m_shader;
1012   std::size_t m_used;
1013   ModuleObservers m_observers;
1014 public:
1015   OpenGLShader() : m_shader(0), m_used(0)
1016   {
1017   }
1018   ~OpenGLShader()
1019   {
1020   }
1021   void construct(const char* name);
1022   void destroy()
1023   {
1024     if(m_shader)
1025     {
1026       m_shader->DecRef();
1027     }
1028     m_shader = 0;
1029
1030     for(Passes::iterator i = m_passes.begin(); i != m_passes.end(); ++i)
1031     {
1032       delete *i;
1033     }
1034     m_passes.clear();
1035   }
1036   void addRenderable(const OpenGLRenderable& renderable, const Matrix4& modelview, const LightList* lights)
1037   {
1038     for(Passes::iterator i = m_passes.begin(); i != m_passes.end(); ++i)
1039     {
1040 #if LIGHT_SHADER_DEBUG
1041       if(((*i)->state().m_state & RENDER_BUMP) != 0)
1042       {
1043         if(lights != 0)
1044         {
1045           CountLights counter;
1046           lights->forEachLight(makeCallback1(counter));
1047           globalOutputStream() << "count = " << counter.count() << "\n";
1048           for(std::size_t i = 0; i < counter.count(); ++i)
1049           {
1050             g_lightDebugShaders[counter.count()]->addRenderable(renderable, modelview);
1051           }
1052         }
1053       }
1054       else
1055 #else
1056       if(((*i)->state().m_state & RENDER_BUMP) != 0)
1057       {
1058         if(lights != 0)
1059         {
1060           OpenGLStateBucketAdd add(*(*i), renderable, modelview);
1061           lights->forEachLight(makeCallback1(add));
1062         }
1063       }
1064       else
1065 #endif
1066       {
1067         (*i)->addRenderable(renderable, modelview);
1068       }
1069     }
1070   }
1071   void incrementUsed()
1072   {
1073     if(++m_used == 1 && m_shader != 0)
1074     { 
1075       m_shader->SetInUse(true);
1076     }
1077   }
1078   void decrementUsed()
1079   {
1080     if(--m_used == 0 && m_shader != 0)
1081     {
1082       m_shader->SetInUse(false);
1083     }
1084   }
1085   bool realised() const
1086   {
1087     return m_shader != 0;
1088   }
1089   void attach(ModuleObserver& observer)
1090   {
1091     if(realised())
1092     {
1093       observer.realise();
1094     }
1095     m_observers.attach(observer);
1096   }
1097   void detach(ModuleObserver& observer)
1098   {
1099     if(realised())
1100     {
1101       observer.unrealise();
1102     }
1103     m_observers.detach(observer);
1104   }
1105   void realise(const CopiedString& name)
1106   {
1107     construct(name.c_str());
1108
1109     if(m_used != 0 && m_shader != 0)
1110     {
1111       m_shader->SetInUse(true);
1112     }
1113     
1114     for(Passes::iterator i = m_passes.begin(); i != m_passes.end(); ++i)
1115     {
1116       g_state_sorted.insert(OpenGLStates::value_type(OpenGLStateReference((*i)->state()), *i));
1117     }
1118
1119     m_observers.realise();
1120   }
1121   void unrealise()
1122   {
1123     m_observers.unrealise();
1124
1125     for(Passes::iterator i = m_passes.begin(); i != m_passes.end(); ++i)
1126     {
1127       g_state_sorted.erase(OpenGLStateReference((*i)->state()));
1128     }
1129
1130     destroy();
1131   }
1132   qtexture_t& getTexture() const
1133   {
1134     ASSERT_NOTNULL(m_shader);
1135     return *m_shader->getTexture();
1136   }
1137   unsigned int getFlags() const
1138   {
1139     ASSERT_NOTNULL(m_shader);
1140     return m_shader->getFlags();
1141   }
1142   IShader& getShader() const
1143   {
1144     ASSERT_NOTNULL(m_shader);
1145     return *m_shader;
1146   }
1147   OpenGLState& appendDefaultPass()
1148   {
1149     m_passes.push_back(new OpenGLStateBucket);
1150     OpenGLState& state = m_passes.back()->state();
1151     OpenGLState_constructDefault(state);
1152     return state;
1153   }
1154 };
1155
1156
1157 inline bool lightEnabled(const RendererLight& light, const LightCullable& cullable)
1158 {
1159   return cullable.testLight(light);
1160 }
1161
1162 typedef std::set<RendererLight*> RendererLights;
1163
1164 #define DEBUG_LIGHT_SYNC 0
1165
1166 class LinearLightList : public LightList
1167 {
1168   LightCullable& m_cullable;
1169   RendererLights& m_allLights;
1170   Callback m_evaluateChanged;
1171
1172   typedef std::list<RendererLight*> Lights;
1173   mutable Lights m_lights;
1174   mutable bool m_lightsChanged;
1175 public:
1176   LinearLightList(LightCullable& cullable, RendererLights& lights, const Callback& evaluateChanged) :
1177     m_cullable(cullable), m_allLights(lights), m_evaluateChanged(evaluateChanged)
1178   {
1179     m_lightsChanged = true;
1180   }
1181   void evaluateLights() const
1182   {
1183     m_evaluateChanged();
1184     if(m_lightsChanged)
1185     {
1186       m_lightsChanged = false;
1187
1188       m_lights.clear();
1189       m_cullable.clearLights();
1190       for(RendererLights::const_iterator i = m_allLights.begin(); i != m_allLights.end(); ++i)
1191       {
1192         if(lightEnabled(*(*i), m_cullable))
1193         {
1194           m_lights.push_back(*i);
1195           m_cullable.insertLight(*(*i));
1196         }
1197       }
1198     }
1199 #if(DEBUG_LIGHT_SYNC)
1200     else
1201     {
1202       Lights lights;
1203       for(RendererLights::const_iterator i = m_allLights.begin(); i != m_allLights.end(); ++i)
1204       {
1205         if(lightEnabled(*(*i), m_cullable))
1206         {
1207           lights.push_back(*i);
1208         }
1209       }
1210       ASSERT_MESSAGE(
1211         !std::lexicographical_compare(lights.begin(), lights.end(), m_lights.begin(), m_lights.end())
1212         && !std::lexicographical_compare(m_lights.begin(), m_lights.end(), lights.begin(), lights.end()),
1213         "lights out of sync"
1214       );
1215     }
1216 #endif
1217   }
1218   void forEachLight(const RendererLightCallback& callback) const
1219   {
1220     evaluateLights();
1221
1222     for(Lights::const_iterator i = m_lights.begin(); i != m_lights.end(); ++i)
1223     {
1224       callback(*(*i));
1225     }
1226   }
1227   void lightsChanged() const
1228   {
1229     m_lightsChanged = true;
1230   }
1231 };
1232
1233 inline void setFogState(const OpenGLFogState& state)
1234 {
1235         glFogi(GL_FOG_MODE, state.mode);
1236         glFogf(GL_FOG_DENSITY, state.density);
1237         glFogf(GL_FOG_START, state.start);
1238         glFogf(GL_FOG_END, state.end);
1239         glFogi(GL_FOG_INDEX, state.index);
1240         glFogfv(GL_FOG_COLOR, vector4_to_array(state.colour));
1241 }
1242
1243 #define DEBUG_SHADERS 0
1244
1245 class OpenGLShaderCache : public ShaderCache, public TexturesCacheObserver, public ModuleObserver
1246 {
1247   class CreateOpenGLShader
1248   {
1249     OpenGLShaderCache* m_cache;
1250   public:
1251     explicit CreateOpenGLShader(OpenGLShaderCache* cache = 0)
1252       : m_cache(cache)
1253     {
1254     }
1255     OpenGLShader* construct(const CopiedString& name)
1256     {
1257       OpenGLShader* shader = new OpenGLShader;
1258       if(m_cache->realised())
1259       {
1260         shader->realise(name);
1261       }
1262       return shader;
1263     }
1264     void destroy(OpenGLShader* shader)
1265     {
1266       if(m_cache->realised())
1267       {
1268         shader->unrealise();
1269       }
1270       delete shader;
1271     }
1272   };
1273
1274   typedef HashedCache<CopiedString, OpenGLShader, HashString, std::equal_to<CopiedString>, CreateOpenGLShader> Shaders;
1275   Shaders m_shaders;
1276   std::size_t m_unrealised;
1277
1278   bool m_lightingEnabled;
1279   bool m_lightingSupported;
1280   bool m_useShaderLanguage;
1281
1282 public:
1283   OpenGLShaderCache()
1284     : m_shaders(CreateOpenGLShader(this)),
1285     m_unrealised(3), // wait until shaders, gl-context and textures are realised before creating any render-states
1286     m_lightingEnabled(true),
1287     m_lightingSupported(false),
1288     m_useShaderLanguage(false),
1289     m_lightsChanged(true),
1290     m_traverseRenderablesMutex(false)
1291   {
1292   }
1293   ~OpenGLShaderCache()
1294   {
1295     for(Shaders::iterator i = m_shaders.begin(); i != m_shaders.end(); ++i)
1296     {
1297       globalOutputStream() << "leaked shader: " << makeQuoted((*i).key.c_str()) << "\n";
1298     }
1299   }
1300   Shader* capture(const char* name)
1301   {
1302     ASSERT_MESSAGE(name[0] == '$'
1303       || *name == '['
1304       || *name == '<'
1305       || *name == '('
1306       || strchr(name, '\\') == 0, "shader name contains invalid characters: \"" << name << "\""); 
1307 #if DEBUG_SHADERS
1308     globalOutputStream() << "shaders capture: " << makeQuoted(name) << '\n';
1309 #endif
1310     return m_shaders.capture(name).get();
1311   }
1312   void release(const char *name)
1313   {
1314 #if DEBUG_SHADERS
1315     globalOutputStream() << "shaders release: " << makeQuoted(name) << '\n';
1316 #endif
1317     m_shaders.release(name);
1318   }
1319   void render(RenderStateFlags globalstate, const Matrix4& modelview, const Matrix4& projection, const Vector3& viewer)
1320   {
1321     glMatrixMode(GL_PROJECTION);
1322     glLoadMatrixf(reinterpret_cast<const float*>(&projection));
1323   #if 0
1324     //qglGetFloatv(GL_PROJECTION_MATRIX, reinterpret_cast<float*>(&projection));
1325   #endif
1326
1327     glMatrixMode(GL_MODELVIEW);
1328     glLoadMatrixf(reinterpret_cast<const float*>(&modelview));
1329   #if 0
1330     //qglGetFloatv(GL_MODELVIEW_MATRIX, reinterpret_cast<float*>(&modelview));
1331   #endif
1332  
1333     ASSERT_MESSAGE(realised(), "render states are not realised");
1334
1335     // global settings that are not set in renderstates
1336     glFrontFace(GL_CW);
1337     glCullFace(GL_BACK);
1338     glPolygonOffset(-1, 1);
1339     {
1340       const GLubyte pattern[132] = {
1341               0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1342               0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1343               0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1344               0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1345               0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1346               0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1347               0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1348               0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1349               0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1350               0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1351               0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1352               0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1353               0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1354               0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1355               0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1356               0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55
1357      };
1358       glPolygonStipple(pattern);
1359     }
1360     glEnableClientState(GL_VERTEX_ARRAY);
1361     g_vertexArray_enabled = true;
1362     glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
1363
1364     if(GlobalOpenGL().GL_1_3())
1365     {
1366       glActiveTexture(GL_TEXTURE0);
1367       glClientActiveTexture(GL_TEXTURE0);
1368     }
1369
1370     if(GlobalOpenGL().ARB_shader_objects())
1371     {
1372       glUseProgramObjectARB(0);
1373       glDisableVertexAttribArrayARB(c_attr_TexCoord0);
1374       glDisableVertexAttribArrayARB(c_attr_Tangent);
1375       glDisableVertexAttribArrayARB(c_attr_Binormal);
1376     }
1377
1378     if(globalstate & RENDER_TEXTURE)
1379     {
1380       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
1381       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
1382     }
1383
1384     OpenGLState current;
1385     OpenGLState_constructDefault(current);
1386     current.m_sort = OpenGLState::eSortFirst;
1387
1388     // default renderstate settings
1389     glLineStipple(current.m_linestipple_factor, current.m_linestipple_pattern);
1390     glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
1391     glDisable(GL_LIGHTING);
1392     glDisable(GL_TEXTURE_2D);
1393     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1394     g_texcoordArray_enabled = false;
1395     glDisableClientState(GL_COLOR_ARRAY);
1396     g_colorArray_enabled = false;
1397     glDisableClientState(GL_NORMAL_ARRAY);
1398     g_normalArray_enabled = false;
1399     glDisable(GL_BLEND);
1400     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1401     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1402     glDisable(GL_CULL_FACE);
1403     glShadeModel(GL_FLAT);
1404     glDisable(GL_DEPTH_TEST);
1405     glDepthMask(GL_FALSE);
1406     glDisable(GL_ALPHA_TEST);
1407     glDisable(GL_LINE_STIPPLE);
1408     glDisable(GL_POLYGON_STIPPLE);
1409     glDisable(GL_POLYGON_OFFSET_LINE);
1410
1411     glBindTexture(GL_TEXTURE_2D, 0);
1412     glColor4f(1,1,1,1);
1413     glDepthFunc(GL_LESS);
1414     glAlphaFunc(GL_ALWAYS, 0);
1415     glLineWidth(1);
1416     glPointSize(1);
1417
1418           glHint(GL_FOG_HINT, GL_NICEST);
1419     glDisable(GL_FOG);
1420     setFogState(OpenGLFogState());
1421
1422     GlobalOpenGL_debugAssertNoErrors();
1423
1424     debug_string("begin rendering");
1425     for(OpenGLStates::iterator i = g_state_sorted.begin(); i != g_state_sorted.end(); ++i)
1426     {
1427       (*i).second->render(current, globalstate, viewer);
1428     }
1429     debug_string("end rendering");
1430   }
1431   void realise()
1432   {
1433     if(--m_unrealised == 0)
1434     {
1435       if(lightingSupported() && lightingEnabled())
1436       {
1437         if(useShaderLanguage())
1438         {
1439           g_bumpGLSL.create();
1440           g_depthFillGLSL.create();
1441         }
1442         else
1443         {
1444           g_bumpARB.create();
1445           g_depthFillARB.create();
1446         }
1447       }
1448
1449       for(Shaders::iterator i = m_shaders.begin(); i != m_shaders.end(); ++i)
1450       {
1451         if(!(*i).value.empty())
1452         {
1453           (*i).value->realise(i->key);
1454         }
1455       }
1456     }
1457   }
1458   void unrealise()
1459   {
1460     if(++m_unrealised == 1)
1461     {
1462       for(Shaders::iterator i = m_shaders.begin(); i != m_shaders.end(); ++i)
1463       {
1464         if(!(*i).value.empty())
1465         {
1466           (*i).value->unrealise();
1467         }
1468       }
1469       if(GlobalOpenGL().contextValid && lightingSupported() && lightingEnabled())
1470       {
1471         if(useShaderLanguage())
1472         {
1473           g_bumpGLSL.destroy();
1474           g_depthFillGLSL.destroy();
1475         }
1476         else
1477         {
1478           g_bumpARB.destroy();
1479           g_depthFillARB.destroy();
1480         }
1481       }
1482     }
1483   }
1484   bool realised()
1485   {
1486     return m_unrealised == 0;
1487   }
1488
1489
1490   bool lightingEnabled() const
1491   {
1492     return m_lightingEnabled;
1493   }
1494   bool lightingSupported() const
1495   {
1496     return m_lightingSupported;
1497   }
1498   bool useShaderLanguage() const
1499   {
1500     return m_useShaderLanguage;
1501   }
1502   void setLighting(bool supported, bool enabled)
1503   {
1504     bool refresh = (m_lightingSupported && m_lightingEnabled) != (supported && enabled);
1505
1506     if(refresh)
1507     {
1508       unrealise();
1509       GlobalShaderSystem().setLightingEnabled(supported && enabled);
1510     }
1511
1512     m_lightingSupported = supported;
1513     m_lightingEnabled = enabled;
1514
1515     if(refresh)
1516     {
1517       realise();
1518     }
1519   }
1520   void extensionsInitialised()
1521   {
1522     setLighting(GlobalOpenGL().GL_1_3()
1523       && GlobalOpenGL().ARB_vertex_program()
1524       && GlobalOpenGL().ARB_fragment_program()
1525       && GlobalOpenGL().ARB_shader_objects()
1526       && GlobalOpenGL().ARB_vertex_shader()
1527       && GlobalOpenGL().ARB_fragment_shader()
1528       && GlobalOpenGL().ARB_shading_language_100(),
1529       m_lightingEnabled
1530     );
1531
1532     if(!lightingSupported())
1533     {
1534       globalOutputStream() << "Lighting mode requires OpenGL features not supported by your graphics drivers:\n";
1535       if(!GlobalOpenGL().GL_1_3())
1536       {
1537         globalOutputStream() << "  GL version 1.3 or better\n";
1538       }
1539       if(!GlobalOpenGL().ARB_vertex_program())
1540       {
1541         globalOutputStream() << "  GL_ARB_vertex_program\n";
1542       }
1543       if(!GlobalOpenGL().ARB_fragment_program())
1544       {
1545         globalOutputStream() << "  GL_ARB_fragment_program\n";
1546       }
1547       if(!GlobalOpenGL().ARB_shader_objects())
1548       {
1549         globalOutputStream() << "  GL_ARB_shader_objects\n";
1550       }
1551       if(!GlobalOpenGL().ARB_vertex_shader())
1552       {
1553         globalOutputStream() << "  GL_ARB_vertex_shader\n";
1554       }
1555       if(!GlobalOpenGL().ARB_fragment_shader())
1556       {
1557         globalOutputStream() << "  GL_ARB_fragment_shader\n";
1558       }
1559       if(!GlobalOpenGL().ARB_shading_language_100())
1560       {
1561         globalOutputStream() << "  GL_ARB_shading_language_100\n";
1562       }
1563     }
1564   }
1565   void setLightingEnabled(bool enabled)
1566   {
1567     setLighting(m_lightingSupported, enabled);
1568   }
1569
1570   // light culling
1571
1572   RendererLights m_lights;
1573   bool m_lightsChanged;
1574   typedef std::map<LightCullable*, LinearLightList> LightLists;
1575   LightLists m_lightLists;
1576
1577   const LightList& attach(LightCullable& cullable)
1578   {
1579     return (*m_lightLists.insert(LightLists::value_type(&cullable, LinearLightList(cullable, m_lights, EvaluateChangedCaller(*this)))).first).second;
1580   }
1581   void detach(LightCullable& cullable)
1582   {
1583     m_lightLists.erase(&cullable);
1584   }
1585   void changed(LightCullable& cullable)
1586   {
1587     LightLists::iterator i = m_lightLists.find(&cullable);
1588     ASSERT_MESSAGE(i != m_lightLists.end(), "cullable not attached");
1589     (*i).second.lightsChanged();
1590   }
1591   void attach(RendererLight& light)
1592   {
1593     ASSERT_MESSAGE(m_lights.find(&light) == m_lights.end(), "light could not be attached");
1594     m_lights.insert(&light);
1595     changed(light);
1596   }
1597   void detach(RendererLight& light)
1598   {
1599     ASSERT_MESSAGE(m_lights.find(&light) != m_lights.end(), "light could not be detached");
1600     m_lights.erase(&light);
1601     changed(light);
1602   }
1603   void changed(RendererLight& light)
1604   {
1605     m_lightsChanged = true;
1606   }
1607   void evaluateChanged()
1608   {
1609     if(m_lightsChanged)
1610     {
1611       m_lightsChanged = false;
1612       for(LightLists::iterator i = m_lightLists.begin(); i != m_lightLists.end(); ++i)
1613       {
1614         (*i).second.lightsChanged();
1615       }
1616     }
1617   }
1618   typedef MemberCaller<OpenGLShaderCache, &OpenGLShaderCache::evaluateChanged> EvaluateChangedCaller;
1619
1620   typedef std::set<const Renderable*> Renderables; 
1621   Renderables m_renderables;
1622   mutable bool m_traverseRenderablesMutex;
1623
1624   // renderables
1625   void attachRenderable(const Renderable& renderable)
1626   {
1627     ASSERT_MESSAGE(!m_traverseRenderablesMutex, "attaching renderable during traversal");
1628     ASSERT_MESSAGE(m_renderables.find(&renderable) == m_renderables.end(), "renderable could not be attached");
1629     m_renderables.insert(&renderable);
1630   }
1631   void detachRenderable(const Renderable& renderable)
1632   {
1633     ASSERT_MESSAGE(!m_traverseRenderablesMutex, "detaching renderable during traversal");
1634     ASSERT_MESSAGE(m_renderables.find(&renderable) != m_renderables.end(), "renderable could not be detached");
1635     m_renderables.erase(&renderable);
1636   }
1637   void forEachRenderable(const RenderableCallback& callback) const
1638   {
1639     ASSERT_MESSAGE(!m_traverseRenderablesMutex, "for-each during traversal");
1640     m_traverseRenderablesMutex = true;
1641     for(Renderables::const_iterator i = m_renderables.begin(); i != m_renderables.end(); ++i)
1642     {
1643       callback(*(*i));
1644     }
1645     m_traverseRenderablesMutex = false;
1646   }
1647 };
1648
1649 static OpenGLShaderCache* g_ShaderCache;
1650
1651 void ShaderCache_extensionsInitialised()
1652 {
1653   g_ShaderCache->extensionsInitialised();
1654 }
1655
1656 void ShaderCache_setBumpEnabled(bool enabled)
1657 {
1658   g_ShaderCache->setLightingEnabled(enabled);
1659 }
1660
1661
1662 Vector3 g_DebugShaderColours[256];
1663 Shader* g_defaultPointLight = 0;
1664
1665 void ShaderCache_Construct()
1666 {
1667   g_ShaderCache = new OpenGLShaderCache;
1668   GlobalTexturesCache().attach(*g_ShaderCache);
1669   GlobalShaderSystem().attach(*g_ShaderCache);
1670
1671   if(g_pGameDescription->mGameType == "doom3")
1672   {
1673     g_defaultPointLight = g_ShaderCache->capture("lights/defaultPointLight");
1674     //Shader* overbright =
1675     g_ShaderCache->capture("$OVERBRIGHT");
1676
1677 #if LIGHT_SHADER_DEBUG
1678     for(std::size_t i = 0; i < 256; ++i)
1679     {
1680       g_DebugShaderColours[i] = Vector3(i / 256.0, i / 256.0, i / 256.0);
1681     }
1682
1683     g_DebugShaderColours[0] = Vector3(1, 0, 0);
1684     g_DebugShaderColours[1] = Vector3(1, 0.5, 0);
1685     g_DebugShaderColours[2] = Vector3(1, 1, 0);
1686     g_DebugShaderColours[3] = Vector3(0.5, 1, 0);
1687     g_DebugShaderColours[4] = Vector3(0, 1, 0);
1688     g_DebugShaderColours[5] = Vector3(0, 1, 0.5);
1689     g_DebugShaderColours[6] = Vector3(0, 1, 1);
1690     g_DebugShaderColours[7] = Vector3(0, 0.5, 1);
1691     g_DebugShaderColours[8] = Vector3(0, 0, 1);
1692     g_DebugShaderColours[9] = Vector3(0.5, 0, 1);
1693     g_DebugShaderColours[10] = Vector3(1, 0, 1);
1694     g_DebugShaderColours[11] = Vector3(1, 0, 0.5);
1695
1696     g_lightDebugShaders.reserve(256);
1697     StringOutputStream buffer(256);
1698     for(std::size_t i = 0; i < 256; ++i)
1699     {
1700       buffer << "(" << g_DebugShaderColours[i].x() << " " << g_DebugShaderColours[i].y() << " " << g_DebugShaderColours[i].z() << ")";
1701       g_lightDebugShaders.push_back(g_ShaderCache->capture(buffer.c_str()));
1702       buffer.clear();
1703     }
1704 #endif
1705   }
1706 }
1707
1708 void ShaderCache_Destroy()
1709 {
1710   if(g_pGameDescription->mGameType == "doom3")
1711   {
1712     g_ShaderCache->release("lights/defaultPointLight");
1713     g_ShaderCache->release("$OVERBRIGHT");
1714     g_defaultPointLight = 0;
1715
1716 #if LIGHT_SHADER_DEBUG
1717     g_lightDebugShaders.clear();
1718     StringOutputStream buffer(256);
1719     for(std::size_t i = 0; i < 256; ++i)
1720     {
1721       buffer << "(" << g_DebugShaderColours[i].x() << " " << g_DebugShaderColours[i].y() << " " << g_DebugShaderColours[i].z() << ")";
1722       g_ShaderCache->release(buffer.c_str());
1723     }
1724 #endif
1725   }
1726
1727   GlobalShaderSystem().detach(*g_ShaderCache);
1728   GlobalTexturesCache().detach(*g_ShaderCache);
1729   delete g_ShaderCache;
1730 }
1731
1732 ShaderCache* GetShaderCache()
1733 {
1734   return g_ShaderCache;
1735 }
1736
1737 inline void setTextureState(GLint& current, const GLint& texture, GLenum textureUnit)
1738 {
1739   if(texture != current)
1740   {
1741     glActiveTexture(textureUnit);
1742     glClientActiveTexture(textureUnit);
1743     glBindTexture(GL_TEXTURE_2D, texture);
1744     GlobalOpenGL_debugAssertNoErrors();
1745     current = texture;
1746   }
1747 }
1748
1749 inline void setTextureState(GLint& current, const GLint& texture)
1750 {
1751   if(texture != current)
1752   {
1753     glBindTexture(GL_TEXTURE_2D, texture);
1754     GlobalOpenGL_debugAssertNoErrors();
1755     current = texture;
1756   }
1757 }
1758
1759 inline void setState(unsigned int state, unsigned int delta, unsigned int flag, GLenum glflag)
1760 {
1761   if(delta & state & flag)
1762   {
1763     glEnable(glflag);
1764     GlobalOpenGL_debugAssertNoErrors();
1765   }
1766   else if(delta & ~state & flag)
1767   {
1768     glDisable(glflag);
1769     GlobalOpenGL_debugAssertNoErrors();
1770   }
1771 }
1772
1773 void OpenGLState_apply(const OpenGLState& self, OpenGLState& current, unsigned int globalstate)
1774 {
1775   debug_int("sort", int(self.m_sort));
1776   debug_int("texture", self.m_texture);
1777   debug_int("state", self.m_state);
1778   debug_int("address", int(std::size_t(&self)));
1779
1780   count_state();
1781
1782   if(self.m_state & RENDER_OVERRIDE)
1783   {
1784     globalstate |= RENDER_FILL | RENDER_DEPTHWRITE;
1785   }
1786
1787   const unsigned int state = self.m_state & globalstate;
1788   const unsigned int delta = state ^ current.m_state;
1789
1790   GlobalOpenGL_debugAssertNoErrors();
1791
1792   GLProgram* program = (state & RENDER_PROGRAM) != 0 ? self.m_program : 0;
1793
1794   if(program != current.m_program)
1795   {
1796     if(current.m_program != 0)
1797     {
1798       current.m_program->disable();
1799       glColor4fv(vector4_to_array(current.m_colour));
1800       debug_colour("cleaning program");
1801     }
1802
1803     current.m_program = program;
1804
1805     if(current.m_program != 0)
1806     {
1807       current.m_program->enable();
1808     }
1809   }
1810
1811   if(delta & state & RENDER_FILL)
1812   {
1813     //qglPolygonMode (GL_BACK, GL_LINE);
1814     //qglPolygonMode (GL_FRONT, GL_FILL);
1815     glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
1816     GlobalOpenGL_debugAssertNoErrors();
1817   }
1818   else if(delta & ~state & RENDER_FILL)
1819   {
1820     glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
1821     GlobalOpenGL_debugAssertNoErrors();
1822   }
1823
1824   setState(state, delta, RENDER_OFFSETLINE, GL_POLYGON_OFFSET_LINE);
1825
1826   if(delta & state & RENDER_LIGHTING)
1827   {
1828     glEnable(GL_LIGHTING);
1829     glEnable(GL_COLOR_MATERIAL);
1830     //qglEnable(GL_RESCALE_NORMAL);
1831     glEnableClientState(GL_NORMAL_ARRAY);
1832     GlobalOpenGL_debugAssertNoErrors();
1833     g_normalArray_enabled = true;
1834   }
1835   else if(delta & ~state & RENDER_LIGHTING)
1836   {
1837     glDisable(GL_LIGHTING);
1838     glDisable(GL_COLOR_MATERIAL);
1839     //qglDisable(GL_RESCALE_NORMAL);
1840     glDisableClientState(GL_NORMAL_ARRAY);
1841     GlobalOpenGL_debugAssertNoErrors();
1842     g_normalArray_enabled = false;
1843   }
1844
1845   if(delta & state & RENDER_TEXTURE)
1846   {
1847     GlobalOpenGL_debugAssertNoErrors();
1848
1849     if(GlobalOpenGL().GL_1_3())
1850     {
1851       glActiveTexture(GL_TEXTURE0);
1852       glClientActiveTexture(GL_TEXTURE0);
1853     }
1854
1855     glEnable(GL_TEXTURE_2D);
1856
1857     glColor4f(1,1,1,self.m_colour[3]);
1858     debug_colour("setting texture");
1859
1860     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1861     GlobalOpenGL_debugAssertNoErrors();
1862     g_texcoordArray_enabled = true;
1863   }
1864   else if(delta & ~state & RENDER_TEXTURE)
1865   {
1866     if(GlobalOpenGL().GL_1_3())
1867     {
1868       glActiveTexture(GL_TEXTURE0);
1869       glClientActiveTexture(GL_TEXTURE0);
1870     }
1871
1872     glDisable(GL_TEXTURE_2D);
1873     glBindTexture(GL_TEXTURE_2D, 0);
1874     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1875
1876     GlobalOpenGL_debugAssertNoErrors();
1877     g_texcoordArray_enabled = false;
1878   }
1879
1880   if(delta & state & RENDER_BLEND)
1881   {
1882 // FIXME: some .TGA are buggy, have a completely empty alpha channel
1883 // if such brushes are rendered in this loop they would be totally transparent with GL_MODULATE
1884 // so I decided using GL_DECAL instead
1885 // if an empty-alpha-channel or nearly-empty texture is used. It will be blank-transparent.
1886 // this could get better if you can get glTexEnviv (GL_TEXTURE_ENV, to work .. patches are welcome
1887
1888     glEnable(GL_BLEND);
1889     if(GlobalOpenGL().GL_1_3())
1890     {
1891       glActiveTexture(GL_TEXTURE0);
1892     }
1893     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
1894     GlobalOpenGL_debugAssertNoErrors();
1895   }
1896   else if(delta & ~state & RENDER_BLEND)
1897   {
1898     glDisable(GL_BLEND);
1899     if(GlobalOpenGL().GL_1_3())
1900     {
1901       glActiveTexture(GL_TEXTURE0);
1902     }
1903     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1904     GlobalOpenGL_debugAssertNoErrors();
1905   }
1906
1907   setState(state, delta, RENDER_CULLFACE, GL_CULL_FACE);
1908
1909   if(delta & state & RENDER_SMOOTH)
1910   {
1911     glShadeModel(GL_SMOOTH);
1912     GlobalOpenGL_debugAssertNoErrors();
1913   }
1914   else if(delta & ~state & RENDER_SMOOTH)
1915   {
1916     glShadeModel(GL_FLAT);
1917     GlobalOpenGL_debugAssertNoErrors();
1918   }
1919
1920   setState(state, delta, RENDER_SCALED, GL_NORMALIZE); // not GL_RESCALE_NORMAL
1921
1922   setState(state, delta, RENDER_DEPTHTEST, GL_DEPTH_TEST);
1923
1924   if(delta & state & RENDER_DEPTHWRITE)
1925   {
1926     glDepthMask(GL_TRUE);
1927
1928 #if DEBUG_RENDER
1929     GLboolean depthEnabled;
1930     glGetBooleanv(GL_DEPTH_WRITEMASK, &depthEnabled);
1931     ASSERT_MESSAGE(depthEnabled, "failed to set depth buffer mask bit");
1932 #endif
1933     debug_string("enabled depth-buffer writing");
1934
1935     GlobalOpenGL_debugAssertNoErrors();
1936   }
1937   else if(delta & ~state & RENDER_DEPTHWRITE)
1938   {
1939     glDepthMask(GL_FALSE);
1940
1941 #if DEBUG_RENDER
1942     GLboolean depthEnabled;
1943     glGetBooleanv(GL_DEPTH_WRITEMASK, &depthEnabled);
1944     ASSERT_MESSAGE(!depthEnabled, "failed to set depth buffer mask bit");
1945 #endif
1946     debug_string("disabled depth-buffer writing");
1947
1948     GlobalOpenGL_debugAssertNoErrors();
1949   }
1950
1951   if(delta & state & RENDER_COLOURWRITE)
1952   {
1953     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1954     GlobalOpenGL_debugAssertNoErrors();
1955   }
1956   else if(delta & ~state & RENDER_COLOURWRITE)
1957   {
1958     glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1959     GlobalOpenGL_debugAssertNoErrors();
1960   }
1961
1962   setState(state, delta, RENDER_ALPHATEST, GL_ALPHA_TEST);
1963   
1964   if(delta & state & RENDER_COLOURARRAY)
1965   {
1966     glEnableClientState(GL_COLOR_ARRAY);
1967     GlobalOpenGL_debugAssertNoErrors();
1968     debug_colour("enabling color_array");
1969     g_colorArray_enabled = true;
1970   }
1971   else if(delta & ~state & RENDER_COLOURARRAY)
1972   {
1973     glDisableClientState(GL_COLOR_ARRAY);
1974     glColor4fv(vector4_to_array(self.m_colour));
1975     debug_colour("cleaning color_array");
1976     GlobalOpenGL_debugAssertNoErrors();
1977     g_colorArray_enabled = false;
1978   }
1979
1980   if(delta & ~state & RENDER_COLOURCHANGE)
1981   {
1982     glColor4fv(vector4_to_array(self.m_colour));
1983     GlobalOpenGL_debugAssertNoErrors();
1984   }
1985
1986   setState(state, delta, RENDER_LINESTIPPLE, GL_LINE_STIPPLE);
1987   setState(state, delta, RENDER_LINESMOOTH, GL_LINE_SMOOTH);
1988
1989   setState(state, delta, RENDER_POLYGONSTIPPLE, GL_POLYGON_STIPPLE);
1990   setState(state, delta, RENDER_POLYGONSMOOTH, GL_POLYGON_SMOOTH);
1991
1992   setState(state, delta, RENDER_FOG, GL_FOG);
1993
1994   if((state & RENDER_FOG) != 0)
1995   {
1996     setFogState(self.m_fog);
1997     GlobalOpenGL_debugAssertNoErrors();
1998     current.m_fog = self.m_fog;
1999   }
2000
2001   if(state & RENDER_DEPTHTEST && self.m_depthfunc != current.m_depthfunc)
2002   {
2003     glDepthFunc(self.m_depthfunc);
2004     GlobalOpenGL_debugAssertNoErrors();
2005     current.m_depthfunc = self.m_depthfunc;
2006   }
2007
2008   if(state & RENDER_LINESTIPPLE
2009     && (self.m_linestipple_factor != current.m_linestipple_factor
2010     || self.m_linestipple_pattern != current.m_linestipple_pattern))
2011   {
2012     glLineStipple(self.m_linestipple_factor, self.m_linestipple_pattern);
2013     GlobalOpenGL_debugAssertNoErrors();
2014     current.m_linestipple_factor = self.m_linestipple_factor;
2015     current.m_linestipple_pattern = self.m_linestipple_pattern;
2016   }
2017
2018
2019   if(state & RENDER_ALPHATEST
2020     && ( self.m_alphafunc != current.m_alphafunc
2021     || self.m_alpharef != current.m_alpharef ) )
2022   {
2023     glAlphaFunc(self.m_alphafunc, self.m_alpharef);
2024     GlobalOpenGL_debugAssertNoErrors();
2025     current.m_alphafunc = self.m_alphafunc;
2026     current.m_alpharef = self.m_alpharef;
2027   }
2028
2029   {
2030     GLint texture0 = 0;
2031     GLint texture1 = 0;
2032     GLint texture2 = 0;
2033     GLint texture3 = 0;
2034     GLint texture4 = 0;
2035     GLint texture5 = 0;
2036     GLint texture6 = 0;
2037     GLint texture7 = 0;
2038     //if(state & RENDER_TEXTURE) != 0)
2039     {
2040       texture0 = self.m_texture;
2041       texture1 = self.m_texture1;
2042       texture2 = self.m_texture2;
2043       texture3 = self.m_texture3;
2044       texture4 = self.m_texture4;
2045       texture5 = self.m_texture5;
2046       texture6 = self.m_texture6;
2047       texture7 = self.m_texture7;
2048     }
2049
2050     if(GlobalOpenGL().GL_1_3())
2051     {
2052       setTextureState(current.m_texture, texture0, GL_TEXTURE0);
2053       setTextureState(current.m_texture1, texture1, GL_TEXTURE1);
2054       setTextureState(current.m_texture2, texture2, GL_TEXTURE2);
2055       setTextureState(current.m_texture3, texture3, GL_TEXTURE3);
2056       setTextureState(current.m_texture4, texture4, GL_TEXTURE4);
2057       setTextureState(current.m_texture5, texture5, GL_TEXTURE5);
2058       setTextureState(current.m_texture6, texture6, GL_TEXTURE6);
2059       setTextureState(current.m_texture7, texture7, GL_TEXTURE7);
2060     }
2061     else
2062     {
2063       setTextureState(current.m_texture, texture0);
2064     }
2065   }
2066
2067
2068   if(state & RENDER_TEXTURE && self.m_colour[3] != current.m_colour[3])
2069   {
2070     debug_colour("setting alpha");
2071     glColor4f(1,1,1,self.m_colour[3]);
2072     GlobalOpenGL_debugAssertNoErrors();
2073   }
2074
2075   if(!(state & RENDER_TEXTURE)
2076     && (self.m_colour[0] != current.m_colour[0]
2077     || self.m_colour[1] != current.m_colour[1]
2078     || self.m_colour[2] != current.m_colour[2]
2079     || self.m_colour[3] != current.m_colour[3]))
2080   {
2081     glColor4fv(vector4_to_array(self.m_colour));
2082     debug_colour("setting non-texture");
2083     GlobalOpenGL_debugAssertNoErrors();
2084   }
2085   current.m_colour = self.m_colour;
2086
2087   if(state & RENDER_BLEND
2088     && (self.m_blend_src != current.m_blend_src || self.m_blend_dst != current.m_blend_dst))
2089   {
2090     glBlendFunc(self.m_blend_src, self.m_blend_dst);
2091     GlobalOpenGL_debugAssertNoErrors();
2092     current.m_blend_src = self.m_blend_src;
2093     current.m_blend_dst = self.m_blend_dst;
2094   }
2095
2096   if(!(state & RENDER_FILL)
2097     && self.m_linewidth != current.m_linewidth)
2098   {
2099     glLineWidth(self.m_linewidth);
2100     GlobalOpenGL_debugAssertNoErrors();
2101     current.m_linewidth = self.m_linewidth;
2102   }
2103
2104   if(!(state & RENDER_FILL)
2105     && self.m_pointsize != current.m_pointsize)
2106   {
2107     glPointSize(self.m_pointsize);
2108     GlobalOpenGL_debugAssertNoErrors();
2109     current.m_pointsize = self.m_pointsize;
2110   }
2111
2112   current.m_state = state;
2113
2114   GlobalOpenGL_debugAssertNoErrors();
2115 }
2116
2117 void Renderables_flush(OpenGLStateBucket::Renderables& renderables, OpenGLState& current, unsigned int globalstate, const Vector3& viewer)
2118 {
2119   const Matrix4* transform = 0;
2120   glPushMatrix();
2121   for(OpenGLStateBucket::Renderables::const_iterator i = renderables.begin(); i != renderables.end(); ++i)
2122   {
2123     //qglLoadMatrixf(i->m_transform);
2124     if(!transform || (transform != (*i).m_transform && !matrix4_affine_equal(*transform, *(*i).m_transform)))
2125     {
2126       count_transform();
2127       transform = (*i).m_transform;
2128       glPopMatrix();
2129       glPushMatrix();
2130       glMultMatrixf(reinterpret_cast<const float*>(transform));
2131       glFrontFace(((current.m_state & RENDER_CULLFACE) != 0 && matrix4_handedness(*transform) == MATRIX4_RIGHTHANDED) ? GL_CW : GL_CCW);
2132     }
2133
2134     count_prim();
2135
2136     if(current.m_program != 0 && (*i).m_light != 0)
2137     {
2138       const IShader& lightShader = static_cast<OpenGLShader*>((*i).m_light->getShader())->getShader();
2139       if(lightShader.firstLayer() != 0)
2140       {
2141         GLuint attenuation_xy = lightShader.firstLayer()->texture()->texture_number;
2142         GLuint attenuation_z = lightShader.lightFalloffImage() != 0
2143           ? lightShader.lightFalloffImage()->texture_number
2144           : static_cast<OpenGLShader*>(g_defaultPointLight)->getShader().lightFalloffImage()->texture_number;
2145
2146         setTextureState(current.m_texture3, attenuation_xy, GL_TEXTURE3);
2147         glActiveTexture(GL_TEXTURE3);
2148         glBindTexture(GL_TEXTURE_2D, attenuation_xy);
2149         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
2150         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
2151
2152         setTextureState(current.m_texture4, attenuation_z, GL_TEXTURE4);
2153         glActiveTexture(GL_TEXTURE4);
2154         glBindTexture(GL_TEXTURE_2D, attenuation_z);
2155         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
2156         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2157
2158
2159         AABB lightBounds((*i).m_light->aabb());
2160
2161         Matrix4 world2light(g_matrix4_identity);
2162
2163         if((*i).m_light->isProjected())
2164         {
2165           world2light = (*i).m_light->projection();
2166           matrix4_multiply_by_matrix4(world2light, matrix4_transposed((*i).m_light->rotation()));
2167           matrix4_translate_by_vec3(world2light, vector3_negated(lightBounds.origin)); // world->lightBounds
2168         }
2169         if(!(*i).m_light->isProjected())
2170         {
2171           matrix4_translate_by_vec3(world2light, Vector3(0.5f, 0.5f, 0.5f));
2172           matrix4_scale_by_vec3(world2light, Vector3(0.5f, 0.5f, 0.5f));
2173           matrix4_scale_by_vec3(world2light, Vector3(1.0f / lightBounds.extents.x(), 1.0f / lightBounds.extents.y(), 1.0f / lightBounds.extents.z()));
2174           matrix4_multiply_by_matrix4(world2light, matrix4_transposed((*i).m_light->rotation()));
2175           matrix4_translate_by_vec3(world2light, vector3_negated(lightBounds.origin)); // world->lightBounds
2176         }
2177
2178         current.m_program->setParameters(viewer, *(*i).m_transform, lightBounds.origin + (*i).m_light->offset(), (*i).m_light->colour(), world2light);
2179         debug_string("set lightBounds parameters");
2180       }
2181     }
2182
2183     (*i).m_renderable->render(current.m_state);
2184   }
2185   glPopMatrix();
2186   renderables.clear();
2187 }
2188
2189 void OpenGLStateBucket::render(OpenGLState& current, unsigned int globalstate, const Vector3& viewer)
2190 {
2191   if((globalstate & m_state.m_state & RENDER_SCREEN) != 0)
2192   {
2193     OpenGLState_apply(m_state, current, globalstate);
2194     debug_colour("screen fill");
2195
2196     glMatrixMode(GL_PROJECTION);
2197     glPushMatrix();
2198     glLoadMatrixf(reinterpret_cast<const float*>(&g_matrix4_identity));
2199
2200     glMatrixMode(GL_MODELVIEW);
2201     glPushMatrix();
2202     glLoadMatrixf(reinterpret_cast<const float*>(&g_matrix4_identity));
2203
2204     glBegin(GL_QUADS);
2205     glVertex3f(-1, -1, 0);
2206     glVertex3f(1, -1, 0);
2207     glVertex3f(1, 1, 0);
2208     glVertex3f(-1, 1, 0);
2209     glEnd();
2210
2211     glMatrixMode(GL_PROJECTION);
2212     glPopMatrix();
2213
2214     glMatrixMode(GL_MODELVIEW);
2215     glPopMatrix();
2216   }
2217   else if(!m_renderables.empty())
2218   {
2219     OpenGLState_apply(m_state, current, globalstate);
2220     Renderables_flush(m_renderables, current, globalstate, viewer);
2221   }
2222 }
2223
2224
2225 class OpenGLStateMap : public OpenGLStateLibrary
2226 {
2227   typedef std::map<CopiedString, OpenGLState> States;
2228   States m_states;
2229 public:
2230   ~OpenGLStateMap()
2231   {
2232     ASSERT_MESSAGE(m_states.empty(), "OpenGLStateMap::~OpenGLStateMap: not empty");
2233   }
2234
2235   typedef States::iterator iterator;
2236   iterator begin()
2237   {
2238     return m_states.begin();
2239   }
2240   iterator end()
2241   {
2242     return m_states.end();
2243   }
2244
2245   void getDefaultState(OpenGLState& state) const
2246   {
2247     OpenGLState_constructDefault(state);
2248   }
2249
2250   void insert(const char* name, const OpenGLState& state)
2251   {
2252     bool inserted = m_states.insert(States::value_type(name, state)).second;
2253     ASSERT_MESSAGE(inserted, "OpenGLStateMap::insert: " << name << " already exists");
2254   }
2255   void erase(const char* name)
2256   {
2257     std::size_t count = m_states.erase(name);
2258     ASSERT_MESSAGE(count == 1, "OpenGLStateMap::erase: " << name << " does not exist");
2259   }
2260
2261   iterator find(const char* name)
2262   {
2263     return m_states.find(name);
2264   }
2265 };
2266
2267 OpenGLStateMap* g_openglStates = 0;
2268
2269 inline GLenum convertBlendFactor(BlendFactor factor)
2270 {
2271   switch(factor)
2272   {
2273   case BLEND_ZERO:
2274     return GL_ZERO;
2275   case BLEND_ONE:
2276     return GL_ONE;
2277   case BLEND_SRC_COLOUR:
2278     return GL_SRC_COLOR;
2279   case BLEND_ONE_MINUS_SRC_COLOUR:
2280     return GL_ONE_MINUS_SRC_COLOR;
2281   case BLEND_SRC_ALPHA:
2282     return GL_SRC_ALPHA;
2283   case BLEND_ONE_MINUS_SRC_ALPHA:
2284     return GL_ONE_MINUS_SRC_ALPHA;
2285   case BLEND_DST_COLOUR:
2286     return GL_DST_COLOR;
2287   case BLEND_ONE_MINUS_DST_COLOUR:
2288     return GL_ONE_MINUS_DST_COLOR;
2289   case BLEND_DST_ALPHA:
2290     return GL_DST_ALPHA;
2291   case BLEND_ONE_MINUS_DST_ALPHA:
2292     return GL_ONE_MINUS_DST_ALPHA;
2293   case BLEND_SRC_ALPHA_SATURATE:
2294     return GL_SRC_ALPHA_SATURATE;
2295   }
2296   return GL_ZERO;
2297 }
2298
2299 /// \todo Define special-case shaders in a data file.
2300 void OpenGLShader::construct(const char* name)
2301 {
2302   OpenGLState& state = appendDefaultPass();
2303   switch(name[0])
2304   {
2305   case '(':
2306     sscanf(name, "(%g %g %g)", &state.m_colour[0], &state.m_colour[1], &state.m_colour[2]);
2307     state.m_colour[3] = 1.0f;
2308     state.m_state = RENDER_FILL|RENDER_LIGHTING|RENDER_DEPTHTEST|RENDER_CULLFACE|RENDER_COLOURWRITE|RENDER_DEPTHWRITE;
2309     state.m_sort = OpenGLState::eSortFullbright;
2310     break;
2311
2312   case '[':
2313     sscanf(name, "[%g %g %g]", &state.m_colour[0], &state.m_colour[1], &state.m_colour[2]);
2314     state.m_colour[3] = 0.5f;
2315     state.m_state = RENDER_FILL|RENDER_LIGHTING|RENDER_DEPTHTEST|RENDER_CULLFACE|RENDER_COLOURWRITE|RENDER_DEPTHWRITE|RENDER_BLEND;
2316     state.m_sort = OpenGLState::eSortTranslucent;
2317     break;
2318
2319   case '<':
2320     sscanf(name, "<%g %g %g>", &state.m_colour[0], &state.m_colour[1], &state.m_colour[2]);
2321     state.m_colour[3] = 1;
2322     state.m_state = RENDER_DEPTHTEST|RENDER_COLOURWRITE|RENDER_DEPTHWRITE;
2323     state.m_sort = OpenGLState::eSortFullbright;
2324     state.m_depthfunc = GL_LESS;
2325     state.m_linewidth = 1;
2326     state.m_pointsize = 1;
2327     break;
2328
2329   case '$':
2330     {
2331       OpenGLStateMap::iterator i = g_openglStates->find(name);
2332       if(i != g_openglStates->end())
2333       {
2334         state = (*i).second;
2335         break;
2336       }
2337     }
2338     if(string_equal(name+1, "POINT"))
2339     {
2340       state.m_state = RENDER_COLOURARRAY|RENDER_COLOURWRITE|RENDER_DEPTHWRITE;
2341       state.m_sort = OpenGLState::eSortControlFirst;
2342       state.m_pointsize = 4;
2343     }
2344     else if(string_equal(name+1, "SELPOINT"))
2345     {
2346       state.m_state = RENDER_COLOURARRAY|RENDER_COLOURWRITE|RENDER_DEPTHWRITE;
2347       state.m_sort = OpenGLState::eSortControlFirst + 1;
2348       state.m_pointsize = 4;
2349     }
2350     else if(string_equal(name+1, "BIGPOINT"))
2351     {
2352       state.m_state = RENDER_COLOURARRAY|RENDER_COLOURWRITE|RENDER_DEPTHWRITE;
2353       state.m_sort = OpenGLState::eSortControlFirst;
2354       state.m_pointsize = 6;
2355     }
2356     else if(string_equal(name+1, "PIVOT"))
2357     {
2358       state.m_state = RENDER_COLOURARRAY|RENDER_COLOURWRITE|RENDER_DEPTHTEST|RENDER_DEPTHWRITE;
2359       state.m_sort = OpenGLState::eSortGUI1;
2360       state.m_linewidth = 2;
2361       state.m_depthfunc = GL_LEQUAL;
2362
2363       OpenGLState& hiddenLine = appendDefaultPass();
2364       hiddenLine.m_state = RENDER_COLOURARRAY|RENDER_COLOURWRITE|RENDER_DEPTHTEST|RENDER_LINESTIPPLE;
2365       hiddenLine.m_sort = OpenGLState::eSortGUI0;
2366       hiddenLine.m_linewidth = 2;
2367       hiddenLine.m_depthfunc = GL_GREATER;
2368     }
2369     else if(string_equal(name+1, "LATTICE"))
2370     {
2371       state.m_colour[0] = 1;
2372       state.m_colour[1] = 0.5;
2373       state.m_colour[2] = 0;
2374       state.m_colour[3] = 1;
2375       state.m_state = RENDER_COLOURWRITE|RENDER_DEPTHWRITE;
2376       state.m_sort = OpenGLState::eSortControlFirst;
2377     }
2378     else if(string_equal(name+1, "WIREFRAME"))
2379     {
2380       state.m_state = RENDER_DEPTHTEST|RENDER_COLOURWRITE|RENDER_DEPTHWRITE;
2381       state.m_sort = OpenGLState::eSortFullbright;
2382     }
2383     else if(string_equal(name+1, "CAM_HIGHLIGHT"))
2384     {
2385       state.m_colour[0] = 1;
2386       state.m_colour[1] = 0;
2387       state.m_colour[2] = 0;
2388       state.m_colour[3] = 0.3f;
2389       state.m_state = RENDER_FILL|RENDER_DEPTHTEST|RENDER_CULLFACE|RENDER_BLEND|RENDER_COLOURWRITE|RENDER_DEPTHWRITE;
2390       state.m_sort = OpenGLState::eSortHighlight;
2391       state.m_depthfunc = GL_LEQUAL;
2392     }
2393     else if(string_equal(name+1, "CAM_OVERLAY"))
2394     {
2395 #if 0
2396       state.m_state = RENDER_CULLFACE|RENDER_COLOURWRITE|RENDER_DEPTHWRITE;
2397       state.m_sort = OpenGLState::eSortOverlayFirst;
2398 #else
2399       state.m_state = RENDER_CULLFACE|RENDER_DEPTHTEST|RENDER_COLOURWRITE|RENDER_DEPTHWRITE|RENDER_OFFSETLINE;
2400       state.m_sort = OpenGLState::eSortOverlayFirst + 1;
2401       state.m_depthfunc = GL_LEQUAL;
2402
2403       OpenGLState& hiddenLine = appendDefaultPass();
2404       hiddenLine.m_colour[0] = 0.75;
2405       hiddenLine.m_colour[1] = 0.75;
2406       hiddenLine.m_colour[2] = 0.75;
2407       hiddenLine.m_colour[3] = 1;
2408       hiddenLine.m_state = RENDER_CULLFACE|RENDER_DEPTHTEST|RENDER_COLOURWRITE|RENDER_OFFSETLINE|RENDER_LINESTIPPLE;
2409       hiddenLine.m_sort = OpenGLState::eSortOverlayFirst;
2410       hiddenLine.m_depthfunc = GL_GREATER;
2411       hiddenLine.m_linestipple_factor = 2;
2412 #endif
2413     }
2414     else if(string_equal(name+1, "XY_OVERLAY"))
2415     {
2416       state.m_colour[0] = g_xywindow_globals.color_selbrushes[0];
2417       state.m_colour[1] = g_xywindow_globals.color_selbrushes[1];
2418       state.m_colour[2] = g_xywindow_globals.color_selbrushes[2];
2419       state.m_colour[3] = 1;
2420       state.m_state = RENDER_COLOURWRITE | RENDER_LINESTIPPLE;
2421       state.m_sort = OpenGLState::eSortOverlayFirst;
2422       state.m_linewidth = 2;
2423       state.m_linestipple_factor = 3;
2424     }
2425     else if(string_equal(name+1, "DEBUG_CLIPPED"))
2426     {
2427       state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE;
2428       state.m_sort = OpenGLState::eSortLast;
2429     }
2430     else if(string_equal(name+1, "POINTFILE"))
2431     {
2432       state.m_colour[0] = 1;
2433       state.m_colour[1] = 0;
2434       state.m_colour[2] = 0;
2435       state.m_colour[3] = 1;
2436       state.m_state = RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_DEPTHWRITE;
2437       state.m_sort = OpenGLState::eSortFullbright;
2438       state.m_linewidth = 4;
2439     }
2440     else if(string_equal(name+1, "LIGHT_SPHERE"))
2441     {
2442       state.m_colour[0] = .15f * .95f;
2443       state.m_colour[1] = .15f * .95f;
2444       state.m_colour[2] = .15f * .95f;
2445       state.m_colour[3] = 1;
2446       state.m_state = RENDER_CULLFACE | RENDER_DEPTHTEST | RENDER_BLEND | RENDER_FILL | RENDER_COLOURWRITE | RENDER_DEPTHWRITE;
2447       state.m_blend_src = GL_ONE;
2448       state.m_blend_dst = GL_ONE;
2449       state.m_sort = OpenGLState::eSortTranslucent;
2450     }
2451     else if(string_equal(name+1, "Q3MAP2_LIGHT_SPHERE"))
2452     {
2453       state.m_colour[0] = .05f;
2454       state.m_colour[1] = .05f;
2455       state.m_colour[2] = .05f;
2456       state.m_colour[3] = 1;
2457       state.m_state = RENDER_CULLFACE | RENDER_DEPTHTEST | RENDER_BLEND | RENDER_FILL;
2458       state.m_blend_src = GL_ONE;
2459       state.m_blend_dst = GL_ONE;
2460       state.m_sort = OpenGLState::eSortTranslucent;
2461     }
2462     else if(string_equal(name+1, "WIRE_OVERLAY"))
2463     {
2464 #if 0
2465       state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE;
2466       state.m_sort = OpenGLState::eSortOverlayFirst;
2467 #else
2468       state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE;
2469       state.m_sort = OpenGLState::eSortGUI1;
2470       state.m_depthfunc = GL_LEQUAL;
2471
2472       OpenGLState& hiddenLine = appendDefaultPass();
2473       hiddenLine.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE | RENDER_LINESTIPPLE;
2474       hiddenLine.m_sort = OpenGLState::eSortGUI0;
2475       hiddenLine.m_depthfunc = GL_GREATER;
2476 #endif
2477     }
2478     else if(string_equal(name+1, "FLATSHADE_OVERLAY"))
2479     {
2480       state.m_state = RENDER_CULLFACE | RENDER_LIGHTING | RENDER_SMOOTH | RENDER_SCALED | RENDER_COLOURARRAY | RENDER_FILL | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE;
2481       state.m_sort = OpenGLState::eSortGUI1;
2482       state.m_depthfunc = GL_LEQUAL;
2483
2484       OpenGLState& hiddenLine = appendDefaultPass();
2485       hiddenLine.m_state = RENDER_CULLFACE | RENDER_LIGHTING | RENDER_SMOOTH | RENDER_SCALED | RENDER_COLOURARRAY | RENDER_FILL | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE | RENDER_POLYGONSTIPPLE;
2486       hiddenLine.m_sort = OpenGLState::eSortGUI0;
2487       hiddenLine.m_depthfunc = GL_GREATER;
2488     }
2489     else if(string_equal(name+1, "CLIPPER_OVERLAY"))
2490     {
2491       state.m_colour[0] = g_xywindow_globals.color_clipper[0];
2492       state.m_colour[1] = g_xywindow_globals.color_clipper[1];
2493       state.m_colour[2] = g_xywindow_globals.color_clipper[2];
2494       state.m_colour[3] = 1;
2495       state.m_state = RENDER_CULLFACE | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_FILL | RENDER_POLYGONSTIPPLE;
2496       state.m_sort = OpenGLState::eSortOverlayFirst;
2497     }
2498     else if(string_equal(name+1, "OVERBRIGHT"))
2499     {
2500       const float lightScale = 2;
2501       state.m_colour[0] = lightScale * 0.5f;
2502       state.m_colour[1] = lightScale * 0.5f;
2503       state.m_colour[2] = lightScale * 0.5f;
2504       state.m_colour[3] = 0.5;
2505       state.m_state = RENDER_FILL|RENDER_BLEND|RENDER_COLOURWRITE|RENDER_SCREEN;
2506       state.m_sort = OpenGLState::eSortOverbrighten;
2507       state.m_blend_src = GL_DST_COLOR;
2508       state.m_blend_dst = GL_SRC_COLOR;
2509     }
2510     else
2511     {
2512       // default to something recognisable.. =)
2513       ERROR_MESSAGE("hardcoded renderstate not found");
2514       state.m_colour[0] = 1;
2515       state.m_colour[1] = 0;
2516       state.m_colour[2] = 1;
2517       state.m_colour[3] = 1;
2518       state.m_state = RENDER_COLOURWRITE | RENDER_DEPTHWRITE;
2519       state.m_sort = OpenGLState::eSortFirst;
2520     }
2521     break;
2522   default:
2523     // construction from IShader
2524     m_shader = QERApp_Shader_ForName(name);
2525
2526     if(g_ShaderCache->lightingSupported() && g_ShaderCache->lightingEnabled() && m_shader->getBump() != 0 && m_shader->getBump()->texture_number != 0) // is a bump shader
2527     {
2528       state.m_state = RENDER_FILL | RENDER_CULLFACE | RENDER_TEXTURE | RENDER_DEPTHTEST | RENDER_DEPTHWRITE | RENDER_COLOURWRITE | RENDER_PROGRAM;
2529       state.m_colour[0] = 0;
2530       state.m_colour[1] = 0;
2531       state.m_colour[2] = 0;
2532       state.m_colour[3] = 1;
2533       state.m_sort = OpenGLState::eSortOpaque;
2534
2535       if(g_ShaderCache->useShaderLanguage())
2536       {
2537         state.m_program = &g_depthFillGLSL;
2538       }
2539       else
2540       {
2541         state.m_program = &g_depthFillARB;
2542       }
2543
2544       OpenGLState& bumpPass = appendDefaultPass();
2545       bumpPass.m_texture = m_shader->getDiffuse()->texture_number;
2546       bumpPass.m_texture1 = m_shader->getBump()->texture_number;
2547       bumpPass.m_texture2 = m_shader->getSpecular()->texture_number;
2548
2549       bumpPass.m_state = RENDER_BLEND|RENDER_FILL|RENDER_CULLFACE|RENDER_DEPTHTEST|RENDER_COLOURWRITE|RENDER_SMOOTH|RENDER_BUMP|RENDER_PROGRAM;
2550
2551       if(g_ShaderCache->useShaderLanguage())
2552       {
2553         bumpPass.m_state |= RENDER_LIGHTING;
2554         bumpPass.m_program = &g_bumpGLSL;
2555       }
2556       else
2557       {
2558         bumpPass.m_program = &g_bumpARB;
2559       }
2560
2561       bumpPass.m_depthfunc = GL_LEQUAL;
2562       bumpPass.m_sort = OpenGLState::eSortMultiFirst;
2563       bumpPass.m_blend_src = GL_ONE;
2564       bumpPass.m_blend_dst = GL_ONE;
2565     }
2566     else
2567     {
2568       state.m_texture = m_shader->getTexture()->texture_number;
2569
2570       state.m_state = RENDER_FILL|RENDER_TEXTURE|RENDER_DEPTHTEST|RENDER_COLOURWRITE|RENDER_LIGHTING|RENDER_SMOOTH;
2571       if((m_shader->getFlags() & QER_CULL) != 0)
2572       {
2573         if(m_shader->getCull() == IShader::eCullBack)
2574         {
2575           state.m_state |= RENDER_CULLFACE;
2576         }
2577       }
2578       else
2579       {
2580         state.m_state |= RENDER_CULLFACE;
2581       }
2582       if((m_shader->getFlags() & QER_ALPHATEST) != 0)
2583       {
2584         state.m_state |= RENDER_ALPHATEST;
2585         IShader::EAlphaFunc alphafunc;
2586         m_shader->getAlphaFunc(&alphafunc, &state.m_alpharef);
2587         switch(alphafunc)
2588         {
2589         case IShader::eAlways:
2590           state.m_alphafunc = GL_ALWAYS;
2591         case IShader::eEqual:
2592           state.m_alphafunc = GL_EQUAL;
2593         case IShader::eLess:
2594           state.m_alphafunc = GL_LESS;
2595         case IShader::eGreater:
2596           state.m_alphafunc = GL_GREATER;
2597         case IShader::eLEqual:
2598           state.m_alphafunc = GL_LEQUAL;
2599         case IShader::eGEqual:
2600           state.m_alphafunc = GL_GEQUAL;
2601         }
2602       }
2603       reinterpret_cast<Vector3&>(state.m_colour) = m_shader->getTexture()->color;
2604       state.m_colour[3] = 1.0f;
2605       
2606       if((m_shader->getFlags() & QER_TRANS) != 0)
2607       {
2608         state.m_state |= RENDER_BLEND;
2609         state.m_colour[3] = m_shader->getTrans();
2610         state.m_sort = OpenGLState::eSortTranslucent;
2611         BlendFunc blendFunc = m_shader->getBlendFunc();
2612         state.m_blend_src = convertBlendFactor(blendFunc.m_src);
2613         state.m_blend_dst = convertBlendFactor(blendFunc.m_dst);
2614         if(state.m_blend_src == GL_SRC_ALPHA || state.m_blend_dst == GL_SRC_ALPHA)
2615         {
2616           state.m_state |= RENDER_DEPTHWRITE;
2617         }
2618       }
2619       else
2620       {
2621         state.m_state |= RENDER_DEPTHWRITE;
2622         state.m_sort = OpenGLState::eSortFullbright;
2623       }
2624     }
2625   }
2626 }
2627
2628
2629 #include "modulesystem/singletonmodule.h"
2630 #include "modulesystem/moduleregistry.h"
2631
2632 class OpenGLStateLibraryAPI
2633 {
2634   OpenGLStateMap m_stateMap;
2635 public:
2636   typedef OpenGLStateLibrary Type;
2637   STRING_CONSTANT(Name, "*");
2638
2639   OpenGLStateLibraryAPI()
2640   {
2641     g_openglStates = &m_stateMap;
2642   }
2643   ~OpenGLStateLibraryAPI()
2644   {
2645     g_openglStates = 0;
2646   }
2647   OpenGLStateLibrary* getTable()
2648   {
2649     return &m_stateMap;
2650   }
2651 };
2652
2653 typedef SingletonModule<OpenGLStateLibraryAPI> OpenGLStateLibraryModule;
2654 typedef Static<OpenGLStateLibraryModule> StaticOpenGLStateLibraryModule;
2655 StaticRegisterModule staticRegisterOpenGLStateLibrary(StaticOpenGLStateLibraryModule::instance());
2656
2657 class ShaderCacheDependencies : public GlobalShadersModuleRef, public GlobalTexturesModuleRef, public GlobalOpenGLStateLibraryModuleRef
2658 {
2659 public:
2660   ShaderCacheDependencies() :
2661     GlobalShadersModuleRef(GlobalRadiant().getRequiredGameDescriptionKeyValue("shaders"))
2662   {
2663   }
2664 };
2665
2666 class ShaderCacheAPI
2667 {
2668   ShaderCache* m_shaderCache;
2669 public:
2670   typedef ShaderCache Type;
2671   STRING_CONSTANT(Name, "*");
2672
2673   ShaderCacheAPI()
2674   {
2675     ShaderCache_Construct();
2676
2677     m_shaderCache = GetShaderCache();
2678   }
2679   ~ShaderCacheAPI()
2680   {
2681     ShaderCache_Destroy();
2682   }
2683   ShaderCache* getTable()
2684   {
2685     return m_shaderCache;
2686   }
2687 };
2688
2689 typedef SingletonModule<ShaderCacheAPI, ShaderCacheDependencies> ShaderCacheModule;
2690 typedef Static<ShaderCacheModule> StaticShaderCacheModule;
2691 StaticRegisterModule staticRegisterShaderCache(StaticShaderCacheModule::instance());
2692
2693