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