2 Copyright (C) 2001-2006, William Joseph.
5 This file is part of GtkRadiant.
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.
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.
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
22 #include "renderstate.h"
24 #include "debugging/debugging.h"
29 #include "itextures.h"
31 #include "renderable.h"
32 #include "qerplugin.h"
39 #include "math/matrix.h"
40 #include "math/aabb.h"
41 #include "generic/callback.h"
42 #include "texturelib.h"
43 #include "string/string.h"
44 #include "container/hashfunc.h"
45 #include "container/cache.h"
46 #include "generic/reference.h"
47 #include "moduleobservers.h"
48 #include "stream/filestream.h"
49 #include "stream/stringstream.h"
51 #include "preferences.h"
57 #define DEBUG_RENDER 0
59 inline void debug_string(const char* string)
62 globalOutputStream() << string << "\n";
66 inline void debug_int(const char* comment, int i)
69 globalOutputStream() << comment << " " << i << "\n";
73 inline void debug_colour(const char* comment)
77 glGetFloatv(GL_CURRENT_COLOR, reinterpret_cast<float*>(&v));
78 globalOutputStream() << comment << " colour: "
83 if(glIsEnabled(GL_COLOR_ARRAY))
85 globalOutputStream() << " ARRAY";
87 if(glIsEnabled(GL_COLOR_MATERIAL))
89 globalOutputStream() << " MATERIAL";
91 globalOutputStream() << "\n";
97 StringOutputStream g_renderer_stats;
98 std::size_t g_count_prims;
99 std::size_t g_count_states;
100 std::size_t g_count_transforms;
103 inline void count_prim()
108 inline void count_state()
113 inline void count_transform()
115 ++g_count_transforms;
118 void Renderer_ResetStats()
122 g_count_transforms = 0;
126 const char* Renderer_GetStats()
128 g_renderer_stats.clear();
129 g_renderer_stats << "prims: " << Unsigned(g_count_prims)
130 << " | states: " << Unsigned(g_count_states)
131 << " | transforms: " << Unsigned(g_count_transforms)
132 << " | msec: " << g_timer.elapsed_msec();
133 return g_renderer_stats.c_str();
137 void printShaderLog(GLhandleARB object)
139 GLint log_length = 0;
140 glGetObjectParameterivARB(object, GL_OBJECT_INFO_LOG_LENGTH_ARB, &log_length);
142 Array<char> log(log_length);
143 glGetInfoLogARB(object, log_length, &log_length, log.data());
145 globalErrorStream() << StringRange(log.begin(), log.begin() + log_length) << "\n";
148 void createShader(GLhandleARB program, const char* filename, GLenum type)
150 GLhandleARB shader = glCreateShaderObjectARB(type);
151 GlobalOpenGL_debugAssertNoErrors();
155 std::size_t size = file_size(filename);
156 FileInputStream file(filename);
157 ASSERT_MESSAGE(!file.failed(), "failed to open " << makeQuoted(filename));
158 Array<GLcharARB> buffer(size);
159 size = file.read(reinterpret_cast<StreamBase::byte_type*>(buffer.data()), size);
161 const GLcharARB* string = buffer.data();
162 GLint length = GLint(size);
163 glShaderSourceARB(shader, 1, &string, &length);
168 glCompileShaderARB(shader);
171 glGetObjectParameterivARB(shader, GL_OBJECT_COMPILE_STATUS_ARB, &compiled);
175 printShaderLog(shader);
178 ASSERT_MESSAGE(compiled, "shader compile failed: " << makeQuoted(filename));
182 glAttachObjectARB(program, shader);
184 glDeleteObjectARB(shader);
186 GlobalOpenGL_debugAssertNoErrors();
189 void GLSLProgram_link(GLhandleARB program)
191 glLinkProgramARB(program);
193 GLint linked = false;
194 glGetObjectParameterivARB(program, GL_OBJECT_LINK_STATUS_ARB, &linked);
198 printShaderLog(program);
201 ASSERT_MESSAGE(linked, "program link failed");
204 void GLSLProgram_validate(GLhandleARB program)
206 glValidateProgramARB(program);
208 GLint validated = false;
209 glGetObjectParameterivARB(program, GL_OBJECT_VALIDATE_STATUS_ARB, &validated);
213 printShaderLog(program);
216 ASSERT_MESSAGE(validated, "program validation failed");
219 bool g_bumpGLSLPass_enabled = false;
220 bool g_depthfillPass_enabled = false;
225 virtual void enable() = 0;
226 virtual void disable() = 0;
227 virtual void setParameters(const Vector3& viewer, const Matrix4& localToWorld, const Vector3& origin, const Vector3& colour, const Matrix4& world2light) = 0;
230 class GLSLBumpProgram : public GLProgram
233 GLhandleARB m_program;
234 qtexture_t* m_light_attenuation_xy;
235 qtexture_t* m_light_attenuation_z;
237 GLint u_light_origin;
240 GLint u_specular_exponent;
242 GLSLBumpProgram() : m_program(0), m_light_attenuation_xy(0), m_light_attenuation_z(0)
249 m_program = glCreateProgramObjectARB();
253 StringOutputStream filename(256);
254 filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_vp.glsl";
255 createShader(m_program, filename.c_str(), GL_VERTEX_SHADER_ARB);
257 filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_fp.glsl";
258 createShader(m_program, filename.c_str(), GL_FRAGMENT_SHADER_ARB);
261 GLSLProgram_link(m_program);
262 GLSLProgram_validate(m_program);
264 glUseProgramObjectARB(m_program);
266 glBindAttribLocationARB(m_program, c_attr_TexCoord0, "attr_TexCoord0");
267 glBindAttribLocationARB(m_program, c_attr_Tangent, "attr_Tangent");
268 glBindAttribLocationARB(m_program, c_attr_Binormal, "attr_Binormal");
270 glUniform1iARB(glGetUniformLocationARB(m_program, "u_diffusemap"), 0);
271 glUniform1iARB(glGetUniformLocationARB(m_program, "u_bumpmap"), 1);
272 glUniform1iARB(glGetUniformLocationARB(m_program, "u_specularmap"), 2);
273 glUniform1iARB(glGetUniformLocationARB(m_program, "u_attenuationmap_xy"), 3);
274 glUniform1iARB(glGetUniformLocationARB(m_program, "u_attenuationmap_z"), 4);
276 u_view_origin = glGetUniformLocationARB(m_program, "u_view_origin");
277 u_light_origin = glGetUniformLocationARB(m_program, "u_light_origin");
278 u_light_color = glGetUniformLocationARB(m_program, "u_light_color");
279 u_bump_scale = glGetUniformLocationARB(m_program, "u_bump_scale");
280 u_specular_exponent = glGetUniformLocationARB(m_program, "u_specular_exponent");
282 glUseProgramObjectARB(0);
284 GlobalOpenGL_debugAssertNoErrors();
289 glDeleteObjectARB(m_program);
295 glUseProgramObjectARB(m_program);
297 glEnableVertexAttribArrayARB(c_attr_TexCoord0);
298 glEnableVertexAttribArrayARB(c_attr_Tangent);
299 glEnableVertexAttribArrayARB(c_attr_Binormal);
301 GlobalOpenGL_debugAssertNoErrors();
303 debug_string("enable bump");
304 g_bumpGLSLPass_enabled = true;
309 glUseProgramObjectARB(0);
311 glDisableVertexAttribArrayARB(c_attr_TexCoord0);
312 glDisableVertexAttribArrayARB(c_attr_Tangent);
313 glDisableVertexAttribArrayARB(c_attr_Binormal);
315 GlobalOpenGL_debugAssertNoErrors();
317 debug_string("disable bump");
318 g_bumpGLSLPass_enabled = false;
321 void setParameters(const Vector3& viewer, const Matrix4& localToWorld, const Vector3& origin, const Vector3& colour, const Matrix4& world2light)
323 Matrix4 world2local(localToWorld);
324 matrix4_affine_invert(world2local);
326 Vector3 localLight(origin);
327 matrix4_transform_point(world2local, localLight);
329 Vector3 localViewer(viewer);
330 matrix4_transform_point(world2local, localViewer);
332 Matrix4 local2light(world2light);
333 matrix4_multiply_by_matrix4(local2light, localToWorld); // local->world->light
335 glUniform3fARB(u_view_origin, localViewer.x(), localViewer.y(), localViewer.z());
336 glUniform3fARB(u_light_origin, localLight.x(), localLight.y(), localLight.z());
337 glUniform3fARB(u_light_color, colour.x(), colour.y(), colour.z());
338 glUniform1fARB(u_bump_scale, 1.0);
339 glUniform1fARB(u_specular_exponent, 32.0);
341 glActiveTexture(GL_TEXTURE3);
342 glClientActiveTexture(GL_TEXTURE3);
344 glMatrixMode(GL_TEXTURE);
345 glLoadMatrixf(reinterpret_cast<const float*>(&local2light));
346 glMatrixMode(GL_MODELVIEW);
348 GlobalOpenGL_debugAssertNoErrors();
352 GLSLBumpProgram g_bumpGLSL;
355 class GLSLDepthFillProgram : public GLProgram
358 GLhandleARB m_program;
363 m_program = glCreateProgramObjectARB();
367 StringOutputStream filename(256);
368 filename << GlobalRadiant().getAppPath() << "gl/zfill_vp.glsl";
369 createShader(m_program, filename.c_str(), GL_VERTEX_SHADER_ARB);
371 filename << GlobalRadiant().getAppPath() << "gl/zfill_fp.glsl";
372 createShader(m_program, filename.c_str(), GL_FRAGMENT_SHADER_ARB);
375 GLSLProgram_link(m_program);
376 GLSLProgram_validate(m_program);
378 GlobalOpenGL_debugAssertNoErrors();
383 glDeleteObjectARB(m_program);
388 glUseProgramObjectARB(m_program);
389 GlobalOpenGL_debugAssertNoErrors();
390 debug_string("enable depthfill");
391 g_depthfillPass_enabled = true;
395 glUseProgramObjectARB(0);
396 GlobalOpenGL_debugAssertNoErrors();
397 debug_string("disable depthfill");
398 g_depthfillPass_enabled = false;
400 void setParameters(const Vector3& viewer, const Matrix4& localToWorld, const Vector3& origin, const Vector3& colour, const Matrix4& world2light)
405 GLSLDepthFillProgram g_depthFillGLSL;
410 void createProgram(const char* filename, GLenum type)
412 std::size_t size = file_size(filename);
413 FileInputStream file(filename);
414 ASSERT_MESSAGE(!file.failed(), "failed to open " << makeQuoted(filename));
415 Array<GLcharARB> buffer(size);
416 size = file.read(reinterpret_cast<StreamBase::byte_type*>(buffer.data()), size);
418 glProgramStringARB(type, GL_PROGRAM_FORMAT_ASCII_ARB, GLsizei(size), buffer.data());
420 if(GL_INVALID_OPERATION == glGetError())
423 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
424 const GLubyte* errString = glGetString(GL_PROGRAM_ERROR_STRING_ARB);
426 globalErrorStream() << reinterpret_cast<const char*>(filename) << ":" << errPos << "\n" << reinterpret_cast<const char*>(errString);
428 ERROR_MESSAGE("error in gl program");
432 class ARBBumpProgram : public GLProgram
435 GLuint m_vertex_program;
436 GLuint m_fragment_program;
440 glEnable(GL_VERTEX_PROGRAM_ARB);
441 glEnable(GL_FRAGMENT_PROGRAM_ARB);
444 glGenProgramsARB(1, &m_vertex_program);
445 glBindProgramARB(GL_VERTEX_PROGRAM_ARB, m_vertex_program);
446 StringOutputStream filename(256);
447 filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_vp.glp";
448 createProgram(filename.c_str(), GL_VERTEX_PROGRAM_ARB);
450 glGenProgramsARB(1, &m_fragment_program);
451 glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, m_fragment_program);
453 filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_fp.glp";
454 createProgram(filename.c_str(), GL_FRAGMENT_PROGRAM_ARB);
457 glDisable(GL_VERTEX_PROGRAM_ARB);
458 glDisable(GL_FRAGMENT_PROGRAM_ARB);
460 GlobalOpenGL_debugAssertNoErrors();
465 glDeleteProgramsARB(1, &m_vertex_program);
466 glDeleteProgramsARB(1, &m_fragment_program);
467 GlobalOpenGL_debugAssertNoErrors();
472 glEnable(GL_VERTEX_PROGRAM_ARB);
473 glEnable(GL_FRAGMENT_PROGRAM_ARB);
474 glBindProgramARB(GL_VERTEX_PROGRAM_ARB, m_vertex_program);
475 glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, m_fragment_program);
477 glEnableVertexAttribArrayARB(8);
478 glEnableVertexAttribArrayARB(9);
479 glEnableVertexAttribArrayARB(10);
480 glEnableVertexAttribArrayARB(11);
482 GlobalOpenGL_debugAssertNoErrors();
487 glDisable(GL_VERTEX_PROGRAM_ARB);
488 glDisable(GL_FRAGMENT_PROGRAM_ARB);
490 glDisableVertexAttribArrayARB(8);
491 glDisableVertexAttribArrayARB(9);
492 glDisableVertexAttribArrayARB(10);
493 glDisableVertexAttribArrayARB(11);
495 GlobalOpenGL_debugAssertNoErrors();
498 void setParameters(const Vector3& viewer, const Matrix4& localToWorld, const Vector3& origin, const Vector3& colour, const Matrix4& world2light)
500 Matrix4 world2local(localToWorld);
501 matrix4_affine_invert(world2local);
503 Vector3 localLight(origin);
504 matrix4_transform_point(world2local, localLight);
506 Vector3 localViewer(viewer);
507 matrix4_transform_point(world2local, localViewer);
509 Matrix4 local2light(world2light);
510 matrix4_multiply_by_matrix4(local2light, localToWorld); // local->world->light
513 glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 4, localViewer.x(), localViewer.y(), localViewer.z(), 0);
516 glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 2, localLight.x(), localLight.y(), localLight.z(), 1);
519 glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 3, colour.x(), colour.y(), colour.z(), 0);
522 glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, 1, 0, 0, 0);
525 glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 5, 32, 0, 0, 0);
528 glActiveTexture(GL_TEXTURE3);
529 glClientActiveTexture(GL_TEXTURE3);
531 glMatrixMode(GL_TEXTURE);
532 glLoadMatrixf(reinterpret_cast<const float*>(&local2light));
533 glMatrixMode(GL_MODELVIEW);
535 GlobalOpenGL_debugAssertNoErrors();
539 class ARBDepthFillProgram : public GLProgram
542 GLuint m_vertex_program;
543 GLuint m_fragment_program;
547 glEnable(GL_VERTEX_PROGRAM_ARB);
548 glEnable(GL_FRAGMENT_PROGRAM_ARB);
551 glGenProgramsARB(1, &m_vertex_program);
552 glBindProgramARB(GL_VERTEX_PROGRAM_ARB, m_vertex_program);
553 StringOutputStream filename(256);
554 filename << GlobalRadiant().getAppPath() << "gl/zfill_vp.glp";
555 createProgram(filename.c_str(), GL_VERTEX_PROGRAM_ARB);
557 glGenProgramsARB(1, &m_fragment_program);
558 glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, m_fragment_program);
560 filename << GlobalRadiant().getAppPath() << "gl/zfill_fp.glp";
561 createProgram(filename.c_str(), GL_FRAGMENT_PROGRAM_ARB);
564 glDisable(GL_VERTEX_PROGRAM_ARB);
565 glDisable(GL_FRAGMENT_PROGRAM_ARB);
567 GlobalOpenGL_debugAssertNoErrors();
572 glDeleteProgramsARB(1, &m_vertex_program);
573 glDeleteProgramsARB(1, &m_fragment_program);
574 GlobalOpenGL_debugAssertNoErrors();
579 glEnable(GL_VERTEX_PROGRAM_ARB);
580 glEnable(GL_FRAGMENT_PROGRAM_ARB);
581 glBindProgramARB(GL_VERTEX_PROGRAM_ARB, m_vertex_program);
582 glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, m_fragment_program);
584 GlobalOpenGL_debugAssertNoErrors();
589 glDisable(GL_VERTEX_PROGRAM_ARB);
590 glDisable(GL_FRAGMENT_PROGRAM_ARB);
592 GlobalOpenGL_debugAssertNoErrors();
595 void setParameters(const Vector3& viewer, const Matrix4& localToWorld, const Vector3& origin, const Vector3& colour, const Matrix4& world2light)
600 ARBBumpProgram g_bumpARB;
601 ARBDepthFillProgram g_depthFillARB;
605 // NV20 path (unfinished)
607 void createProgram(GLint program, const char* filename, GLenum type)
609 std::size_t size = file_size(filename);
610 FileInputStream file(filename);
611 ASSERT_MESSAGE(!file.failed(), "failed to open " << makeQuoted(filename));
612 Array<GLubyte> buffer(size);
613 size = file.read(reinterpret_cast<StreamBase::byte_type*>(buffer.data()), size);
615 glLoadProgramNV(type, program, GLsizei(size), buffer.data());
617 if(GL_INVALID_OPERATION == glGetError())
620 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_NV, &errPos);
621 const GLubyte* errString = glGetString(GL_PROGRAM_ERROR_STRING_NV);
623 globalErrorStream() << filename << ":" << errPos << "\n" << errString;
625 ERROR_MESSAGE("error in gl program");
629 GLuint m_vertex_program;
630 GLuint m_fragment_program;
631 qtexture_t* g_cube = 0;
632 qtexture_t* g_specular_lookup = 0;
633 qtexture_t* g_attenuation_xy = 0;
634 qtexture_t* g_attenuation_z = 0;
636 void createVertexProgram()
639 glGenProgramsNV(1, &m_vertex_program);
640 glBindProgramNV(GL_VERTEX_PROGRAM_NV, m_vertex_program);
641 StringOutputStream filename(256);
642 filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_vp.nv30";
643 createProgram(m_vertex_program, filename.c_str(), GL_VERTEX_PROGRAM_NV);
645 glGenProgramsNV(1, &m_fragment_program);
646 glBindProgramNV(GL_FRAGMENT_PROGRAM_NV, m_fragment_program);
648 filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_fp.nv30";
649 createProgram(m_fragment_program, filename.c_str(), GL_FRAGMENT_PROGRAM_NV);
652 g_cube = GlobalTexturesCache().capture("generated/cube");
653 g_specular_lookup = GlobalTexturesCache().capture("generated/specular");
655 g_attenuation_xy = GlobalTexturesCache().capture("lights/squarelight1");
656 glActiveTexture(GL_TEXTURE0);
657 glBindTexture(GL_TEXTURE_2D, g_attenuation_xy->texture_number);
658 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
659 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
661 g_attenuation_z = GlobalTexturesCache().capture("lights/squarelight1a");
662 glActiveTexture(GL_TEXTURE0);
663 glBindTexture(GL_TEXTURE_2D, g_attenuation_z->texture_number);
664 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
665 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
667 GlobalOpenGL_debugAssertNoErrors();
670 void destroyVertexProgram()
672 glDeleteProgramsNV(1, &m_vertex_program);
673 glDeleteProgramsNV(1, &m_fragment_program);
674 GlobalOpenGL_debugAssertNoErrors();
676 GlobalTexturesCache().release(g_cube);
677 GlobalTexturesCache().release(g_specular_lookup);
678 GlobalTexturesCache().release(g_attenuation_xy);
679 GlobalTexturesCache().release(g_attenuation_z);
682 bool g_vertexProgram_enabled = false;
684 void enableVertexProgram()
686 //set up the register combiners
687 //two general combiners
688 glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, 2);
690 //combiner 0 does tex0+tex1 -> spare0
691 glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_A_NV, GL_TEXTURE0_ARB,
692 GL_UNSIGNED_IDENTITY_NV, GL_RGB);
693 glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_B_NV, GL_ZERO,
694 GL_UNSIGNED_INVERT_NV, GL_RGB);
695 glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_C_NV, GL_TEXTURE1_ARB,
696 GL_UNSIGNED_IDENTITY_NV, GL_RGB);
697 glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_D_NV, GL_ZERO,
698 GL_UNSIGNED_INVERT_NV, GL_RGB);
699 glCombinerOutputNV(GL_COMBINER0_NV, GL_RGB, GL_DISCARD_NV, GL_DISCARD_NV, GL_SPARE0_NV,
700 GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE);
702 //combiner 1 does tex2 dot tex3 -> spare1
703 glCombinerInputNV(GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_A_NV, GL_TEXTURE2_ARB,
704 GL_EXPAND_NORMAL_NV, GL_RGB);
705 glCombinerInputNV(GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_B_NV, GL_TEXTURE3_ARB,
706 GL_EXPAND_NORMAL_NV, GL_RGB);
707 glCombinerOutputNV(GL_COMBINER1_NV, GL_RGB, GL_SPARE1_NV, GL_DISCARD_NV, GL_DISCARD_NV,
708 GL_NONE, GL_NONE, GL_TRUE, GL_FALSE, GL_FALSE);
712 //final combiner outputs (1-spare0)*constant color 0*spare1
713 //do constant color 0*spare1 in the EF multiplier
714 glFinalCombinerInputNV(GL_VARIABLE_E_NV, GL_SPARE1_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
715 glFinalCombinerInputNV(GL_VARIABLE_F_NV, GL_CONSTANT_COLOR0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
717 //now do (1-spare0)*EF
718 glFinalCombinerInputNV(GL_VARIABLE_A_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
719 glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
720 glFinalCombinerInputNV(GL_VARIABLE_C_NV, GL_E_TIMES_F_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
721 glFinalCombinerInputNV(GL_VARIABLE_D_NV, GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
723 glEnable(GL_VERTEX_PROGRAM_NV);
724 glEnable(GL_REGISTER_COMBINERS_NV);
725 glBindProgramNV(GL_VERTEX_PROGRAM_NV, m_vertex_program);
726 glBindProgramNV(GL_FRAGMENT_PROGRAM_NV, m_fragment_program);
728 glActiveTexture(GL_TEXTURE0);
729 glEnable(GL_TEXTURE_2D);
730 glActiveTexture(GL_TEXTURE1);
731 glEnable(GL_TEXTURE_1D);
732 glActiveTexture(GL_TEXTURE2);
733 glEnable(GL_TEXTURE_2D);
734 glActiveTexture(GL_TEXTURE3);
735 glEnable(GL_TEXTURE_2D);
737 glEnableClientState(GL_VERTEX_ATTRIB_ARRAY8_NV);
738 glEnableClientState(GL_VERTEX_ATTRIB_ARRAY9_NV);
739 glEnableClientState(GL_VERTEX_ATTRIB_ARRAY10_NV);
740 glEnableClientState(GL_VERTEX_ATTRIB_ARRAY11_NV);
742 GlobalOpenGL_debugAssertNoErrors();
743 g_vertexProgram_enabled = true;
746 void disableVertexProgram()
748 glDisable(GL_VERTEX_PROGRAM_NV);
749 glDisable(GL_REGISTER_COMBINERS_NV);
751 glActiveTexture(GL_TEXTURE0);
752 glDisable(GL_TEXTURE_2D);
753 glActiveTexture(GL_TEXTURE1);
754 glDisable(GL_TEXTURE_1D);
755 glActiveTexture(GL_TEXTURE2);
756 glDisable(GL_TEXTURE_2D);
757 glActiveTexture(GL_TEXTURE3);
758 glDisable(GL_TEXTURE_2D);
760 glDisableClientState(GL_VERTEX_ATTRIB_ARRAY8_NV);
761 glDisableClientState(GL_VERTEX_ATTRIB_ARRAY9_NV);
762 glDisableClientState(GL_VERTEX_ATTRIB_ARRAY10_NV);
763 glDisableClientState(GL_VERTEX_ATTRIB_ARRAY11_NV);
765 GlobalOpenGL_debugAssertNoErrors();
766 g_vertexProgram_enabled = false;
772 const GLubyte* m_string;
773 const GLint m_length;
774 GLstringNV(const char* string) : m_string(reinterpret_cast<const GLubyte*>(string)), m_length(GLint(string_length(string)))
779 GLstringNV g_light_origin("light_origin");
780 GLstringNV g_view_origin("view_origin");
781 GLstringNV g_light_color("light_color");
782 GLstringNV g_bumpGLSL_scale("bump_scale");
783 GLstringNV g_specular_exponent("specular_exponent");
785 void setVertexProgramEnvironment(const Vector3& localViewer)
787 Matrix4 local2light(g_matrix4_identity);
788 matrix4_translate_by_vec3(local2light, Vector3(0.5, 0.5, 0.5));
789 matrix4_scale_by_vec3(local2light, Vector3(0.5, 0.5, 0.5));
790 matrix4_scale_by_vec3(local2light, Vector3(1.0 / 512.0, 1.0 / 512.0, 1.0 / 512.0));
791 matrix4_translate_by_vec3(local2light, vector3_negated(localViewer));
793 glActiveTexture(GL_TEXTURE3);
794 glClientActiveTexture(GL_TEXTURE3);
796 glMatrixMode(GL_TEXTURE);
797 glLoadMatrixf(reinterpret_cast<const float*>(&local2light));
798 glMatrixMode(GL_MODELVIEW);
800 glTrackMatrixNV(GL_VERTEX_PROGRAM_NV, 0, GL_MODELVIEW_PROJECTION_NV, GL_IDENTITY_NV);
801 glTrackMatrixNV(GL_VERTEX_PROGRAM_NV, 4, GL_TEXTURE0_ARB, GL_IDENTITY_NV);
804 //qglProgramNamedParameter4fNV(m_fragment_program, g_view_origin.m_length, g_view_origin.m_string, localViewer.x(), localViewer.y(), localViewer.z(), 0);
807 glProgramParameter4fNV(GL_VERTEX_PROGRAM_NV, 8, localViewer.x(), localViewer.y(), localViewer.z(), 1.0f);
810 glCombinerParameterfNV(GL_CONSTANT_COLOR0_NV, 1, 1, 1, 1)
813 //qglProgramNamedParameter4fNV(m_fragment_program, g_bumpGLSL_scale.m_length, g_bumpGLSL_scale.m_string, 1, 0, 0, 0);
816 //qglProgramNamedParameter4fNV(m_fragment_program, g_specular_exponent.m_length, g_specular_exponent.m_string, 32, 0, 0, 0);
818 GlobalOpenGL_debugAssertNoErrors();
824 bool g_vertexArray_enabled = false;
825 bool g_normalArray_enabled = false;
826 bool g_texcoordArray_enabled = false;
827 bool g_colorArray_enabled = false;
829 //! A collection of opengl state information.
838 eSortMultiLast = 1023,
839 eSortOverbrighten = 1024,
840 eSortFullbright = 1025,
841 eSortHighlight = 1026,
842 eSortTranslucent = 1027,
843 eSortOverlayFirst = 1028,
844 eSortOverlayLast = 2047,
845 eSortControlFirst = 2048,
846 eSortControlLast = 3071,
852 unsigned int m_state;
863 GLenum m_blend_src, m_blend_dst;
869 GLint m_linestipple_factor;
870 GLushort m_linestipple_pattern;
871 GLProgram* m_program;
873 OpenGLState() : m_program(0)
878 inline bool OpenGLState_less(const OpenGLState& self, const OpenGLState& other)
880 //! Sort by sort-order override.
881 if(self.m_sort != other.m_sort)
883 return self.m_sort < other.m_sort;
885 //! Sort by texture handle.
886 if(self.m_texture != other.m_texture)
888 return self.m_texture < other.m_texture;
890 if(self.m_texture1 != other.m_texture1)
892 return self.m_texture1 < other.m_texture1;
894 if(self.m_texture2 != other.m_texture2)
896 return self.m_texture2 < other.m_texture2;
898 if(self.m_texture3 != other.m_texture3)
900 return self.m_texture3 < other.m_texture3;
902 if(self.m_texture4 != other.m_texture4)
904 return self.m_texture4 < other.m_texture4;
906 if(self.m_texture5 != other.m_texture5)
908 return self.m_texture5 < other.m_texture5;
910 if(self.m_texture6 != other.m_texture6)
912 return self.m_texture6 < other.m_texture6;
914 if(self.m_texture7 != other.m_texture7)
916 return self.m_texture7 < other.m_texture7;
918 //! Sort by state bit-vector.
919 if(self.m_state != other.m_state)
921 return self.m_state < other.m_state;
923 //! Comparing address makes sure states are never equal.
924 return &self < &other;
927 void OpenGLState_constructDefault(OpenGLState& state)
929 state.m_state = RENDER_DEFAULT;
932 state.m_texture1 = 0;
933 state.m_texture2 = 0;
934 state.m_texture3 = 0;
935 state.m_texture4 = 0;
936 state.m_texture5 = 0;
937 state.m_texture6 = 0;
938 state.m_texture7 = 0;
940 state.m_colour[0] = 1;
941 state.m_colour[1] = 1;
942 state.m_colour[2] = 1;
943 state.m_colour[3] = 1;
945 state.m_depthfunc = GL_LESS;
947 state.m_blend_src = GL_SRC_ALPHA;
948 state.m_blend_dst = GL_ONE_MINUS_SRC_ALPHA;
950 state.m_alphafunc = GL_ALWAYS;
951 state.m_alpharef = 0;
953 state.m_linewidth = 1;
954 state.m_pointsize = 1;
956 state.m_linestipple_factor = 1;
957 state.m_linestipple_pattern = 0xaaaa;
963 /// \brief A container of Renderable references.
964 /// May contain the same Renderable multiple times, with different transforms.
965 class OpenGLStateBucket
968 struct RenderTransform
970 const Matrix4* m_transform;
971 const OpenGLRenderable *m_renderable;
972 const RendererLight* m_light;
974 RenderTransform(const OpenGLRenderable& renderable, const Matrix4& transform, const RendererLight* light)
975 : m_transform(&transform), m_renderable(&renderable), m_light(light)
980 typedef std::vector<RenderTransform> Renderables;
985 Renderables m_renderables;
991 void addRenderable(const OpenGLRenderable& renderable, const Matrix4& modelview, const RendererLight* light = 0)
993 m_renderables.push_back(RenderTransform(renderable, modelview, light));
1001 void render(OpenGLState& current, unsigned int globalstate, const Vector3& viewer);
1004 #define LIGHT_SHADER_DEBUG 0
1006 #if LIGHT_SHADER_DEBUG
1007 typedef std::vector<Shader*> LightDebugShaders;
1008 LightDebugShaders g_lightDebugShaders;
1011 class OpenGLStateLess
1014 bool operator()(const OpenGLState& self, const OpenGLState& other) const
1016 return OpenGLState_less(self, other);
1020 typedef ConstReference<OpenGLState> OpenGLStateReference;
1021 typedef std::map<OpenGLStateReference, OpenGLStateBucket*, OpenGLStateLess> OpenGLStates;
1022 OpenGLStates g_state_sorted;
1024 class OpenGLStateBucketAdd
1026 OpenGLStateBucket& m_bucket;
1027 const OpenGLRenderable& m_renderable;
1028 const Matrix4& m_modelview;
1030 typedef const RendererLight& first_argument_type;
1032 OpenGLStateBucketAdd(OpenGLStateBucket& bucket, const OpenGLRenderable& renderable, const Matrix4& modelview) :
1033 m_bucket(bucket), m_renderable(renderable), m_modelview(modelview)
1036 void operator()(const RendererLight& light)
1038 m_bucket.addRenderable(m_renderable, m_modelview, &light);
1044 std::size_t m_count;
1046 typedef RendererLight& first_argument_type;
1048 CountLights() : m_count(0)
1051 void operator()(const RendererLight& light)
1055 std::size_t count() const
1061 class OpenGLShader : public Shader
1063 typedef std::list<OpenGLStateBucket*> Passes;
1067 ModuleObservers m_observers;
1069 OpenGLShader() : m_shader(0), m_used(0)
1075 void construct(const char* name);
1084 for(Passes::iterator i = m_passes.begin(); i != m_passes.end(); ++i)
1090 void addRenderable(const OpenGLRenderable& renderable, const Matrix4& modelview, const LightList* lights)
1092 for(Passes::iterator i = m_passes.begin(); i != m_passes.end(); ++i)
1094 #if LIGHT_SHADER_DEBUG
1095 if(((*i)->state().m_state & RENDER_BUMP) != 0)
1099 CountLights counter;
1100 lights->forEachLight(makeCallback1(counter));
1101 globalOutputStream() << "count = " << counter.count() << "\n";
1102 for(std::size_t i = 0; i < counter.count(); ++i)
1104 g_lightDebugShaders[counter.count()]->addRenderable(renderable, modelview);
1110 if(((*i)->state().m_state & RENDER_BUMP) != 0)
1114 OpenGLStateBucketAdd add(*(*i), renderable, modelview);
1115 lights->forEachLight(makeCallback1(add));
1121 (*i)->addRenderable(renderable, modelview);
1125 void incrementUsed()
1127 if(++m_used == 1 && m_shader != 0)
1129 m_shader->SetInUse(true);
1132 void decrementUsed()
1134 if(--m_used == 0 && m_shader != 0)
1136 m_shader->SetInUse(false);
1139 bool realised() const
1141 return m_shader != 0;
1143 void attach(ModuleObserver& observer)
1149 m_observers.attach(observer);
1151 void detach(ModuleObserver& observer)
1155 observer.unrealise();
1157 m_observers.detach(observer);
1159 void realise(const CopiedString& name)
1161 construct(name.c_str());
1163 if(m_used != 0 && m_shader != 0)
1165 m_shader->SetInUse(true);
1168 for(Passes::iterator i = m_passes.begin(); i != m_passes.end(); ++i)
1170 g_state_sorted.insert(OpenGLStates::value_type(OpenGLStateReference((*i)->state()), *i));
1173 m_observers.realise();
1177 m_observers.unrealise();
1179 for(Passes::iterator i = m_passes.begin(); i != m_passes.end(); ++i)
1181 g_state_sorted.erase(OpenGLStateReference((*i)->state()));
1186 qtexture_t& getTexture() const
1188 ASSERT_NOTNULL(m_shader);
1189 return *m_shader->getTexture();
1191 unsigned int getFlags() const
1193 ASSERT_NOTNULL(m_shader);
1194 return m_shader->getFlags();
1196 IShader& getShader() const
1198 ASSERT_NOTNULL(m_shader);
1201 OpenGLState& appendDefaultPass()
1203 m_passes.push_back(new OpenGLStateBucket);
1204 OpenGLState& state = m_passes.back()->state();
1205 OpenGLState_constructDefault(state);
1211 inline bool lightEnabled(const RendererLight& light, const LightCullable& cullable)
1213 return cullable.testLight(light);
1216 typedef std::set<RendererLight*> RendererLights;
1218 #define DEBUG_LIGHT_SYNC 0
1220 class LinearLightList : public LightList
1222 LightCullable& m_cullable;
1223 RendererLights& m_allLights;
1224 Callback m_evaluateChanged;
1226 typedef std::list<RendererLight*> Lights;
1227 mutable Lights m_lights;
1228 mutable bool m_lightsChanged;
1230 LinearLightList(LightCullable& cullable, RendererLights& lights, const Callback& evaluateChanged) :
1231 m_cullable(cullable), m_allLights(lights), m_evaluateChanged(evaluateChanged)
1233 m_lightsChanged = true;
1235 void evaluateLights() const
1237 m_evaluateChanged();
1240 m_lightsChanged = false;
1243 m_cullable.clearLights();
1244 for(RendererLights::const_iterator i = m_allLights.begin(); i != m_allLights.end(); ++i)
1246 if(lightEnabled(*(*i), m_cullable))
1248 m_lights.push_back(*i);
1249 m_cullable.insertLight(*(*i));
1253 #if(DEBUG_LIGHT_SYNC)
1257 for(RendererLights::const_iterator i = m_allLights.begin(); i != m_allLights.end(); ++i)
1259 if(lightEnabled(*(*i), m_cullable))
1261 lights.push_back(*i);
1265 !std::lexicographical_compare(lights.begin(), lights.end(), m_lights.begin(), m_lights.end())
1266 && !std::lexicographical_compare(m_lights.begin(), m_lights.end(), lights.begin(), lights.end()),
1267 "lights out of sync"
1272 void forEachLight(const RendererLightCallback& callback) const
1276 for(Lights::const_iterator i = m_lights.begin(); i != m_lights.end(); ++i)
1281 void lightsChanged() const
1283 m_lightsChanged = true;
1287 #define DEBUG_SHADERS 0
1289 class OpenGLShaderCache : public ShaderCache, public TexturesCacheObserver, public ModuleObserver
1291 class CreateOpenGLShader
1293 OpenGLShaderCache* m_cache;
1295 explicit CreateOpenGLShader(OpenGLShaderCache* cache = 0)
1299 OpenGLShader* construct(const CopiedString& name)
1301 OpenGLShader* shader = new OpenGLShader;
1302 if(m_cache->realised())
1304 shader->realise(name);
1308 void destroy(OpenGLShader* shader)
1310 if(m_cache->realised())
1312 shader->unrealise();
1318 typedef HashedCache<CopiedString, OpenGLShader, HashString, std::equal_to<CopiedString>, CreateOpenGLShader> Shaders;
1320 std::size_t m_unrealised;
1322 bool m_lightingEnabled;
1323 bool m_lightingSupported;
1324 bool m_useShaderLanguage;
1328 : m_shaders(CreateOpenGLShader(this)),
1329 m_unrealised(3), // wait until shaders, gl-context and textures are realised before creating any render-states
1330 m_lightingEnabled(true),
1331 m_lightingSupported(false),
1332 m_useShaderLanguage(false),
1333 m_lightsChanged(true),
1334 m_traverseRenderablesMutex(false)
1337 ~OpenGLShaderCache()
1339 for(Shaders::iterator i = m_shaders.begin(); i != m_shaders.end(); ++i)
1341 globalOutputStream() << "leaked shader: " << makeQuoted((*i).key.c_str()) << "\n";
1344 Shader* capture(const char* name)
1346 ASSERT_MESSAGE(name[0] == '$'
1350 || strchr(name, '\\') == 0, "shader name contains invalid characters: \"" << name << "\"");
1352 globalOutputStream() << "shaders capture: " << makeQuoted(name) << '\n';
1354 return m_shaders.capture(name).get();
1356 void release(const char *name)
1359 globalOutputStream() << "shaders release: " << makeQuoted(name) << '\n';
1361 m_shaders.release(name);
1363 void render(RenderStateFlags globalstate, const Matrix4& modelview, const Matrix4& projection, const Vector3& viewer)
1365 glMatrixMode(GL_PROJECTION);
1366 glLoadMatrixf(reinterpret_cast<const float*>(&projection));
1368 //qglGetFloatv(GL_PROJECTION_MATRIX, reinterpret_cast<float*>(&projection));
1371 glMatrixMode(GL_MODELVIEW);
1372 glLoadMatrixf(reinterpret_cast<const float*>(&modelview));
1374 //qglGetFloatv(GL_MODELVIEW_MATRIX, reinterpret_cast<float*>(&modelview));
1377 ASSERT_MESSAGE(realised(), "render states are not realised");
1379 // global settings that are not set in renderstates
1381 glCullFace(GL_BACK);
1382 glPolygonOffset(-1, 1);
1384 const GLubyte pattern[132] = {
1385 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1386 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1387 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1388 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1389 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1390 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1391 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1392 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1393 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1394 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1395 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1396 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1397 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1398 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1399 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1400 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55
1402 glPolygonStipple(pattern);
1404 glEnableClientState(GL_VERTEX_ARRAY);
1405 g_vertexArray_enabled = true;
1406 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
1408 if(GlobalOpenGL().GL_1_3())
1410 glActiveTexture(GL_TEXTURE0);
1411 glClientActiveTexture(GL_TEXTURE0);
1414 if(GlobalOpenGL().ARB_shader_objects())
1416 glUseProgramObjectARB(0);
1417 glDisableVertexAttribArrayARB(c_attr_TexCoord0);
1418 glDisableVertexAttribArrayARB(c_attr_Tangent);
1419 glDisableVertexAttribArrayARB(c_attr_Binormal);
1422 if(globalstate & RENDER_TEXTURE)
1424 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
1425 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
1428 OpenGLState current;
1429 OpenGLState_constructDefault(current);
1430 current.m_sort = OpenGLState::eSortFirst;
1432 // default renderstate settings
1433 glLineStipple(current.m_linestipple_factor, current.m_linestipple_pattern);
1434 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
1435 glDisable(GL_LIGHTING);
1436 glDisable(GL_TEXTURE_2D);
1437 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1438 g_texcoordArray_enabled = false;
1439 glDisableClientState(GL_COLOR_ARRAY);
1440 g_colorArray_enabled = false;
1441 glDisableClientState(GL_NORMAL_ARRAY);
1442 g_normalArray_enabled = false;
1443 glDisable(GL_BLEND);
1444 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1445 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1446 glDisable(GL_CULL_FACE);
1447 glShadeModel(GL_FLAT);
1448 glDisable(GL_DEPTH_TEST);
1449 glDepthMask(GL_FALSE);
1450 glDisable(GL_ALPHA_TEST);
1451 glDisable(GL_LINE_STIPPLE);
1452 glDisable(GL_POLYGON_STIPPLE);
1453 glDisable(GL_POLYGON_OFFSET_LINE);
1455 glBindTexture(GL_TEXTURE_2D, 0);
1457 glDepthFunc(GL_LESS);
1458 glAlphaFunc(GL_ALWAYS, 0);
1462 GlobalOpenGL_debugAssertNoErrors();
1464 debug_string("begin rendering");
1465 for(OpenGLStates::iterator i = g_state_sorted.begin(); i != g_state_sorted.end(); ++i)
1467 (*i).second->render(current, globalstate, viewer);
1469 debug_string("end rendering");
1473 if(--m_unrealised == 0)
1475 if(lightingSupported() && lightingEnabled())
1477 if(useShaderLanguage())
1479 g_bumpGLSL.create();
1480 g_depthFillGLSL.create();
1485 g_depthFillARB.create();
1489 for(Shaders::iterator i = m_shaders.begin(); i != m_shaders.end(); ++i)
1491 if(!(*i).value.empty())
1493 (*i).value->realise(i->key);
1500 if(++m_unrealised == 1)
1502 for(Shaders::iterator i = m_shaders.begin(); i != m_shaders.end(); ++i)
1504 if(!(*i).value.empty())
1506 (*i).value->unrealise();
1509 if(GlobalOpenGL().contextValid && lightingSupported() && lightingEnabled())
1511 if(useShaderLanguage())
1513 g_bumpGLSL.destroy();
1514 g_depthFillGLSL.destroy();
1518 g_bumpARB.destroy();
1519 g_depthFillARB.destroy();
1526 return m_unrealised == 0;
1530 bool lightingEnabled() const
1532 return m_lightingEnabled;
1534 bool lightingSupported() const
1536 return m_lightingSupported;
1538 bool useShaderLanguage() const
1540 return m_useShaderLanguage;
1542 void setLighting(bool supported, bool enabled)
1544 bool refresh = (m_lightingSupported && m_lightingEnabled) != (supported && enabled);
1549 GlobalShaderSystem().setLightingEnabled(supported && enabled);
1552 m_lightingSupported = supported;
1553 m_lightingEnabled = enabled;
1560 void extensionsInitialised()
1562 setLighting(GlobalOpenGL().GL_1_3()
1563 && GlobalOpenGL().ARB_vertex_program()
1564 && GlobalOpenGL().ARB_fragment_program()
1565 && GlobalOpenGL().ARB_shader_objects()
1566 && GlobalOpenGL().ARB_vertex_shader()
1567 && GlobalOpenGL().ARB_fragment_shader()
1568 && GlobalOpenGL().ARB_shading_language_100(),
1572 if(!lightingSupported())
1574 globalOutputStream() << "Lighting mode requires OpenGL features not supported by your graphics drivers:\n";
1575 if(!GlobalOpenGL().GL_1_3())
1577 globalOutputStream() << " GL version 1.3 or better\n";
1579 if(!GlobalOpenGL().ARB_vertex_program())
1581 globalOutputStream() << " GL_ARB_vertex_program\n";
1583 if(!GlobalOpenGL().ARB_fragment_program())
1585 globalOutputStream() << " GL_ARB_fragment_program\n";
1587 if(!GlobalOpenGL().ARB_shader_objects())
1589 globalOutputStream() << " GL_ARB_shader_objects\n";
1591 if(!GlobalOpenGL().ARB_vertex_shader())
1593 globalOutputStream() << " GL_ARB_vertex_shader\n";
1595 if(!GlobalOpenGL().ARB_fragment_shader())
1597 globalOutputStream() << " GL_ARB_fragment_shader\n";
1599 if(!GlobalOpenGL().ARB_shading_language_100())
1601 globalOutputStream() << " GL_ARB_shading_language_100\n";
1605 void setLightingEnabled(bool enabled)
1607 setLighting(m_lightingSupported, enabled);
1612 RendererLights m_lights;
1613 bool m_lightsChanged;
1614 typedef std::map<LightCullable*, LinearLightList> LightLists;
1615 LightLists m_lightLists;
1617 const LightList& attach(LightCullable& cullable)
1619 return (*m_lightLists.insert(LightLists::value_type(&cullable, LinearLightList(cullable, m_lights, EvaluateChangedCaller(*this)))).first).second;
1621 void detach(LightCullable& cullable)
1623 m_lightLists.erase(&cullable);
1625 void changed(LightCullable& cullable)
1627 LightLists::iterator i = m_lightLists.find(&cullable);
1628 ASSERT_MESSAGE(i != m_lightLists.end(), "cullable not attached");
1629 (*i).second.lightsChanged();
1631 void attach(RendererLight& light)
1633 ASSERT_MESSAGE(m_lights.find(&light) == m_lights.end(), "light could not be attached");
1634 m_lights.insert(&light);
1637 void detach(RendererLight& light)
1639 ASSERT_MESSAGE(m_lights.find(&light) != m_lights.end(), "light could not be detached");
1640 m_lights.erase(&light);
1643 void changed(RendererLight& light)
1645 m_lightsChanged = true;
1647 void evaluateChanged()
1651 m_lightsChanged = false;
1652 for(LightLists::iterator i = m_lightLists.begin(); i != m_lightLists.end(); ++i)
1654 (*i).second.lightsChanged();
1658 typedef MemberCaller<OpenGLShaderCache, &OpenGLShaderCache::evaluateChanged> EvaluateChangedCaller;
1660 typedef std::set<const Renderable*> Renderables;
1661 Renderables m_renderables;
1662 mutable bool m_traverseRenderablesMutex;
1665 void attachRenderable(const Renderable& renderable)
1667 ASSERT_MESSAGE(!m_traverseRenderablesMutex, "attaching renderable during traversal");
1668 ASSERT_MESSAGE(m_renderables.find(&renderable) == m_renderables.end(), "renderable could not be attached");
1669 m_renderables.insert(&renderable);
1671 void detachRenderable(const Renderable& renderable)
1673 ASSERT_MESSAGE(!m_traverseRenderablesMutex, "detaching renderable during traversal");
1674 ASSERT_MESSAGE(m_renderables.find(&renderable) != m_renderables.end(), "renderable could not be detached");
1675 m_renderables.erase(&renderable);
1677 void forEachRenderable(const RenderableCallback& callback) const
1679 ASSERT_MESSAGE(!m_traverseRenderablesMutex, "for-each during traversal");
1680 m_traverseRenderablesMutex = true;
1681 for(Renderables::const_iterator i = m_renderables.begin(); i != m_renderables.end(); ++i)
1685 m_traverseRenderablesMutex = false;
1689 static OpenGLShaderCache* g_ShaderCache;
1691 void ShaderCache_extensionsInitialised()
1693 g_ShaderCache->extensionsInitialised();
1696 void ShaderCache_setBumpEnabled(bool enabled)
1698 g_ShaderCache->setLightingEnabled(enabled);
1702 Vector3 g_DebugShaderColours[256];
1703 Shader* g_defaultPointLight = 0;
1705 void ShaderCache_Construct()
1707 g_ShaderCache = new OpenGLShaderCache;
1708 GlobalTexturesCache().attach(*g_ShaderCache);
1709 GlobalShaderSystem().attach(*g_ShaderCache);
1711 if(g_pGameDescription->mGameType == "doom3")
1713 g_defaultPointLight = g_ShaderCache->capture("lights/defaultPointLight");
1714 //Shader* overbright =
1715 g_ShaderCache->capture("$OVERBRIGHT");
1717 #if LIGHT_SHADER_DEBUG
1718 for(std::size_t i = 0; i < 256; ++i)
1720 g_DebugShaderColours[i] = Vector3(i / 256.0, i / 256.0, i / 256.0);
1723 g_DebugShaderColours[0] = Vector3(1, 0, 0);
1724 g_DebugShaderColours[1] = Vector3(1, 0.5, 0);
1725 g_DebugShaderColours[2] = Vector3(1, 1, 0);
1726 g_DebugShaderColours[3] = Vector3(0.5, 1, 0);
1727 g_DebugShaderColours[4] = Vector3(0, 1, 0);
1728 g_DebugShaderColours[5] = Vector3(0, 1, 0.5);
1729 g_DebugShaderColours[6] = Vector3(0, 1, 1);
1730 g_DebugShaderColours[7] = Vector3(0, 0.5, 1);
1731 g_DebugShaderColours[8] = Vector3(0, 0, 1);
1732 g_DebugShaderColours[9] = Vector3(0.5, 0, 1);
1733 g_DebugShaderColours[10] = Vector3(1, 0, 1);
1734 g_DebugShaderColours[11] = Vector3(1, 0, 0.5);
1736 g_lightDebugShaders.reserve(256);
1737 StringOutputStream buffer(256);
1738 for(std::size_t i = 0; i < 256; ++i)
1740 buffer << "(" << g_DebugShaderColours[i].x() << " " << g_DebugShaderColours[i].y() << " " << g_DebugShaderColours[i].z() << ")";
1741 g_lightDebugShaders.push_back(g_ShaderCache->capture(buffer.c_str()));
1748 void ShaderCache_Destroy()
1750 if(g_pGameDescription->mGameType == "doom3")
1752 g_ShaderCache->release("lights/defaultPointLight");
1753 g_ShaderCache->release("$OVERBRIGHT");
1754 g_defaultPointLight = 0;
1756 #if LIGHT_SHADER_DEBUG
1757 g_lightDebugShaders.clear();
1758 StringOutputStream buffer(256);
1759 for(std::size_t i = 0; i < 256; ++i)
1761 buffer << "(" << g_DebugShaderColours[i].x() << " " << g_DebugShaderColours[i].y() << " " << g_DebugShaderColours[i].z() << ")";
1762 g_ShaderCache->release(buffer.c_str());
1767 GlobalShaderSystem().detach(*g_ShaderCache);
1768 GlobalTexturesCache().detach(*g_ShaderCache);
1769 delete g_ShaderCache;
1772 ShaderCache* GetShaderCache()
1774 return g_ShaderCache;
1777 inline void setTextureState(GLint& current, const GLint& texture, GLenum textureUnit)
1779 if(texture != current)
1781 glActiveTexture(textureUnit);
1782 glClientActiveTexture(textureUnit);
1783 glBindTexture(GL_TEXTURE_2D, texture);
1784 GlobalOpenGL_debugAssertNoErrors();
1789 inline void setTextureState(GLint& current, const GLint& texture)
1791 if(texture != current)
1793 glBindTexture(GL_TEXTURE_2D, texture);
1794 GlobalOpenGL_debugAssertNoErrors();
1799 void OpenGLState_apply(const OpenGLState& self, OpenGLState& current, unsigned int globalstate)
1801 debug_int("sort", int(self.m_sort));
1802 debug_int("texture", self.m_texture);
1803 debug_int("state", self.m_state);
1804 debug_int("address", int(std::size_t(&self)));
1808 if(self.m_state & RENDER_OVERRIDE)
1810 globalstate |= RENDER_FILL | RENDER_DEPTHWRITE;
1813 const unsigned int state = self.m_state & globalstate;
1814 const unsigned int delta = state ^ current.m_state;
1816 GlobalOpenGL_debugAssertNoErrors();
1818 GLProgram* program = (state & RENDER_PROGRAM) != 0 ? self.m_program : 0;
1820 if(program != current.m_program)
1822 if(current.m_program != 0)
1824 current.m_program->disable();
1825 glColor4fv(vector4_to_array(current.m_colour));
1826 debug_colour("cleaning program");
1829 current.m_program = program;
1831 if(current.m_program != 0)
1833 current.m_program->enable();
1837 if(delta & state & RENDER_FILL)
1839 //qglPolygonMode (GL_BACK, GL_LINE);
1840 //qglPolygonMode (GL_FRONT, GL_FILL);
1841 glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
1842 GlobalOpenGL_debugAssertNoErrors();
1844 else if(delta & ~state & RENDER_FILL)
1846 glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
1847 GlobalOpenGL_debugAssertNoErrors();
1850 if(delta & state & RENDER_OFFSETLINE)
1852 glEnable(GL_POLYGON_OFFSET_LINE);
1854 else if(delta & ~state & RENDER_OFFSETLINE)
1856 glDisable(GL_POLYGON_OFFSET_LINE);
1859 if(delta & state & RENDER_LIGHTING)
1861 glEnable(GL_LIGHTING);
1862 glEnable(GL_COLOR_MATERIAL);
1863 //qglEnable(GL_RESCALE_NORMAL);
1864 glEnableClientState(GL_NORMAL_ARRAY);
1865 GlobalOpenGL_debugAssertNoErrors();
1866 g_normalArray_enabled = true;
1868 else if(delta & ~state & RENDER_LIGHTING)
1870 glDisable(GL_LIGHTING);
1871 glDisable(GL_COLOR_MATERIAL);
1872 //qglDisable(GL_RESCALE_NORMAL);
1873 glDisableClientState(GL_NORMAL_ARRAY);
1874 GlobalOpenGL_debugAssertNoErrors();
1875 g_normalArray_enabled = false;
1878 if(delta & state & RENDER_TEXTURE)
1880 GlobalOpenGL_debugAssertNoErrors();
1882 if(GlobalOpenGL().GL_1_3())
1884 glActiveTexture(GL_TEXTURE0);
1885 glClientActiveTexture(GL_TEXTURE0);
1888 glEnable(GL_TEXTURE_2D);
1890 glColor4f(1,1,1,self.m_colour[3]);
1891 debug_colour("setting texture");
1893 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1894 GlobalOpenGL_debugAssertNoErrors();
1895 g_texcoordArray_enabled = true;
1897 else if(delta & ~state & RENDER_TEXTURE)
1899 if(GlobalOpenGL().GL_1_3())
1901 glActiveTexture(GL_TEXTURE0);
1902 glClientActiveTexture(GL_TEXTURE0);
1905 glDisable(GL_TEXTURE_2D);
1906 glBindTexture(GL_TEXTURE_2D, 0);
1907 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1909 GlobalOpenGL_debugAssertNoErrors();
1910 g_texcoordArray_enabled = false;
1913 if(delta & state & RENDER_BLEND)
1915 // FIXME: some .TGA are buggy, have a completely empty alpha channel
1916 // if such brushes are rendered in this loop they would be totally transparent with GL_MODULATE
1917 // so I decided using GL_DECAL instead
1918 // if an empty-alpha-channel or nearly-empty texture is used. It will be blank-transparent.
1919 // this could get better if you can get glTexEnviv (GL_TEXTURE_ENV, to work .. patches are welcome
1922 if(GlobalOpenGL().GL_1_3())
1924 glActiveTexture(GL_TEXTURE0);
1926 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
1927 GlobalOpenGL_debugAssertNoErrors();
1929 else if(delta & ~state & RENDER_BLEND)
1931 glDisable(GL_BLEND);
1932 if(GlobalOpenGL().GL_1_3())
1934 glActiveTexture(GL_TEXTURE0);
1936 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1937 GlobalOpenGL_debugAssertNoErrors();
1940 if(delta & state & RENDER_CULLFACE)
1942 glEnable(GL_CULL_FACE);
1943 GlobalOpenGL_debugAssertNoErrors();
1945 else if(delta & ~state & RENDER_CULLFACE)
1947 glDisable(GL_CULL_FACE);
1948 GlobalOpenGL_debugAssertNoErrors();
1951 if(delta & state & RENDER_SMOOTH)
1953 glShadeModel(GL_SMOOTH);
1954 GlobalOpenGL_debugAssertNoErrors();
1956 else if(delta & ~state & RENDER_SMOOTH)
1958 glShadeModel(GL_FLAT);
1959 GlobalOpenGL_debugAssertNoErrors();
1962 if(delta & state & RENDER_SCALED)
1964 //qglEnable(GL_RESCALE_NORMAL);
1965 glEnable(GL_NORMALIZE);
1966 GlobalOpenGL_debugAssertNoErrors();
1968 else if(delta & ~state & RENDER_SCALED)
1970 //qglDisable(GL_RESCALE_NORMAL);
1971 glDisable(GL_NORMALIZE);
1972 GlobalOpenGL_debugAssertNoErrors();
1975 if(delta & state & RENDER_DEPTHTEST)
1977 glEnable(GL_DEPTH_TEST);
1978 GlobalOpenGL_debugAssertNoErrors();
1980 else if(delta & ~state & RENDER_DEPTHTEST)
1982 glDisable(GL_DEPTH_TEST);
1983 GlobalOpenGL_debugAssertNoErrors();
1986 if(delta & state & RENDER_DEPTHWRITE)
1988 glDepthMask(GL_TRUE);
1991 GLboolean depthEnabled;
1992 glGetBooleanv(GL_DEPTH_WRITEMASK, &depthEnabled);
1993 ASSERT_MESSAGE(depthEnabled, "failed to set depth buffer mask bit");
1995 debug_string("enabled depth-buffer writing");
1997 GlobalOpenGL_debugAssertNoErrors();
1999 else if(delta & ~state & RENDER_DEPTHWRITE)
2001 glDepthMask(GL_FALSE);
2004 GLboolean depthEnabled;
2005 glGetBooleanv(GL_DEPTH_WRITEMASK, &depthEnabled);
2006 ASSERT_MESSAGE(!depthEnabled, "failed to set depth buffer mask bit");
2008 debug_string("disabled depth-buffer writing");
2010 GlobalOpenGL_debugAssertNoErrors();
2013 if(delta & state & RENDER_COLOURWRITE)
2015 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2016 GlobalOpenGL_debugAssertNoErrors();
2018 else if(delta & ~state & RENDER_COLOURWRITE)
2020 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
2021 GlobalOpenGL_debugAssertNoErrors();
2024 if(delta & state & RENDER_ALPHATEST)
2026 glEnable(GL_ALPHA_TEST);
2027 GlobalOpenGL_debugAssertNoErrors();
2029 else if(delta & ~state & RENDER_ALPHATEST)
2031 glDisable(GL_ALPHA_TEST);
2032 GlobalOpenGL_debugAssertNoErrors();
2035 if(delta & state & RENDER_COLOUR)
2037 glEnableClientState(GL_COLOR_ARRAY);
2038 GlobalOpenGL_debugAssertNoErrors();
2039 debug_colour("enabling color_array");
2040 g_colorArray_enabled = true;
2042 else if(delta & ~state & RENDER_COLOUR)
2044 glDisableClientState(GL_COLOR_ARRAY);
2045 glColor4fv(vector4_to_array(self.m_colour));
2046 debug_colour("cleaning color_array");
2047 GlobalOpenGL_debugAssertNoErrors();
2048 g_colorArray_enabled = false;
2051 if(delta & state & RENDER_LINESTIPPLE)
2053 glEnable(GL_LINE_STIPPLE);
2054 GlobalOpenGL_debugAssertNoErrors();
2056 else if(delta & ~state & RENDER_LINESTIPPLE)
2058 glDisable(GL_LINE_STIPPLE);
2059 GlobalOpenGL_debugAssertNoErrors();
2062 if(delta & state & RENDER_POLYGONSTIPPLE)
2064 glEnable(GL_POLYGON_STIPPLE);
2065 GlobalOpenGL_debugAssertNoErrors();
2067 else if(delta & ~state & RENDER_POLYGONSTIPPLE)
2069 glDisable(GL_POLYGON_STIPPLE);
2070 GlobalOpenGL_debugAssertNoErrors();
2073 if(state & RENDER_DEPTHTEST && self.m_depthfunc != current.m_depthfunc)
2075 glDepthFunc(self.m_depthfunc);
2076 GlobalOpenGL_debugAssertNoErrors();
2077 current.m_depthfunc = self.m_depthfunc;
2080 if(state & RENDER_LINESTIPPLE
2081 && (self.m_linestipple_factor != current.m_linestipple_factor
2082 || self.m_linestipple_pattern != current.m_linestipple_pattern))
2084 glLineStipple(self.m_linestipple_factor, self.m_linestipple_pattern);
2085 GlobalOpenGL_debugAssertNoErrors();
2086 current.m_linestipple_factor = self.m_linestipple_factor;
2087 current.m_linestipple_pattern = self.m_linestipple_pattern;
2091 if(state & RENDER_ALPHATEST
2092 && ( self.m_alphafunc != current.m_alphafunc
2093 || self.m_alpharef != current.m_alpharef ) )
2095 glAlphaFunc(self.m_alphafunc, self.m_alpharef);
2096 GlobalOpenGL_debugAssertNoErrors();
2097 current.m_alphafunc = self.m_alphafunc;
2098 current.m_alpharef = self.m_alpharef;
2110 //if(state & RENDER_TEXTURE) != 0)
2112 texture0 = self.m_texture;
2113 texture1 = self.m_texture1;
2114 texture2 = self.m_texture2;
2115 texture3 = self.m_texture3;
2116 texture4 = self.m_texture4;
2117 texture5 = self.m_texture5;
2118 texture6 = self.m_texture6;
2119 texture7 = self.m_texture7;
2122 if(GlobalOpenGL().GL_1_3())
2124 setTextureState(current.m_texture, texture0, GL_TEXTURE0);
2125 setTextureState(current.m_texture1, texture1, GL_TEXTURE1);
2126 setTextureState(current.m_texture2, texture2, GL_TEXTURE2);
2127 setTextureState(current.m_texture3, texture3, GL_TEXTURE3);
2128 setTextureState(current.m_texture4, texture4, GL_TEXTURE4);
2129 setTextureState(current.m_texture5, texture5, GL_TEXTURE5);
2130 setTextureState(current.m_texture6, texture6, GL_TEXTURE6);
2131 setTextureState(current.m_texture7, texture7, GL_TEXTURE7);
2135 setTextureState(current.m_texture, texture0);
2140 if(state & RENDER_TEXTURE && self.m_colour[3] != current.m_colour[3])
2142 debug_colour("setting alpha");
2143 glColor4f(1,1,1,self.m_colour[3]);
2144 GlobalOpenGL_debugAssertNoErrors();
2147 if(!(state & RENDER_TEXTURE)
2148 && (self.m_colour[0] != current.m_colour[0]
2149 || self.m_colour[1] != current.m_colour[1]
2150 || self.m_colour[2] != current.m_colour[2]
2151 || self.m_colour[3] != current.m_colour[3]))
2153 glColor4fv(vector4_to_array(self.m_colour));
2154 debug_colour("setting non-texture");
2155 GlobalOpenGL_debugAssertNoErrors();
2157 current.m_colour = self.m_colour;
2159 if(state & RENDER_BLEND
2160 && (self.m_blend_src != current.m_blend_src || self.m_blend_dst != current.m_blend_dst))
2162 glBlendFunc(self.m_blend_src, self.m_blend_dst);
2163 GlobalOpenGL_debugAssertNoErrors();
2164 current.m_blend_src = self.m_blend_src;
2165 current.m_blend_dst = self.m_blend_dst;
2168 if(!(state & RENDER_FILL)
2169 && self.m_linewidth != current.m_linewidth)
2171 glLineWidth(self.m_linewidth);
2172 GlobalOpenGL_debugAssertNoErrors();
2173 current.m_linewidth = self.m_linewidth;
2176 if(!(state & RENDER_FILL)
2177 && self.m_pointsize != current.m_pointsize)
2179 glPointSize(self.m_pointsize);
2180 GlobalOpenGL_debugAssertNoErrors();
2181 current.m_pointsize = self.m_pointsize;
2184 current.m_state = state;
2186 GlobalOpenGL_debugAssertNoErrors();
2189 void Renderables_flush(OpenGLStateBucket::Renderables& renderables, OpenGLState& current, unsigned int globalstate, const Vector3& viewer)
2191 const Matrix4* transform = 0;
2193 for(OpenGLStateBucket::Renderables::const_iterator i = renderables.begin(); i != renderables.end(); ++i)
2195 //qglLoadMatrixf(i->m_transform);
2196 if(!transform || (transform != (*i).m_transform && !matrix4_affine_equal(*transform, *(*i).m_transform)))
2199 transform = (*i).m_transform;
2202 glMultMatrixf(reinterpret_cast<const float*>(transform));
2203 glFrontFace(((current.m_state & RENDER_CULLFACE) != 0 && matrix4_handedness(*transform) == MATRIX4_RIGHTHANDED) ? GL_CW : GL_CCW);
2208 if(current.m_program != 0 && (*i).m_light != 0)
2210 const IShader& lightShader = static_cast<OpenGLShader*>((*i).m_light->getShader())->getShader();
2211 if(lightShader.firstLayer() != 0)
2213 GLuint attenuation_xy = lightShader.firstLayer()->texture()->texture_number;
2214 GLuint attenuation_z = lightShader.lightFalloffImage() != 0
2215 ? lightShader.lightFalloffImage()->texture_number
2216 : static_cast<OpenGLShader*>(g_defaultPointLight)->getShader().lightFalloffImage()->texture_number;
2218 setTextureState(current.m_texture3, attenuation_xy, GL_TEXTURE3);
2219 glActiveTexture(GL_TEXTURE3);
2220 glBindTexture(GL_TEXTURE_2D, attenuation_xy);
2221 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
2222 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
2224 setTextureState(current.m_texture4, attenuation_z, GL_TEXTURE4);
2225 glActiveTexture(GL_TEXTURE4);
2226 glBindTexture(GL_TEXTURE_2D, attenuation_z);
2227 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
2228 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2231 AABB lightBounds((*i).m_light->aabb());
2233 Matrix4 world2light(g_matrix4_identity);
2235 if((*i).m_light->isProjected())
2237 world2light = (*i).m_light->projection();
2238 matrix4_multiply_by_matrix4(world2light, matrix4_transposed((*i).m_light->rotation()));
2239 matrix4_translate_by_vec3(world2light, vector3_negated(lightBounds.origin)); // world->lightBounds
2241 if(!(*i).m_light->isProjected())
2243 matrix4_translate_by_vec3(world2light, Vector3(0.5f, 0.5f, 0.5f));
2244 matrix4_scale_by_vec3(world2light, Vector3(0.5f, 0.5f, 0.5f));
2245 matrix4_scale_by_vec3(world2light, Vector3(1.0f / lightBounds.extents.x(), 1.0f / lightBounds.extents.y(), 1.0f / lightBounds.extents.z()));
2246 matrix4_multiply_by_matrix4(world2light, matrix4_transposed((*i).m_light->rotation()));
2247 matrix4_translate_by_vec3(world2light, vector3_negated(lightBounds.origin)); // world->lightBounds
2250 current.m_program->setParameters(viewer, *(*i).m_transform, lightBounds.origin + (*i).m_light->offset(), (*i).m_light->colour(), world2light);
2251 debug_string("set lightBounds parameters");
2255 (*i).m_renderable->render(current.m_state);
2258 renderables.clear();
2261 void OpenGLStateBucket::render(OpenGLState& current, unsigned int globalstate, const Vector3& viewer)
2263 if((globalstate & m_state.m_state & RENDER_SCREEN) != 0)
2265 OpenGLState_apply(m_state, current, globalstate);
2266 debug_colour("screen fill");
2268 glMatrixMode(GL_PROJECTION);
2270 glLoadMatrixf(reinterpret_cast<const float*>(&g_matrix4_identity));
2272 glMatrixMode(GL_MODELVIEW);
2274 glLoadMatrixf(reinterpret_cast<const float*>(&g_matrix4_identity));
2277 glVertex3f(-1, -1, 0);
2278 glVertex3f(1, -1, 0);
2279 glVertex3f(1, 1, 0);
2280 glVertex3f(-1, 1, 0);
2283 glMatrixMode(GL_PROJECTION);
2286 glMatrixMode(GL_MODELVIEW);
2289 else if(!m_renderables.empty())
2291 OpenGLState_apply(m_state, current, globalstate);
2292 Renderables_flush(m_renderables, current, globalstate, viewer);
2296 inline GLenum convertBlendFactor(BlendFactor factor)
2304 case BLEND_SRC_COLOUR:
2305 return GL_SRC_COLOR;
2306 case BLEND_ONE_MINUS_SRC_COLOUR:
2307 return GL_ONE_MINUS_SRC_COLOR;
2308 case BLEND_SRC_ALPHA:
2309 return GL_SRC_ALPHA;
2310 case BLEND_ONE_MINUS_SRC_ALPHA:
2311 return GL_ONE_MINUS_SRC_ALPHA;
2312 case BLEND_DST_COLOUR:
2313 return GL_DST_COLOR;
2314 case BLEND_ONE_MINUS_DST_COLOUR:
2315 return GL_ONE_MINUS_DST_COLOR;
2316 case BLEND_DST_ALPHA:
2317 return GL_DST_ALPHA;
2318 case BLEND_ONE_MINUS_DST_ALPHA:
2319 return GL_ONE_MINUS_DST_ALPHA;
2320 case BLEND_SRC_ALPHA_SATURATE:
2321 return GL_SRC_ALPHA_SATURATE;
2326 /// \todo Define special-case shaders in a data file.
2327 void OpenGLShader::construct(const char* name)
2329 OpenGLState& state = appendDefaultPass();
2333 sscanf(name, "(%g %g %g)", &state.m_colour[0], &state.m_colour[1], &state.m_colour[2]);
2334 state.m_colour[3] = 1.0f;
2335 state.m_state = RENDER_FILL|RENDER_LIGHTING|RENDER_DEPTHTEST|RENDER_CULLFACE|RENDER_COLOURWRITE|RENDER_DEPTHWRITE;
2336 state.m_sort = OpenGLState::eSortFullbright;
2340 sscanf(name, "[%g %g %g]", &state.m_colour[0], &state.m_colour[1], &state.m_colour[2]);
2341 state.m_colour[3] = 0.5f;
2342 state.m_state = RENDER_FILL|RENDER_LIGHTING|RENDER_DEPTHTEST|RENDER_CULLFACE|RENDER_COLOURWRITE|RENDER_DEPTHWRITE|RENDER_BLEND;
2343 state.m_sort = OpenGLState::eSortTranslucent;
2347 sscanf(name, "<%g %g %g>", &state.m_colour[0], &state.m_colour[1], &state.m_colour[2]);
2348 state.m_colour[3] = 1;
2349 state.m_state = RENDER_DEPTHTEST|RENDER_COLOURWRITE|RENDER_DEPTHWRITE;
2350 state.m_sort = OpenGLState::eSortFullbright;
2351 state.m_depthfunc = GL_LESS;
2352 state.m_linewidth = 1;
2353 state.m_pointsize = 1;
2357 if(string_equal(name+1, "POINT"))
2359 state.m_state = RENDER_COLOUR|RENDER_COLOURWRITE|RENDER_DEPTHWRITE;
2360 state.m_sort = OpenGLState::eSortControlFirst;
2361 state.m_pointsize = 4;
2363 else if(string_equal(name+1, "SELPOINT"))
2365 state.m_state = RENDER_COLOUR|RENDER_COLOURWRITE|RENDER_DEPTHWRITE;
2366 state.m_sort = OpenGLState::eSortControlFirst + 1;
2367 state.m_pointsize = 4;
2369 else if(string_equal(name+1, "BIGPOINT"))
2371 state.m_state = RENDER_COLOUR|RENDER_COLOURWRITE|RENDER_DEPTHWRITE;
2372 state.m_sort = OpenGLState::eSortControlFirst;
2373 state.m_pointsize = 6;
2375 else if(string_equal(name+1, "PIVOT"))
2377 state.m_state = RENDER_COLOUR|RENDER_COLOURWRITE|RENDER_DEPTHTEST|RENDER_DEPTHWRITE;
2378 state.m_sort = OpenGLState::eSortGUI1;
2379 state.m_linewidth = 2;
2380 state.m_depthfunc = GL_LEQUAL;
2382 OpenGLState& hiddenLine = appendDefaultPass();
2383 hiddenLine.m_state = RENDER_COLOUR|RENDER_COLOURWRITE|RENDER_DEPTHTEST|RENDER_LINESTIPPLE;
2384 hiddenLine.m_sort = OpenGLState::eSortGUI0;
2385 hiddenLine.m_linewidth = 2;
2386 hiddenLine.m_depthfunc = GL_GREATER;
2388 else if(string_equal(name+1, "LATTICE"))
2390 state.m_colour[0] = 1;
2391 state.m_colour[1] = 0.5;
2392 state.m_colour[2] = 0;
2393 state.m_colour[3] = 1;
2394 state.m_state = RENDER_COLOURWRITE|RENDER_DEPTHWRITE;
2395 state.m_sort = OpenGLState::eSortControlFirst;
2397 else if(string_equal(name+1, "WIREFRAME"))
2399 state.m_state = RENDER_DEPTHTEST|RENDER_COLOURWRITE|RENDER_DEPTHWRITE;
2400 state.m_sort = OpenGLState::eSortFullbright;
2402 else if(string_equal(name+1, "CAM_HIGHLIGHT"))
2404 state.m_colour[0] = 1;
2405 state.m_colour[1] = 0;
2406 state.m_colour[2] = 0;
2407 state.m_colour[3] = 0.3f;
2408 state.m_state = RENDER_FILL|RENDER_DEPTHTEST|RENDER_CULLFACE|RENDER_BLEND|RENDER_COLOURWRITE|RENDER_DEPTHWRITE;
2409 state.m_sort = OpenGLState::eSortHighlight;
2410 state.m_depthfunc = GL_LEQUAL;
2412 else if(string_equal(name+1, "CAM_OVERLAY"))
2415 state.m_state = RENDER_CULLFACE|RENDER_COLOURWRITE|RENDER_DEPTHWRITE;
2416 state.m_sort = OpenGLState::eSortOverlayFirst;
2418 state.m_state = RENDER_CULLFACE|RENDER_DEPTHTEST|RENDER_COLOURWRITE|RENDER_DEPTHWRITE|RENDER_OFFSETLINE;
2419 state.m_sort = OpenGLState::eSortOverlayFirst + 1;
2420 state.m_depthfunc = GL_LEQUAL;
2422 OpenGLState& hiddenLine = appendDefaultPass();
2423 hiddenLine.m_colour[0] = 0.75;
2424 hiddenLine.m_colour[1] = 0.75;
2425 hiddenLine.m_colour[2] = 0.75;
2426 hiddenLine.m_colour[3] = 1;
2427 hiddenLine.m_state = RENDER_CULLFACE|RENDER_DEPTHTEST|RENDER_COLOURWRITE|RENDER_OFFSETLINE|RENDER_LINESTIPPLE;
2428 hiddenLine.m_sort = OpenGLState::eSortOverlayFirst;
2429 hiddenLine.m_depthfunc = GL_GREATER;
2430 hiddenLine.m_linestipple_factor = 2;
2433 else if(string_equal(name+1, "XY_OVERLAY"))
2435 state.m_colour[0] = g_xywindow_globals.color_selbrushes[0];
2436 state.m_colour[1] = g_xywindow_globals.color_selbrushes[1];
2437 state.m_colour[2] = g_xywindow_globals.color_selbrushes[2];
2438 state.m_colour[3] = 1;
2439 state.m_state = RENDER_COLOURWRITE | RENDER_LINESTIPPLE;
2440 state.m_sort = OpenGLState::eSortOverlayFirst;
2441 state.m_linewidth = 2;
2442 state.m_linestipple_factor = 3;
2444 else if(string_equal(name+1, "DEBUG_CLIPPED"))
2446 state.m_state = RENDER_COLOUR | RENDER_COLOURWRITE | RENDER_DEPTHWRITE;
2447 state.m_sort = OpenGLState::eSortLast;
2449 else if(string_equal(name+1, "POINTFILE"))
2451 state.m_colour[0] = 1;
2452 state.m_colour[1] = 0;
2453 state.m_colour[2] = 0;
2454 state.m_colour[3] = 1;
2455 state.m_state = RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_DEPTHWRITE;
2456 state.m_sort = OpenGLState::eSortFullbright;
2457 state.m_linewidth = 4;
2459 else if(string_equal(name+1, "LIGHT_SPHERE"))
2461 state.m_colour[0] = .15f * .95f;
2462 state.m_colour[1] = .15f * .95f;
2463 state.m_colour[2] = .15f * .95f;
2464 state.m_colour[3] = 1;
2465 state.m_state = RENDER_CULLFACE | RENDER_DEPTHTEST | RENDER_BLEND | RENDER_FILL | RENDER_COLOURWRITE | RENDER_DEPTHWRITE;
2466 state.m_blend_src = GL_ONE;
2467 state.m_blend_dst = GL_ONE;
2468 state.m_sort = OpenGLState::eSortTranslucent;
2470 else if(string_equal(name+1, "Q3MAP2_LIGHT_SPHERE"))
2472 state.m_colour[0] = .05f;
2473 state.m_colour[1] = .05f;
2474 state.m_colour[2] = .05f;
2475 state.m_colour[3] = 1;
2476 state.m_state = RENDER_CULLFACE | RENDER_DEPTHTEST | RENDER_BLEND | RENDER_FILL;
2477 state.m_blend_src = GL_ONE;
2478 state.m_blend_dst = GL_ONE;
2479 state.m_sort = OpenGLState::eSortTranslucent;
2481 else if(string_equal(name+1, "WIRE_OVERLAY"))
2484 state.m_state = RENDER_COLOUR | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE;
2485 state.m_sort = OpenGLState::eSortOverlayFirst;
2487 state.m_state = RENDER_COLOUR | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE;
2488 state.m_sort = OpenGLState::eSortGUI1;
2489 state.m_depthfunc = GL_LEQUAL;
2491 OpenGLState& hiddenLine = appendDefaultPass();
2492 hiddenLine.m_state = RENDER_COLOUR | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE | RENDER_LINESTIPPLE;
2493 hiddenLine.m_sort = OpenGLState::eSortGUI0;
2494 hiddenLine.m_depthfunc = GL_GREATER;
2497 else if(string_equal(name+1, "FLATSHADE_OVERLAY"))
2499 state.m_state = RENDER_CULLFACE | RENDER_LIGHTING | RENDER_SMOOTH | RENDER_SCALED | RENDER_COLOUR | RENDER_FILL | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE;
2500 state.m_sort = OpenGLState::eSortGUI1;
2501 state.m_depthfunc = GL_LEQUAL;
2503 OpenGLState& hiddenLine = appendDefaultPass();
2504 hiddenLine.m_state = RENDER_CULLFACE | RENDER_LIGHTING | RENDER_SMOOTH | RENDER_SCALED | RENDER_COLOUR | RENDER_FILL | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE | RENDER_POLYGONSTIPPLE;
2505 hiddenLine.m_sort = OpenGLState::eSortGUI0;
2506 hiddenLine.m_depthfunc = GL_GREATER;
2508 else if(string_equal(name+1, "CLIPPER_OVERLAY"))
2510 state.m_colour[0] = g_xywindow_globals.color_clipper[0];
2511 state.m_colour[1] = g_xywindow_globals.color_clipper[1];
2512 state.m_colour[2] = g_xywindow_globals.color_clipper[2];
2513 state.m_colour[3] = 1;
2514 state.m_state = RENDER_CULLFACE | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_FILL | RENDER_POLYGONSTIPPLE;
2515 state.m_sort = OpenGLState::eSortOverlayFirst;
2517 else if(string_equal(name+1, "OVERBRIGHT"))
2519 const float lightScale = 2;
2520 state.m_colour[0] = lightScale * 0.5f;
2521 state.m_colour[1] = lightScale * 0.5f;
2522 state.m_colour[2] = lightScale * 0.5f;
2523 state.m_colour[3] = 0.5;
2524 state.m_state = RENDER_FILL|RENDER_BLEND|RENDER_COLOURWRITE|RENDER_SCREEN;
2525 state.m_sort = OpenGLState::eSortOverbrighten;
2526 state.m_blend_src = GL_DST_COLOR;
2527 state.m_blend_dst = GL_SRC_COLOR;
2531 // default to something recognisable.. =)
2532 ERROR_MESSAGE("hardcoded renderstate not found");
2533 state.m_colour[0] = 1;
2534 state.m_colour[1] = 0;
2535 state.m_colour[2] = 1;
2536 state.m_colour[3] = 1;
2537 state.m_state = RENDER_COLOURWRITE | RENDER_DEPTHWRITE;
2538 state.m_sort = OpenGLState::eSortFirst;
2542 // construction from IShader
2543 m_shader = QERApp_Shader_ForName(name);
2545 if(g_ShaderCache->lightingSupported() && g_ShaderCache->lightingEnabled() && m_shader->getBump() != 0 && m_shader->getBump()->texture_number != 0) // is a bump shader
2547 state.m_state = RENDER_FILL | RENDER_CULLFACE | RENDER_TEXTURE | RENDER_DEPTHTEST | RENDER_DEPTHWRITE | RENDER_COLOURWRITE | RENDER_PROGRAM;
2548 state.m_colour[0] = 0;
2549 state.m_colour[1] = 0;
2550 state.m_colour[2] = 0;
2551 state.m_colour[3] = 1;
2552 state.m_sort = OpenGLState::eSortOpaque;
2554 if(g_ShaderCache->useShaderLanguage())
2556 state.m_program = &g_depthFillGLSL;
2560 state.m_program = &g_depthFillARB;
2563 OpenGLState& bumpPass = appendDefaultPass();
2564 bumpPass.m_texture = m_shader->getDiffuse()->texture_number;
2565 bumpPass.m_texture1 = m_shader->getBump()->texture_number;
2566 bumpPass.m_texture2 = m_shader->getSpecular()->texture_number;
2568 bumpPass.m_state = RENDER_BLEND|RENDER_FILL|RENDER_CULLFACE|RENDER_DEPTHTEST|RENDER_COLOURWRITE|RENDER_SMOOTH|RENDER_BUMP|RENDER_PROGRAM;
2570 if(g_ShaderCache->useShaderLanguage())
2572 bumpPass.m_state |= RENDER_LIGHTING;
2573 bumpPass.m_program = &g_bumpGLSL;
2577 bumpPass.m_program = &g_bumpARB;
2580 bumpPass.m_depthfunc = GL_LEQUAL;
2581 bumpPass.m_sort = OpenGLState::eSortMultiFirst;
2582 bumpPass.m_blend_src = GL_ONE;
2583 bumpPass.m_blend_dst = GL_ONE;
2587 state.m_texture = m_shader->getTexture()->texture_number;
2589 state.m_state = RENDER_FILL|RENDER_TEXTURE|RENDER_DEPTHTEST|RENDER_COLOURWRITE|RENDER_LIGHTING|RENDER_SMOOTH;
2590 if((m_shader->getFlags() & QER_CULL) != 0)
2592 if(m_shader->getCull() == IShader::eCullBack)
2594 state.m_state |= RENDER_CULLFACE;
2599 state.m_state |= RENDER_CULLFACE;
2601 if((m_shader->getFlags() & QER_ALPHATEST) != 0)
2603 state.m_state |= RENDER_ALPHATEST;
2604 IShader::EAlphaFunc alphafunc;
2605 m_shader->getAlphaFunc(&alphafunc, &state.m_alpharef);
2608 case IShader::eAlways:
2609 state.m_alphafunc = GL_ALWAYS;
2610 case IShader::eEqual:
2611 state.m_alphafunc = GL_EQUAL;
2612 case IShader::eLess:
2613 state.m_alphafunc = GL_LESS;
2614 case IShader::eGreater:
2615 state.m_alphafunc = GL_GREATER;
2616 case IShader::eLEqual:
2617 state.m_alphafunc = GL_LEQUAL;
2618 case IShader::eGEqual:
2619 state.m_alphafunc = GL_GEQUAL;
2622 reinterpret_cast<Vector3&>(state.m_colour) = m_shader->getTexture()->color;
2623 state.m_colour[3] = 1.0f;
2625 if((m_shader->getFlags() & QER_TRANS) != 0)
2627 state.m_state |= RENDER_BLEND;
2628 state.m_colour[3] = m_shader->getTrans();
2629 state.m_sort = OpenGLState::eSortTranslucent;
2630 BlendFunc blendFunc = m_shader->getBlendFunc();
2631 state.m_blend_src = convertBlendFactor(blendFunc.m_src);
2632 state.m_blend_dst = convertBlendFactor(blendFunc.m_dst);
2633 if(state.m_blend_src == GL_SRC_ALPHA || state.m_blend_dst == GL_SRC_ALPHA)
2635 state.m_state |= RENDER_DEPTHWRITE;
2640 state.m_state |= RENDER_DEPTHWRITE;
2641 state.m_sort = OpenGLState::eSortFullbright;
2648 #include "modulesystem/singletonmodule.h"
2649 #include "modulesystem/moduleregistry.h"
2651 class ShaderCacheDependencies : public GlobalShadersModuleRef, public GlobalTexturesModuleRef
2654 ShaderCacheDependencies() :
2655 GlobalShadersModuleRef(GlobalRadiant().getRequiredGameDescriptionKeyValue("shaders"))
2660 class ShaderCacheAPI
2662 ShaderCache* m_shaderCache;
2664 typedef ShaderCache Type;
2665 STRING_CONSTANT(Name, "*");
2669 ShaderCache_Construct();
2671 m_shaderCache = GetShaderCache();
2675 ShaderCache_Destroy();
2677 ShaderCache* getTable()
2679 return m_shaderCache;
2683 typedef SingletonModule<ShaderCacheAPI, ShaderCacheDependencies> ShaderCacheModule;
2684 typedef Static<ShaderCacheModule> StaticShaderCacheModule;
2685 StaticRegisterModule staticRegisterShaderCache(StaticShaderCacheModule::instance());