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