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