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