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