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 "iglrender.h"
32 #include "renderable.h"
33 #include "qerplugin.h"
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"
52 #include "preferences.h"
58 #define DEBUG_RENDER 0
60 inline void debug_string(const char* string)
63 globalOutputStream() << string << "\n";
67 inline void debug_int(const char* comment, int i)
70 globalOutputStream() << comment << " " << i << "\n";
74 inline void debug_colour(const char* comment)
78 glGetFloatv(GL_CURRENT_COLOR, reinterpret_cast<float*>(&v));
79 globalOutputStream() << comment << " colour: "
84 if(glIsEnabled(GL_COLOR_ARRAY))
86 globalOutputStream() << " ARRAY";
88 if(glIsEnabled(GL_COLOR_MATERIAL))
90 globalOutputStream() << " MATERIAL";
92 globalOutputStream() << "\n";
98 StringOutputStream g_renderer_stats;
99 std::size_t g_count_prims;
100 std::size_t g_count_states;
101 std::size_t g_count_transforms;
104 inline void count_prim()
109 inline void count_state()
114 inline void count_transform()
116 ++g_count_transforms;
119 void Renderer_ResetStats()
123 g_count_transforms = 0;
127 const char* Renderer_GetStats()
129 g_renderer_stats.clear();
130 g_renderer_stats << "prims: " << Unsigned(g_count_prims)
131 << " | states: " << Unsigned(g_count_states)
132 << " | transforms: " << Unsigned(g_count_transforms)
133 << " | msec: " << g_timer.elapsed_msec();
134 return g_renderer_stats.c_str();
138 void printShaderLog(GLhandleARB object)
140 GLint log_length = 0;
141 glGetObjectParameterivARB(object, GL_OBJECT_INFO_LOG_LENGTH_ARB, &log_length);
143 Array<char> log(log_length);
144 glGetInfoLogARB(object, log_length, &log_length, log.data());
146 globalErrorStream() << StringRange(log.begin(), log.begin() + log_length) << "\n";
149 void createShader(GLhandleARB program, const char* filename, GLenum type)
151 GLhandleARB shader = glCreateShaderObjectARB(type);
152 GlobalOpenGL_debugAssertNoErrors();
156 std::size_t size = file_size(filename);
157 FileInputStream file(filename);
158 ASSERT_MESSAGE(!file.failed(), "failed to open " << makeQuoted(filename));
159 Array<GLcharARB> buffer(size);
160 size = file.read(reinterpret_cast<StreamBase::byte_type*>(buffer.data()), size);
162 const GLcharARB* string = buffer.data();
163 GLint length = GLint(size);
164 glShaderSourceARB(shader, 1, &string, &length);
169 glCompileShaderARB(shader);
172 glGetObjectParameterivARB(shader, GL_OBJECT_COMPILE_STATUS_ARB, &compiled);
176 printShaderLog(shader);
179 ASSERT_MESSAGE(compiled, "shader compile failed: " << makeQuoted(filename));
183 glAttachObjectARB(program, shader);
185 glDeleteObjectARB(shader);
187 GlobalOpenGL_debugAssertNoErrors();
190 void GLSLProgram_link(GLhandleARB program)
192 glLinkProgramARB(program);
194 GLint linked = false;
195 glGetObjectParameterivARB(program, GL_OBJECT_LINK_STATUS_ARB, &linked);
199 printShaderLog(program);
202 ASSERT_MESSAGE(linked, "program link failed");
205 void GLSLProgram_validate(GLhandleARB program)
207 glValidateProgramARB(program);
209 GLint validated = false;
210 glGetObjectParameterivARB(program, GL_OBJECT_VALIDATE_STATUS_ARB, &validated);
214 printShaderLog(program);
217 ASSERT_MESSAGE(validated, "program validation failed");
220 bool g_bumpGLSLPass_enabled = false;
221 bool g_depthfillPass_enabled = false;
223 class GLSLBumpProgram : public GLProgram
226 GLhandleARB m_program;
227 qtexture_t* m_light_attenuation_xy;
228 qtexture_t* m_light_attenuation_z;
230 GLint u_light_origin;
233 GLint u_specular_exponent;
235 GLSLBumpProgram() : m_program(0), m_light_attenuation_xy(0), m_light_attenuation_z(0)
242 m_program = glCreateProgramObjectARB();
246 StringOutputStream filename(256);
247 filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_vp.glsl";
248 createShader(m_program, filename.c_str(), GL_VERTEX_SHADER_ARB);
250 filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_fp.glsl";
251 createShader(m_program, filename.c_str(), GL_FRAGMENT_SHADER_ARB);
254 GLSLProgram_link(m_program);
255 GLSLProgram_validate(m_program);
257 glUseProgramObjectARB(m_program);
259 glBindAttribLocationARB(m_program, c_attr_TexCoord0, "attr_TexCoord0");
260 glBindAttribLocationARB(m_program, c_attr_Tangent, "attr_Tangent");
261 glBindAttribLocationARB(m_program, c_attr_Binormal, "attr_Binormal");
263 glUniform1iARB(glGetUniformLocationARB(m_program, "u_diffusemap"), 0);
264 glUniform1iARB(glGetUniformLocationARB(m_program, "u_bumpmap"), 1);
265 glUniform1iARB(glGetUniformLocationARB(m_program, "u_specularmap"), 2);
266 glUniform1iARB(glGetUniformLocationARB(m_program, "u_attenuationmap_xy"), 3);
267 glUniform1iARB(glGetUniformLocationARB(m_program, "u_attenuationmap_z"), 4);
269 u_view_origin = glGetUniformLocationARB(m_program, "u_view_origin");
270 u_light_origin = glGetUniformLocationARB(m_program, "u_light_origin");
271 u_light_color = glGetUniformLocationARB(m_program, "u_light_color");
272 u_bump_scale = glGetUniformLocationARB(m_program, "u_bump_scale");
273 u_specular_exponent = glGetUniformLocationARB(m_program, "u_specular_exponent");
275 glUseProgramObjectARB(0);
277 GlobalOpenGL_debugAssertNoErrors();
282 glDeleteObjectARB(m_program);
288 glUseProgramObjectARB(m_program);
290 glEnableVertexAttribArrayARB(c_attr_TexCoord0);
291 glEnableVertexAttribArrayARB(c_attr_Tangent);
292 glEnableVertexAttribArrayARB(c_attr_Binormal);
294 GlobalOpenGL_debugAssertNoErrors();
296 debug_string("enable bump");
297 g_bumpGLSLPass_enabled = true;
302 glUseProgramObjectARB(0);
304 glDisableVertexAttribArrayARB(c_attr_TexCoord0);
305 glDisableVertexAttribArrayARB(c_attr_Tangent);
306 glDisableVertexAttribArrayARB(c_attr_Binormal);
308 GlobalOpenGL_debugAssertNoErrors();
310 debug_string("disable bump");
311 g_bumpGLSLPass_enabled = false;
314 void setParameters(const Vector3& viewer, const Matrix4& localToWorld, const Vector3& origin, const Vector3& colour, const Matrix4& world2light)
316 Matrix4 world2local(localToWorld);
317 matrix4_affine_invert(world2local);
319 Vector3 localLight(origin);
320 matrix4_transform_point(world2local, localLight);
322 Vector3 localViewer(viewer);
323 matrix4_transform_point(world2local, localViewer);
325 Matrix4 local2light(world2light);
326 matrix4_multiply_by_matrix4(local2light, localToWorld); // local->world->light
328 glUniform3fARB(u_view_origin, localViewer.x(), localViewer.y(), localViewer.z());
329 glUniform3fARB(u_light_origin, localLight.x(), localLight.y(), localLight.z());
330 glUniform3fARB(u_light_color, colour.x(), colour.y(), colour.z());
331 glUniform1fARB(u_bump_scale, 1.0);
332 glUniform1fARB(u_specular_exponent, 32.0);
334 glActiveTexture(GL_TEXTURE3);
335 glClientActiveTexture(GL_TEXTURE3);
337 glMatrixMode(GL_TEXTURE);
338 glLoadMatrixf(reinterpret_cast<const float*>(&local2light));
339 glMatrixMode(GL_MODELVIEW);
341 GlobalOpenGL_debugAssertNoErrors();
345 GLSLBumpProgram g_bumpGLSL;
348 class GLSLDepthFillProgram : public GLProgram
351 GLhandleARB m_program;
356 m_program = glCreateProgramObjectARB();
360 StringOutputStream filename(256);
361 filename << GlobalRadiant().getAppPath() << "gl/zfill_vp.glsl";
362 createShader(m_program, filename.c_str(), GL_VERTEX_SHADER_ARB);
364 filename << GlobalRadiant().getAppPath() << "gl/zfill_fp.glsl";
365 createShader(m_program, filename.c_str(), GL_FRAGMENT_SHADER_ARB);
368 GLSLProgram_link(m_program);
369 GLSLProgram_validate(m_program);
371 GlobalOpenGL_debugAssertNoErrors();
376 glDeleteObjectARB(m_program);
381 glUseProgramObjectARB(m_program);
382 GlobalOpenGL_debugAssertNoErrors();
383 debug_string("enable depthfill");
384 g_depthfillPass_enabled = true;
388 glUseProgramObjectARB(0);
389 GlobalOpenGL_debugAssertNoErrors();
390 debug_string("disable depthfill");
391 g_depthfillPass_enabled = false;
393 void setParameters(const Vector3& viewer, const Matrix4& localToWorld, const Vector3& origin, const Vector3& colour, const Matrix4& world2light)
398 GLSLDepthFillProgram g_depthFillGLSL;
403 void createProgram(const char* filename, GLenum type)
405 std::size_t size = file_size(filename);
406 FileInputStream file(filename);
407 ASSERT_MESSAGE(!file.failed(), "failed to open " << makeQuoted(filename));
408 Array<GLcharARB> buffer(size);
409 size = file.read(reinterpret_cast<StreamBase::byte_type*>(buffer.data()), size);
411 glProgramStringARB(type, GL_PROGRAM_FORMAT_ASCII_ARB, GLsizei(size), buffer.data());
413 if(GL_INVALID_OPERATION == glGetError())
416 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
417 const GLubyte* errString = glGetString(GL_PROGRAM_ERROR_STRING_ARB);
419 globalErrorStream() << reinterpret_cast<const char*>(filename) << ":" << errPos << "\n" << reinterpret_cast<const char*>(errString);
421 ERROR_MESSAGE("error in gl program");
425 class ARBBumpProgram : public GLProgram
428 GLuint m_vertex_program;
429 GLuint m_fragment_program;
433 glEnable(GL_VERTEX_PROGRAM_ARB);
434 glEnable(GL_FRAGMENT_PROGRAM_ARB);
437 glGenProgramsARB(1, &m_vertex_program);
438 glBindProgramARB(GL_VERTEX_PROGRAM_ARB, m_vertex_program);
439 StringOutputStream filename(256);
440 filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_vp.glp";
441 createProgram(filename.c_str(), GL_VERTEX_PROGRAM_ARB);
443 glGenProgramsARB(1, &m_fragment_program);
444 glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, m_fragment_program);
446 filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_fp.glp";
447 createProgram(filename.c_str(), GL_FRAGMENT_PROGRAM_ARB);
450 glDisable(GL_VERTEX_PROGRAM_ARB);
451 glDisable(GL_FRAGMENT_PROGRAM_ARB);
453 GlobalOpenGL_debugAssertNoErrors();
458 glDeleteProgramsARB(1, &m_vertex_program);
459 glDeleteProgramsARB(1, &m_fragment_program);
460 GlobalOpenGL_debugAssertNoErrors();
465 glEnable(GL_VERTEX_PROGRAM_ARB);
466 glEnable(GL_FRAGMENT_PROGRAM_ARB);
467 glBindProgramARB(GL_VERTEX_PROGRAM_ARB, m_vertex_program);
468 glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, m_fragment_program);
470 glEnableVertexAttribArrayARB(8);
471 glEnableVertexAttribArrayARB(9);
472 glEnableVertexAttribArrayARB(10);
473 glEnableVertexAttribArrayARB(11);
475 GlobalOpenGL_debugAssertNoErrors();
480 glDisable(GL_VERTEX_PROGRAM_ARB);
481 glDisable(GL_FRAGMENT_PROGRAM_ARB);
483 glDisableVertexAttribArrayARB(8);
484 glDisableVertexAttribArrayARB(9);
485 glDisableVertexAttribArrayARB(10);
486 glDisableVertexAttribArrayARB(11);
488 GlobalOpenGL_debugAssertNoErrors();
491 void setParameters(const Vector3& viewer, const Matrix4& localToWorld, const Vector3& origin, const Vector3& colour, const Matrix4& world2light)
493 Matrix4 world2local(localToWorld);
494 matrix4_affine_invert(world2local);
496 Vector3 localLight(origin);
497 matrix4_transform_point(world2local, localLight);
499 Vector3 localViewer(viewer);
500 matrix4_transform_point(world2local, localViewer);
502 Matrix4 local2light(world2light);
503 matrix4_multiply_by_matrix4(local2light, localToWorld); // local->world->light
506 glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 4, localViewer.x(), localViewer.y(), localViewer.z(), 0);
509 glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 2, localLight.x(), localLight.y(), localLight.z(), 1);
512 glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 3, colour.x(), colour.y(), colour.z(), 0);
515 glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, 1, 0, 0, 0);
518 glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 5, 32, 0, 0, 0);
521 glActiveTexture(GL_TEXTURE3);
522 glClientActiveTexture(GL_TEXTURE3);
524 glMatrixMode(GL_TEXTURE);
525 glLoadMatrixf(reinterpret_cast<const float*>(&local2light));
526 glMatrixMode(GL_MODELVIEW);
528 GlobalOpenGL_debugAssertNoErrors();
532 class ARBDepthFillProgram : public GLProgram
535 GLuint m_vertex_program;
536 GLuint m_fragment_program;
540 glEnable(GL_VERTEX_PROGRAM_ARB);
541 glEnable(GL_FRAGMENT_PROGRAM_ARB);
544 glGenProgramsARB(1, &m_vertex_program);
545 glBindProgramARB(GL_VERTEX_PROGRAM_ARB, m_vertex_program);
546 StringOutputStream filename(256);
547 filename << GlobalRadiant().getAppPath() << "gl/zfill_vp.glp";
548 createProgram(filename.c_str(), GL_VERTEX_PROGRAM_ARB);
550 glGenProgramsARB(1, &m_fragment_program);
551 glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, m_fragment_program);
553 filename << GlobalRadiant().getAppPath() << "gl/zfill_fp.glp";
554 createProgram(filename.c_str(), GL_FRAGMENT_PROGRAM_ARB);
557 glDisable(GL_VERTEX_PROGRAM_ARB);
558 glDisable(GL_FRAGMENT_PROGRAM_ARB);
560 GlobalOpenGL_debugAssertNoErrors();
565 glDeleteProgramsARB(1, &m_vertex_program);
566 glDeleteProgramsARB(1, &m_fragment_program);
567 GlobalOpenGL_debugAssertNoErrors();
572 glEnable(GL_VERTEX_PROGRAM_ARB);
573 glEnable(GL_FRAGMENT_PROGRAM_ARB);
574 glBindProgramARB(GL_VERTEX_PROGRAM_ARB, m_vertex_program);
575 glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, m_fragment_program);
577 GlobalOpenGL_debugAssertNoErrors();
582 glDisable(GL_VERTEX_PROGRAM_ARB);
583 glDisable(GL_FRAGMENT_PROGRAM_ARB);
585 GlobalOpenGL_debugAssertNoErrors();
588 void setParameters(const Vector3& viewer, const Matrix4& localToWorld, const Vector3& origin, const Vector3& colour, const Matrix4& world2light)
593 ARBBumpProgram g_bumpARB;
594 ARBDepthFillProgram g_depthFillARB;
598 // NV20 path (unfinished)
600 void createProgram(GLint program, const char* filename, GLenum type)
602 std::size_t size = file_size(filename);
603 FileInputStream file(filename);
604 ASSERT_MESSAGE(!file.failed(), "failed to open " << makeQuoted(filename));
605 Array<GLubyte> buffer(size);
606 size = file.read(reinterpret_cast<StreamBase::byte_type*>(buffer.data()), size);
608 glLoadProgramNV(type, program, GLsizei(size), buffer.data());
610 if(GL_INVALID_OPERATION == glGetError())
613 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_NV, &errPos);
614 const GLubyte* errString = glGetString(GL_PROGRAM_ERROR_STRING_NV);
616 globalErrorStream() << filename << ":" << errPos << "\n" << errString;
618 ERROR_MESSAGE("error in gl program");
622 GLuint m_vertex_program;
623 GLuint m_fragment_program;
624 qtexture_t* g_cube = 0;
625 qtexture_t* g_specular_lookup = 0;
626 qtexture_t* g_attenuation_xy = 0;
627 qtexture_t* g_attenuation_z = 0;
629 void createVertexProgram()
632 glGenProgramsNV(1, &m_vertex_program);
633 glBindProgramNV(GL_VERTEX_PROGRAM_NV, m_vertex_program);
634 StringOutputStream filename(256);
635 filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_vp.nv30";
636 createProgram(m_vertex_program, filename.c_str(), GL_VERTEX_PROGRAM_NV);
638 glGenProgramsNV(1, &m_fragment_program);
639 glBindProgramNV(GL_FRAGMENT_PROGRAM_NV, m_fragment_program);
641 filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_fp.nv30";
642 createProgram(m_fragment_program, filename.c_str(), GL_FRAGMENT_PROGRAM_NV);
645 g_cube = GlobalTexturesCache().capture("generated/cube");
646 g_specular_lookup = GlobalTexturesCache().capture("generated/specular");
648 g_attenuation_xy = GlobalTexturesCache().capture("lights/squarelight1");
649 glActiveTexture(GL_TEXTURE0);
650 glBindTexture(GL_TEXTURE_2D, g_attenuation_xy->texture_number);
651 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
652 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
654 g_attenuation_z = GlobalTexturesCache().capture("lights/squarelight1a");
655 glActiveTexture(GL_TEXTURE0);
656 glBindTexture(GL_TEXTURE_2D, g_attenuation_z->texture_number);
657 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
658 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
660 GlobalOpenGL_debugAssertNoErrors();
663 void destroyVertexProgram()
665 glDeleteProgramsNV(1, &m_vertex_program);
666 glDeleteProgramsNV(1, &m_fragment_program);
667 GlobalOpenGL_debugAssertNoErrors();
669 GlobalTexturesCache().release(g_cube);
670 GlobalTexturesCache().release(g_specular_lookup);
671 GlobalTexturesCache().release(g_attenuation_xy);
672 GlobalTexturesCache().release(g_attenuation_z);
675 bool g_vertexProgram_enabled = false;
677 void enableVertexProgram()
679 //set up the register combiners
680 //two general combiners
681 glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, 2);
683 //combiner 0 does tex0+tex1 -> spare0
684 glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_A_NV, GL_TEXTURE0_ARB,
685 GL_UNSIGNED_IDENTITY_NV, GL_RGB);
686 glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_B_NV, GL_ZERO,
687 GL_UNSIGNED_INVERT_NV, GL_RGB);
688 glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_C_NV, GL_TEXTURE1_ARB,
689 GL_UNSIGNED_IDENTITY_NV, GL_RGB);
690 glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_D_NV, GL_ZERO,
691 GL_UNSIGNED_INVERT_NV, GL_RGB);
692 glCombinerOutputNV(GL_COMBINER0_NV, GL_RGB, GL_DISCARD_NV, GL_DISCARD_NV, GL_SPARE0_NV,
693 GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE);
695 //combiner 1 does tex2 dot tex3 -> spare1
696 glCombinerInputNV(GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_A_NV, GL_TEXTURE2_ARB,
697 GL_EXPAND_NORMAL_NV, GL_RGB);
698 glCombinerInputNV(GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_B_NV, GL_TEXTURE3_ARB,
699 GL_EXPAND_NORMAL_NV, GL_RGB);
700 glCombinerOutputNV(GL_COMBINER1_NV, GL_RGB, GL_SPARE1_NV, GL_DISCARD_NV, GL_DISCARD_NV,
701 GL_NONE, GL_NONE, GL_TRUE, GL_FALSE, GL_FALSE);
705 //final combiner outputs (1-spare0)*constant color 0*spare1
706 //do constant color 0*spare1 in the EF multiplier
707 glFinalCombinerInputNV(GL_VARIABLE_E_NV, GL_SPARE1_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
708 glFinalCombinerInputNV(GL_VARIABLE_F_NV, GL_CONSTANT_COLOR0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
710 //now do (1-spare0)*EF
711 glFinalCombinerInputNV(GL_VARIABLE_A_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
712 glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
713 glFinalCombinerInputNV(GL_VARIABLE_C_NV, GL_E_TIMES_F_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
714 glFinalCombinerInputNV(GL_VARIABLE_D_NV, GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
716 glEnable(GL_VERTEX_PROGRAM_NV);
717 glEnable(GL_REGISTER_COMBINERS_NV);
718 glBindProgramNV(GL_VERTEX_PROGRAM_NV, m_vertex_program);
719 glBindProgramNV(GL_FRAGMENT_PROGRAM_NV, m_fragment_program);
721 glActiveTexture(GL_TEXTURE0);
722 glEnable(GL_TEXTURE_2D);
723 glActiveTexture(GL_TEXTURE1);
724 glEnable(GL_TEXTURE_1D);
725 glActiveTexture(GL_TEXTURE2);
726 glEnable(GL_TEXTURE_2D);
727 glActiveTexture(GL_TEXTURE3);
728 glEnable(GL_TEXTURE_2D);
730 glEnableClientState(GL_VERTEX_ATTRIB_ARRAY8_NV);
731 glEnableClientState(GL_VERTEX_ATTRIB_ARRAY9_NV);
732 glEnableClientState(GL_VERTEX_ATTRIB_ARRAY10_NV);
733 glEnableClientState(GL_VERTEX_ATTRIB_ARRAY11_NV);
735 GlobalOpenGL_debugAssertNoErrors();
736 g_vertexProgram_enabled = true;
739 void disableVertexProgram()
741 glDisable(GL_VERTEX_PROGRAM_NV);
742 glDisable(GL_REGISTER_COMBINERS_NV);
744 glActiveTexture(GL_TEXTURE0);
745 glDisable(GL_TEXTURE_2D);
746 glActiveTexture(GL_TEXTURE1);
747 glDisable(GL_TEXTURE_1D);
748 glActiveTexture(GL_TEXTURE2);
749 glDisable(GL_TEXTURE_2D);
750 glActiveTexture(GL_TEXTURE3);
751 glDisable(GL_TEXTURE_2D);
753 glDisableClientState(GL_VERTEX_ATTRIB_ARRAY8_NV);
754 glDisableClientState(GL_VERTEX_ATTRIB_ARRAY9_NV);
755 glDisableClientState(GL_VERTEX_ATTRIB_ARRAY10_NV);
756 glDisableClientState(GL_VERTEX_ATTRIB_ARRAY11_NV);
758 GlobalOpenGL_debugAssertNoErrors();
759 g_vertexProgram_enabled = false;
765 const GLubyte* m_string;
766 const GLint m_length;
767 GLstringNV(const char* string) : m_string(reinterpret_cast<const GLubyte*>(string)), m_length(GLint(string_length(string)))
772 GLstringNV g_light_origin("light_origin");
773 GLstringNV g_view_origin("view_origin");
774 GLstringNV g_light_color("light_color");
775 GLstringNV g_bumpGLSL_scale("bump_scale");
776 GLstringNV g_specular_exponent("specular_exponent");
778 void setVertexProgramEnvironment(const Vector3& localViewer)
780 Matrix4 local2light(g_matrix4_identity);
781 matrix4_translate_by_vec3(local2light, Vector3(0.5, 0.5, 0.5));
782 matrix4_scale_by_vec3(local2light, Vector3(0.5, 0.5, 0.5));
783 matrix4_scale_by_vec3(local2light, Vector3(1.0 / 512.0, 1.0 / 512.0, 1.0 / 512.0));
784 matrix4_translate_by_vec3(local2light, vector3_negated(localViewer));
786 glActiveTexture(GL_TEXTURE3);
787 glClientActiveTexture(GL_TEXTURE3);
789 glMatrixMode(GL_TEXTURE);
790 glLoadMatrixf(reinterpret_cast<const float*>(&local2light));
791 glMatrixMode(GL_MODELVIEW);
793 glTrackMatrixNV(GL_VERTEX_PROGRAM_NV, 0, GL_MODELVIEW_PROJECTION_NV, GL_IDENTITY_NV);
794 glTrackMatrixNV(GL_VERTEX_PROGRAM_NV, 4, GL_TEXTURE0_ARB, GL_IDENTITY_NV);
797 //qglProgramNamedParameter4fNV(m_fragment_program, g_view_origin.m_length, g_view_origin.m_string, localViewer.x(), localViewer.y(), localViewer.z(), 0);
800 glProgramParameter4fNV(GL_VERTEX_PROGRAM_NV, 8, localViewer.x(), localViewer.y(), localViewer.z(), 1.0f);
803 glCombinerParameterfNV(GL_CONSTANT_COLOR0_NV, 1, 1, 1, 1)
806 //qglProgramNamedParameter4fNV(m_fragment_program, g_bumpGLSL_scale.m_length, g_bumpGLSL_scale.m_string, 1, 0, 0, 0);
809 //qglProgramNamedParameter4fNV(m_fragment_program, g_specular_exponent.m_length, g_specular_exponent.m_string, 32, 0, 0, 0);
811 GlobalOpenGL_debugAssertNoErrors();
817 bool g_vertexArray_enabled = false;
818 bool g_normalArray_enabled = false;
819 bool g_texcoordArray_enabled = false;
820 bool g_colorArray_enabled = false;
822 inline bool OpenGLState_less(const OpenGLState& self, const OpenGLState& other)
824 //! Sort by sort-order override.
825 if(self.m_sort != other.m_sort)
827 return self.m_sort < other.m_sort;
829 //! Sort by texture handle.
830 if(self.m_texture != other.m_texture)
832 return self.m_texture < other.m_texture;
834 if(self.m_texture1 != other.m_texture1)
836 return self.m_texture1 < other.m_texture1;
838 if(self.m_texture2 != other.m_texture2)
840 return self.m_texture2 < other.m_texture2;
842 if(self.m_texture3 != other.m_texture3)
844 return self.m_texture3 < other.m_texture3;
846 if(self.m_texture4 != other.m_texture4)
848 return self.m_texture4 < other.m_texture4;
850 if(self.m_texture5 != other.m_texture5)
852 return self.m_texture5 < other.m_texture5;
854 if(self.m_texture6 != other.m_texture6)
856 return self.m_texture6 < other.m_texture6;
858 if(self.m_texture7 != other.m_texture7)
860 return self.m_texture7 < other.m_texture7;
862 //! Sort by state bit-vector.
863 if(self.m_state != other.m_state)
865 return self.m_state < other.m_state;
867 //! Comparing address makes sure states are never equal.
868 return &self < &other;
871 void OpenGLState_constructDefault(OpenGLState& state)
873 state.m_state = RENDER_DEFAULT;
876 state.m_texture1 = 0;
877 state.m_texture2 = 0;
878 state.m_texture3 = 0;
879 state.m_texture4 = 0;
880 state.m_texture5 = 0;
881 state.m_texture6 = 0;
882 state.m_texture7 = 0;
884 state.m_colour[0] = 1;
885 state.m_colour[1] = 1;
886 state.m_colour[2] = 1;
887 state.m_colour[3] = 1;
889 state.m_depthfunc = GL_LESS;
891 state.m_blend_src = GL_SRC_ALPHA;
892 state.m_blend_dst = GL_ONE_MINUS_SRC_ALPHA;
894 state.m_alphafunc = GL_ALWAYS;
895 state.m_alpharef = 0;
897 state.m_linewidth = 1;
898 state.m_pointsize = 1;
900 state.m_linestipple_factor = 1;
901 state.m_linestipple_pattern = 0xaaaa;
903 state.m_fog = OpenGLFogState();
909 /// \brief A container of Renderable references.
910 /// May contain the same Renderable multiple times, with different transforms.
911 class OpenGLStateBucket
914 struct RenderTransform
916 const Matrix4* m_transform;
917 const OpenGLRenderable *m_renderable;
918 const RendererLight* m_light;
920 RenderTransform(const OpenGLRenderable& renderable, const Matrix4& transform, const RendererLight* light)
921 : m_transform(&transform), m_renderable(&renderable), m_light(light)
926 typedef std::vector<RenderTransform> Renderables;
931 Renderables m_renderables;
937 void addRenderable(const OpenGLRenderable& renderable, const Matrix4& modelview, const RendererLight* light = 0)
939 m_renderables.push_back(RenderTransform(renderable, modelview, light));
947 void render(OpenGLState& current, unsigned int globalstate, const Vector3& viewer);
950 #define LIGHT_SHADER_DEBUG 0
952 #if LIGHT_SHADER_DEBUG
953 typedef std::vector<Shader*> LightDebugShaders;
954 LightDebugShaders g_lightDebugShaders;
957 class OpenGLStateLess
960 bool operator()(const OpenGLState& self, const OpenGLState& other) const
962 return OpenGLState_less(self, other);
966 typedef ConstReference<OpenGLState> OpenGLStateReference;
967 typedef std::map<OpenGLStateReference, OpenGLStateBucket*, OpenGLStateLess> OpenGLStates;
968 OpenGLStates g_state_sorted;
970 class OpenGLStateBucketAdd
972 OpenGLStateBucket& m_bucket;
973 const OpenGLRenderable& m_renderable;
974 const Matrix4& m_modelview;
976 typedef const RendererLight& first_argument_type;
978 OpenGLStateBucketAdd(OpenGLStateBucket& bucket, const OpenGLRenderable& renderable, const Matrix4& modelview) :
979 m_bucket(bucket), m_renderable(renderable), m_modelview(modelview)
982 void operator()(const RendererLight& light)
984 m_bucket.addRenderable(m_renderable, m_modelview, &light);
992 typedef RendererLight& first_argument_type;
994 CountLights() : m_count(0)
997 void operator()(const RendererLight& light)
1001 std::size_t count() const
1007 class OpenGLShader : public Shader
1009 typedef std::list<OpenGLStateBucket*> Passes;
1013 ModuleObservers m_observers;
1015 OpenGLShader() : m_shader(0), m_used(0)
1021 void construct(const char* name);
1030 for(Passes::iterator i = m_passes.begin(); i != m_passes.end(); ++i)
1036 void addRenderable(const OpenGLRenderable& renderable, const Matrix4& modelview, const LightList* lights)
1038 for(Passes::iterator i = m_passes.begin(); i != m_passes.end(); ++i)
1040 #if LIGHT_SHADER_DEBUG
1041 if(((*i)->state().m_state & RENDER_BUMP) != 0)
1045 CountLights counter;
1046 lights->forEachLight(makeCallback1(counter));
1047 globalOutputStream() << "count = " << counter.count() << "\n";
1048 for(std::size_t i = 0; i < counter.count(); ++i)
1050 g_lightDebugShaders[counter.count()]->addRenderable(renderable, modelview);
1056 if(((*i)->state().m_state & RENDER_BUMP) != 0)
1060 OpenGLStateBucketAdd add(*(*i), renderable, modelview);
1061 lights->forEachLight(makeCallback1(add));
1067 (*i)->addRenderable(renderable, modelview);
1071 void incrementUsed()
1073 if(++m_used == 1 && m_shader != 0)
1075 m_shader->SetInUse(true);
1078 void decrementUsed()
1080 if(--m_used == 0 && m_shader != 0)
1082 m_shader->SetInUse(false);
1085 bool realised() const
1087 return m_shader != 0;
1089 void attach(ModuleObserver& observer)
1095 m_observers.attach(observer);
1097 void detach(ModuleObserver& observer)
1101 observer.unrealise();
1103 m_observers.detach(observer);
1105 void realise(const CopiedString& name)
1107 construct(name.c_str());
1109 if(m_used != 0 && m_shader != 0)
1111 m_shader->SetInUse(true);
1114 for(Passes::iterator i = m_passes.begin(); i != m_passes.end(); ++i)
1116 g_state_sorted.insert(OpenGLStates::value_type(OpenGLStateReference((*i)->state()), *i));
1119 m_observers.realise();
1123 m_observers.unrealise();
1125 for(Passes::iterator i = m_passes.begin(); i != m_passes.end(); ++i)
1127 g_state_sorted.erase(OpenGLStateReference((*i)->state()));
1132 qtexture_t& getTexture() const
1134 ASSERT_NOTNULL(m_shader);
1135 return *m_shader->getTexture();
1137 unsigned int getFlags() const
1139 ASSERT_NOTNULL(m_shader);
1140 return m_shader->getFlags();
1142 IShader& getShader() const
1144 ASSERT_NOTNULL(m_shader);
1147 OpenGLState& appendDefaultPass()
1149 m_passes.push_back(new OpenGLStateBucket);
1150 OpenGLState& state = m_passes.back()->state();
1151 OpenGLState_constructDefault(state);
1157 inline bool lightEnabled(const RendererLight& light, const LightCullable& cullable)
1159 return cullable.testLight(light);
1162 typedef std::set<RendererLight*> RendererLights;
1164 #define DEBUG_LIGHT_SYNC 0
1166 class LinearLightList : public LightList
1168 LightCullable& m_cullable;
1169 RendererLights& m_allLights;
1170 Callback m_evaluateChanged;
1172 typedef std::list<RendererLight*> Lights;
1173 mutable Lights m_lights;
1174 mutable bool m_lightsChanged;
1176 LinearLightList(LightCullable& cullable, RendererLights& lights, const Callback& evaluateChanged) :
1177 m_cullable(cullable), m_allLights(lights), m_evaluateChanged(evaluateChanged)
1179 m_lightsChanged = true;
1181 void evaluateLights() const
1183 m_evaluateChanged();
1186 m_lightsChanged = false;
1189 m_cullable.clearLights();
1190 for(RendererLights::const_iterator i = m_allLights.begin(); i != m_allLights.end(); ++i)
1192 if(lightEnabled(*(*i), m_cullable))
1194 m_lights.push_back(*i);
1195 m_cullable.insertLight(*(*i));
1199 #if(DEBUG_LIGHT_SYNC)
1203 for(RendererLights::const_iterator i = m_allLights.begin(); i != m_allLights.end(); ++i)
1205 if(lightEnabled(*(*i), m_cullable))
1207 lights.push_back(*i);
1211 !std::lexicographical_compare(lights.begin(), lights.end(), m_lights.begin(), m_lights.end())
1212 && !std::lexicographical_compare(m_lights.begin(), m_lights.end(), lights.begin(), lights.end()),
1213 "lights out of sync"
1218 void forEachLight(const RendererLightCallback& callback) const
1222 for(Lights::const_iterator i = m_lights.begin(); i != m_lights.end(); ++i)
1227 void lightsChanged() const
1229 m_lightsChanged = true;
1233 inline void setFogState(const OpenGLFogState& state)
1235 glFogi(GL_FOG_MODE, state.mode);
1236 glFogf(GL_FOG_DENSITY, state.density);
1237 glFogf(GL_FOG_START, state.start);
1238 glFogf(GL_FOG_END, state.end);
1239 glFogi(GL_FOG_INDEX, state.index);
1240 glFogfv(GL_FOG_COLOR, vector4_to_array(state.colour));
1243 #define DEBUG_SHADERS 0
1245 class OpenGLShaderCache : public ShaderCache, public TexturesCacheObserver, public ModuleObserver
1247 class CreateOpenGLShader
1249 OpenGLShaderCache* m_cache;
1251 explicit CreateOpenGLShader(OpenGLShaderCache* cache = 0)
1255 OpenGLShader* construct(const CopiedString& name)
1257 OpenGLShader* shader = new OpenGLShader;
1258 if(m_cache->realised())
1260 shader->realise(name);
1264 void destroy(OpenGLShader* shader)
1266 if(m_cache->realised())
1268 shader->unrealise();
1274 typedef HashedCache<CopiedString, OpenGLShader, HashString, std::equal_to<CopiedString>, CreateOpenGLShader> Shaders;
1276 std::size_t m_unrealised;
1278 bool m_lightingEnabled;
1279 bool m_lightingSupported;
1280 bool m_useShaderLanguage;
1284 : m_shaders(CreateOpenGLShader(this)),
1285 m_unrealised(3), // wait until shaders, gl-context and textures are realised before creating any render-states
1286 m_lightingEnabled(true),
1287 m_lightingSupported(false),
1288 m_useShaderLanguage(false),
1289 m_lightsChanged(true),
1290 m_traverseRenderablesMutex(false)
1293 ~OpenGLShaderCache()
1295 for(Shaders::iterator i = m_shaders.begin(); i != m_shaders.end(); ++i)
1297 globalOutputStream() << "leaked shader: " << makeQuoted((*i).key.c_str()) << "\n";
1300 Shader* capture(const char* name)
1302 ASSERT_MESSAGE(name[0] == '$'
1306 || strchr(name, '\\') == 0, "shader name contains invalid characters: \"" << name << "\"");
1308 globalOutputStream() << "shaders capture: " << makeQuoted(name) << '\n';
1310 return m_shaders.capture(name).get();
1312 void release(const char *name)
1315 globalOutputStream() << "shaders release: " << makeQuoted(name) << '\n';
1317 m_shaders.release(name);
1319 void render(RenderStateFlags globalstate, const Matrix4& modelview, const Matrix4& projection, const Vector3& viewer)
1321 glMatrixMode(GL_PROJECTION);
1322 glLoadMatrixf(reinterpret_cast<const float*>(&projection));
1324 //qglGetFloatv(GL_PROJECTION_MATRIX, reinterpret_cast<float*>(&projection));
1327 glMatrixMode(GL_MODELVIEW);
1328 glLoadMatrixf(reinterpret_cast<const float*>(&modelview));
1330 //qglGetFloatv(GL_MODELVIEW_MATRIX, reinterpret_cast<float*>(&modelview));
1333 ASSERT_MESSAGE(realised(), "render states are not realised");
1335 // global settings that are not set in renderstates
1337 glCullFace(GL_BACK);
1338 glPolygonOffset(-1, 1);
1340 const GLubyte pattern[132] = {
1341 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1342 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1343 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1344 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1345 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1346 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1347 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1348 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1349 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1350 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1351 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1352 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1353 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1354 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1355 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
1356 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55
1358 glPolygonStipple(pattern);
1360 glEnableClientState(GL_VERTEX_ARRAY);
1361 g_vertexArray_enabled = true;
1362 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
1364 if(GlobalOpenGL().GL_1_3())
1366 glActiveTexture(GL_TEXTURE0);
1367 glClientActiveTexture(GL_TEXTURE0);
1370 if(GlobalOpenGL().ARB_shader_objects())
1372 glUseProgramObjectARB(0);
1373 glDisableVertexAttribArrayARB(c_attr_TexCoord0);
1374 glDisableVertexAttribArrayARB(c_attr_Tangent);
1375 glDisableVertexAttribArrayARB(c_attr_Binormal);
1378 if(globalstate & RENDER_TEXTURE)
1380 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
1381 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
1384 OpenGLState current;
1385 OpenGLState_constructDefault(current);
1386 current.m_sort = OpenGLState::eSortFirst;
1388 // default renderstate settings
1389 glLineStipple(current.m_linestipple_factor, current.m_linestipple_pattern);
1390 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
1391 glDisable(GL_LIGHTING);
1392 glDisable(GL_TEXTURE_2D);
1393 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1394 g_texcoordArray_enabled = false;
1395 glDisableClientState(GL_COLOR_ARRAY);
1396 g_colorArray_enabled = false;
1397 glDisableClientState(GL_NORMAL_ARRAY);
1398 g_normalArray_enabled = false;
1399 glDisable(GL_BLEND);
1400 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1401 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1402 glDisable(GL_CULL_FACE);
1403 glShadeModel(GL_FLAT);
1404 glDisable(GL_DEPTH_TEST);
1405 glDepthMask(GL_FALSE);
1406 glDisable(GL_ALPHA_TEST);
1407 glDisable(GL_LINE_STIPPLE);
1408 glDisable(GL_POLYGON_STIPPLE);
1409 glDisable(GL_POLYGON_OFFSET_LINE);
1411 glBindTexture(GL_TEXTURE_2D, 0);
1413 glDepthFunc(GL_LESS);
1414 glAlphaFunc(GL_ALWAYS, 0);
1418 glHint(GL_FOG_HINT, GL_NICEST);
1420 setFogState(OpenGLFogState());
1422 GlobalOpenGL_debugAssertNoErrors();
1424 debug_string("begin rendering");
1425 for(OpenGLStates::iterator i = g_state_sorted.begin(); i != g_state_sorted.end(); ++i)
1427 (*i).second->render(current, globalstate, viewer);
1429 debug_string("end rendering");
1433 if(--m_unrealised == 0)
1435 if(lightingSupported() && lightingEnabled())
1437 if(useShaderLanguage())
1439 g_bumpGLSL.create();
1440 g_depthFillGLSL.create();
1445 g_depthFillARB.create();
1449 for(Shaders::iterator i = m_shaders.begin(); i != m_shaders.end(); ++i)
1451 if(!(*i).value.empty())
1453 (*i).value->realise(i->key);
1460 if(++m_unrealised == 1)
1462 for(Shaders::iterator i = m_shaders.begin(); i != m_shaders.end(); ++i)
1464 if(!(*i).value.empty())
1466 (*i).value->unrealise();
1469 if(GlobalOpenGL().contextValid && lightingSupported() && lightingEnabled())
1471 if(useShaderLanguage())
1473 g_bumpGLSL.destroy();
1474 g_depthFillGLSL.destroy();
1478 g_bumpARB.destroy();
1479 g_depthFillARB.destroy();
1486 return m_unrealised == 0;
1490 bool lightingEnabled() const
1492 return m_lightingEnabled;
1494 bool lightingSupported() const
1496 return m_lightingSupported;
1498 bool useShaderLanguage() const
1500 return m_useShaderLanguage;
1502 void setLighting(bool supported, bool enabled)
1504 bool refresh = (m_lightingSupported && m_lightingEnabled) != (supported && enabled);
1509 GlobalShaderSystem().setLightingEnabled(supported && enabled);
1512 m_lightingSupported = supported;
1513 m_lightingEnabled = enabled;
1520 void extensionsInitialised()
1522 setLighting(GlobalOpenGL().GL_1_3()
1523 && GlobalOpenGL().ARB_vertex_program()
1524 && GlobalOpenGL().ARB_fragment_program()
1525 && GlobalOpenGL().ARB_shader_objects()
1526 && GlobalOpenGL().ARB_vertex_shader()
1527 && GlobalOpenGL().ARB_fragment_shader()
1528 && GlobalOpenGL().ARB_shading_language_100(),
1532 if(!lightingSupported())
1534 globalOutputStream() << "Lighting mode requires OpenGL features not supported by your graphics drivers:\n";
1535 if(!GlobalOpenGL().GL_1_3())
1537 globalOutputStream() << " GL version 1.3 or better\n";
1539 if(!GlobalOpenGL().ARB_vertex_program())
1541 globalOutputStream() << " GL_ARB_vertex_program\n";
1543 if(!GlobalOpenGL().ARB_fragment_program())
1545 globalOutputStream() << " GL_ARB_fragment_program\n";
1547 if(!GlobalOpenGL().ARB_shader_objects())
1549 globalOutputStream() << " GL_ARB_shader_objects\n";
1551 if(!GlobalOpenGL().ARB_vertex_shader())
1553 globalOutputStream() << " GL_ARB_vertex_shader\n";
1555 if(!GlobalOpenGL().ARB_fragment_shader())
1557 globalOutputStream() << " GL_ARB_fragment_shader\n";
1559 if(!GlobalOpenGL().ARB_shading_language_100())
1561 globalOutputStream() << " GL_ARB_shading_language_100\n";
1565 void setLightingEnabled(bool enabled)
1567 setLighting(m_lightingSupported, enabled);
1572 RendererLights m_lights;
1573 bool m_lightsChanged;
1574 typedef std::map<LightCullable*, LinearLightList> LightLists;
1575 LightLists m_lightLists;
1577 const LightList& attach(LightCullable& cullable)
1579 return (*m_lightLists.insert(LightLists::value_type(&cullable, LinearLightList(cullable, m_lights, EvaluateChangedCaller(*this)))).first).second;
1581 void detach(LightCullable& cullable)
1583 m_lightLists.erase(&cullable);
1585 void changed(LightCullable& cullable)
1587 LightLists::iterator i = m_lightLists.find(&cullable);
1588 ASSERT_MESSAGE(i != m_lightLists.end(), "cullable not attached");
1589 (*i).second.lightsChanged();
1591 void attach(RendererLight& light)
1593 ASSERT_MESSAGE(m_lights.find(&light) == m_lights.end(), "light could not be attached");
1594 m_lights.insert(&light);
1597 void detach(RendererLight& light)
1599 ASSERT_MESSAGE(m_lights.find(&light) != m_lights.end(), "light could not be detached");
1600 m_lights.erase(&light);
1603 void changed(RendererLight& light)
1605 m_lightsChanged = true;
1607 void evaluateChanged()
1611 m_lightsChanged = false;
1612 for(LightLists::iterator i = m_lightLists.begin(); i != m_lightLists.end(); ++i)
1614 (*i).second.lightsChanged();
1618 typedef MemberCaller<OpenGLShaderCache, &OpenGLShaderCache::evaluateChanged> EvaluateChangedCaller;
1620 typedef std::set<const Renderable*> Renderables;
1621 Renderables m_renderables;
1622 mutable bool m_traverseRenderablesMutex;
1625 void attachRenderable(const Renderable& renderable)
1627 ASSERT_MESSAGE(!m_traverseRenderablesMutex, "attaching renderable during traversal");
1628 ASSERT_MESSAGE(m_renderables.find(&renderable) == m_renderables.end(), "renderable could not be attached");
1629 m_renderables.insert(&renderable);
1631 void detachRenderable(const Renderable& renderable)
1633 ASSERT_MESSAGE(!m_traverseRenderablesMutex, "detaching renderable during traversal");
1634 ASSERT_MESSAGE(m_renderables.find(&renderable) != m_renderables.end(), "renderable could not be detached");
1635 m_renderables.erase(&renderable);
1637 void forEachRenderable(const RenderableCallback& callback) const
1639 ASSERT_MESSAGE(!m_traverseRenderablesMutex, "for-each during traversal");
1640 m_traverseRenderablesMutex = true;
1641 for(Renderables::const_iterator i = m_renderables.begin(); i != m_renderables.end(); ++i)
1645 m_traverseRenderablesMutex = false;
1649 static OpenGLShaderCache* g_ShaderCache;
1651 void ShaderCache_extensionsInitialised()
1653 g_ShaderCache->extensionsInitialised();
1656 void ShaderCache_setBumpEnabled(bool enabled)
1658 g_ShaderCache->setLightingEnabled(enabled);
1662 Vector3 g_DebugShaderColours[256];
1663 Shader* g_defaultPointLight = 0;
1665 void ShaderCache_Construct()
1667 g_ShaderCache = new OpenGLShaderCache;
1668 GlobalTexturesCache().attach(*g_ShaderCache);
1669 GlobalShaderSystem().attach(*g_ShaderCache);
1671 if(g_pGameDescription->mGameType == "doom3")
1673 g_defaultPointLight = g_ShaderCache->capture("lights/defaultPointLight");
1674 //Shader* overbright =
1675 g_ShaderCache->capture("$OVERBRIGHT");
1677 #if LIGHT_SHADER_DEBUG
1678 for(std::size_t i = 0; i < 256; ++i)
1680 g_DebugShaderColours[i] = Vector3(i / 256.0, i / 256.0, i / 256.0);
1683 g_DebugShaderColours[0] = Vector3(1, 0, 0);
1684 g_DebugShaderColours[1] = Vector3(1, 0.5, 0);
1685 g_DebugShaderColours[2] = Vector3(1, 1, 0);
1686 g_DebugShaderColours[3] = Vector3(0.5, 1, 0);
1687 g_DebugShaderColours[4] = Vector3(0, 1, 0);
1688 g_DebugShaderColours[5] = Vector3(0, 1, 0.5);
1689 g_DebugShaderColours[6] = Vector3(0, 1, 1);
1690 g_DebugShaderColours[7] = Vector3(0, 0.5, 1);
1691 g_DebugShaderColours[8] = Vector3(0, 0, 1);
1692 g_DebugShaderColours[9] = Vector3(0.5, 0, 1);
1693 g_DebugShaderColours[10] = Vector3(1, 0, 1);
1694 g_DebugShaderColours[11] = Vector3(1, 0, 0.5);
1696 g_lightDebugShaders.reserve(256);
1697 StringOutputStream buffer(256);
1698 for(std::size_t i = 0; i < 256; ++i)
1700 buffer << "(" << g_DebugShaderColours[i].x() << " " << g_DebugShaderColours[i].y() << " " << g_DebugShaderColours[i].z() << ")";
1701 g_lightDebugShaders.push_back(g_ShaderCache->capture(buffer.c_str()));
1708 void ShaderCache_Destroy()
1710 if(g_pGameDescription->mGameType == "doom3")
1712 g_ShaderCache->release("lights/defaultPointLight");
1713 g_ShaderCache->release("$OVERBRIGHT");
1714 g_defaultPointLight = 0;
1716 #if LIGHT_SHADER_DEBUG
1717 g_lightDebugShaders.clear();
1718 StringOutputStream buffer(256);
1719 for(std::size_t i = 0; i < 256; ++i)
1721 buffer << "(" << g_DebugShaderColours[i].x() << " " << g_DebugShaderColours[i].y() << " " << g_DebugShaderColours[i].z() << ")";
1722 g_ShaderCache->release(buffer.c_str());
1727 GlobalShaderSystem().detach(*g_ShaderCache);
1728 GlobalTexturesCache().detach(*g_ShaderCache);
1729 delete g_ShaderCache;
1732 ShaderCache* GetShaderCache()
1734 return g_ShaderCache;
1737 inline void setTextureState(GLint& current, const GLint& texture, GLenum textureUnit)
1739 if(texture != current)
1741 glActiveTexture(textureUnit);
1742 glClientActiveTexture(textureUnit);
1743 glBindTexture(GL_TEXTURE_2D, texture);
1744 GlobalOpenGL_debugAssertNoErrors();
1749 inline void setTextureState(GLint& current, const GLint& texture)
1751 if(texture != current)
1753 glBindTexture(GL_TEXTURE_2D, texture);
1754 GlobalOpenGL_debugAssertNoErrors();
1759 inline void setState(unsigned int state, unsigned int delta, unsigned int flag, GLenum glflag)
1761 if(delta & state & flag)
1764 GlobalOpenGL_debugAssertNoErrors();
1766 else if(delta & ~state & flag)
1769 GlobalOpenGL_debugAssertNoErrors();
1773 void OpenGLState_apply(const OpenGLState& self, OpenGLState& current, unsigned int globalstate)
1775 debug_int("sort", int(self.m_sort));
1776 debug_int("texture", self.m_texture);
1777 debug_int("state", self.m_state);
1778 debug_int("address", int(std::size_t(&self)));
1782 if(self.m_state & RENDER_OVERRIDE)
1784 globalstate |= RENDER_FILL | RENDER_DEPTHWRITE;
1787 const unsigned int state = self.m_state & globalstate;
1788 const unsigned int delta = state ^ current.m_state;
1790 GlobalOpenGL_debugAssertNoErrors();
1792 GLProgram* program = (state & RENDER_PROGRAM) != 0 ? self.m_program : 0;
1794 if(program != current.m_program)
1796 if(current.m_program != 0)
1798 current.m_program->disable();
1799 glColor4fv(vector4_to_array(current.m_colour));
1800 debug_colour("cleaning program");
1803 current.m_program = program;
1805 if(current.m_program != 0)
1807 current.m_program->enable();
1811 if(delta & state & RENDER_FILL)
1813 //qglPolygonMode (GL_BACK, GL_LINE);
1814 //qglPolygonMode (GL_FRONT, GL_FILL);
1815 glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
1816 GlobalOpenGL_debugAssertNoErrors();
1818 else if(delta & ~state & RENDER_FILL)
1820 glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
1821 GlobalOpenGL_debugAssertNoErrors();
1824 setState(state, delta, RENDER_OFFSETLINE, GL_POLYGON_OFFSET_LINE);
1826 if(delta & state & RENDER_LIGHTING)
1828 glEnable(GL_LIGHTING);
1829 glEnable(GL_COLOR_MATERIAL);
1830 //qglEnable(GL_RESCALE_NORMAL);
1831 glEnableClientState(GL_NORMAL_ARRAY);
1832 GlobalOpenGL_debugAssertNoErrors();
1833 g_normalArray_enabled = true;
1835 else if(delta & ~state & RENDER_LIGHTING)
1837 glDisable(GL_LIGHTING);
1838 glDisable(GL_COLOR_MATERIAL);
1839 //qglDisable(GL_RESCALE_NORMAL);
1840 glDisableClientState(GL_NORMAL_ARRAY);
1841 GlobalOpenGL_debugAssertNoErrors();
1842 g_normalArray_enabled = false;
1845 if(delta & state & RENDER_TEXTURE)
1847 GlobalOpenGL_debugAssertNoErrors();
1849 if(GlobalOpenGL().GL_1_3())
1851 glActiveTexture(GL_TEXTURE0);
1852 glClientActiveTexture(GL_TEXTURE0);
1855 glEnable(GL_TEXTURE_2D);
1857 glColor4f(1,1,1,self.m_colour[3]);
1858 debug_colour("setting texture");
1860 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1861 GlobalOpenGL_debugAssertNoErrors();
1862 g_texcoordArray_enabled = true;
1864 else if(delta & ~state & RENDER_TEXTURE)
1866 if(GlobalOpenGL().GL_1_3())
1868 glActiveTexture(GL_TEXTURE0);
1869 glClientActiveTexture(GL_TEXTURE0);
1872 glDisable(GL_TEXTURE_2D);
1873 glBindTexture(GL_TEXTURE_2D, 0);
1874 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1876 GlobalOpenGL_debugAssertNoErrors();
1877 g_texcoordArray_enabled = false;
1880 if(delta & state & RENDER_BLEND)
1882 // FIXME: some .TGA are buggy, have a completely empty alpha channel
1883 // if such brushes are rendered in this loop they would be totally transparent with GL_MODULATE
1884 // so I decided using GL_DECAL instead
1885 // if an empty-alpha-channel or nearly-empty texture is used. It will be blank-transparent.
1886 // this could get better if you can get glTexEnviv (GL_TEXTURE_ENV, to work .. patches are welcome
1889 if(GlobalOpenGL().GL_1_3())
1891 glActiveTexture(GL_TEXTURE0);
1893 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
1894 GlobalOpenGL_debugAssertNoErrors();
1896 else if(delta & ~state & RENDER_BLEND)
1898 glDisable(GL_BLEND);
1899 if(GlobalOpenGL().GL_1_3())
1901 glActiveTexture(GL_TEXTURE0);
1903 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1904 GlobalOpenGL_debugAssertNoErrors();
1907 setState(state, delta, RENDER_CULLFACE, GL_CULL_FACE);
1909 if(delta & state & RENDER_SMOOTH)
1911 glShadeModel(GL_SMOOTH);
1912 GlobalOpenGL_debugAssertNoErrors();
1914 else if(delta & ~state & RENDER_SMOOTH)
1916 glShadeModel(GL_FLAT);
1917 GlobalOpenGL_debugAssertNoErrors();
1920 setState(state, delta, RENDER_SCALED, GL_NORMALIZE); // not GL_RESCALE_NORMAL
1922 setState(state, delta, RENDER_DEPTHTEST, GL_DEPTH_TEST);
1924 if(delta & state & RENDER_DEPTHWRITE)
1926 glDepthMask(GL_TRUE);
1929 GLboolean depthEnabled;
1930 glGetBooleanv(GL_DEPTH_WRITEMASK, &depthEnabled);
1931 ASSERT_MESSAGE(depthEnabled, "failed to set depth buffer mask bit");
1933 debug_string("enabled depth-buffer writing");
1935 GlobalOpenGL_debugAssertNoErrors();
1937 else if(delta & ~state & RENDER_DEPTHWRITE)
1939 glDepthMask(GL_FALSE);
1942 GLboolean depthEnabled;
1943 glGetBooleanv(GL_DEPTH_WRITEMASK, &depthEnabled);
1944 ASSERT_MESSAGE(!depthEnabled, "failed to set depth buffer mask bit");
1946 debug_string("disabled depth-buffer writing");
1948 GlobalOpenGL_debugAssertNoErrors();
1951 if(delta & state & RENDER_COLOURWRITE)
1953 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1954 GlobalOpenGL_debugAssertNoErrors();
1956 else if(delta & ~state & RENDER_COLOURWRITE)
1958 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1959 GlobalOpenGL_debugAssertNoErrors();
1962 setState(state, delta, RENDER_ALPHATEST, GL_ALPHA_TEST);
1964 if(delta & state & RENDER_COLOURARRAY)
1966 glEnableClientState(GL_COLOR_ARRAY);
1967 GlobalOpenGL_debugAssertNoErrors();
1968 debug_colour("enabling color_array");
1969 g_colorArray_enabled = true;
1971 else if(delta & ~state & RENDER_COLOURARRAY)
1973 glDisableClientState(GL_COLOR_ARRAY);
1974 glColor4fv(vector4_to_array(self.m_colour));
1975 debug_colour("cleaning color_array");
1976 GlobalOpenGL_debugAssertNoErrors();
1977 g_colorArray_enabled = false;
1980 if(delta & ~state & RENDER_COLOURCHANGE)
1982 glColor4fv(vector4_to_array(self.m_colour));
1983 GlobalOpenGL_debugAssertNoErrors();
1986 setState(state, delta, RENDER_LINESTIPPLE, GL_LINE_STIPPLE);
1987 setState(state, delta, RENDER_LINESMOOTH, GL_LINE_SMOOTH);
1989 setState(state, delta, RENDER_POLYGONSTIPPLE, GL_POLYGON_STIPPLE);
1990 setState(state, delta, RENDER_POLYGONSMOOTH, GL_POLYGON_SMOOTH);
1992 setState(state, delta, RENDER_FOG, GL_FOG);
1994 if((state & RENDER_FOG) != 0)
1996 setFogState(self.m_fog);
1997 GlobalOpenGL_debugAssertNoErrors();
1998 current.m_fog = self.m_fog;
2001 if(state & RENDER_DEPTHTEST && self.m_depthfunc != current.m_depthfunc)
2003 glDepthFunc(self.m_depthfunc);
2004 GlobalOpenGL_debugAssertNoErrors();
2005 current.m_depthfunc = self.m_depthfunc;
2008 if(state & RENDER_LINESTIPPLE
2009 && (self.m_linestipple_factor != current.m_linestipple_factor
2010 || self.m_linestipple_pattern != current.m_linestipple_pattern))
2012 glLineStipple(self.m_linestipple_factor, self.m_linestipple_pattern);
2013 GlobalOpenGL_debugAssertNoErrors();
2014 current.m_linestipple_factor = self.m_linestipple_factor;
2015 current.m_linestipple_pattern = self.m_linestipple_pattern;
2019 if(state & RENDER_ALPHATEST
2020 && ( self.m_alphafunc != current.m_alphafunc
2021 || self.m_alpharef != current.m_alpharef ) )
2023 glAlphaFunc(self.m_alphafunc, self.m_alpharef);
2024 GlobalOpenGL_debugAssertNoErrors();
2025 current.m_alphafunc = self.m_alphafunc;
2026 current.m_alpharef = self.m_alpharef;
2038 //if(state & RENDER_TEXTURE) != 0)
2040 texture0 = self.m_texture;
2041 texture1 = self.m_texture1;
2042 texture2 = self.m_texture2;
2043 texture3 = self.m_texture3;
2044 texture4 = self.m_texture4;
2045 texture5 = self.m_texture5;
2046 texture6 = self.m_texture6;
2047 texture7 = self.m_texture7;
2050 if(GlobalOpenGL().GL_1_3())
2052 setTextureState(current.m_texture, texture0, GL_TEXTURE0);
2053 setTextureState(current.m_texture1, texture1, GL_TEXTURE1);
2054 setTextureState(current.m_texture2, texture2, GL_TEXTURE2);
2055 setTextureState(current.m_texture3, texture3, GL_TEXTURE3);
2056 setTextureState(current.m_texture4, texture4, GL_TEXTURE4);
2057 setTextureState(current.m_texture5, texture5, GL_TEXTURE5);
2058 setTextureState(current.m_texture6, texture6, GL_TEXTURE6);
2059 setTextureState(current.m_texture7, texture7, GL_TEXTURE7);
2063 setTextureState(current.m_texture, texture0);
2068 if(state & RENDER_TEXTURE && self.m_colour[3] != current.m_colour[3])
2070 debug_colour("setting alpha");
2071 glColor4f(1,1,1,self.m_colour[3]);
2072 GlobalOpenGL_debugAssertNoErrors();
2075 if(!(state & RENDER_TEXTURE)
2076 && (self.m_colour[0] != current.m_colour[0]
2077 || self.m_colour[1] != current.m_colour[1]
2078 || self.m_colour[2] != current.m_colour[2]
2079 || self.m_colour[3] != current.m_colour[3]))
2081 glColor4fv(vector4_to_array(self.m_colour));
2082 debug_colour("setting non-texture");
2083 GlobalOpenGL_debugAssertNoErrors();
2085 current.m_colour = self.m_colour;
2087 if(state & RENDER_BLEND
2088 && (self.m_blend_src != current.m_blend_src || self.m_blend_dst != current.m_blend_dst))
2090 glBlendFunc(self.m_blend_src, self.m_blend_dst);
2091 GlobalOpenGL_debugAssertNoErrors();
2092 current.m_blend_src = self.m_blend_src;
2093 current.m_blend_dst = self.m_blend_dst;
2096 if(!(state & RENDER_FILL)
2097 && self.m_linewidth != current.m_linewidth)
2099 glLineWidth(self.m_linewidth);
2100 GlobalOpenGL_debugAssertNoErrors();
2101 current.m_linewidth = self.m_linewidth;
2104 if(!(state & RENDER_FILL)
2105 && self.m_pointsize != current.m_pointsize)
2107 glPointSize(self.m_pointsize);
2108 GlobalOpenGL_debugAssertNoErrors();
2109 current.m_pointsize = self.m_pointsize;
2112 current.m_state = state;
2114 GlobalOpenGL_debugAssertNoErrors();
2117 void Renderables_flush(OpenGLStateBucket::Renderables& renderables, OpenGLState& current, unsigned int globalstate, const Vector3& viewer)
2119 const Matrix4* transform = 0;
2121 for(OpenGLStateBucket::Renderables::const_iterator i = renderables.begin(); i != renderables.end(); ++i)
2123 //qglLoadMatrixf(i->m_transform);
2124 if(!transform || (transform != (*i).m_transform && !matrix4_affine_equal(*transform, *(*i).m_transform)))
2127 transform = (*i).m_transform;
2130 glMultMatrixf(reinterpret_cast<const float*>(transform));
2131 glFrontFace(((current.m_state & RENDER_CULLFACE) != 0 && matrix4_handedness(*transform) == MATRIX4_RIGHTHANDED) ? GL_CW : GL_CCW);
2136 if(current.m_program != 0 && (*i).m_light != 0)
2138 const IShader& lightShader = static_cast<OpenGLShader*>((*i).m_light->getShader())->getShader();
2139 if(lightShader.firstLayer() != 0)
2141 GLuint attenuation_xy = lightShader.firstLayer()->texture()->texture_number;
2142 GLuint attenuation_z = lightShader.lightFalloffImage() != 0
2143 ? lightShader.lightFalloffImage()->texture_number
2144 : static_cast<OpenGLShader*>(g_defaultPointLight)->getShader().lightFalloffImage()->texture_number;
2146 setTextureState(current.m_texture3, attenuation_xy, GL_TEXTURE3);
2147 glActiveTexture(GL_TEXTURE3);
2148 glBindTexture(GL_TEXTURE_2D, attenuation_xy);
2149 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
2150 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
2152 setTextureState(current.m_texture4, attenuation_z, GL_TEXTURE4);
2153 glActiveTexture(GL_TEXTURE4);
2154 glBindTexture(GL_TEXTURE_2D, attenuation_z);
2155 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
2156 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2159 AABB lightBounds((*i).m_light->aabb());
2161 Matrix4 world2light(g_matrix4_identity);
2163 if((*i).m_light->isProjected())
2165 world2light = (*i).m_light->projection();
2166 matrix4_multiply_by_matrix4(world2light, matrix4_transposed((*i).m_light->rotation()));
2167 matrix4_translate_by_vec3(world2light, vector3_negated(lightBounds.origin)); // world->lightBounds
2169 if(!(*i).m_light->isProjected())
2171 matrix4_translate_by_vec3(world2light, Vector3(0.5f, 0.5f, 0.5f));
2172 matrix4_scale_by_vec3(world2light, Vector3(0.5f, 0.5f, 0.5f));
2173 matrix4_scale_by_vec3(world2light, Vector3(1.0f / lightBounds.extents.x(), 1.0f / lightBounds.extents.y(), 1.0f / lightBounds.extents.z()));
2174 matrix4_multiply_by_matrix4(world2light, matrix4_transposed((*i).m_light->rotation()));
2175 matrix4_translate_by_vec3(world2light, vector3_negated(lightBounds.origin)); // world->lightBounds
2178 current.m_program->setParameters(viewer, *(*i).m_transform, lightBounds.origin + (*i).m_light->offset(), (*i).m_light->colour(), world2light);
2179 debug_string("set lightBounds parameters");
2183 (*i).m_renderable->render(current.m_state);
2186 renderables.clear();
2189 void OpenGLStateBucket::render(OpenGLState& current, unsigned int globalstate, const Vector3& viewer)
2191 if((globalstate & m_state.m_state & RENDER_SCREEN) != 0)
2193 OpenGLState_apply(m_state, current, globalstate);
2194 debug_colour("screen fill");
2196 glMatrixMode(GL_PROJECTION);
2198 glLoadMatrixf(reinterpret_cast<const float*>(&g_matrix4_identity));
2200 glMatrixMode(GL_MODELVIEW);
2202 glLoadMatrixf(reinterpret_cast<const float*>(&g_matrix4_identity));
2205 glVertex3f(-1, -1, 0);
2206 glVertex3f(1, -1, 0);
2207 glVertex3f(1, 1, 0);
2208 glVertex3f(-1, 1, 0);
2211 glMatrixMode(GL_PROJECTION);
2214 glMatrixMode(GL_MODELVIEW);
2217 else if(!m_renderables.empty())
2219 OpenGLState_apply(m_state, current, globalstate);
2220 Renderables_flush(m_renderables, current, globalstate, viewer);
2225 class OpenGLStateMap : public OpenGLStateLibrary
2227 typedef std::map<CopiedString, OpenGLState> States;
2232 ASSERT_MESSAGE(m_states.empty(), "OpenGLStateMap::~OpenGLStateMap: not empty");
2235 typedef States::iterator iterator;
2238 return m_states.begin();
2242 return m_states.end();
2245 void getDefaultState(OpenGLState& state) const
2247 OpenGLState_constructDefault(state);
2250 void insert(const char* name, const OpenGLState& state)
2252 bool inserted = m_states.insert(States::value_type(name, state)).second;
2253 ASSERT_MESSAGE(inserted, "OpenGLStateMap::insert: " << name << " already exists");
2255 void erase(const char* name)
2257 std::size_t count = m_states.erase(name);
2258 ASSERT_MESSAGE(count == 1, "OpenGLStateMap::erase: " << name << " does not exist");
2261 iterator find(const char* name)
2263 return m_states.find(name);
2267 OpenGLStateMap* g_openglStates = 0;
2269 inline GLenum convertBlendFactor(BlendFactor factor)
2277 case BLEND_SRC_COLOUR:
2278 return GL_SRC_COLOR;
2279 case BLEND_ONE_MINUS_SRC_COLOUR:
2280 return GL_ONE_MINUS_SRC_COLOR;
2281 case BLEND_SRC_ALPHA:
2282 return GL_SRC_ALPHA;
2283 case BLEND_ONE_MINUS_SRC_ALPHA:
2284 return GL_ONE_MINUS_SRC_ALPHA;
2285 case BLEND_DST_COLOUR:
2286 return GL_DST_COLOR;
2287 case BLEND_ONE_MINUS_DST_COLOUR:
2288 return GL_ONE_MINUS_DST_COLOR;
2289 case BLEND_DST_ALPHA:
2290 return GL_DST_ALPHA;
2291 case BLEND_ONE_MINUS_DST_ALPHA:
2292 return GL_ONE_MINUS_DST_ALPHA;
2293 case BLEND_SRC_ALPHA_SATURATE:
2294 return GL_SRC_ALPHA_SATURATE;
2299 /// \todo Define special-case shaders in a data file.
2300 void OpenGLShader::construct(const char* name)
2302 OpenGLState& state = appendDefaultPass();
2306 sscanf(name, "(%g %g %g)", &state.m_colour[0], &state.m_colour[1], &state.m_colour[2]);
2307 state.m_colour[3] = 1.0f;
2308 state.m_state = RENDER_FILL|RENDER_LIGHTING|RENDER_DEPTHTEST|RENDER_CULLFACE|RENDER_COLOURWRITE|RENDER_DEPTHWRITE;
2309 state.m_sort = OpenGLState::eSortFullbright;
2313 sscanf(name, "[%g %g %g]", &state.m_colour[0], &state.m_colour[1], &state.m_colour[2]);
2314 state.m_colour[3] = 0.5f;
2315 state.m_state = RENDER_FILL|RENDER_LIGHTING|RENDER_DEPTHTEST|RENDER_CULLFACE|RENDER_COLOURWRITE|RENDER_DEPTHWRITE|RENDER_BLEND;
2316 state.m_sort = OpenGLState::eSortTranslucent;
2320 sscanf(name, "<%g %g %g>", &state.m_colour[0], &state.m_colour[1], &state.m_colour[2]);
2321 state.m_colour[3] = 1;
2322 state.m_state = RENDER_DEPTHTEST|RENDER_COLOURWRITE|RENDER_DEPTHWRITE;
2323 state.m_sort = OpenGLState::eSortFullbright;
2324 state.m_depthfunc = GL_LESS;
2325 state.m_linewidth = 1;
2326 state.m_pointsize = 1;
2331 OpenGLStateMap::iterator i = g_openglStates->find(name);
2332 if(i != g_openglStates->end())
2334 state = (*i).second;
2338 if(string_equal(name+1, "POINT"))
2340 state.m_state = RENDER_COLOURARRAY|RENDER_COLOURWRITE|RENDER_DEPTHWRITE;
2341 state.m_sort = OpenGLState::eSortControlFirst;
2342 state.m_pointsize = 4;
2344 else if(string_equal(name+1, "SELPOINT"))
2346 state.m_state = RENDER_COLOURARRAY|RENDER_COLOURWRITE|RENDER_DEPTHWRITE;
2347 state.m_sort = OpenGLState::eSortControlFirst + 1;
2348 state.m_pointsize = 4;
2350 else if(string_equal(name+1, "BIGPOINT"))
2352 state.m_state = RENDER_COLOURARRAY|RENDER_COLOURWRITE|RENDER_DEPTHWRITE;
2353 state.m_sort = OpenGLState::eSortControlFirst;
2354 state.m_pointsize = 6;
2356 else if(string_equal(name+1, "PIVOT"))
2358 state.m_state = RENDER_COLOURARRAY|RENDER_COLOURWRITE|RENDER_DEPTHTEST|RENDER_DEPTHWRITE;
2359 state.m_sort = OpenGLState::eSortGUI1;
2360 state.m_linewidth = 2;
2361 state.m_depthfunc = GL_LEQUAL;
2363 OpenGLState& hiddenLine = appendDefaultPass();
2364 hiddenLine.m_state = RENDER_COLOURARRAY|RENDER_COLOURWRITE|RENDER_DEPTHTEST|RENDER_LINESTIPPLE;
2365 hiddenLine.m_sort = OpenGLState::eSortGUI0;
2366 hiddenLine.m_linewidth = 2;
2367 hiddenLine.m_depthfunc = GL_GREATER;
2369 else if(string_equal(name+1, "LATTICE"))
2371 state.m_colour[0] = 1;
2372 state.m_colour[1] = 0.5;
2373 state.m_colour[2] = 0;
2374 state.m_colour[3] = 1;
2375 state.m_state = RENDER_COLOURWRITE|RENDER_DEPTHWRITE;
2376 state.m_sort = OpenGLState::eSortControlFirst;
2378 else if(string_equal(name+1, "WIREFRAME"))
2380 state.m_state = RENDER_DEPTHTEST|RENDER_COLOURWRITE|RENDER_DEPTHWRITE;
2381 state.m_sort = OpenGLState::eSortFullbright;
2383 else if(string_equal(name+1, "CAM_HIGHLIGHT"))
2385 state.m_colour[0] = 1;
2386 state.m_colour[1] = 0;
2387 state.m_colour[2] = 0;
2388 state.m_colour[3] = 0.3f;
2389 state.m_state = RENDER_FILL|RENDER_DEPTHTEST|RENDER_CULLFACE|RENDER_BLEND|RENDER_COLOURWRITE|RENDER_DEPTHWRITE;
2390 state.m_sort = OpenGLState::eSortHighlight;
2391 state.m_depthfunc = GL_LEQUAL;
2393 else if(string_equal(name+1, "CAM_OVERLAY"))
2396 state.m_state = RENDER_CULLFACE|RENDER_COLOURWRITE|RENDER_DEPTHWRITE;
2397 state.m_sort = OpenGLState::eSortOverlayFirst;
2399 state.m_state = RENDER_CULLFACE|RENDER_DEPTHTEST|RENDER_COLOURWRITE|RENDER_DEPTHWRITE|RENDER_OFFSETLINE;
2400 state.m_sort = OpenGLState::eSortOverlayFirst + 1;
2401 state.m_depthfunc = GL_LEQUAL;
2403 OpenGLState& hiddenLine = appendDefaultPass();
2404 hiddenLine.m_colour[0] = 0.75;
2405 hiddenLine.m_colour[1] = 0.75;
2406 hiddenLine.m_colour[2] = 0.75;
2407 hiddenLine.m_colour[3] = 1;
2408 hiddenLine.m_state = RENDER_CULLFACE|RENDER_DEPTHTEST|RENDER_COLOURWRITE|RENDER_OFFSETLINE|RENDER_LINESTIPPLE;
2409 hiddenLine.m_sort = OpenGLState::eSortOverlayFirst;
2410 hiddenLine.m_depthfunc = GL_GREATER;
2411 hiddenLine.m_linestipple_factor = 2;
2414 else if(string_equal(name+1, "XY_OVERLAY"))
2416 state.m_colour[0] = g_xywindow_globals.color_selbrushes[0];
2417 state.m_colour[1] = g_xywindow_globals.color_selbrushes[1];
2418 state.m_colour[2] = g_xywindow_globals.color_selbrushes[2];
2419 state.m_colour[3] = 1;
2420 state.m_state = RENDER_COLOURWRITE | RENDER_LINESTIPPLE;
2421 state.m_sort = OpenGLState::eSortOverlayFirst;
2422 state.m_linewidth = 2;
2423 state.m_linestipple_factor = 3;
2425 else if(string_equal(name+1, "DEBUG_CLIPPED"))
2427 state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE;
2428 state.m_sort = OpenGLState::eSortLast;
2430 else if(string_equal(name+1, "POINTFILE"))
2432 state.m_colour[0] = 1;
2433 state.m_colour[1] = 0;
2434 state.m_colour[2] = 0;
2435 state.m_colour[3] = 1;
2436 state.m_state = RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_DEPTHWRITE;
2437 state.m_sort = OpenGLState::eSortFullbright;
2438 state.m_linewidth = 4;
2440 else if(string_equal(name+1, "LIGHT_SPHERE"))
2442 state.m_colour[0] = .15f * .95f;
2443 state.m_colour[1] = .15f * .95f;
2444 state.m_colour[2] = .15f * .95f;
2445 state.m_colour[3] = 1;
2446 state.m_state = RENDER_CULLFACE | RENDER_DEPTHTEST | RENDER_BLEND | RENDER_FILL | RENDER_COLOURWRITE | RENDER_DEPTHWRITE;
2447 state.m_blend_src = GL_ONE;
2448 state.m_blend_dst = GL_ONE;
2449 state.m_sort = OpenGLState::eSortTranslucent;
2451 else if(string_equal(name+1, "Q3MAP2_LIGHT_SPHERE"))
2453 state.m_colour[0] = .05f;
2454 state.m_colour[1] = .05f;
2455 state.m_colour[2] = .05f;
2456 state.m_colour[3] = 1;
2457 state.m_state = RENDER_CULLFACE | RENDER_DEPTHTEST | RENDER_BLEND | RENDER_FILL;
2458 state.m_blend_src = GL_ONE;
2459 state.m_blend_dst = GL_ONE;
2460 state.m_sort = OpenGLState::eSortTranslucent;
2462 else if(string_equal(name+1, "WIRE_OVERLAY"))
2465 state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE;
2466 state.m_sort = OpenGLState::eSortOverlayFirst;
2468 state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE;
2469 state.m_sort = OpenGLState::eSortGUI1;
2470 state.m_depthfunc = GL_LEQUAL;
2472 OpenGLState& hiddenLine = appendDefaultPass();
2473 hiddenLine.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE | RENDER_LINESTIPPLE;
2474 hiddenLine.m_sort = OpenGLState::eSortGUI0;
2475 hiddenLine.m_depthfunc = GL_GREATER;
2478 else if(string_equal(name+1, "FLATSHADE_OVERLAY"))
2480 state.m_state = RENDER_CULLFACE | RENDER_LIGHTING | RENDER_SMOOTH | RENDER_SCALED | RENDER_COLOURARRAY | RENDER_FILL | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE;
2481 state.m_sort = OpenGLState::eSortGUI1;
2482 state.m_depthfunc = GL_LEQUAL;
2484 OpenGLState& hiddenLine = appendDefaultPass();
2485 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;
2486 hiddenLine.m_sort = OpenGLState::eSortGUI0;
2487 hiddenLine.m_depthfunc = GL_GREATER;
2489 else if(string_equal(name+1, "CLIPPER_OVERLAY"))
2491 state.m_colour[0] = g_xywindow_globals.color_clipper[0];
2492 state.m_colour[1] = g_xywindow_globals.color_clipper[1];
2493 state.m_colour[2] = g_xywindow_globals.color_clipper[2];
2494 state.m_colour[3] = 1;
2495 state.m_state = RENDER_CULLFACE | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_FILL | RENDER_POLYGONSTIPPLE;
2496 state.m_sort = OpenGLState::eSortOverlayFirst;
2498 else if(string_equal(name+1, "OVERBRIGHT"))
2500 const float lightScale = 2;
2501 state.m_colour[0] = lightScale * 0.5f;
2502 state.m_colour[1] = lightScale * 0.5f;
2503 state.m_colour[2] = lightScale * 0.5f;
2504 state.m_colour[3] = 0.5;
2505 state.m_state = RENDER_FILL|RENDER_BLEND|RENDER_COLOURWRITE|RENDER_SCREEN;
2506 state.m_sort = OpenGLState::eSortOverbrighten;
2507 state.m_blend_src = GL_DST_COLOR;
2508 state.m_blend_dst = GL_SRC_COLOR;
2512 // default to something recognisable.. =)
2513 ERROR_MESSAGE("hardcoded renderstate not found");
2514 state.m_colour[0] = 1;
2515 state.m_colour[1] = 0;
2516 state.m_colour[2] = 1;
2517 state.m_colour[3] = 1;
2518 state.m_state = RENDER_COLOURWRITE | RENDER_DEPTHWRITE;
2519 state.m_sort = OpenGLState::eSortFirst;
2523 // construction from IShader
2524 m_shader = QERApp_Shader_ForName(name);
2526 if(g_ShaderCache->lightingSupported() && g_ShaderCache->lightingEnabled() && m_shader->getBump() != 0 && m_shader->getBump()->texture_number != 0) // is a bump shader
2528 state.m_state = RENDER_FILL | RENDER_CULLFACE | RENDER_TEXTURE | RENDER_DEPTHTEST | RENDER_DEPTHWRITE | RENDER_COLOURWRITE | RENDER_PROGRAM;
2529 state.m_colour[0] = 0;
2530 state.m_colour[1] = 0;
2531 state.m_colour[2] = 0;
2532 state.m_colour[3] = 1;
2533 state.m_sort = OpenGLState::eSortOpaque;
2535 if(g_ShaderCache->useShaderLanguage())
2537 state.m_program = &g_depthFillGLSL;
2541 state.m_program = &g_depthFillARB;
2544 OpenGLState& bumpPass = appendDefaultPass();
2545 bumpPass.m_texture = m_shader->getDiffuse()->texture_number;
2546 bumpPass.m_texture1 = m_shader->getBump()->texture_number;
2547 bumpPass.m_texture2 = m_shader->getSpecular()->texture_number;
2549 bumpPass.m_state = RENDER_BLEND|RENDER_FILL|RENDER_CULLFACE|RENDER_DEPTHTEST|RENDER_COLOURWRITE|RENDER_SMOOTH|RENDER_BUMP|RENDER_PROGRAM;
2551 if(g_ShaderCache->useShaderLanguage())
2553 bumpPass.m_state |= RENDER_LIGHTING;
2554 bumpPass.m_program = &g_bumpGLSL;
2558 bumpPass.m_program = &g_bumpARB;
2561 bumpPass.m_depthfunc = GL_LEQUAL;
2562 bumpPass.m_sort = OpenGLState::eSortMultiFirst;
2563 bumpPass.m_blend_src = GL_ONE;
2564 bumpPass.m_blend_dst = GL_ONE;
2568 state.m_texture = m_shader->getTexture()->texture_number;
2570 state.m_state = RENDER_FILL|RENDER_TEXTURE|RENDER_DEPTHTEST|RENDER_COLOURWRITE|RENDER_LIGHTING|RENDER_SMOOTH;
2571 if((m_shader->getFlags() & QER_CULL) != 0)
2573 if(m_shader->getCull() == IShader::eCullBack)
2575 state.m_state |= RENDER_CULLFACE;
2580 state.m_state |= RENDER_CULLFACE;
2582 if((m_shader->getFlags() & QER_ALPHATEST) != 0)
2584 state.m_state |= RENDER_ALPHATEST;
2585 IShader::EAlphaFunc alphafunc;
2586 m_shader->getAlphaFunc(&alphafunc, &state.m_alpharef);
2589 case IShader::eAlways:
2590 state.m_alphafunc = GL_ALWAYS;
2591 case IShader::eEqual:
2592 state.m_alphafunc = GL_EQUAL;
2593 case IShader::eLess:
2594 state.m_alphafunc = GL_LESS;
2595 case IShader::eGreater:
2596 state.m_alphafunc = GL_GREATER;
2597 case IShader::eLEqual:
2598 state.m_alphafunc = GL_LEQUAL;
2599 case IShader::eGEqual:
2600 state.m_alphafunc = GL_GEQUAL;
2603 reinterpret_cast<Vector3&>(state.m_colour) = m_shader->getTexture()->color;
2604 state.m_colour[3] = 1.0f;
2606 if((m_shader->getFlags() & QER_TRANS) != 0)
2608 state.m_state |= RENDER_BLEND;
2609 state.m_colour[3] = m_shader->getTrans();
2610 state.m_sort = OpenGLState::eSortTranslucent;
2611 BlendFunc blendFunc = m_shader->getBlendFunc();
2612 state.m_blend_src = convertBlendFactor(blendFunc.m_src);
2613 state.m_blend_dst = convertBlendFactor(blendFunc.m_dst);
2614 if(state.m_blend_src == GL_SRC_ALPHA || state.m_blend_dst == GL_SRC_ALPHA)
2616 state.m_state |= RENDER_DEPTHWRITE;
2621 state.m_state |= RENDER_DEPTHWRITE;
2622 state.m_sort = OpenGLState::eSortFullbright;
2629 #include "modulesystem/singletonmodule.h"
2630 #include "modulesystem/moduleregistry.h"
2632 class OpenGLStateLibraryAPI
2634 OpenGLStateMap m_stateMap;
2636 typedef OpenGLStateLibrary Type;
2637 STRING_CONSTANT(Name, "*");
2639 OpenGLStateLibraryAPI()
2641 g_openglStates = &m_stateMap;
2643 ~OpenGLStateLibraryAPI()
2647 OpenGLStateLibrary* getTable()
2653 typedef SingletonModule<OpenGLStateLibraryAPI> OpenGLStateLibraryModule;
2654 typedef Static<OpenGLStateLibraryModule> StaticOpenGLStateLibraryModule;
2655 StaticRegisterModule staticRegisterOpenGLStateLibrary(StaticOpenGLStateLibraryModule::instance());
2657 class ShaderCacheDependencies : public GlobalShadersModuleRef, public GlobalTexturesModuleRef, public GlobalOpenGLStateLibraryModuleRef
2660 ShaderCacheDependencies() :
2661 GlobalShadersModuleRef(GlobalRadiant().getRequiredGameDescriptionKeyValue("shaders"))
2666 class ShaderCacheAPI
2668 ShaderCache* m_shaderCache;
2670 typedef ShaderCache Type;
2671 STRING_CONSTANT(Name, "*");
2675 ShaderCache_Construct();
2677 m_shaderCache = GetShaderCache();
2681 ShaderCache_Destroy();
2683 ShaderCache* getTable()
2685 return m_shaderCache;
2689 typedef SingletonModule<ShaderCacheAPI, ShaderCacheDependencies> ShaderCacheModule;
2690 typedef Static<ShaderCacheModule> StaticShaderCacheModule;
2691 StaticRegisterModule staticRegisterShaderCache(StaticShaderCacheModule::instance());