]> git.xonotic.org Git - xonotic/netradiant.git/blob - radiant/renderstate.cpp
Wrap GtkVBox
[xonotic/netradiant.git] / radiant / renderstate.cpp
1 /*
2    Copyright (C) 2001-2006, William Joseph.
3    All Rights Reserved.
4
5    This file is part of GtkRadiant.
6
7    GtkRadiant is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    GtkRadiant is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with GtkRadiant; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21
22 #include "renderstate.h"
23
24 #include "debugging/debugging.h"
25 #include "warnings.h"
26
27 #include "ishaders.h"
28 #include "irender.h"
29 #include "itextures.h"
30 #include "igl.h"
31 #include "iglrender.h"
32 #include "renderable.h"
33 #include "qerplugin.h"
34
35 #include <set>
36 #include <vector>
37 #include <list>
38 #include <map>
39
40 #include "math/matrix.h"
41 #include "math/aabb.h"
42 #include "generic/callback.h"
43 #include "texturelib.h"
44 #include "string/string.h"
45 #include "container/hashfunc.h"
46 #include "container/cache.h"
47 #include "generic/reference.h"
48 #include "moduleobservers.h"
49 #include "stream/filestream.h"
50 #include "stream/stringstream.h"
51 #include "os/file.h"
52 #include "preferences.h"
53
54 #include "xywindow.h"
55
56
57
58 #define DEBUG_RENDER 0
59
60 inline void debug_string( const char* string ){
61 #if (DEBUG_RENDER)
62         globalOutputStream() << string << "\n";
63 #endif
64 }
65
66 inline void debug_int( const char* comment, int i ){
67 #if (DEBUG_RENDER)
68         globalOutputStream() << comment << " " << i << "\n";
69 #endif
70 }
71
72 inline void debug_colour( const char* comment ){
73 #if ( DEBUG_RENDER )
74         Vector4 v;
75         glGetFloatv( GL_CURRENT_COLOR, reinterpret_cast<float*>( &v ) );
76         globalOutputStream() << comment << " colour: "
77                                                  << v[0] << " "
78                                                  << v[1] << " "
79                                                  << v[2] << " "
80                                                  << v[3];
81         if ( glIsEnabled( GL_COLOR_ARRAY ) ) {
82                 globalOutputStream() << " ARRAY";
83         }
84         if ( glIsEnabled( GL_COLOR_MATERIAL ) ) {
85                 globalOutputStream() << " MATERIAL";
86         }
87         globalOutputStream() << "\n";
88 #endif
89 }
90
91 #include "timer.h"
92
93 StringOutputStream g_renderer_stats;
94 std::size_t g_count_prims;
95 std::size_t g_count_states;
96 std::size_t g_count_transforms;
97 Timer g_timer;
98
99 inline void count_prim(){
100         ++g_count_prims;
101 }
102
103 inline void count_state(){
104         ++g_count_states;
105 }
106
107 inline void count_transform(){
108         ++g_count_transforms;
109 }
110
111 void Renderer_ResetStats(){
112         g_count_prims = 0;
113         g_count_states = 0;
114         g_count_transforms = 0;
115         g_timer.start();
116 }
117
118 const char* Renderer_GetStats(){
119         g_renderer_stats.clear();
120         g_renderer_stats << "prims: " << Unsigned( g_count_prims )
121                                          << " | states: " << Unsigned( g_count_states )
122                                          << " | transforms: " << Unsigned( g_count_transforms )
123                                          << " | msec: " << g_timer.elapsed_msec();
124         return g_renderer_stats.c_str();
125 }
126
127
128 void printShaderLog( GLhandleARB object ){
129         GLint log_length = 0;
130         glGetObjectParameterivARB( object, GL_OBJECT_INFO_LOG_LENGTH_ARB, &log_length );
131
132
133         std::string log( log_length, ' ' );
134         if ( !log.empty() )
135                 glGetInfoLogARB( object, log_length, &log_length, &log[0] );
136
137         globalErrorStream() << StringRange( log.data(), log.data() + log_length ) << "\n";
138 }
139
140 void createShader( GLhandleARB program, const char* filename, GLenum type ){
141         GLhandleARB shader = glCreateShaderObjectARB( type );
142         GlobalOpenGL_debugAssertNoErrors();
143
144         // load shader
145         {
146                 std::size_t size = file_size( filename );
147                 FileInputStream file( filename );
148                 ASSERT_MESSAGE( !file.failed(), "failed to open " << makeQuoted( filename ) );
149                 Array<GLcharARB> buffer( size );
150                 size = file.read( reinterpret_cast<StreamBase::byte_type*>( buffer.data() ), size );
151
152                 const GLcharARB* string = buffer.data();
153                 GLint length = GLint( size );
154                 glShaderSourceARB( shader, 1, &string, &length );
155         }
156
157         // compile shader
158         {
159                 glCompileShaderARB( shader );
160
161                 GLint compiled = 0;
162                 glGetObjectParameterivARB( shader, GL_OBJECT_COMPILE_STATUS_ARB, &compiled );
163
164                 if ( !compiled ) {
165                         printShaderLog( shader );
166                 }
167
168                 ASSERT_MESSAGE( compiled, "shader compile failed: " << makeQuoted( filename ) );
169         }
170
171         // attach shader
172         glAttachObjectARB( program, shader );
173
174         glDeleteObjectARB( shader );
175
176         GlobalOpenGL_debugAssertNoErrors();
177 }
178
179 void GLSLProgram_link( GLhandleARB program ){
180         glLinkProgramARB( program );
181
182         GLint linked = false;
183         glGetObjectParameterivARB( program, GL_OBJECT_LINK_STATUS_ARB, &linked );
184
185         if ( !linked ) {
186                 printShaderLog( program );
187         }
188
189         ASSERT_MESSAGE( linked, "program link failed" );
190 }
191
192 void GLSLProgram_validate( GLhandleARB program ){
193         glValidateProgramARB( program );
194
195         GLint validated = false;
196         glGetObjectParameterivARB( program, GL_OBJECT_VALIDATE_STATUS_ARB, &validated );
197
198         if ( !validated ) {
199                 printShaderLog( program );
200         }
201
202         ASSERT_MESSAGE( validated, "program validation failed" );
203 }
204
205 bool g_bumpGLSLPass_enabled = false;
206 bool g_depthfillPass_enabled = false;
207
208 class GLSLBumpProgram : public GLProgram
209 {
210 public:
211 GLhandleARB m_program;
212 qtexture_t* m_light_attenuation_xy;
213 qtexture_t* m_light_attenuation_z;
214 GLint u_view_origin;
215 GLint u_light_origin;
216 GLint u_light_color;
217 GLint u_bump_scale;
218 GLint u_specular_exponent;
219
220 GLSLBumpProgram() : m_program( 0 ), m_light_attenuation_xy( 0 ), m_light_attenuation_z( 0 ){
221 }
222
223 void create(){
224         // create program
225         m_program = glCreateProgramObjectARB();
226
227         // create shader
228         {
229                 StringOutputStream filename( 256 );
230                 filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_vp.glsl";
231                 createShader( m_program, filename.c_str(), GL_VERTEX_SHADER_ARB );
232                 filename.clear();
233                 filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_fp.glsl";
234                 createShader( m_program, filename.c_str(), GL_FRAGMENT_SHADER_ARB );
235         }
236
237         GLSLProgram_link( m_program );
238         GLSLProgram_validate( m_program );
239
240         glUseProgramObjectARB( m_program );
241
242         glBindAttribLocationARB( m_program, c_attr_TexCoord0, "attr_TexCoord0" );
243         glBindAttribLocationARB( m_program, c_attr_Tangent, "attr_Tangent" );
244         glBindAttribLocationARB( m_program, c_attr_Binormal, "attr_Binormal" );
245
246         glUniform1iARB( glGetUniformLocationARB( m_program, "u_diffusemap" ), 0 );
247         glUniform1iARB( glGetUniformLocationARB( m_program, "u_bumpmap" ), 1 );
248         glUniform1iARB( glGetUniformLocationARB( m_program, "u_specularmap" ), 2 );
249         glUniform1iARB( glGetUniformLocationARB( m_program, "u_attenuationmap_xy" ), 3 );
250         glUniform1iARB( glGetUniformLocationARB( m_program, "u_attenuationmap_z" ), 4 );
251
252         u_view_origin = glGetUniformLocationARB( m_program, "u_view_origin" );
253         u_light_origin = glGetUniformLocationARB( m_program, "u_light_origin" );
254         u_light_color = glGetUniformLocationARB( m_program, "u_light_color" );
255         u_bump_scale = glGetUniformLocationARB( m_program, "u_bump_scale" );
256         u_specular_exponent = glGetUniformLocationARB( m_program, "u_specular_exponent" );
257
258         glUseProgramObjectARB( 0 );
259
260         GlobalOpenGL_debugAssertNoErrors();
261 }
262
263 void destroy(){
264         glDeleteObjectARB( m_program );
265         m_program = 0;
266 }
267
268 void enable(){
269         glUseProgramObjectARB( m_program );
270
271         glEnableVertexAttribArrayARB( c_attr_TexCoord0 );
272         glEnableVertexAttribArrayARB( c_attr_Tangent );
273         glEnableVertexAttribArrayARB( c_attr_Binormal );
274
275         GlobalOpenGL_debugAssertNoErrors();
276
277         debug_string( "enable bump" );
278         g_bumpGLSLPass_enabled = true;
279 }
280
281 void disable(){
282         glUseProgramObjectARB( 0 );
283
284         glDisableVertexAttribArrayARB( c_attr_TexCoord0 );
285         glDisableVertexAttribArrayARB( c_attr_Tangent );
286         glDisableVertexAttribArrayARB( c_attr_Binormal );
287
288         GlobalOpenGL_debugAssertNoErrors();
289
290         debug_string( "disable bump" );
291         g_bumpGLSLPass_enabled = false;
292 }
293
294 void setParameters( const Vector3& viewer, const Matrix4& localToWorld, const Vector3& origin, const Vector3& colour, const Matrix4& world2light ){
295         Matrix4 world2local( localToWorld );
296         matrix4_affine_invert( world2local );
297
298         Vector3 localLight( origin );
299         matrix4_transform_point( world2local, localLight );
300
301         Vector3 localViewer( viewer );
302         matrix4_transform_point( world2local, localViewer );
303
304         Matrix4 local2light( world2light );
305         matrix4_multiply_by_matrix4( local2light, localToWorld ); // local->world->light
306
307         glUniform3fARB( u_view_origin, localViewer.x(), localViewer.y(), localViewer.z() );
308         glUniform3fARB( u_light_origin, localLight.x(), localLight.y(), localLight.z() );
309         glUniform3fARB( u_light_color, colour.x(), colour.y(), colour.z() );
310         glUniform1fARB( u_bump_scale, 1.0 );
311         glUniform1fARB( u_specular_exponent, 32.0 );
312
313         glActiveTexture( GL_TEXTURE3 );
314         glClientActiveTexture( GL_TEXTURE3 );
315
316         glMatrixMode( GL_TEXTURE );
317         glLoadMatrixf( reinterpret_cast<const float*>( &local2light ) );
318         glMatrixMode( GL_MODELVIEW );
319
320         GlobalOpenGL_debugAssertNoErrors();
321 }
322 };
323
324 GLSLBumpProgram g_bumpGLSL;
325
326
327 class GLSLDepthFillProgram : public GLProgram
328 {
329 public:
330 GLhandleARB m_program;
331
332 void create(){
333         // create program
334         m_program = glCreateProgramObjectARB();
335
336         // create shader
337         {
338                 StringOutputStream filename( 256 );
339                 filename << GlobalRadiant().getAppPath() << "gl/zfill_vp.glsl";
340                 createShader( m_program, filename.c_str(), GL_VERTEX_SHADER_ARB );
341                 filename.clear();
342                 filename << GlobalRadiant().getAppPath() << "gl/zfill_fp.glsl";
343                 createShader( m_program, filename.c_str(), GL_FRAGMENT_SHADER_ARB );
344         }
345
346         GLSLProgram_link( m_program );
347         GLSLProgram_validate( m_program );
348
349         GlobalOpenGL_debugAssertNoErrors();
350 }
351
352 void destroy(){
353         glDeleteObjectARB( m_program );
354         m_program = 0;
355 }
356 void enable(){
357         glUseProgramObjectARB( m_program );
358         GlobalOpenGL_debugAssertNoErrors();
359         debug_string( "enable depthfill" );
360         g_depthfillPass_enabled = true;
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().getAppPath() << "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().getAppPath() << "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().getAppPath() << "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().getAppPath() << "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().getAppPath() << "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().getAppPath() << "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
850
851 /// \brief A container of Renderable references.
852 /// May contain the same Renderable multiple times, with different transforms.
853 class OpenGLStateBucket
854 {
855 public:
856 struct RenderTransform
857 {
858         const Matrix4* m_transform;
859         const OpenGLRenderable *m_renderable;
860         const RendererLight* m_light;
861
862         RenderTransform( const OpenGLRenderable& renderable, const Matrix4& transform, const RendererLight* light )
863                 : m_transform( &transform ), m_renderable( &renderable ), m_light( light ){
864         }
865 };
866
867 typedef std::vector<RenderTransform> Renderables;
868
869 private:
870
871 OpenGLState m_state;
872 Renderables m_renderables;
873
874 public:
875 OpenGLStateBucket(){
876 }
877 void addRenderable( const OpenGLRenderable& renderable, const Matrix4& modelview, const RendererLight* light = 0 ){
878         m_renderables.push_back( RenderTransform( renderable, modelview, light ) );
879 }
880
881 OpenGLState& state(){
882         return m_state;
883 }
884
885 void render( OpenGLState& current, unsigned int globalstate, const Vector3& viewer );
886 };
887
888 #define LIGHT_SHADER_DEBUG 0
889
890 #if LIGHT_SHADER_DEBUG
891 typedef std::vector<Shader*> LightDebugShaders;
892 LightDebugShaders g_lightDebugShaders;
893 #endif
894
895 class OpenGLStateLess
896 {
897 public:
898 bool operator()( const OpenGLState& self, const OpenGLState& other ) const {
899         return OpenGLState_less( self, other );
900 }
901 };
902
903 typedef ConstReference<OpenGLState> OpenGLStateReference;
904 typedef std::map<OpenGLStateReference, OpenGLStateBucket*, OpenGLStateLess> OpenGLStates;
905 OpenGLStates g_state_sorted;
906
907 class OpenGLStateBucketAdd
908 {
909 OpenGLStateBucket& m_bucket;
910 const OpenGLRenderable& m_renderable;
911 const Matrix4& m_modelview;
912 public:
913 typedef const RendererLight& first_argument_type;
914
915 OpenGLStateBucketAdd( OpenGLStateBucket& bucket, const OpenGLRenderable& renderable, const Matrix4& modelview ) :
916         m_bucket( bucket ), m_renderable( renderable ), m_modelview( modelview ){
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 typedef RendererLight& first_argument_type;
928
929 CountLights() : m_count( 0 ){
930 }
931 void operator()( const RendererLight& light ){
932         ++m_count;
933 }
934 std::size_t count() const {
935         return m_count;
936 }
937 };
938
939 class OpenGLShader : public Shader
940 {
941 typedef std::list<OpenGLStateBucket*> Passes;
942 Passes m_passes;
943 IShader* m_shader;
944 std::size_t m_used;
945 ModuleObservers m_observers;
946 public:
947 OpenGLShader() : m_shader( 0 ), m_used( 0 ){
948 }
949 ~OpenGLShader(){
950 }
951 void construct( const char* name );
952 void destroy(){
953         if ( m_shader ) {
954                 m_shader->DecRef();
955         }
956         m_shader = 0;
957
958         for ( Passes::iterator i = m_passes.begin(); i != m_passes.end(); ++i )
959         {
960                 delete *i;
961         }
962         m_passes.clear();
963 }
964 void addRenderable( const OpenGLRenderable& renderable, const Matrix4& modelview, const LightList* lights ){
965         for ( Passes::iterator i = m_passes.begin(); i != m_passes.end(); ++i )
966         {
967 #if LIGHT_SHADER_DEBUG
968                 if ( ( ( *i )->state().m_state & RENDER_BUMP ) != 0 ) {
969                         if ( lights != 0 ) {
970                                 CountLights counter;
971                                 lights->forEachLight( makeCallback1( counter ) );
972                                 globalOutputStream() << "count = " << counter.count() << "\n";
973                                 for ( std::size_t i = 0; i < counter.count(); ++i )
974                                 {
975                                         g_lightDebugShaders[counter.count()]->addRenderable( renderable, modelview );
976                                 }
977                         }
978                 }
979                 else
980 #else
981                 if ( ( ( *i )->state().m_state & RENDER_BUMP ) != 0 ) {
982                         if ( lights != 0 ) {
983                                 OpenGLStateBucketAdd add( *( *i ), renderable, modelview );
984                                 lights->forEachLight( makeCallback1( add ) );
985                         }
986                 }
987                 else
988 #endif
989                 {
990                         ( *i )->addRenderable( renderable, modelview );
991                 }
992         }
993 }
994 void incrementUsed(){
995         if ( ++m_used == 1 && m_shader != 0 ) {
996                 m_shader->SetInUse( true );
997         }
998 }
999 void decrementUsed(){
1000         if ( --m_used == 0 && m_shader != 0 ) {
1001                 m_shader->SetInUse( false );
1002         }
1003 }
1004 bool realised() const {
1005         return m_shader != 0;
1006 }
1007 void attach( ModuleObserver& observer ){
1008         if ( realised() ) {
1009                 observer.realise();
1010         }
1011         m_observers.attach( observer );
1012 }
1013 void detach( ModuleObserver& observer ){
1014         if ( realised() ) {
1015                 observer.unrealise();
1016         }
1017         m_observers.detach( observer );
1018 }
1019 void realise( const std::string& name ){
1020         construct( name.c_str() );
1021
1022         if ( m_used != 0 && m_shader != 0 ) {
1023                 m_shader->SetInUse( true );
1024         }
1025
1026         for ( Passes::iterator i = m_passes.begin(); i != m_passes.end(); ++i )
1027         {
1028                 g_state_sorted.insert( OpenGLStates::value_type( OpenGLStateReference( ( *i )->state() ), *i ) );
1029         }
1030
1031         m_observers.realise();
1032 }
1033 void unrealise(){
1034         m_observers.unrealise();
1035
1036         for ( Passes::iterator i = m_passes.begin(); i != m_passes.end(); ++i )
1037         {
1038                 g_state_sorted.erase( OpenGLStateReference( ( *i )->state() ) );
1039         }
1040
1041         destroy();
1042 }
1043 qtexture_t& getTexture() const {
1044         ASSERT_NOTNULL( m_shader );
1045         return *m_shader->getTexture();
1046 }
1047 unsigned int getFlags() const {
1048         ASSERT_NOTNULL( m_shader );
1049         return m_shader->getFlags();
1050 }
1051 IShader& getShader() const {
1052         ASSERT_NOTNULL( m_shader );
1053         return *m_shader;
1054 }
1055 OpenGLState& appendDefaultPass(){
1056         m_passes.push_back( new OpenGLStateBucket );
1057         OpenGLState& state = m_passes.back()->state();
1058         OpenGLState_constructDefault( state );
1059         return state;
1060 }
1061 };
1062
1063
1064 inline bool lightEnabled( const RendererLight& light, const LightCullable& cullable ){
1065         return cullable.testLight( light );
1066 }
1067
1068 typedef std::set<RendererLight*> RendererLights;
1069
1070 #define DEBUG_LIGHT_SYNC 0
1071
1072 class LinearLightList : public LightList
1073 {
1074 LightCullable& m_cullable;
1075 RendererLights& m_allLights;
1076 Callback m_evaluateChanged;
1077
1078 typedef std::list<RendererLight*> Lights;
1079 mutable Lights m_lights;
1080 mutable bool m_lightsChanged;
1081 public:
1082 LinearLightList( LightCullable& cullable, RendererLights& lights, const Callback& evaluateChanged ) :
1083         m_cullable( cullable ), m_allLights( lights ), m_evaluateChanged( evaluateChanged ){
1084         m_lightsChanged = true;
1085 }
1086 void evaluateLights() const {
1087         m_evaluateChanged();
1088         if ( m_lightsChanged ) {
1089                 m_lightsChanged = false;
1090
1091                 m_lights.clear();
1092                 m_cullable.clearLights();
1093                 for ( RendererLights::const_iterator i = m_allLights.begin(); i != m_allLights.end(); ++i )
1094                 {
1095                         if ( lightEnabled( *( *i ), m_cullable ) ) {
1096                                 m_lights.push_back( *i );
1097                                 m_cullable.insertLight( *( *i ) );
1098                         }
1099                 }
1100         }
1101 #if ( DEBUG_LIGHT_SYNC )
1102         else
1103         {
1104                 Lights lights;
1105                 for ( RendererLights::const_iterator i = m_allLights.begin(); i != m_allLights.end(); ++i )
1106                 {
1107                         if ( lightEnabled( *( *i ), m_cullable ) ) {
1108                                 lights.push_back( *i );
1109                         }
1110                 }
1111                 ASSERT_MESSAGE(
1112                         !std::lexicographical_compare( lights.begin(), lights.end(), m_lights.begin(), m_lights.end() )
1113                         && !std::lexicographical_compare( m_lights.begin(), m_lights.end(), lights.begin(), lights.end() ),
1114                         "lights out of sync"
1115                         );
1116         }
1117 #endif
1118 }
1119 void forEachLight( const RendererLightCallback& callback ) const {
1120         evaluateLights();
1121
1122         for ( Lights::const_iterator i = m_lights.begin(); i != m_lights.end(); ++i )
1123         {
1124                 callback( *( *i ) );
1125         }
1126 }
1127 void lightsChanged() const {
1128         m_lightsChanged = true;
1129 }
1130 };
1131
1132 inline void setFogState( const OpenGLFogState& state ){
1133         glFogi( GL_FOG_MODE, state.mode );
1134         glFogf( GL_FOG_DENSITY, state.density );
1135         glFogf( GL_FOG_START, state.start );
1136         glFogf( GL_FOG_END, state.end );
1137         glFogi( GL_FOG_INDEX, state.index );
1138         glFogfv( GL_FOG_COLOR, vector4_to_array( state.colour ) );
1139 }
1140
1141 #define DEBUG_SHADERS 0
1142
1143 class OpenGLShaderCache : public ShaderCache, public TexturesCacheObserver, public ModuleObserver
1144 {
1145 class CreateOpenGLShader
1146 {
1147 OpenGLShaderCache* m_cache;
1148 public:
1149 explicit CreateOpenGLShader( OpenGLShaderCache* cache = 0 )
1150         : m_cache( cache ){
1151 }
1152 OpenGLShader* construct( const std::string& name ){
1153         OpenGLShader* shader = new OpenGLShader;
1154         if ( m_cache->realised() ) {
1155                 shader->realise( name );
1156         }
1157         return shader;
1158 }
1159 void destroy( OpenGLShader* shader ){
1160         if ( m_cache->realised() ) {
1161                 shader->unrealise();
1162         }
1163         delete shader;
1164 }
1165 };
1166
1167 typedef HashedCache<std::string, OpenGLShader, HashString, std::equal_to<std::string>, CreateOpenGLShader> Shaders;
1168 Shaders m_shaders;
1169 std::size_t m_unrealised;
1170
1171 bool m_lightingEnabled;
1172 bool m_lightingSupported;
1173 bool m_useShaderLanguage;
1174
1175 public:
1176 OpenGLShaderCache()
1177         : m_shaders( CreateOpenGLShader( this ) ),
1178         m_unrealised( 3 ), // wait until shaders, gl-context and textures are realised before creating any render-states
1179         m_lightingEnabled( true ),
1180         m_lightingSupported( false ),
1181         m_useShaderLanguage( false ),
1182         m_lightsChanged( true ),
1183         m_traverseRenderablesMutex( false ){
1184 }
1185 ~OpenGLShaderCache(){
1186         for ( Shaders::iterator i = m_shaders.begin(); i != m_shaders.end(); ++i )
1187         {
1188                 globalOutputStream() << "leaked shader: " << makeQuoted( ( *i ).first.c_str() ) << "\n";
1189         }
1190 }
1191 Shader* capture( const char* name ){
1192         ASSERT_MESSAGE( name[0] == '$'
1193                                         || *name == '['
1194                                         || *name == '<'
1195                                         || *name == '('
1196                                         || strchr( name, '\\' ) == 0, "shader name contains invalid characters: \"" << name << "\"" );
1197 #if DEBUG_SHADERS
1198         globalOutputStream() << "shaders capture: " << makeQuoted( name ) << '\n';
1199 #endif
1200         return m_shaders.capture( name ).get();
1201 }
1202 void release( const char *name ){
1203 #if DEBUG_SHADERS
1204         globalOutputStream() << "shaders release: " << makeQuoted( name ) << '\n';
1205 #endif
1206         m_shaders.release( name );
1207 }
1208 void render( RenderStateFlags globalstate, const Matrix4& modelview, const Matrix4& projection, const Vector3& viewer ){
1209         glMatrixMode( GL_PROJECTION );
1210         glLoadMatrixf( reinterpret_cast<const float*>( &projection ) );
1211   #if 0
1212         //qglGetFloatv(GL_PROJECTION_MATRIX, reinterpret_cast<float*>(&projection));
1213   #endif
1214
1215         glMatrixMode( GL_MODELVIEW );
1216         glLoadMatrixf( reinterpret_cast<const float*>( &modelview ) );
1217   #if 0
1218         //qglGetFloatv(GL_MODELVIEW_MATRIX, reinterpret_cast<float*>(&modelview));
1219   #endif
1220
1221         ASSERT_MESSAGE( realised(), "render states are not realised" );
1222
1223         // global settings that are not set in renderstates
1224         glFrontFace( GL_CW );
1225         glCullFace( GL_BACK );
1226         glPolygonOffset( -1, 1 );
1227         {
1228                 const GLubyte pattern[132] = {
1229                         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1230                         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1231                         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1232                         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1233                         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1234                         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1235                         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1236                         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1237                         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1238                         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1239                         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1240                         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1241                         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1242                         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1243                         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1244                         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55
1245                 };
1246                 glPolygonStipple( pattern );
1247         }
1248         glEnableClientState( GL_VERTEX_ARRAY );
1249         g_vertexArray_enabled = true;
1250         glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
1251
1252         if ( GlobalOpenGL().GL_1_3() ) {
1253                 glActiveTexture( GL_TEXTURE0 );
1254                 glClientActiveTexture( GL_TEXTURE0 );
1255         }
1256
1257         if ( GlobalOpenGL().ARB_shader_objects() ) {
1258                 glUseProgramObjectARB( 0 );
1259                 glDisableVertexAttribArrayARB( c_attr_TexCoord0 );
1260                 glDisableVertexAttribArrayARB( c_attr_Tangent );
1261                 glDisableVertexAttribArrayARB( c_attr_Binormal );
1262         }
1263
1264         if ( globalstate & RENDER_TEXTURE ) {
1265                 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
1266                 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
1267         }
1268
1269         OpenGLState current;
1270         OpenGLState_constructDefault( current );
1271         current.m_sort = OpenGLState::eSortFirst;
1272
1273         // default renderstate settings
1274         glLineStipple( current.m_linestipple_factor, current.m_linestipple_pattern );
1275         glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
1276         glDisable( GL_LIGHTING );
1277         glDisable( GL_TEXTURE_2D );
1278         glDisableClientState( GL_TEXTURE_COORD_ARRAY );
1279         g_texcoordArray_enabled = false;
1280         glDisableClientState( GL_COLOR_ARRAY );
1281         g_colorArray_enabled = false;
1282         glDisableClientState( GL_NORMAL_ARRAY );
1283         g_normalArray_enabled = false;
1284         glDisable( GL_BLEND );
1285         glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
1286         glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
1287         glDisable( GL_CULL_FACE );
1288         glShadeModel( GL_FLAT );
1289         glDisable( GL_DEPTH_TEST );
1290         glDepthMask( GL_FALSE );
1291         glDisable( GL_ALPHA_TEST );
1292         glDisable( GL_LINE_STIPPLE );
1293         glDisable( GL_POLYGON_STIPPLE );
1294         glDisable( GL_POLYGON_OFFSET_LINE );
1295
1296         glBindTexture( GL_TEXTURE_2D, 0 );
1297         glColor4f( 1,1,1,1 );
1298         glDepthFunc( GL_LESS );
1299         glAlphaFunc( GL_ALWAYS, 0 );
1300         glLineWidth( 1 );
1301         glPointSize( 1 );
1302
1303         glHint( GL_FOG_HINT, GL_NICEST );
1304         glDisable( GL_FOG );
1305         setFogState( OpenGLFogState() );
1306
1307         GlobalOpenGL_debugAssertNoErrors();
1308
1309         debug_string( "begin rendering" );
1310         for ( OpenGLStates::iterator i = g_state_sorted.begin(); i != g_state_sorted.end(); ++i )
1311         {
1312                 ( *i ).second->render( current, globalstate, viewer );
1313         }
1314         debug_string( "end rendering" );
1315 }
1316 void realise(){
1317         if ( --m_unrealised == 0 ) {
1318                 if ( lightingSupported() && lightingEnabled() ) {
1319                         if ( useShaderLanguage() ) {
1320                                 g_bumpGLSL.create();
1321                                 g_depthFillGLSL.create();
1322                         }
1323                         else
1324                         {
1325                                 g_bumpARB.create();
1326                                 g_depthFillARB.create();
1327                         }
1328                 }
1329
1330                 for ( Shaders::iterator i = m_shaders.begin(); i != m_shaders.end(); ++i )
1331                 {
1332                         if ( !( *i ).second.empty() ) {
1333                                 ( *i ).second->realise( i->first );
1334                         }
1335                 }
1336         }
1337 }
1338 void unrealise(){
1339         if ( ++m_unrealised == 1 ) {
1340                 for ( Shaders::iterator i = m_shaders.begin(); i != m_shaders.end(); ++i )
1341                 {
1342                         if ( !( *i ).second.empty() ) {
1343                                 ( *i ).second->unrealise();
1344                         }
1345                 }
1346                 if ( GlobalOpenGL().contextValid && lightingSupported() && lightingEnabled() ) {
1347                         if ( useShaderLanguage() ) {
1348                                 g_bumpGLSL.destroy();
1349                                 g_depthFillGLSL.destroy();
1350                         }
1351                         else
1352                         {
1353                                 g_bumpARB.destroy();
1354                                 g_depthFillARB.destroy();
1355                         }
1356                 }
1357         }
1358 }
1359 bool realised(){
1360         return m_unrealised == 0;
1361 }
1362
1363
1364 bool lightingEnabled() const {
1365         return m_lightingEnabled;
1366 }
1367 bool lightingSupported() const {
1368         return m_lightingSupported;
1369 }
1370 bool useShaderLanguage() const {
1371         return m_useShaderLanguage;
1372 }
1373 void setLighting( bool supported, bool enabled ){
1374         bool refresh = ( m_lightingSupported && m_lightingEnabled ) != ( supported && enabled );
1375
1376         if ( refresh ) {
1377                 unrealise();
1378                 GlobalShaderSystem().setLightingEnabled( supported && enabled );
1379         }
1380
1381         m_lightingSupported = supported;
1382         m_lightingEnabled = enabled;
1383
1384         if ( refresh ) {
1385                 realise();
1386         }
1387 }
1388 void extensionsInitialised(){
1389         setLighting( GlobalOpenGL().GL_1_3()
1390                                  && GlobalOpenGL().ARB_vertex_program()
1391                                  && GlobalOpenGL().ARB_fragment_program()
1392                                  && GlobalOpenGL().ARB_shader_objects()
1393                                  && GlobalOpenGL().ARB_vertex_shader()
1394                                  && GlobalOpenGL().ARB_fragment_shader()
1395                                  && GlobalOpenGL().ARB_shading_language_100(),
1396                                  m_lightingEnabled
1397                                  );
1398
1399         if ( !lightingSupported() ) {
1400                 globalOutputStream() << "Lighting mode requires OpenGL features not supported by your graphics drivers:\n";
1401                 if ( !GlobalOpenGL().GL_1_3() ) {
1402                         globalOutputStream() << "  GL version 1.3 or better\n";
1403                 }
1404                 if ( !GlobalOpenGL().ARB_vertex_program() ) {
1405                         globalOutputStream() << "  GL_ARB_vertex_program\n";
1406                 }
1407                 if ( !GlobalOpenGL().ARB_fragment_program() ) {
1408                         globalOutputStream() << "  GL_ARB_fragment_program\n";
1409                 }
1410                 if ( !GlobalOpenGL().ARB_shader_objects() ) {
1411                         globalOutputStream() << "  GL_ARB_shader_objects\n";
1412                 }
1413                 if ( !GlobalOpenGL().ARB_vertex_shader() ) {
1414                         globalOutputStream() << "  GL_ARB_vertex_shader\n";
1415                 }
1416                 if ( !GlobalOpenGL().ARB_fragment_shader() ) {
1417                         globalOutputStream() << "  GL_ARB_fragment_shader\n";
1418                 }
1419                 if ( !GlobalOpenGL().ARB_shading_language_100() ) {
1420                         globalOutputStream() << "  GL_ARB_shading_language_100\n";
1421                 }
1422         }
1423 }
1424 void setLightingEnabled( bool enabled ){
1425         setLighting( m_lightingSupported, enabled );
1426 }
1427
1428 // light culling
1429
1430 RendererLights m_lights;
1431 bool m_lightsChanged;
1432 typedef std::map<LightCullable*, LinearLightList> LightLists;
1433 LightLists m_lightLists;
1434
1435 const LightList& attach( LightCullable& cullable ){
1436         return ( *m_lightLists.insert( LightLists::value_type( &cullable, LinearLightList( cullable, m_lights, EvaluateChangedCaller( *this ) ) ) ).first ).second;
1437 }
1438 void detach( LightCullable& cullable ){
1439         m_lightLists.erase( &cullable );
1440 }
1441 void changed( LightCullable& cullable ){
1442         LightLists::iterator i = m_lightLists.find( &cullable );
1443         ASSERT_MESSAGE( i != m_lightLists.end(), "cullable not attached" );
1444         ( *i ).second.lightsChanged();
1445 }
1446 void attach( RendererLight& light ){
1447         ASSERT_MESSAGE( m_lights.find( &light ) == m_lights.end(), "light could not be attached" );
1448         m_lights.insert( &light );
1449         changed( light );
1450 }
1451 void detach( RendererLight& light ){
1452         ASSERT_MESSAGE( m_lights.find( &light ) != m_lights.end(), "light could not be detached" );
1453         m_lights.erase( &light );
1454         changed( light );
1455 }
1456 void changed( RendererLight& light ){
1457         m_lightsChanged = true;
1458 }
1459 void evaluateChanged(){
1460         if ( m_lightsChanged ) {
1461                 m_lightsChanged = false;
1462                 for ( LightLists::iterator i = m_lightLists.begin(); i != m_lightLists.end(); ++i )
1463                 {
1464                         ( *i ).second.lightsChanged();
1465                 }
1466         }
1467 }
1468 typedef MemberCaller<OpenGLShaderCache, &OpenGLShaderCache::evaluateChanged> EvaluateChangedCaller;
1469
1470 typedef std::set<const Renderable*> Renderables;
1471 Renderables m_renderables;
1472 mutable bool m_traverseRenderablesMutex;
1473
1474 // renderables
1475 void attachRenderable( const Renderable& renderable ){
1476         ASSERT_MESSAGE( !m_traverseRenderablesMutex, "attaching renderable during traversal" );
1477         ASSERT_MESSAGE( m_renderables.find( &renderable ) == m_renderables.end(), "renderable could not be attached" );
1478         m_renderables.insert( &renderable );
1479 }
1480 void detachRenderable( const Renderable& renderable ){
1481         ASSERT_MESSAGE( !m_traverseRenderablesMutex, "detaching renderable during traversal" );
1482         ASSERT_MESSAGE( m_renderables.find( &renderable ) != m_renderables.end(), "renderable could not be detached" );
1483         m_renderables.erase( &renderable );
1484 }
1485 void forEachRenderable( const RenderableCallback& callback ) const {
1486         ASSERT_MESSAGE( !m_traverseRenderablesMutex, "for-each during traversal" );
1487         m_traverseRenderablesMutex = true;
1488         for ( Renderables::const_iterator i = m_renderables.begin(); i != m_renderables.end(); ++i )
1489         {
1490                 callback( *( *i ) );
1491         }
1492         m_traverseRenderablesMutex = false;
1493 }
1494 };
1495
1496 static OpenGLShaderCache* g_ShaderCache;
1497
1498 void ShaderCache_extensionsInitialised(){
1499         g_ShaderCache->extensionsInitialised();
1500 }
1501
1502 void ShaderCache_setBumpEnabled( bool enabled ){
1503         g_ShaderCache->setLightingEnabled( enabled );
1504 }
1505
1506
1507 Vector3 g_DebugShaderColours[256];
1508 Shader* g_defaultPointLight = 0;
1509
1510 void ShaderCache_Construct(){
1511         g_ShaderCache = new OpenGLShaderCache;
1512         GlobalTexturesCache().attach( *g_ShaderCache );
1513         GlobalShaderSystem().attach( *g_ShaderCache );
1514
1515         if ( g_pGameDescription->mGameType == "doom3" ) {
1516                 g_defaultPointLight = g_ShaderCache->capture( "lights/defaultPointLight" );
1517                 //Shader* overbright =
1518                 g_ShaderCache->capture( "$OVERBRIGHT" );
1519
1520 #if LIGHT_SHADER_DEBUG
1521                 for ( std::size_t i = 0; i < 256; ++i )
1522                 {
1523                         g_DebugShaderColours[i] = Vector3( i / 256.0, i / 256.0, i / 256.0 );
1524                 }
1525
1526                 g_DebugShaderColours[0] = Vector3( 1, 0, 0 );
1527                 g_DebugShaderColours[1] = Vector3( 1, 0.5, 0 );
1528                 g_DebugShaderColours[2] = Vector3( 1, 1, 0 );
1529                 g_DebugShaderColours[3] = Vector3( 0.5, 1, 0 );
1530                 g_DebugShaderColours[4] = Vector3( 0, 1, 0 );
1531                 g_DebugShaderColours[5] = Vector3( 0, 1, 0.5 );
1532                 g_DebugShaderColours[6] = Vector3( 0, 1, 1 );
1533                 g_DebugShaderColours[7] = Vector3( 0, 0.5, 1 );
1534                 g_DebugShaderColours[8] = Vector3( 0, 0, 1 );
1535                 g_DebugShaderColours[9] = Vector3( 0.5, 0, 1 );
1536                 g_DebugShaderColours[10] = Vector3( 1, 0, 1 );
1537                 g_DebugShaderColours[11] = Vector3( 1, 0, 0.5 );
1538
1539                 g_lightDebugShaders.reserve( 256 );
1540                 StringOutputStream buffer( 256 );
1541                 for ( std::size_t i = 0; i < 256; ++i )
1542                 {
1543                         buffer << "(" << g_DebugShaderColours[i].x() << " " << g_DebugShaderColours[i].y() << " " << g_DebugShaderColours[i].z() << ")";
1544                         g_lightDebugShaders.push_back( g_ShaderCache->capture( buffer.c_str() ) );
1545                         buffer.clear();
1546                 }
1547 #endif
1548         }
1549 }
1550
1551 void ShaderCache_Destroy(){
1552         if ( g_pGameDescription->mGameType == "doom3" ) {
1553                 g_ShaderCache->release( "lights/defaultPointLight" );
1554                 g_ShaderCache->release( "$OVERBRIGHT" );
1555                 g_defaultPointLight = 0;
1556
1557 #if LIGHT_SHADER_DEBUG
1558                 g_lightDebugShaders.clear();
1559                 StringOutputStream buffer( 256 );
1560                 for ( std::size_t i = 0; i < 256; ++i )
1561                 {
1562                         buffer << "(" << g_DebugShaderColours[i].x() << " " << g_DebugShaderColours[i].y() << " " << g_DebugShaderColours[i].z() << ")";
1563                         g_ShaderCache->release( buffer.c_str() );
1564                 }
1565 #endif
1566         }
1567
1568         GlobalShaderSystem().detach( *g_ShaderCache );
1569         GlobalTexturesCache().detach( *g_ShaderCache );
1570         delete g_ShaderCache;
1571 }
1572
1573 ShaderCache* GetShaderCache(){
1574         return g_ShaderCache;
1575 }
1576
1577 inline void setTextureState( GLint& current, const GLint& texture, GLenum textureUnit ){
1578         if ( texture != current ) {
1579                 glActiveTexture( textureUnit );
1580                 glClientActiveTexture( textureUnit );
1581                 glBindTexture( GL_TEXTURE_2D, texture );
1582                 GlobalOpenGL_debugAssertNoErrors();
1583                 current = texture;
1584         }
1585 }
1586
1587 inline void setTextureState( GLint& current, const GLint& texture ){
1588         if ( texture != current ) {
1589                 glBindTexture( GL_TEXTURE_2D, texture );
1590                 GlobalOpenGL_debugAssertNoErrors();
1591                 current = texture;
1592         }
1593 }
1594
1595 inline void setState( unsigned int state, unsigned int delta, unsigned int flag, GLenum glflag ){
1596         if ( delta & state & flag ) {
1597                 glEnable( glflag );
1598                 GlobalOpenGL_debugAssertNoErrors();
1599         }
1600         else if ( delta & ~state & flag ) {
1601                 glDisable( glflag );
1602                 GlobalOpenGL_debugAssertNoErrors();
1603         }
1604 }
1605
1606 void OpenGLState_apply( const OpenGLState& self, OpenGLState& current, unsigned int globalstate ){
1607         debug_int( "sort", int(self.m_sort) );
1608         debug_int( "texture", self.m_texture );
1609         debug_int( "state", self.m_state );
1610         debug_int( "address", int(std::size_t( &self ) ) );
1611
1612         count_state();
1613
1614         if ( self.m_state & RENDER_OVERRIDE ) {
1615                 globalstate |= RENDER_FILL | RENDER_DEPTHWRITE;
1616         }
1617
1618         const unsigned int state = self.m_state & globalstate;
1619         const unsigned int delta = state ^ current.m_state;
1620
1621         GlobalOpenGL_debugAssertNoErrors();
1622
1623         GLProgram* program = ( state & RENDER_PROGRAM ) != 0 ? self.m_program : 0;
1624
1625         if ( program != current.m_program ) {
1626                 if ( current.m_program != 0 ) {
1627                         current.m_program->disable();
1628                         glColor4fv( vector4_to_array( current.m_colour ) );
1629                         debug_colour( "cleaning program" );
1630                 }
1631
1632                 current.m_program = program;
1633
1634                 if ( current.m_program != 0 ) {
1635                         current.m_program->enable();
1636                 }
1637         }
1638
1639         if ( delta & state & RENDER_FILL ) {
1640                 //qglPolygonMode (GL_BACK, GL_LINE);
1641                 //qglPolygonMode (GL_FRONT, GL_FILL);
1642                 glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
1643                 GlobalOpenGL_debugAssertNoErrors();
1644         }
1645         else if ( delta & ~state & RENDER_FILL ) {
1646                 glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
1647                 GlobalOpenGL_debugAssertNoErrors();
1648         }
1649
1650         setState( state, delta, RENDER_OFFSETLINE, GL_POLYGON_OFFSET_LINE );
1651
1652         if ( delta & state & RENDER_LIGHTING ) {
1653                 glEnable( GL_LIGHTING );
1654                 glEnable( GL_COLOR_MATERIAL );
1655                 glEnable( GL_RESCALE_NORMAL );
1656                 glEnableClientState( GL_NORMAL_ARRAY );
1657                 GlobalOpenGL_debugAssertNoErrors();
1658                 g_normalArray_enabled = true;
1659         }
1660         else if ( delta & ~state & RENDER_LIGHTING ) {
1661                 glDisable( GL_LIGHTING );
1662                 glDisable( GL_COLOR_MATERIAL );
1663                 glDisable( GL_RESCALE_NORMAL );
1664                 glDisableClientState( GL_NORMAL_ARRAY );
1665                 GlobalOpenGL_debugAssertNoErrors();
1666                 g_normalArray_enabled = false;
1667         }
1668
1669         if ( delta & state & RENDER_TEXTURE ) {
1670                 GlobalOpenGL_debugAssertNoErrors();
1671
1672                 if ( GlobalOpenGL().GL_1_3() ) {
1673                         glActiveTexture( GL_TEXTURE0 );
1674                         glClientActiveTexture( GL_TEXTURE0 );
1675                 }
1676
1677                 glEnable( GL_TEXTURE_2D );
1678
1679                 glColor4f( 1,1,1,self.m_colour[3] );
1680                 debug_colour( "setting texture" );
1681
1682                 glEnableClientState( GL_TEXTURE_COORD_ARRAY );
1683                 GlobalOpenGL_debugAssertNoErrors();
1684                 g_texcoordArray_enabled = true;
1685         }
1686         else if ( delta & ~state & RENDER_TEXTURE ) {
1687                 if ( GlobalOpenGL().GL_1_3() ) {
1688                         glActiveTexture( GL_TEXTURE0 );
1689                         glClientActiveTexture( GL_TEXTURE0 );
1690                 }
1691
1692                 glDisable( GL_TEXTURE_2D );
1693                 glBindTexture( GL_TEXTURE_2D, 0 );
1694                 glDisableClientState( GL_TEXTURE_COORD_ARRAY );
1695
1696                 GlobalOpenGL_debugAssertNoErrors();
1697                 g_texcoordArray_enabled = false;
1698         }
1699
1700         if ( delta & state & RENDER_BLEND ) {
1701 // FIXME: some .TGA are buggy, have a completely empty alpha channel
1702 // if such brushes are rendered in this loop they would be totally transparent with GL_MODULATE
1703 // so I decided using GL_DECAL instead
1704 // if an empty-alpha-channel or nearly-empty texture is used. It will be blank-transparent.
1705 // this could get better if you can get glTexEnviv (GL_TEXTURE_ENV, to work .. patches are welcome
1706
1707                 glEnable( GL_BLEND );
1708                 if ( GlobalOpenGL().GL_1_3() ) {
1709                         glActiveTexture( GL_TEXTURE0 );
1710                 }
1711                 glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL );
1712                 GlobalOpenGL_debugAssertNoErrors();
1713         }
1714         else if ( delta & ~state & RENDER_BLEND ) {
1715                 glDisable( GL_BLEND );
1716                 if ( GlobalOpenGL().GL_1_3() ) {
1717                         glActiveTexture( GL_TEXTURE0 );
1718                 }
1719                 glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
1720                 GlobalOpenGL_debugAssertNoErrors();
1721         }
1722
1723         setState( state, delta, RENDER_CULLFACE, GL_CULL_FACE );
1724
1725         if ( delta & state & RENDER_SMOOTH ) {
1726                 glShadeModel( GL_SMOOTH );
1727                 GlobalOpenGL_debugAssertNoErrors();
1728         }
1729         else if ( delta & ~state & RENDER_SMOOTH ) {
1730                 glShadeModel( GL_FLAT );
1731                 GlobalOpenGL_debugAssertNoErrors();
1732         }
1733
1734         setState( state, delta, RENDER_SCALED, GL_NORMALIZE ); // not GL_RESCALE_NORMAL
1735
1736         setState( state, delta, RENDER_DEPTHTEST, GL_DEPTH_TEST );
1737
1738         if ( delta & state & RENDER_DEPTHWRITE ) {
1739                 glDepthMask( GL_TRUE );
1740
1741 #if DEBUG_RENDER
1742                 GLboolean depthEnabled;
1743                 glGetBooleanv( GL_DEPTH_WRITEMASK, &depthEnabled );
1744                 ASSERT_MESSAGE( depthEnabled, "failed to set depth buffer mask bit" );
1745 #endif
1746                 debug_string( "enabled depth-buffer writing" );
1747
1748                 GlobalOpenGL_debugAssertNoErrors();
1749         }
1750         else if ( delta & ~state & RENDER_DEPTHWRITE ) {
1751                 glDepthMask( GL_FALSE );
1752
1753 #if DEBUG_RENDER
1754                 GLboolean depthEnabled;
1755                 glGetBooleanv( GL_DEPTH_WRITEMASK, &depthEnabled );
1756                 ASSERT_MESSAGE( !depthEnabled, "failed to set depth buffer mask bit" );
1757 #endif
1758                 debug_string( "disabled depth-buffer writing" );
1759
1760                 GlobalOpenGL_debugAssertNoErrors();
1761         }
1762
1763         if ( delta & state & RENDER_COLOURWRITE ) {
1764                 glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
1765                 GlobalOpenGL_debugAssertNoErrors();
1766         }
1767         else if ( delta & ~state & RENDER_COLOURWRITE ) {
1768                 glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
1769                 GlobalOpenGL_debugAssertNoErrors();
1770         }
1771
1772         setState( state, delta, RENDER_ALPHATEST, GL_ALPHA_TEST );
1773
1774         if ( delta & state & RENDER_COLOURARRAY ) {
1775                 glEnableClientState( GL_COLOR_ARRAY );
1776                 GlobalOpenGL_debugAssertNoErrors();
1777                 debug_colour( "enabling color_array" );
1778                 g_colorArray_enabled = true;
1779         }
1780         else if ( delta & ~state & RENDER_COLOURARRAY ) {
1781                 glDisableClientState( GL_COLOR_ARRAY );
1782                 glColor4fv( vector4_to_array( self.m_colour ) );
1783                 debug_colour( "cleaning color_array" );
1784                 GlobalOpenGL_debugAssertNoErrors();
1785                 g_colorArray_enabled = false;
1786         }
1787
1788         if ( delta & ~state & RENDER_COLOURCHANGE ) {
1789                 glColor4fv( vector4_to_array( self.m_colour ) );
1790                 GlobalOpenGL_debugAssertNoErrors();
1791         }
1792
1793         setState( state, delta, RENDER_LINESTIPPLE, GL_LINE_STIPPLE );
1794         setState( state, delta, RENDER_LINESMOOTH, GL_LINE_SMOOTH );
1795
1796         setState( state, delta, RENDER_POLYGONSTIPPLE, GL_POLYGON_STIPPLE );
1797         setState( state, delta, RENDER_POLYGONSMOOTH, GL_POLYGON_SMOOTH );
1798
1799         setState( state, delta, RENDER_FOG, GL_FOG );
1800
1801         if ( ( state & RENDER_FOG ) != 0 ) {
1802                 setFogState( self.m_fog );
1803                 GlobalOpenGL_debugAssertNoErrors();
1804                 current.m_fog = self.m_fog;
1805         }
1806
1807         if ( state & RENDER_DEPTHTEST && self.m_depthfunc != current.m_depthfunc ) {
1808                 glDepthFunc( self.m_depthfunc );
1809                 GlobalOpenGL_debugAssertNoErrors();
1810                 current.m_depthfunc = self.m_depthfunc;
1811         }
1812
1813         if ( state & RENDER_LINESTIPPLE
1814                  && ( self.m_linestipple_factor != current.m_linestipple_factor
1815                           || self.m_linestipple_pattern != current.m_linestipple_pattern ) ) {
1816                 glLineStipple( self.m_linestipple_factor, self.m_linestipple_pattern );
1817                 GlobalOpenGL_debugAssertNoErrors();
1818                 current.m_linestipple_factor = self.m_linestipple_factor;
1819                 current.m_linestipple_pattern = self.m_linestipple_pattern;
1820         }
1821
1822
1823         if ( state & RENDER_ALPHATEST
1824                  && ( self.m_alphafunc != current.m_alphafunc
1825                           || self.m_alpharef != current.m_alpharef ) ) {
1826                 glAlphaFunc( self.m_alphafunc, self.m_alpharef );
1827                 GlobalOpenGL_debugAssertNoErrors();
1828                 current.m_alphafunc = self.m_alphafunc;
1829                 current.m_alpharef = self.m_alpharef;
1830         }
1831
1832         {
1833                 GLint texture0 = 0;
1834                 GLint texture1 = 0;
1835                 GLint texture2 = 0;
1836                 GLint texture3 = 0;
1837                 GLint texture4 = 0;
1838                 GLint texture5 = 0;
1839                 GLint texture6 = 0;
1840                 GLint texture7 = 0;
1841                 //if(state & RENDER_TEXTURE) != 0)
1842                 {
1843                         texture0 = self.m_texture;
1844                         texture1 = self.m_texture1;
1845                         texture2 = self.m_texture2;
1846                         texture3 = self.m_texture3;
1847                         texture4 = self.m_texture4;
1848                         texture5 = self.m_texture5;
1849                         texture6 = self.m_texture6;
1850                         texture7 = self.m_texture7;
1851                 }
1852
1853                 if ( GlobalOpenGL().GL_1_3() ) {
1854                         setTextureState( current.m_texture, texture0, GL_TEXTURE0 );
1855                         setTextureState( current.m_texture1, texture1, GL_TEXTURE1 );
1856                         setTextureState( current.m_texture2, texture2, GL_TEXTURE2 );
1857                         setTextureState( current.m_texture3, texture3, GL_TEXTURE3 );
1858                         setTextureState( current.m_texture4, texture4, GL_TEXTURE4 );
1859                         setTextureState( current.m_texture5, texture5, GL_TEXTURE5 );
1860                         setTextureState( current.m_texture6, texture6, GL_TEXTURE6 );
1861                         setTextureState( current.m_texture7, texture7, GL_TEXTURE7 );
1862                 }
1863                 else
1864                 {
1865                         setTextureState( current.m_texture, texture0 );
1866                 }
1867         }
1868
1869
1870         if ( state & RENDER_TEXTURE && self.m_colour[3] != current.m_colour[3] ) {
1871                 debug_colour( "setting alpha" );
1872                 glColor4f( 1,1,1,self.m_colour[3] );
1873                 GlobalOpenGL_debugAssertNoErrors();
1874         }
1875
1876         if ( !( state & RENDER_TEXTURE )
1877                  && ( self.m_colour[0] != current.m_colour[0]
1878                           || self.m_colour[1] != current.m_colour[1]
1879                           || self.m_colour[2] != current.m_colour[2]
1880                           || self.m_colour[3] != current.m_colour[3] ) ) {
1881                 glColor4fv( vector4_to_array( self.m_colour ) );
1882                 debug_colour( "setting non-texture" );
1883                 GlobalOpenGL_debugAssertNoErrors();
1884         }
1885         current.m_colour = self.m_colour;
1886
1887         if ( state & RENDER_BLEND
1888                  && ( self.m_blend_src != current.m_blend_src || self.m_blend_dst != current.m_blend_dst ) ) {
1889                 glBlendFunc( self.m_blend_src, self.m_blend_dst );
1890                 GlobalOpenGL_debugAssertNoErrors();
1891                 current.m_blend_src = self.m_blend_src;
1892                 current.m_blend_dst = self.m_blend_dst;
1893         }
1894
1895         if ( !( state & RENDER_FILL )
1896                  && self.m_linewidth != current.m_linewidth ) {
1897                 glLineWidth( self.m_linewidth );
1898                 GlobalOpenGL_debugAssertNoErrors();
1899                 current.m_linewidth = self.m_linewidth;
1900         }
1901
1902         if ( !( state & RENDER_FILL )
1903                  && self.m_pointsize != current.m_pointsize ) {
1904                 glPointSize( self.m_pointsize );
1905                 GlobalOpenGL_debugAssertNoErrors();
1906                 current.m_pointsize = self.m_pointsize;
1907         }
1908
1909         current.m_state = state;
1910
1911         GlobalOpenGL_debugAssertNoErrors();
1912 }
1913
1914 void Renderables_flush( OpenGLStateBucket::Renderables& renderables, OpenGLState& current, unsigned int globalstate, const Vector3& viewer ){
1915         const Matrix4* transform = 0;
1916         glPushMatrix();
1917         for ( OpenGLStateBucket::Renderables::const_iterator i = renderables.begin(); i != renderables.end(); ++i )
1918         {
1919                 //qglLoadMatrixf(i->m_transform);
1920                 if ( !transform || ( transform != ( *i ).m_transform && !matrix4_affine_equal( *transform, *( *i ).m_transform ) ) ) {
1921                         count_transform();
1922                         transform = ( *i ).m_transform;
1923                         glPopMatrix();
1924                         glPushMatrix();
1925                         glMultMatrixf( reinterpret_cast<const float*>( transform ) );
1926                         glFrontFace( ( ( current.m_state & RENDER_CULLFACE ) != 0 && matrix4_handedness( *transform ) == MATRIX4_RIGHTHANDED ) ? GL_CW : GL_CCW );
1927                 }
1928
1929                 count_prim();
1930
1931                 if ( current.m_program != 0 && ( *i ).m_light != 0 ) {
1932                         const IShader& lightShader = static_cast<OpenGLShader*>( ( *i ).m_light->getShader() )->getShader();
1933                         if ( lightShader.firstLayer() != 0 ) {
1934                                 GLuint attenuation_xy = lightShader.firstLayer()->texture()->texture_number;
1935                                 GLuint attenuation_z = lightShader.lightFalloffImage() != 0
1936                                                                            ? lightShader.lightFalloffImage()->texture_number
1937                                                                            : static_cast<OpenGLShader*>( g_defaultPointLight )->getShader().lightFalloffImage()->texture_number;
1938
1939                                 setTextureState( current.m_texture3, attenuation_xy, GL_TEXTURE3 );
1940                                 glActiveTexture( GL_TEXTURE3 );
1941                                 glBindTexture( GL_TEXTURE_2D, attenuation_xy );
1942                                 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER );
1943                                 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER );
1944
1945                                 setTextureState( current.m_texture4, attenuation_z, GL_TEXTURE4 );
1946                                 glActiveTexture( GL_TEXTURE4 );
1947                                 glBindTexture( GL_TEXTURE_2D, attenuation_z );
1948                                 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER );
1949                                 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
1950
1951
1952                                 AABB lightBounds( ( *i ).m_light->aabb() );
1953
1954                                 Matrix4 world2light( g_matrix4_identity );
1955
1956                                 if ( ( *i ).m_light->isProjected() ) {
1957                                         world2light = ( *i ).m_light->projection();
1958                                         matrix4_multiply_by_matrix4( world2light, matrix4_transposed( ( *i ).m_light->rotation() ) );
1959                                         matrix4_translate_by_vec3( world2light, vector3_negated( lightBounds.origin ) ); // world->lightBounds
1960                                 }
1961                                 if ( !( *i ).m_light->isProjected() ) {
1962                                         matrix4_translate_by_vec3( world2light, Vector3( 0.5f, 0.5f, 0.5f ) );
1963                                         matrix4_scale_by_vec3( world2light, Vector3( 0.5f, 0.5f, 0.5f ) );
1964                                         matrix4_scale_by_vec3( world2light, Vector3( 1.0f / lightBounds.extents.x(), 1.0f / lightBounds.extents.y(), 1.0f / lightBounds.extents.z() ) );
1965                                         matrix4_multiply_by_matrix4( world2light, matrix4_transposed( ( *i ).m_light->rotation() ) );
1966                                         matrix4_translate_by_vec3( world2light, vector3_negated( lightBounds.origin ) ); // world->lightBounds
1967                                 }
1968
1969                                 current.m_program->setParameters( viewer, *( *i ).m_transform, lightBounds.origin + ( *i ).m_light->offset(), ( *i ).m_light->colour(), world2light );
1970                                 debug_string( "set lightBounds parameters" );
1971                         }
1972                 }
1973
1974                 ( *i ).m_renderable->render( current.m_state );
1975         }
1976         glPopMatrix();
1977         renderables.clear();
1978 }
1979
1980 void OpenGLStateBucket::render( OpenGLState& current, unsigned int globalstate, const Vector3& viewer ){
1981         if ( ( globalstate & m_state.m_state & RENDER_SCREEN ) != 0 ) {
1982                 OpenGLState_apply( m_state, current, globalstate );
1983                 debug_colour( "screen fill" );
1984
1985                 glMatrixMode( GL_PROJECTION );
1986                 glPushMatrix();
1987                 glLoadMatrixf( reinterpret_cast<const float*>( &g_matrix4_identity ) );
1988
1989                 glMatrixMode( GL_MODELVIEW );
1990                 glPushMatrix();
1991                 glLoadMatrixf( reinterpret_cast<const float*>( &g_matrix4_identity ) );
1992
1993                 glBegin( GL_QUADS );
1994                 glVertex3f( -1, -1, 0 );
1995                 glVertex3f( 1, -1, 0 );
1996                 glVertex3f( 1, 1, 0 );
1997                 glVertex3f( -1, 1, 0 );
1998                 glEnd();
1999
2000                 glMatrixMode( GL_PROJECTION );
2001                 glPopMatrix();
2002
2003                 glMatrixMode( GL_MODELVIEW );
2004                 glPopMatrix();
2005         }
2006         else if ( !m_renderables.empty() ) {
2007                 OpenGLState_apply( m_state, current, globalstate );
2008                 Renderables_flush( m_renderables, current, globalstate, viewer );
2009         }
2010 }
2011
2012
2013 class OpenGLStateMap : public OpenGLStateLibrary
2014 {
2015 typedef std::map<std::string, OpenGLState> States;
2016 States m_states;
2017 public:
2018 ~OpenGLStateMap(){
2019         ASSERT_MESSAGE( m_states.empty(), "OpenGLStateMap::~OpenGLStateMap: not empty" );
2020 }
2021
2022 typedef States::iterator iterator;
2023 iterator begin(){
2024         return m_states.begin();
2025 }
2026 iterator end(){
2027         return m_states.end();
2028 }
2029
2030 void getDefaultState( OpenGLState& state ) const {
2031         OpenGLState_constructDefault( state );
2032 }
2033
2034 void insert( const char* name, const OpenGLState& state ){
2035         bool inserted = m_states.insert( States::value_type( name, state ) ).second;
2036         ASSERT_MESSAGE( inserted, "OpenGLStateMap::insert: " << name << " already exists" );
2037 }
2038 void erase( const char* name ){
2039         std::size_t count = m_states.erase( name );
2040         ASSERT_MESSAGE( count == 1, "OpenGLStateMap::erase: " << name << " does not exist" );
2041 }
2042
2043 iterator find( const char* name ){
2044         return m_states.find( name );
2045 }
2046 };
2047
2048 OpenGLStateMap* g_openglStates = 0;
2049
2050 inline GLenum convertBlendFactor( BlendFactor factor ){
2051         switch ( factor )
2052         {
2053         case BLEND_ZERO:
2054                 return GL_ZERO;
2055         case BLEND_ONE:
2056                 return GL_ONE;
2057         case BLEND_SRC_COLOUR:
2058                 return GL_SRC_COLOR;
2059         case BLEND_ONE_MINUS_SRC_COLOUR:
2060                 return GL_ONE_MINUS_SRC_COLOR;
2061         case BLEND_SRC_ALPHA:
2062                 return GL_SRC_ALPHA;
2063         case BLEND_ONE_MINUS_SRC_ALPHA:
2064                 return GL_ONE_MINUS_SRC_ALPHA;
2065         case BLEND_DST_COLOUR:
2066                 return GL_DST_COLOR;
2067         case BLEND_ONE_MINUS_DST_COLOUR:
2068                 return GL_ONE_MINUS_DST_COLOR;
2069         case BLEND_DST_ALPHA:
2070                 return GL_DST_ALPHA;
2071         case BLEND_ONE_MINUS_DST_ALPHA:
2072                 return GL_ONE_MINUS_DST_ALPHA;
2073         case BLEND_SRC_ALPHA_SATURATE:
2074                 return GL_SRC_ALPHA_SATURATE;
2075         }
2076         return GL_ZERO;
2077 }
2078
2079 /// \todo Define special-case shaders in a data file.
2080 void OpenGLShader::construct( const char* name ){
2081         OpenGLState& state = appendDefaultPass();
2082         switch ( name[0] )
2083         {
2084         case '(':
2085                 sscanf( name, "(%g %g %g)", &state.m_colour[0], &state.m_colour[1], &state.m_colour[2] );
2086                 state.m_colour[3] = 1.0f;
2087                 state.m_state = RENDER_FILL | RENDER_LIGHTING | RENDER_DEPTHTEST | RENDER_CULLFACE | RENDER_COLOURWRITE | RENDER_DEPTHWRITE;
2088                 state.m_sort = OpenGLState::eSortFullbright;
2089                 break;
2090
2091         case '[':
2092                 sscanf( name, "[%g %g %g]", &state.m_colour[0], &state.m_colour[1], &state.m_colour[2] );
2093                 state.m_colour[3] = 0.5f;
2094                 state.m_state = RENDER_FILL | RENDER_LIGHTING | RENDER_DEPTHTEST | RENDER_CULLFACE | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_BLEND;
2095                 state.m_sort = OpenGLState::eSortTranslucent;
2096                 break;
2097
2098         case '<':
2099                 sscanf( name, "<%g %g %g>", &state.m_colour[0], &state.m_colour[1], &state.m_colour[2] );
2100                 state.m_colour[3] = 1;
2101                 state.m_state = RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_DEPTHWRITE;
2102                 state.m_sort = OpenGLState::eSortFullbright;
2103                 state.m_depthfunc = GL_LESS;
2104                 state.m_linewidth = 1;
2105                 state.m_pointsize = 1;
2106                 break;
2107
2108         case '$':
2109         {
2110                 OpenGLStateMap::iterator i = g_openglStates->find( name );
2111                 if ( i != g_openglStates->end() ) {
2112                         state = ( *i ).second;
2113                         break;
2114                 }
2115         }
2116                 if ( string_equal( name + 1, "POINT" ) ) {
2117                         state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE;
2118                         state.m_sort = OpenGLState::eSortControlFirst;
2119                         state.m_pointsize = 4;
2120                 }
2121                 else if ( string_equal( name + 1, "SELPOINT" ) ) {
2122                         state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE;
2123                         state.m_sort = OpenGLState::eSortControlFirst + 1;
2124                         state.m_pointsize = 4;
2125                 }
2126                 else if ( string_equal( name + 1, "BIGPOINT" ) ) {
2127                         state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE;
2128                         state.m_sort = OpenGLState::eSortControlFirst;
2129                         state.m_pointsize = 6;
2130                 }
2131                 else if ( string_equal( name + 1, "PIVOT" ) ) {
2132                         state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHTEST | RENDER_DEPTHWRITE;
2133                         state.m_sort = OpenGLState::eSortGUI1;
2134                         state.m_linewidth = 2;
2135                         state.m_depthfunc = GL_LEQUAL;
2136
2137                         OpenGLState& hiddenLine = appendDefaultPass();
2138                         hiddenLine.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHTEST | RENDER_LINESTIPPLE;
2139                         hiddenLine.m_sort = OpenGLState::eSortGUI0;
2140                         hiddenLine.m_linewidth = 2;
2141                         hiddenLine.m_depthfunc = GL_GREATER;
2142                 }
2143                 else if ( string_equal( name + 1, "LATTICE" ) ) {
2144                         state.m_colour[0] = 1;
2145                         state.m_colour[1] = 0.5;
2146                         state.m_colour[2] = 0;
2147                         state.m_colour[3] = 1;
2148                         state.m_state = RENDER_COLOURWRITE | RENDER_DEPTHWRITE;
2149                         state.m_sort = OpenGLState::eSortControlFirst;
2150                 }
2151                 else if ( string_equal( name + 1, "WIREFRAME" ) ) {
2152                         state.m_state = RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_DEPTHWRITE;
2153                         state.m_sort = OpenGLState::eSortFullbright;
2154                 }
2155                 else if ( string_equal( name + 1, "CAM_HIGHLIGHT" ) ) {
2156                         state.m_colour[0] = 1;
2157                         state.m_colour[1] = 0;
2158                         state.m_colour[2] = 0;
2159                         state.m_colour[3] = 0.3f;
2160                         state.m_state = RENDER_FILL | RENDER_DEPTHTEST | RENDER_CULLFACE | RENDER_BLEND | RENDER_COLOURWRITE | RENDER_DEPTHWRITE;
2161                         state.m_sort = OpenGLState::eSortHighlight;
2162                         state.m_depthfunc = GL_LEQUAL;
2163                 }
2164                 else if ( string_equal( name + 1, "CAM_OVERLAY" ) ) {
2165 #if 0
2166                         state.m_state = RENDER_CULLFACE | RENDER_COLOURWRITE | RENDER_DEPTHWRITE;
2167                         state.m_sort = OpenGLState::eSortOverlayFirst;
2168 #else
2169                         state.m_state = RENDER_CULLFACE | RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_OFFSETLINE;
2170                         state.m_sort = OpenGLState::eSortOverlayFirst + 1;
2171                         state.m_depthfunc = GL_LEQUAL;
2172
2173                         OpenGLState& hiddenLine = appendDefaultPass();
2174                         hiddenLine.m_colour[0] = 0.75;
2175                         hiddenLine.m_colour[1] = 0.75;
2176                         hiddenLine.m_colour[2] = 0.75;
2177                         hiddenLine.m_colour[3] = 1;
2178                         hiddenLine.m_state = RENDER_CULLFACE | RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_OFFSETLINE | RENDER_LINESTIPPLE;
2179                         hiddenLine.m_sort = OpenGLState::eSortOverlayFirst;
2180                         hiddenLine.m_depthfunc = GL_GREATER;
2181                         hiddenLine.m_linestipple_factor = 2;
2182 #endif
2183                 }
2184                 else if ( string_equal( name + 1, "XY_OVERLAY" ) ) {
2185                         state.m_colour[0] = g_xywindow_globals.color_selbrushes[0];
2186                         state.m_colour[1] = g_xywindow_globals.color_selbrushes[1];
2187                         state.m_colour[2] = g_xywindow_globals.color_selbrushes[2];
2188                         state.m_colour[3] = 1;
2189                         state.m_state = RENDER_COLOURWRITE | RENDER_LINESTIPPLE;
2190                         state.m_sort = OpenGLState::eSortOverlayFirst;
2191                         state.m_linewidth = 2;
2192                         state.m_linestipple_factor = 3;
2193                 }
2194                 else if ( string_equal( name + 1, "DEBUG_CLIPPED" ) ) {
2195                         state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE;
2196                         state.m_sort = OpenGLState::eSortLast;
2197                 }
2198                 else if ( string_equal( name + 1, "POINTFILE" ) ) {
2199                         state.m_colour[0] = 1;
2200                         state.m_colour[1] = 0;
2201                         state.m_colour[2] = 0;
2202                         state.m_colour[3] = 1;
2203                         state.m_state = RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_DEPTHWRITE;
2204                         state.m_sort = OpenGLState::eSortFullbright;
2205                         state.m_linewidth = 4;
2206                 }
2207                 else if ( string_equal( name + 1, "LIGHT_SPHERE" ) ) {
2208                         state.m_colour[0] = .15f * .95f;
2209                         state.m_colour[1] = .15f * .95f;
2210                         state.m_colour[2] = .15f * .95f;
2211                         state.m_colour[3] = 1;
2212                         state.m_state = RENDER_CULLFACE | RENDER_DEPTHTEST | RENDER_BLEND | RENDER_FILL | RENDER_COLOURWRITE | RENDER_DEPTHWRITE;
2213                         state.m_blend_src = GL_ONE;
2214                         state.m_blend_dst = GL_ONE;
2215                         state.m_sort = OpenGLState::eSortTranslucent;
2216                 }
2217                 else if ( string_equal( name + 1, "Q3MAP2_LIGHT_SPHERE" ) ) {
2218                         state.m_colour[0] = .05f;
2219                         state.m_colour[1] = .05f;
2220                         state.m_colour[2] = .05f;
2221                         state.m_colour[3] = 1;
2222                         state.m_state = RENDER_CULLFACE | RENDER_DEPTHTEST | RENDER_BLEND | RENDER_FILL;
2223                         state.m_blend_src = GL_ONE;
2224                         state.m_blend_dst = GL_ONE;
2225                         state.m_sort = OpenGLState::eSortTranslucent;
2226                 }
2227                 else if ( string_equal( name + 1, "WIRE_OVERLAY" ) ) {
2228 #if 0
2229                         state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE;
2230                         state.m_sort = OpenGLState::eSortOverlayFirst;
2231 #else
2232                         state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE;
2233                         state.m_sort = OpenGLState::eSortGUI1;
2234                         state.m_depthfunc = GL_LEQUAL;
2235
2236                         OpenGLState& hiddenLine = appendDefaultPass();
2237                         hiddenLine.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE | RENDER_LINESTIPPLE;
2238                         hiddenLine.m_sort = OpenGLState::eSortGUI0;
2239                         hiddenLine.m_depthfunc = GL_GREATER;
2240 #endif
2241                 }
2242                 else if ( string_equal( name + 1, "FLATSHADE_OVERLAY" ) ) {
2243                         state.m_state = RENDER_CULLFACE | RENDER_LIGHTING | RENDER_SMOOTH | RENDER_SCALED | RENDER_COLOURARRAY | RENDER_FILL | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE;
2244                         state.m_sort = OpenGLState::eSortGUI1;
2245                         state.m_depthfunc = GL_LEQUAL;
2246
2247                         OpenGLState& hiddenLine = appendDefaultPass();
2248                         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;
2249                         hiddenLine.m_sort = OpenGLState::eSortGUI0;
2250                         hiddenLine.m_depthfunc = GL_GREATER;
2251                 }
2252                 else if ( string_equal( name + 1, "CLIPPER_OVERLAY" ) ) {
2253                         state.m_colour[0] = g_xywindow_globals.color_clipper[0];
2254                         state.m_colour[1] = g_xywindow_globals.color_clipper[1];
2255                         state.m_colour[2] = g_xywindow_globals.color_clipper[2];
2256                         state.m_colour[3] = 1;
2257                         state.m_state = RENDER_CULLFACE | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_FILL | RENDER_POLYGONSTIPPLE;
2258                         state.m_sort = OpenGLState::eSortOverlayFirst;
2259                 }
2260                 else if ( string_equal( name + 1, "OVERBRIGHT" ) ) {
2261                         const float lightScale = 2;
2262                         state.m_colour[0] = lightScale * 0.5f;
2263                         state.m_colour[1] = lightScale * 0.5f;
2264                         state.m_colour[2] = lightScale * 0.5f;
2265                         state.m_colour[3] = 0.5;
2266                         state.m_state = RENDER_FILL | RENDER_BLEND | RENDER_COLOURWRITE | RENDER_SCREEN;
2267                         state.m_sort = OpenGLState::eSortOverbrighten;
2268                         state.m_blend_src = GL_DST_COLOR;
2269                         state.m_blend_dst = GL_SRC_COLOR;
2270                 }
2271                 else
2272                 {
2273                         // default to something recognisable.. =)
2274                         ERROR_MESSAGE( "hardcoded renderstate not found" );
2275                         state.m_colour[0] = 1;
2276                         state.m_colour[1] = 0;
2277                         state.m_colour[2] = 1;
2278                         state.m_colour[3] = 1;
2279                         state.m_state = RENDER_COLOURWRITE | RENDER_DEPTHWRITE;
2280                         state.m_sort = OpenGLState::eSortFirst;
2281                 }
2282                 break;
2283         default:
2284                 // construction from IShader
2285                 m_shader = QERApp_Shader_ForName( name );
2286
2287                 if ( g_ShaderCache->lightingSupported() && g_ShaderCache->lightingEnabled() && m_shader->getBump() != 0 && m_shader->getBump()->texture_number != 0 ) { // is a bump shader
2288                         state.m_state = RENDER_FILL | RENDER_CULLFACE | RENDER_TEXTURE | RENDER_DEPTHTEST | RENDER_DEPTHWRITE | RENDER_COLOURWRITE | RENDER_PROGRAM;
2289                         state.m_colour[0] = 0;
2290                         state.m_colour[1] = 0;
2291                         state.m_colour[2] = 0;
2292                         state.m_colour[3] = 1;
2293                         state.m_sort = OpenGLState::eSortOpaque;
2294
2295                         if ( g_ShaderCache->useShaderLanguage() ) {
2296                                 state.m_program = &g_depthFillGLSL;
2297                         }
2298                         else
2299                         {
2300                                 state.m_program = &g_depthFillARB;
2301                         }
2302
2303                         OpenGLState& bumpPass = appendDefaultPass();
2304                         bumpPass.m_texture = m_shader->getDiffuse()->texture_number;
2305                         bumpPass.m_texture1 = m_shader->getBump()->texture_number;
2306                         bumpPass.m_texture2 = m_shader->getSpecular()->texture_number;
2307
2308                         bumpPass.m_state = RENDER_BLEND | RENDER_FILL | RENDER_CULLFACE | RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_SMOOTH | RENDER_BUMP | RENDER_PROGRAM;
2309
2310                         if ( g_ShaderCache->useShaderLanguage() ) {
2311                                 bumpPass.m_state |= RENDER_LIGHTING;
2312                                 bumpPass.m_program = &g_bumpGLSL;
2313                         }
2314                         else
2315                         {
2316                                 bumpPass.m_program = &g_bumpARB;
2317                         }
2318
2319                         bumpPass.m_depthfunc = GL_LEQUAL;
2320                         bumpPass.m_sort = OpenGLState::eSortMultiFirst;
2321                         bumpPass.m_blend_src = GL_ONE;
2322                         bumpPass.m_blend_dst = GL_ONE;
2323                 }
2324                 else
2325                 {
2326                         state.m_texture = m_shader->getTexture()->texture_number;
2327
2328                         state.m_state = RENDER_FILL | RENDER_TEXTURE | RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_LIGHTING | RENDER_SMOOTH;
2329                         if ( ( m_shader->getFlags() & QER_CULL ) != 0 ) {
2330                                 if ( m_shader->getCull() == IShader::eCullBack ) {
2331                                         state.m_state |= RENDER_CULLFACE;
2332                                 }
2333                         }
2334                         else
2335                         {
2336                                 state.m_state |= RENDER_CULLFACE;
2337                         }
2338                         if ( ( m_shader->getFlags() & QER_ALPHATEST ) != 0 ) {
2339                                 state.m_state |= RENDER_ALPHATEST;
2340                                 IShader::EAlphaFunc alphafunc;
2341                                 m_shader->getAlphaFunc( &alphafunc, &state.m_alpharef );
2342                                 switch ( alphafunc )
2343                                 {
2344                                 case IShader::eAlways:
2345                                         state.m_alphafunc = GL_ALWAYS;
2346                                 case IShader::eEqual:
2347                                         state.m_alphafunc = GL_EQUAL;
2348                                 case IShader::eLess:
2349                                         state.m_alphafunc = GL_LESS;
2350                                 case IShader::eGreater:
2351                                         state.m_alphafunc = GL_GREATER;
2352                                 case IShader::eLEqual:
2353                                         state.m_alphafunc = GL_LEQUAL;
2354                                 case IShader::eGEqual:
2355                                         state.m_alphafunc = GL_GEQUAL;
2356                                 }
2357                         }
2358                         reinterpret_cast<Vector3&>( state.m_colour ) = m_shader->getTexture()->color;
2359                         state.m_colour[3] = 1.0f;
2360
2361                         if ( ( m_shader->getFlags() & QER_TRANS ) != 0 ) {
2362                                 state.m_state |= RENDER_BLEND;
2363                                 state.m_colour[3] = m_shader->getTrans();
2364                                 state.m_sort = OpenGLState::eSortTranslucent;
2365                                 BlendFunc blendFunc = m_shader->getBlendFunc();
2366                                 state.m_blend_src = convertBlendFactor( blendFunc.m_src );
2367                                 state.m_blend_dst = convertBlendFactor( blendFunc.m_dst );
2368                                 if ( state.m_blend_src == GL_SRC_ALPHA || state.m_blend_dst == GL_SRC_ALPHA ) {
2369                                         state.m_state |= RENDER_DEPTHWRITE;
2370                                 }
2371                         }
2372                         else
2373                         {
2374                                 state.m_state |= RENDER_DEPTHWRITE;
2375                                 state.m_sort = OpenGLState::eSortFullbright;
2376                         }
2377                 }
2378         }
2379 }
2380
2381
2382 #include "modulesystem/singletonmodule.h"
2383 #include "modulesystem/moduleregistry.h"
2384
2385 class OpenGLStateLibraryAPI
2386 {
2387 OpenGLStateMap m_stateMap;
2388 public:
2389 typedef OpenGLStateLibrary Type;
2390 STRING_CONSTANT( Name, "*" );
2391
2392 OpenGLStateLibraryAPI(){
2393         g_openglStates = &m_stateMap;
2394 }
2395 ~OpenGLStateLibraryAPI(){
2396         g_openglStates = 0;
2397 }
2398 OpenGLStateLibrary* getTable(){
2399         return &m_stateMap;
2400 }
2401 };
2402
2403 typedef SingletonModule<OpenGLStateLibraryAPI> OpenGLStateLibraryModule;
2404 typedef Static<OpenGLStateLibraryModule> StaticOpenGLStateLibraryModule;
2405 StaticRegisterModule staticRegisterOpenGLStateLibrary( StaticOpenGLStateLibraryModule::instance() );
2406
2407 class ShaderCacheDependencies : public GlobalShadersModuleRef, public GlobalTexturesModuleRef, public GlobalOpenGLStateLibraryModuleRef
2408 {
2409 public:
2410 ShaderCacheDependencies() :
2411         GlobalShadersModuleRef( GlobalRadiant().getRequiredGameDescriptionKeyValue( "shaders" ) ){
2412 }
2413 };
2414
2415 class ShaderCacheAPI
2416 {
2417 ShaderCache* m_shaderCache;
2418 public:
2419 typedef ShaderCache Type;
2420 STRING_CONSTANT( Name, "*" );
2421
2422 ShaderCacheAPI(){
2423         ShaderCache_Construct();
2424
2425         m_shaderCache = GetShaderCache();
2426 }
2427 ~ShaderCacheAPI(){
2428         ShaderCache_Destroy();
2429 }
2430 ShaderCache* getTable(){
2431         return m_shaderCache;
2432 }
2433 };
2434
2435 typedef SingletonModule<ShaderCacheAPI, ShaderCacheDependencies> ShaderCacheModule;
2436 typedef Static<ShaderCacheModule> StaticShaderCacheModule;
2437 StaticRegisterModule staticRegisterShaderCache( StaticShaderCacheModule::instance() );