X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fnetradiant.git;a=blobdiff_plain;f=radiant%2Frenderstate.cpp;h=faa04502e1ff524033d19c5c0d1bd0053d9bb936;hp=9dc8e2de0a2136076eea4e0789036b1e2b437d78;hb=9dfae1c9b270ee369c6362903a9205b30751b95f;hpb=0a6d5683b0cfa1a0bd7ef64bada105dbe4ddd6e1 diff --git a/radiant/renderstate.cpp b/radiant/renderstate.cpp index 9dc8e2de..faa04502 100644 --- a/radiant/renderstate.cpp +++ b/radiant/renderstate.cpp @@ -54,24 +54,26 @@ #include "xywindow.h" - #define DEBUG_RENDER 0 -inline void debug_string( const char* string ){ +inline void debug_string(const char *string) +{ #if (DEBUG_RENDER) - globalOutputStream() << string << "\n"; + globalOutputStream() << string << "\n"; #endif } -inline void debug_int( const char* comment, int i ){ +inline void debug_int(const char *comment, int i) +{ #if (DEBUG_RENDER) - globalOutputStream() << comment << " " << i << "\n"; + globalOutputStream() << comment << " " << i << "\n"; #endif } -inline void debug_colour( const char* comment ){ -#if ( DEBUG_RENDER ) - Vector4 v; +inline void debug_colour(const char *comment) +{ +#if (DEBUG_RENDER) + Vector4 v; glGetFloatv( GL_CURRENT_COLOR, reinterpret_cast( &v ) ); globalOutputStream() << comment << " colour: " << v[0] << " " @@ -96,275 +98,298 @@ std::size_t g_count_states; std::size_t g_count_transforms; Timer g_timer; -inline void count_prim(){ - ++g_count_prims; +inline void count_prim() +{ + ++g_count_prims; } -inline void count_state(){ - ++g_count_states; +inline void count_state() +{ + ++g_count_states; } -inline void count_transform(){ - ++g_count_transforms; +inline void count_transform() +{ + ++g_count_transforms; } -void Renderer_ResetStats(){ - g_count_prims = 0; - g_count_states = 0; - g_count_transforms = 0; - g_timer.start(); +void Renderer_ResetStats() +{ + g_count_prims = 0; + g_count_states = 0; + g_count_transforms = 0; + g_timer.start(); } -const char* Renderer_GetStats(){ - g_renderer_stats.clear(); - g_renderer_stats << "prims: " << Unsigned( g_count_prims ) - << " | states: " << Unsigned( g_count_states ) - << " | transforms: " << Unsigned( g_count_transforms ) - << " | msec: " << g_timer.elapsed_msec(); - return g_renderer_stats.c_str(); +const char *Renderer_GetStats() +{ + g_renderer_stats.clear(); + g_renderer_stats << "prims: " << Unsigned(g_count_prims) + << " | states: " << Unsigned(g_count_states) + << " | transforms: " << Unsigned(g_count_transforms) + << " | msec: " << g_timer.elapsed_msec(); + return g_renderer_stats.c_str(); } -void printShaderLog( GLhandleARB object ){ - GLint log_length = 0; - glGetObjectParameterivARB( object, GL_OBJECT_INFO_LOG_LENGTH_ARB, &log_length ); +void printShaderLog(GLhandleARB object) +{ + GLint log_length = 0; + glGetObjectParameterivARB(object, GL_OBJECT_INFO_LOG_LENGTH_ARB, &log_length); - Array log( log_length ); - glGetInfoLogARB( object, log_length, &log_length, log.data() ); + Array log(log_length); + glGetInfoLogARB(object, log_length, &log_length, log.data()); - globalErrorStream() << StringRange( log.begin(), log.begin() + log_length ) << "\n"; + globalErrorStream() << StringRange(log.begin(), log.begin() + log_length) << "\n"; } -void createShader( GLhandleARB program, const char* filename, GLenum type ){ - GLhandleARB shader = glCreateShaderObjectARB( type ); - GlobalOpenGL_debugAssertNoErrors(); +void createShader(GLhandleARB program, const char *filename, GLenum type) +{ + GLhandleARB shader = glCreateShaderObjectARB(type); + GlobalOpenGL_debugAssertNoErrors(); - // load shader - { - std::size_t size = file_size( filename ); - FileInputStream file( filename ); - ASSERT_MESSAGE( !file.failed(), "failed to open " << makeQuoted( filename ) ); - Array buffer( size ); - size = file.read( reinterpret_cast( buffer.data() ), size ); - - const GLcharARB* string = buffer.data(); - GLint length = GLint( size ); - glShaderSourceARB( shader, 1, &string, &length ); - } + // load shader + { + std::size_t size = file_size(filename); + FileInputStream file(filename); + ASSERT_MESSAGE(!file.failed(), "failed to open " << makeQuoted(filename)); + Array buffer(size); + size = file.read(reinterpret_cast( buffer.data()), size); - // compile shader - { - glCompileShaderARB( shader ); + const GLcharARB *string = buffer.data(); + GLint length = GLint(size); + glShaderSourceARB(shader, 1, &string, &length); + } - GLint compiled = 0; - glGetObjectParameterivARB( shader, GL_OBJECT_COMPILE_STATUS_ARB, &compiled ); + // compile shader + { + glCompileShaderARB(shader); - if ( !compiled ) { - printShaderLog( shader ); - } + GLint compiled = 0; + glGetObjectParameterivARB(shader, GL_OBJECT_COMPILE_STATUS_ARB, &compiled); - ASSERT_MESSAGE( compiled, "shader compile failed: " << makeQuoted( filename ) ); - } + if (!compiled) { + printShaderLog(shader); + } - // attach shader - glAttachObjectARB( program, shader ); + ASSERT_MESSAGE(compiled, "shader compile failed: " << makeQuoted(filename)); + } - glDeleteObjectARB( shader ); + // attach shader + glAttachObjectARB(program, shader); - GlobalOpenGL_debugAssertNoErrors(); + glDeleteObjectARB(shader); + + GlobalOpenGL_debugAssertNoErrors(); } -void GLSLProgram_link( GLhandleARB program ){ - glLinkProgramARB( program ); +void GLSLProgram_link(GLhandleARB program) +{ + glLinkProgramARB(program); - GLint linked = false; - glGetObjectParameterivARB( program, GL_OBJECT_LINK_STATUS_ARB, &linked ); + GLint linked = false; + glGetObjectParameterivARB(program, GL_OBJECT_LINK_STATUS_ARB, &linked); - if ( !linked ) { - printShaderLog( program ); - } + if (!linked) { + printShaderLog(program); + } - ASSERT_MESSAGE( linked, "program link failed" ); + ASSERT_MESSAGE(linked, "program link failed"); } -void GLSLProgram_validate( GLhandleARB program ){ - glValidateProgramARB( program ); +void GLSLProgram_validate(GLhandleARB program) +{ + glValidateProgramARB(program); - GLint validated = false; - glGetObjectParameterivARB( program, GL_OBJECT_VALIDATE_STATUS_ARB, &validated ); + GLint validated = false; + glGetObjectParameterivARB(program, GL_OBJECT_VALIDATE_STATUS_ARB, &validated); - if ( !validated ) { - printShaderLog( program ); - } + if (!validated) { + printShaderLog(program); + } - ASSERT_MESSAGE( validated, "program validation failed" ); + ASSERT_MESSAGE(validated, "program validation failed"); } bool g_bumpGLSLPass_enabled = false; bool g_depthfillPass_enabled = false; -class GLSLBumpProgram : public GLProgram -{ +class GLSLBumpProgram : public GLProgram { public: -GLhandleARB m_program; -qtexture_t* m_light_attenuation_xy; -qtexture_t* m_light_attenuation_z; -GLint u_view_origin; -GLint u_light_origin; -GLint u_light_color; -GLint u_bump_scale; -GLint u_specular_exponent; - -GLSLBumpProgram() : m_program( 0 ), m_light_attenuation_xy( 0 ), m_light_attenuation_z( 0 ){ -} - -void create(){ - // create program - m_program = glCreateProgramObjectARB(); - - // create shader - { - StringOutputStream filename( 256 ); - filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_vp.glsl"; - createShader( m_program, filename.c_str(), GL_VERTEX_SHADER_ARB ); - filename.clear(); - filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_fp.glsl"; - createShader( m_program, filename.c_str(), GL_FRAGMENT_SHADER_ARB ); - } + GLhandleARB m_program; + qtexture_t *m_light_attenuation_xy; + qtexture_t *m_light_attenuation_z; + GLint u_view_origin; + GLint u_light_origin; + GLint u_light_color; + GLint u_bump_scale; + GLint u_specular_exponent; + + GLSLBumpProgram() : m_program(0), m_light_attenuation_xy(0), m_light_attenuation_z(0) + { + } + + void create() + { + // create program + m_program = glCreateProgramObjectARB(); + + // create shader + { + StringOutputStream filename(256); + filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_vp.glsl"; + createShader(m_program, filename.c_str(), GL_VERTEX_SHADER_ARB); + filename.clear(); + filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_fp.glsl"; + createShader(m_program, filename.c_str(), GL_FRAGMENT_SHADER_ARB); + } + + GLSLProgram_link(m_program); + GLSLProgram_validate(m_program); + + glUseProgramObjectARB(m_program); + + glBindAttribLocationARB(m_program, c_attr_TexCoord0, "attr_TexCoord0"); + glBindAttribLocationARB(m_program, c_attr_Tangent, "attr_Tangent"); + glBindAttribLocationARB(m_program, c_attr_Binormal, "attr_Binormal"); + + glUniform1iARB(glGetUniformLocationARB(m_program, "u_diffusemap"), 0); + glUniform1iARB(glGetUniformLocationARB(m_program, "u_bumpmap"), 1); + glUniform1iARB(glGetUniformLocationARB(m_program, "u_specularmap"), 2); + glUniform1iARB(glGetUniformLocationARB(m_program, "u_attenuationmap_xy"), 3); + glUniform1iARB(glGetUniformLocationARB(m_program, "u_attenuationmap_z"), 4); + + u_view_origin = glGetUniformLocationARB(m_program, "u_view_origin"); + u_light_origin = glGetUniformLocationARB(m_program, "u_light_origin"); + u_light_color = glGetUniformLocationARB(m_program, "u_light_color"); + u_bump_scale = glGetUniformLocationARB(m_program, "u_bump_scale"); + u_specular_exponent = glGetUniformLocationARB(m_program, "u_specular_exponent"); + + glUseProgramObjectARB(0); + + GlobalOpenGL_debugAssertNoErrors(); + } + + void destroy() + { + glDeleteObjectARB(m_program); + m_program = 0; + } + + void enable() + { + glUseProgramObjectARB(m_program); + + glEnableVertexAttribArrayARB(c_attr_TexCoord0); + glEnableVertexAttribArrayARB(c_attr_Tangent); + glEnableVertexAttribArrayARB(c_attr_Binormal); + + GlobalOpenGL_debugAssertNoErrors(); + + debug_string("enable bump"); + g_bumpGLSLPass_enabled = true; + } + + void disable() + { + glUseProgramObjectARB(0); + + glDisableVertexAttribArrayARB(c_attr_TexCoord0); + glDisableVertexAttribArrayARB(c_attr_Tangent); + glDisableVertexAttribArrayARB(c_attr_Binormal); + + GlobalOpenGL_debugAssertNoErrors(); + + debug_string("disable bump"); + g_bumpGLSLPass_enabled = false; + } + + void setParameters(const Vector3 &viewer, const Matrix4 &localToWorld, const Vector3 &origin, const Vector3 &colour, + const Matrix4 &world2light) + { + Matrix4 world2local(localToWorld); + matrix4_affine_invert(world2local); + + Vector3 localLight(origin); + matrix4_transform_point(world2local, localLight); + + Vector3 localViewer(viewer); + matrix4_transform_point(world2local, localViewer); + + Matrix4 local2light(world2light); + matrix4_multiply_by_matrix4(local2light, localToWorld); // local->world->light + + glUniform3fARB(u_view_origin, localViewer.x(), localViewer.y(), localViewer.z()); + glUniform3fARB(u_light_origin, localLight.x(), localLight.y(), localLight.z()); + glUniform3fARB(u_light_color, colour.x(), colour.y(), colour.z()); + glUniform1fARB(u_bump_scale, 1.0); + glUniform1fARB(u_specular_exponent, 32.0); - GLSLProgram_link( m_program ); - GLSLProgram_validate( m_program ); + glActiveTexture(GL_TEXTURE3); + glClientActiveTexture(GL_TEXTURE3); - glUseProgramObjectARB( m_program ); - - glBindAttribLocationARB( m_program, c_attr_TexCoord0, "attr_TexCoord0" ); - glBindAttribLocationARB( m_program, c_attr_Tangent, "attr_Tangent" ); - glBindAttribLocationARB( m_program, c_attr_Binormal, "attr_Binormal" ); - - glUniform1iARB( glGetUniformLocationARB( m_program, "u_diffusemap" ), 0 ); - glUniform1iARB( glGetUniformLocationARB( m_program, "u_bumpmap" ), 1 ); - glUniform1iARB( glGetUniformLocationARB( m_program, "u_specularmap" ), 2 ); - glUniform1iARB( glGetUniformLocationARB( m_program, "u_attenuationmap_xy" ), 3 ); - glUniform1iARB( glGetUniformLocationARB( m_program, "u_attenuationmap_z" ), 4 ); - - u_view_origin = glGetUniformLocationARB( m_program, "u_view_origin" ); - u_light_origin = glGetUniformLocationARB( m_program, "u_light_origin" ); - u_light_color = glGetUniformLocationARB( m_program, "u_light_color" ); - u_bump_scale = glGetUniformLocationARB( m_program, "u_bump_scale" ); - u_specular_exponent = glGetUniformLocationARB( m_program, "u_specular_exponent" ); - - glUseProgramObjectARB( 0 ); - - GlobalOpenGL_debugAssertNoErrors(); -} - -void destroy(){ - glDeleteObjectARB( m_program ); - m_program = 0; -} - -void enable(){ - glUseProgramObjectARB( m_program ); - - glEnableVertexAttribArrayARB( c_attr_TexCoord0 ); - glEnableVertexAttribArrayARB( c_attr_Tangent ); - glEnableVertexAttribArrayARB( c_attr_Binormal ); - - GlobalOpenGL_debugAssertNoErrors(); - - debug_string( "enable bump" ); - g_bumpGLSLPass_enabled = true; -} - -void disable(){ - glUseProgramObjectARB( 0 ); - - glDisableVertexAttribArrayARB( c_attr_TexCoord0 ); - glDisableVertexAttribArrayARB( c_attr_Tangent ); - glDisableVertexAttribArrayARB( c_attr_Binormal ); - - GlobalOpenGL_debugAssertNoErrors(); - - debug_string( "disable bump" ); - g_bumpGLSLPass_enabled = false; -} - -void setParameters( const Vector3& viewer, const Matrix4& localToWorld, const Vector3& origin, const Vector3& colour, const Matrix4& world2light ){ - Matrix4 world2local( localToWorld ); - matrix4_affine_invert( world2local ); - - Vector3 localLight( origin ); - matrix4_transform_point( world2local, localLight ); - - Vector3 localViewer( viewer ); - matrix4_transform_point( world2local, localViewer ); - - Matrix4 local2light( world2light ); - matrix4_multiply_by_matrix4( local2light, localToWorld ); // local->world->light - - glUniform3fARB( u_view_origin, localViewer.x(), localViewer.y(), localViewer.z() ); - glUniform3fARB( u_light_origin, localLight.x(), localLight.y(), localLight.z() ); - glUniform3fARB( u_light_color, colour.x(), colour.y(), colour.z() ); - glUniform1fARB( u_bump_scale, 1.0 ); - glUniform1fARB( u_specular_exponent, 32.0 ); - - glActiveTexture( GL_TEXTURE3 ); - glClientActiveTexture( GL_TEXTURE3 ); - - glMatrixMode( GL_TEXTURE ); - glLoadMatrixf( reinterpret_cast( &local2light ) ); - glMatrixMode( GL_MODELVIEW ); + glMatrixMode(GL_TEXTURE); + glLoadMatrixf(reinterpret_cast( &local2light )); + glMatrixMode(GL_MODELVIEW); - GlobalOpenGL_debugAssertNoErrors(); -} + GlobalOpenGL_debugAssertNoErrors(); + } }; GLSLBumpProgram g_bumpGLSL; -class GLSLDepthFillProgram : public GLProgram -{ +class GLSLDepthFillProgram : public GLProgram { public: -GLhandleARB m_program; - -void create(){ - // create program - m_program = glCreateProgramObjectARB(); - - // create shader - { - StringOutputStream filename( 256 ); - filename << GlobalRadiant().getAppPath() << "gl/zfill_vp.glsl"; - createShader( m_program, filename.c_str(), GL_VERTEX_SHADER_ARB ); - filename.clear(); - filename << GlobalRadiant().getAppPath() << "gl/zfill_fp.glsl"; - createShader( m_program, filename.c_str(), GL_FRAGMENT_SHADER_ARB ); - } - - GLSLProgram_link( m_program ); - GLSLProgram_validate( m_program ); - - GlobalOpenGL_debugAssertNoErrors(); -} - -void destroy(){ - glDeleteObjectARB( m_program ); - m_program = 0; -} -void enable(){ - glUseProgramObjectARB( m_program ); - GlobalOpenGL_debugAssertNoErrors(); - debug_string( "enable depthfill" ); - g_depthfillPass_enabled = true; -} -void disable(){ - glUseProgramObjectARB( 0 ); - GlobalOpenGL_debugAssertNoErrors(); - debug_string( "disable depthfill" ); - g_depthfillPass_enabled = false; -} -void setParameters( const Vector3& viewer, const Matrix4& localToWorld, const Vector3& origin, const Vector3& colour, const Matrix4& world2light ){ -} + GLhandleARB m_program; + + void create() + { + // create program + m_program = glCreateProgramObjectARB(); + + // create shader + { + StringOutputStream filename(256); + filename << GlobalRadiant().getAppPath() << "gl/zfill_vp.glsl"; + createShader(m_program, filename.c_str(), GL_VERTEX_SHADER_ARB); + filename.clear(); + filename << GlobalRadiant().getAppPath() << "gl/zfill_fp.glsl"; + createShader(m_program, filename.c_str(), GL_FRAGMENT_SHADER_ARB); + } + + GLSLProgram_link(m_program); + GLSLProgram_validate(m_program); + + GlobalOpenGL_debugAssertNoErrors(); + } + + void destroy() + { + glDeleteObjectARB(m_program); + m_program = 0; + } + + void enable() + { + glUseProgramObjectARB(m_program); + GlobalOpenGL_debugAssertNoErrors(); + debug_string("enable depthfill"); + g_depthfillPass_enabled = true; + } + + void disable() + { + glUseProgramObjectARB(0); + GlobalOpenGL_debugAssertNoErrors(); + debug_string("disable depthfill"); + g_depthfillPass_enabled = false; + } + + void setParameters(const Vector3 &viewer, const Matrix4 &localToWorld, const Vector3 &origin, const Vector3 &colour, + const Matrix4 &world2light) + { + } }; GLSLDepthFillProgram g_depthFillGLSL; @@ -372,182 +397,194 @@ GLSLDepthFillProgram g_depthFillGLSL; // ARB path -void createProgram( const char* filename, GLenum type ){ - std::size_t size = file_size( filename ); - FileInputStream file( filename ); - ASSERT_MESSAGE( !file.failed(), "failed to open " << makeQuoted( filename ) ); - Array buffer( size ); - size = file.read( reinterpret_cast( buffer.data() ), size ); +void createProgram(const char *filename, GLenum type) +{ + std::size_t size = file_size(filename); + FileInputStream file(filename); + ASSERT_MESSAGE(!file.failed(), "failed to open " << makeQuoted(filename)); + Array buffer(size); + size = file.read(reinterpret_cast( buffer.data()), size); - glProgramStringARB( type, GL_PROGRAM_FORMAT_ASCII_ARB, GLsizei( size ), buffer.data() ); + glProgramStringARB(type, GL_PROGRAM_FORMAT_ASCII_ARB, GLsizei(size), buffer.data()); - if ( GL_INVALID_OPERATION == glGetError() ) { - GLint errPos; - glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos ); - const GLubyte* errString = glGetString( GL_PROGRAM_ERROR_STRING_ARB ); + if (GL_INVALID_OPERATION == glGetError()) { + GLint errPos; + glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos); + const GLubyte *errString = glGetString(GL_PROGRAM_ERROR_STRING_ARB); - globalErrorStream() << reinterpret_cast( filename ) << ":" << errPos << "\n" << reinterpret_cast( errString ); + globalErrorStream() << reinterpret_cast( filename ) << ":" << errPos << "\n" + << reinterpret_cast( errString ); - ERROR_MESSAGE( "error in gl program" ); - } + ERROR_MESSAGE("error in gl program"); + } } -class ARBBumpProgram : public GLProgram -{ +class ARBBumpProgram : public GLProgram { public: -GLuint m_vertex_program; -GLuint m_fragment_program; + GLuint m_vertex_program; + GLuint m_fragment_program; -void create(){ - glEnable( GL_VERTEX_PROGRAM_ARB ); - glEnable( GL_FRAGMENT_PROGRAM_ARB ); + void create() + { + glEnable(GL_VERTEX_PROGRAM_ARB); + glEnable(GL_FRAGMENT_PROGRAM_ARB); - { - glGenProgramsARB( 1, &m_vertex_program ); - glBindProgramARB( GL_VERTEX_PROGRAM_ARB, m_vertex_program ); - StringOutputStream filename( 256 ); - filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_vp.glp"; - createProgram( filename.c_str(), GL_VERTEX_PROGRAM_ARB ); + { + glGenProgramsARB(1, &m_vertex_program); + glBindProgramARB(GL_VERTEX_PROGRAM_ARB, m_vertex_program); + StringOutputStream filename(256); + filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_vp.glp"; + createProgram(filename.c_str(), GL_VERTEX_PROGRAM_ARB); - glGenProgramsARB( 1, &m_fragment_program ); - glBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, m_fragment_program ); - filename.clear(); - filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_fp.glp"; - createProgram( filename.c_str(), GL_FRAGMENT_PROGRAM_ARB ); - } + glGenProgramsARB(1, &m_fragment_program); + glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, m_fragment_program); + filename.clear(); + filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_fp.glp"; + createProgram(filename.c_str(), GL_FRAGMENT_PROGRAM_ARB); + } - glDisable( GL_VERTEX_PROGRAM_ARB ); - glDisable( GL_FRAGMENT_PROGRAM_ARB ); + glDisable(GL_VERTEX_PROGRAM_ARB); + glDisable(GL_FRAGMENT_PROGRAM_ARB); - GlobalOpenGL_debugAssertNoErrors(); -} + GlobalOpenGL_debugAssertNoErrors(); + } -void destroy(){ - glDeleteProgramsARB( 1, &m_vertex_program ); - glDeleteProgramsARB( 1, &m_fragment_program ); - GlobalOpenGL_debugAssertNoErrors(); -} + void destroy() + { + glDeleteProgramsARB(1, &m_vertex_program); + glDeleteProgramsARB(1, &m_fragment_program); + GlobalOpenGL_debugAssertNoErrors(); + } -void enable(){ - glEnable( GL_VERTEX_PROGRAM_ARB ); - glEnable( GL_FRAGMENT_PROGRAM_ARB ); - glBindProgramARB( GL_VERTEX_PROGRAM_ARB, m_vertex_program ); - glBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, m_fragment_program ); + void enable() + { + glEnable(GL_VERTEX_PROGRAM_ARB); + glEnable(GL_FRAGMENT_PROGRAM_ARB); + glBindProgramARB(GL_VERTEX_PROGRAM_ARB, m_vertex_program); + glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, m_fragment_program); - glEnableVertexAttribArrayARB( 8 ); - glEnableVertexAttribArrayARB( 9 ); - glEnableVertexAttribArrayARB( 10 ); - glEnableVertexAttribArrayARB( 11 ); + glEnableVertexAttribArrayARB(8); + glEnableVertexAttribArrayARB(9); + glEnableVertexAttribArrayARB(10); + glEnableVertexAttribArrayARB(11); - GlobalOpenGL_debugAssertNoErrors(); -} + GlobalOpenGL_debugAssertNoErrors(); + } -void disable(){ - glDisable( GL_VERTEX_PROGRAM_ARB ); - glDisable( GL_FRAGMENT_PROGRAM_ARB ); + void disable() + { + glDisable(GL_VERTEX_PROGRAM_ARB); + glDisable(GL_FRAGMENT_PROGRAM_ARB); - glDisableVertexAttribArrayARB( 8 ); - glDisableVertexAttribArrayARB( 9 ); - glDisableVertexAttribArrayARB( 10 ); - glDisableVertexAttribArrayARB( 11 ); + glDisableVertexAttribArrayARB(8); + glDisableVertexAttribArrayARB(9); + glDisableVertexAttribArrayARB(10); + glDisableVertexAttribArrayARB(11); - GlobalOpenGL_debugAssertNoErrors(); -} + GlobalOpenGL_debugAssertNoErrors(); + } -void setParameters( const Vector3& viewer, const Matrix4& localToWorld, const Vector3& origin, const Vector3& colour, const Matrix4& world2light ){ - Matrix4 world2local( localToWorld ); - matrix4_affine_invert( world2local ); + void setParameters(const Vector3 &viewer, const Matrix4 &localToWorld, const Vector3 &origin, const Vector3 &colour, + const Matrix4 &world2light) + { + Matrix4 world2local(localToWorld); + matrix4_affine_invert(world2local); - Vector3 localLight( origin ); - matrix4_transform_point( world2local, localLight ); + Vector3 localLight(origin); + matrix4_transform_point(world2local, localLight); - Vector3 localViewer( viewer ); - matrix4_transform_point( world2local, localViewer ); + Vector3 localViewer(viewer); + matrix4_transform_point(world2local, localViewer); - Matrix4 local2light( world2light ); - matrix4_multiply_by_matrix4( local2light, localToWorld ); // local->world->light + Matrix4 local2light(world2light); + matrix4_multiply_by_matrix4(local2light, localToWorld); // local->world->light - // view origin - glProgramLocalParameter4fARB( GL_FRAGMENT_PROGRAM_ARB, 4, localViewer.x(), localViewer.y(), localViewer.z(), 0 ); + // view origin + glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 4, localViewer.x(), localViewer.y(), localViewer.z(), 0); - // light origin - glProgramLocalParameter4fARB( GL_FRAGMENT_PROGRAM_ARB, 2, localLight.x(), localLight.y(), localLight.z(), 1 ); + // light origin + glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 2, localLight.x(), localLight.y(), localLight.z(), 1); - // light colour - glProgramLocalParameter4fARB( GL_FRAGMENT_PROGRAM_ARB, 3, colour.x(), colour.y(), colour.z(), 0 ); + // light colour + glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 3, colour.x(), colour.y(), colour.z(), 0); - // bump scale - glProgramLocalParameter4fARB( GL_FRAGMENT_PROGRAM_ARB, 1, 1, 0, 0, 0 ); + // bump scale + glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, 1, 0, 0, 0); - // specular exponent - glProgramLocalParameter4fARB( GL_FRAGMENT_PROGRAM_ARB, 5, 32, 0, 0, 0 ); + // specular exponent + glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 5, 32, 0, 0, 0); - glActiveTexture( GL_TEXTURE3 ); - glClientActiveTexture( GL_TEXTURE3 ); + glActiveTexture(GL_TEXTURE3); + glClientActiveTexture(GL_TEXTURE3); - glMatrixMode( GL_TEXTURE ); - glLoadMatrixf( reinterpret_cast( &local2light ) ); - glMatrixMode( GL_MODELVIEW ); + glMatrixMode(GL_TEXTURE); + glLoadMatrixf(reinterpret_cast( &local2light )); + glMatrixMode(GL_MODELVIEW); - GlobalOpenGL_debugAssertNoErrors(); -} + GlobalOpenGL_debugAssertNoErrors(); + } }; -class ARBDepthFillProgram : public GLProgram -{ +class ARBDepthFillProgram : public GLProgram { public: -GLuint m_vertex_program; -GLuint m_fragment_program; - -void create(){ - glEnable( GL_VERTEX_PROGRAM_ARB ); - glEnable( GL_FRAGMENT_PROGRAM_ARB ); - - { - glGenProgramsARB( 1, &m_vertex_program ); - glBindProgramARB( GL_VERTEX_PROGRAM_ARB, m_vertex_program ); - StringOutputStream filename( 256 ); - filename << GlobalRadiant().getAppPath() << "gl/zfill_vp.glp"; - createProgram( filename.c_str(), GL_VERTEX_PROGRAM_ARB ); - - glGenProgramsARB( 1, &m_fragment_program ); - glBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, m_fragment_program ); - filename.clear(); - filename << GlobalRadiant().getAppPath() << "gl/zfill_fp.glp"; - createProgram( filename.c_str(), GL_FRAGMENT_PROGRAM_ARB ); - } - - glDisable( GL_VERTEX_PROGRAM_ARB ); - glDisable( GL_FRAGMENT_PROGRAM_ARB ); - - GlobalOpenGL_debugAssertNoErrors(); -} - -void destroy(){ - glDeleteProgramsARB( 1, &m_vertex_program ); - glDeleteProgramsARB( 1, &m_fragment_program ); - GlobalOpenGL_debugAssertNoErrors(); -} - -void enable(){ - glEnable( GL_VERTEX_PROGRAM_ARB ); - glEnable( GL_FRAGMENT_PROGRAM_ARB ); - glBindProgramARB( GL_VERTEX_PROGRAM_ARB, m_vertex_program ); - glBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, m_fragment_program ); - - GlobalOpenGL_debugAssertNoErrors(); -} - -void disable(){ - glDisable( GL_VERTEX_PROGRAM_ARB ); - glDisable( GL_FRAGMENT_PROGRAM_ARB ); - - GlobalOpenGL_debugAssertNoErrors(); -} - -void setParameters( const Vector3& viewer, const Matrix4& localToWorld, const Vector3& origin, const Vector3& colour, const Matrix4& world2light ){ -} + GLuint m_vertex_program; + GLuint m_fragment_program; + + void create() + { + glEnable(GL_VERTEX_PROGRAM_ARB); + glEnable(GL_FRAGMENT_PROGRAM_ARB); + + { + glGenProgramsARB(1, &m_vertex_program); + glBindProgramARB(GL_VERTEX_PROGRAM_ARB, m_vertex_program); + StringOutputStream filename(256); + filename << GlobalRadiant().getAppPath() << "gl/zfill_vp.glp"; + createProgram(filename.c_str(), GL_VERTEX_PROGRAM_ARB); + + glGenProgramsARB(1, &m_fragment_program); + glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, m_fragment_program); + filename.clear(); + filename << GlobalRadiant().getAppPath() << "gl/zfill_fp.glp"; + createProgram(filename.c_str(), GL_FRAGMENT_PROGRAM_ARB); + } + + glDisable(GL_VERTEX_PROGRAM_ARB); + glDisable(GL_FRAGMENT_PROGRAM_ARB); + + GlobalOpenGL_debugAssertNoErrors(); + } + + void destroy() + { + glDeleteProgramsARB(1, &m_vertex_program); + glDeleteProgramsARB(1, &m_fragment_program); + GlobalOpenGL_debugAssertNoErrors(); + } + + void enable() + { + glEnable(GL_VERTEX_PROGRAM_ARB); + glEnable(GL_FRAGMENT_PROGRAM_ARB); + glBindProgramARB(GL_VERTEX_PROGRAM_ARB, m_vertex_program); + glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, m_fragment_program); + + GlobalOpenGL_debugAssertNoErrors(); + } + + void disable() + { + glDisable(GL_VERTEX_PROGRAM_ARB); + glDisable(GL_FRAGMENT_PROGRAM_ARB); + + GlobalOpenGL_debugAssertNoErrors(); + } + + void setParameters(const Vector3 &viewer, const Matrix4 &localToWorld, const Vector3 &origin, const Vector3 &colour, + const Matrix4 &world2light) + { + } }; ARBBumpProgram g_bumpARB; @@ -555,7 +592,7 @@ ARBDepthFillProgram g_depthFillARB; #if 0 -// NV20 path (unfinished) + // NV20 path (unfinished) void createProgram( GLint program, const char* filename, GLenum type ){ std::size_t size = file_size( filename ); @@ -771,199 +808,213 @@ bool g_normalArray_enabled = false; bool g_texcoordArray_enabled = false; bool g_colorArray_enabled = false; -inline bool OpenGLState_less( const OpenGLState& self, const OpenGLState& other ){ - //! Sort by sort-order override. - if ( self.m_sort != other.m_sort ) { - return self.m_sort < other.m_sort; - } - //! Sort by texture handle. - if ( self.m_texture != other.m_texture ) { - return self.m_texture < other.m_texture; - } - if ( self.m_texture1 != other.m_texture1 ) { - return self.m_texture1 < other.m_texture1; - } - if ( self.m_texture2 != other.m_texture2 ) { - return self.m_texture2 < other.m_texture2; - } - if ( self.m_texture3 != other.m_texture3 ) { - return self.m_texture3 < other.m_texture3; - } - if ( self.m_texture4 != other.m_texture4 ) { - return self.m_texture4 < other.m_texture4; - } - if ( self.m_texture5 != other.m_texture5 ) { - return self.m_texture5 < other.m_texture5; - } - if ( self.m_texture6 != other.m_texture6 ) { - return self.m_texture6 < other.m_texture6; - } - if ( self.m_texture7 != other.m_texture7 ) { - return self.m_texture7 < other.m_texture7; - } - //! Sort by state bit-vector. - if ( self.m_state != other.m_state ) { - return self.m_state < other.m_state; - } - //! Comparing address makes sure states are never equal. - return &self < &other; -} - -void OpenGLState_constructDefault( OpenGLState& state ){ - state.m_state = RENDER_DEFAULT; +inline bool OpenGLState_less(const OpenGLState &self, const OpenGLState &other) +{ + //! Sort by sort-order override. + if (self.m_sort != other.m_sort) { + return self.m_sort < other.m_sort; + } + //! Sort by texture handle. + if (self.m_texture != other.m_texture) { + return self.m_texture < other.m_texture; + } + if (self.m_texture1 != other.m_texture1) { + return self.m_texture1 < other.m_texture1; + } + if (self.m_texture2 != other.m_texture2) { + return self.m_texture2 < other.m_texture2; + } + if (self.m_texture3 != other.m_texture3) { + return self.m_texture3 < other.m_texture3; + } + if (self.m_texture4 != other.m_texture4) { + return self.m_texture4 < other.m_texture4; + } + if (self.m_texture5 != other.m_texture5) { + return self.m_texture5 < other.m_texture5; + } + if (self.m_texture6 != other.m_texture6) { + return self.m_texture6 < other.m_texture6; + } + if (self.m_texture7 != other.m_texture7) { + return self.m_texture7 < other.m_texture7; + } + //! Sort by state bit-vector. + if (self.m_state != other.m_state) { + return self.m_state < other.m_state; + } + //! Comparing address makes sure states are never equal. + return &self < &other; +} + +void OpenGLState_constructDefault(OpenGLState &state) +{ + state.m_state = RENDER_DEFAULT; - state.m_texture = 0; - state.m_texture1 = 0; - state.m_texture2 = 0; - state.m_texture3 = 0; - state.m_texture4 = 0; - state.m_texture5 = 0; - state.m_texture6 = 0; - state.m_texture7 = 0; + state.m_texture = 0; + state.m_texture1 = 0; + state.m_texture2 = 0; + state.m_texture3 = 0; + state.m_texture4 = 0; + state.m_texture5 = 0; + state.m_texture6 = 0; + state.m_texture7 = 0; - state.m_colour[0] = 1; - state.m_colour[1] = 1; - state.m_colour[2] = 1; - state.m_colour[3] = 1; + state.m_colour[0] = 1; + state.m_colour[1] = 1; + state.m_colour[2] = 1; + state.m_colour[3] = 1; - state.m_depthfunc = GL_LESS; + state.m_depthfunc = GL_LESS; - state.m_blend_src = GL_SRC_ALPHA; - state.m_blend_dst = GL_ONE_MINUS_SRC_ALPHA; + state.m_blend_src = GL_SRC_ALPHA; + state.m_blend_dst = GL_ONE_MINUS_SRC_ALPHA; - state.m_alphafunc = GL_ALWAYS; - state.m_alpharef = 0; + state.m_alphafunc = GL_ALWAYS; + state.m_alpharef = 0; - state.m_linewidth = 1; - state.m_pointsize = 1; + state.m_linewidth = 1; + state.m_pointsize = 1; - state.m_linestipple_factor = 1; - state.m_linestipple_pattern = 0xaaaa; + state.m_linestipple_factor = 1; + state.m_linestipple_pattern = 0xaaaa; - state.m_fog = OpenGLFogState(); + state.m_fog = OpenGLFogState(); } - - /// \brief A container of Renderable references. /// May contain the same Renderable multiple times, with different transforms. -class OpenGLStateBucket -{ +class OpenGLStateBucket { public: -struct RenderTransform -{ - const Matrix4* m_transform; - const OpenGLRenderable *m_renderable; - const RendererLight* m_light; + struct RenderTransform { + const Matrix4 *m_transform; + const OpenGLRenderable *m_renderable; + const RendererLight *m_light; - RenderTransform( const OpenGLRenderable& renderable, const Matrix4& transform, const RendererLight* light ) - : m_transform( &transform ), m_renderable( &renderable ), m_light( light ){ - } -}; + RenderTransform(const OpenGLRenderable &renderable, const Matrix4 &transform, const RendererLight *light) + : m_transform(&transform), m_renderable(&renderable), m_light(light) + { + } + }; -typedef std::vector Renderables; + typedef std::vector Renderables; private: -OpenGLState m_state; -Renderables m_renderables; + OpenGLState m_state; + Renderables m_renderables; public: -OpenGLStateBucket(){ -} -void addRenderable( const OpenGLRenderable& renderable, const Matrix4& modelview, const RendererLight* light = 0 ){ - m_renderables.push_back( RenderTransform( renderable, modelview, light ) ); -} + OpenGLStateBucket() + { + } -OpenGLState& state(){ - return m_state; -} + void addRenderable(const OpenGLRenderable &renderable, const Matrix4 &modelview, const RendererLight *light = 0) + { + m_renderables.push_back(RenderTransform(renderable, modelview, light)); + } + + OpenGLState &state() + { + return m_state; + } -void render( OpenGLState& current, unsigned int globalstate, const Vector3& viewer ); + void render(OpenGLState ¤t, unsigned int globalstate, const Vector3 &viewer); }; #define LIGHT_SHADER_DEBUG 0 #if LIGHT_SHADER_DEBUG -typedef std::vector LightDebugShaders; + typedef std::vector LightDebugShaders; LightDebugShaders g_lightDebugShaders; #endif -class OpenGLStateLess -{ +class OpenGLStateLess { public: -bool operator()( const OpenGLState& self, const OpenGLState& other ) const { - return OpenGLState_less( self, other ); -} + bool operator()(const OpenGLState &self, const OpenGLState &other) const + { + return OpenGLState_less(self, other); + } }; typedef ConstReference OpenGLStateReference; -typedef std::map OpenGLStates; +typedef std::map OpenGLStates; OpenGLStates g_state_sorted; -class OpenGLStateBucketAdd -{ -OpenGLStateBucket& m_bucket; -const OpenGLRenderable& m_renderable; -const Matrix4& m_modelview; +class OpenGLStateBucketAdd { + OpenGLStateBucket &m_bucket; + const OpenGLRenderable &m_renderable; + const Matrix4 &m_modelview; public: -using func = void(const RendererLight&); + using func = void(const RendererLight &); -OpenGLStateBucketAdd( OpenGLStateBucket& bucket, const OpenGLRenderable& renderable, const Matrix4& modelview ) : - m_bucket( bucket ), m_renderable( renderable ), m_modelview( modelview ){ -} -void operator()( const RendererLight& light ){ - m_bucket.addRenderable( m_renderable, m_modelview, &light ); -} + OpenGLStateBucketAdd(OpenGLStateBucket &bucket, const OpenGLRenderable &renderable, const Matrix4 &modelview) : + m_bucket(bucket), m_renderable(renderable), m_modelview(modelview) + { + } + + void operator()(const RendererLight &light) + { + m_bucket.addRenderable(m_renderable, m_modelview, &light); + } }; -class CountLights -{ -std::size_t m_count; +class CountLights { + std::size_t m_count; public: -using func = void(RendererLight&); + using func = void(RendererLight &); -CountLights() : m_count( 0 ){ -} -void operator()( const RendererLight& light ){ - ++m_count; -} -std::size_t count() const { - return m_count; -} + CountLights() : m_count(0) + { + } + + void operator()(const RendererLight &light) + { + ++m_count; + } + + std::size_t count() const + { + return m_count; + } }; -class OpenGLShader : public Shader -{ -typedef std::list Passes; -Passes m_passes; -IShader* m_shader; -std::size_t m_used; -ModuleObservers m_observers; +class OpenGLShader : public Shader { + typedef std::list Passes; + Passes m_passes; + IShader *m_shader; + std::size_t m_used; + ModuleObservers m_observers; public: -OpenGLShader() : m_shader( 0 ), m_used( 0 ){ -} -~OpenGLShader(){ -} -void construct( const char* name ); -void destroy(){ - if ( m_shader ) { - m_shader->DecRef(); - } - m_shader = 0; - - for ( Passes::iterator i = m_passes.begin(); i != m_passes.end(); ++i ) - { - delete *i; - } - m_passes.clear(); -} -void addRenderable( const OpenGLRenderable& renderable, const Matrix4& modelview, const LightList* lights ){ - for ( Passes::iterator i = m_passes.begin(); i != m_passes.end(); ++i ) - { + OpenGLShader() : m_shader(0), m_used(0) + { + } + + ~OpenGLShader() + { + } + + void construct(const char *name); + + void destroy() + { + if (m_shader) { + m_shader->DecRef(); + } + m_shader = 0; + + for (Passes::iterator i = m_passes.begin(); i != m_passes.end(); ++i) { + delete *i; + } + m_passes.clear(); + } + + void addRenderable(const OpenGLRenderable &renderable, const Matrix4 &modelview, const LightList *lights) + { + for (Passes::iterator i = m_passes.begin(); i != m_passes.end(); ++i) { #if LIGHT_SHADER_DEBUG - if ( ( ( *i )->state().m_state & RENDER_BUMP ) != 0 ) { + if ( ( ( *i )->state().m_state & RENDER_BUMP ) != 0 ) { if ( lights != 0 ) { CountLights counter; lights->forEachLight( makeCallback1( counter ) ); @@ -976,128 +1027,149 @@ void addRenderable( const OpenGLRenderable& renderable, const Matrix4& modelview } else #else - if ( ( ( *i )->state().m_state & RENDER_BUMP ) != 0 ) { - if ( lights != 0 ) { - OpenGLStateBucketAdd add( *( *i ), renderable, modelview ); - lights->forEachLight(makeCallback( add ) ); - } - } - else + if (((*i)->state().m_state & RENDER_BUMP) != 0) { + if (lights != 0) { + OpenGLStateBucketAdd add(*(*i), renderable, modelview); + lights->forEachLight(makeCallback(add)); + } + } else #endif - { - ( *i )->addRenderable( renderable, modelview ); - } - } -} -void incrementUsed(){ - if ( ++m_used == 1 && m_shader != 0 ) { - m_shader->SetInUse( true ); - } -} -void decrementUsed(){ - if ( --m_used == 0 && m_shader != 0 ) { - m_shader->SetInUse( false ); - } -} -bool realised() const { - return m_shader != 0; -} -void attach( ModuleObserver& observer ){ - if ( realised() ) { - observer.realise(); - } - m_observers.attach( observer ); -} -void detach( ModuleObserver& observer ){ - if ( realised() ) { - observer.unrealise(); - } - m_observers.detach( observer ); -} -void realise( const CopiedString& name ){ - construct( name.c_str() ); - - if ( m_used != 0 && m_shader != 0 ) { - m_shader->SetInUse( true ); - } - - for ( Passes::iterator i = m_passes.begin(); i != m_passes.end(); ++i ) - { - g_state_sorted.insert( OpenGLStates::value_type( OpenGLStateReference( ( *i )->state() ), *i ) ); - } - - m_observers.realise(); -} -void unrealise(){ - m_observers.unrealise(); - - for ( Passes::iterator i = m_passes.begin(); i != m_passes.end(); ++i ) - { - g_state_sorted.erase( OpenGLStateReference( ( *i )->state() ) ); - } - - destroy(); -} -qtexture_t& getTexture() const { - ASSERT_NOTNULL( m_shader ); - return *m_shader->getTexture(); -} -unsigned int getFlags() const { - ASSERT_NOTNULL( m_shader ); - return m_shader->getFlags(); -} -IShader& getShader() const { - ASSERT_NOTNULL( m_shader ); - return *m_shader; -} -OpenGLState& appendDefaultPass(){ - m_passes.push_back( new OpenGLStateBucket ); - OpenGLState& state = m_passes.back()->state(); - OpenGLState_constructDefault( state ); - return state; -} + { + (*i)->addRenderable(renderable, modelview); + } + } + } + + void incrementUsed() + { + if (++m_used == 1 && m_shader != 0) { + m_shader->SetInUse(true); + } + } + + void decrementUsed() + { + if (--m_used == 0 && m_shader != 0) { + m_shader->SetInUse(false); + } + } + + bool realised() const + { + return m_shader != 0; + } + + void attach(ModuleObserver &observer) + { + if (realised()) { + observer.realise(); + } + m_observers.attach(observer); + } + + void detach(ModuleObserver &observer) + { + if (realised()) { + observer.unrealise(); + } + m_observers.detach(observer); + } + + void realise(const CopiedString &name) + { + construct(name.c_str()); + + if (m_used != 0 && m_shader != 0) { + m_shader->SetInUse(true); + } + + for (Passes::iterator i = m_passes.begin(); i != m_passes.end(); ++i) { + g_state_sorted.insert(OpenGLStates::value_type(OpenGLStateReference((*i)->state()), *i)); + } + + m_observers.realise(); + } + + void unrealise() + { + m_observers.unrealise(); + + for (Passes::iterator i = m_passes.begin(); i != m_passes.end(); ++i) { + g_state_sorted.erase(OpenGLStateReference((*i)->state())); + } + + destroy(); + } + + qtexture_t &getTexture() const + { + ASSERT_NOTNULL(m_shader); + return *m_shader->getTexture(); + } + + unsigned int getFlags() const + { + ASSERT_NOTNULL(m_shader); + return m_shader->getFlags(); + } + + IShader &getShader() const + { + ASSERT_NOTNULL(m_shader); + return *m_shader; + } + + OpenGLState &appendDefaultPass() + { + m_passes.push_back(new OpenGLStateBucket); + OpenGLState &state = m_passes.back()->state(); + OpenGLState_constructDefault(state); + return state; + } }; -inline bool lightEnabled( const RendererLight& light, const LightCullable& cullable ){ - return cullable.testLight( light ); +inline bool lightEnabled(const RendererLight &light, const LightCullable &cullable) +{ + return cullable.testLight(light); } -typedef std::set RendererLights; +typedef std::set RendererLights; #define DEBUG_LIGHT_SYNC 0 -class LinearLightList : public LightList -{ -LightCullable& m_cullable; -RendererLights& m_allLights; -Callback m_evaluateChanged; +class LinearLightList : public LightList { + LightCullable &m_cullable; + RendererLights &m_allLights; + Callback m_evaluateChanged; -typedef std::list Lights; -mutable Lights m_lights; -mutable bool m_lightsChanged; + typedef std::list Lights; + mutable Lights m_lights; + mutable bool m_lightsChanged; public: -LinearLightList( LightCullable& cullable, RendererLights& lights, const Callback& evaluateChanged ) : - m_cullable( cullable ), m_allLights( lights ), m_evaluateChanged( evaluateChanged ){ - m_lightsChanged = true; -} -void evaluateLights() const { - m_evaluateChanged(); - if ( m_lightsChanged ) { - m_lightsChanged = false; - - m_lights.clear(); - m_cullable.clearLights(); - for ( RendererLights::const_iterator i = m_allLights.begin(); i != m_allLights.end(); ++i ) - { - if ( lightEnabled( *( *i ), m_cullable ) ) { - m_lights.push_back( *i ); - m_cullable.insertLight( *( *i ) ); - } - } - } -#if ( DEBUG_LIGHT_SYNC ) - else + LinearLightList(LightCullable &cullable, RendererLights &lights, const Callback &evaluateChanged) : + m_cullable(cullable), m_allLights(lights), m_evaluateChanged(evaluateChanged) + { + m_lightsChanged = true; + } + + void evaluateLights() const + { + m_evaluateChanged(); + if (m_lightsChanged) { + m_lightsChanged = false; + + m_lights.clear(); + m_cullable.clearLights(); + for (RendererLights::const_iterator i = m_allLights.begin(); i != m_allLights.end(); ++i) { + if (lightEnabled(*(*i), m_cullable)) { + m_lights.push_back(*i); + m_cullable.insertLight(*(*i)); + } + } + } +#if (DEBUG_LIGHT_SYNC) + else { Lights lights; for ( RendererLights::const_iterator i = m_allLights.begin(); i != m_allLights.end(); ++i ) @@ -1113,410 +1185,459 @@ void evaluateLights() const { ); } #endif -} -void forEachLight( const RendererLightCallback& callback ) const { - evaluateLights(); + } - for ( Lights::const_iterator i = m_lights.begin(); i != m_lights.end(); ++i ) - { - callback( *( *i ) ); - } -} -void lightsChanged() const { - m_lightsChanged = true; -} -}; + void forEachLight(const RendererLightCallback &callback) const + { + evaluateLights(); -inline void setFogState( const OpenGLFogState& state ){ - glFogi( GL_FOG_MODE, state.mode ); - glFogf( GL_FOG_DENSITY, state.density ); - glFogf( GL_FOG_START, state.start ); - glFogf( GL_FOG_END, state.end ); - glFogi( GL_FOG_INDEX, state.index ); - glFogfv( GL_FOG_COLOR, vector4_to_array( state.colour ) ); -} + for (Lights::const_iterator i = m_lights.begin(); i != m_lights.end(); ++i) { + callback(*(*i)); + } + } -#define DEBUG_SHADERS 0 + void lightsChanged() const + { + m_lightsChanged = true; + } +}; -class OpenGLShaderCache : public ShaderCache, public TexturesCacheObserver, public ModuleObserver -{ -class CreateOpenGLShader +inline void setFogState(const OpenGLFogState &state) { -OpenGLShaderCache* m_cache; -public: -explicit CreateOpenGLShader( OpenGLShaderCache* cache = 0 ) - : m_cache( cache ){ -} -OpenGLShader* construct( const CopiedString& name ){ - OpenGLShader* shader = new OpenGLShader; - if ( m_cache->realised() ) { - shader->realise( name ); - } - return shader; -} -void destroy( OpenGLShader* shader ){ - if ( m_cache->realised() ) { - shader->unrealise(); - } - delete shader; + glFogi(GL_FOG_MODE, state.mode); + glFogf(GL_FOG_DENSITY, state.density); + glFogf(GL_FOG_START, state.start); + glFogf(GL_FOG_END, state.end); + glFogi(GL_FOG_INDEX, state.index); + glFogfv(GL_FOG_COLOR, vector4_to_array(state.colour)); } -}; -typedef HashedCache, CreateOpenGLShader> Shaders; -Shaders m_shaders; -std::size_t m_unrealised; +#define DEBUG_SHADERS 0 -bool m_lightingEnabled; -bool m_lightingSupported; -bool m_useShaderLanguage; +class OpenGLShaderCache : public ShaderCache, public TexturesCacheObserver, public ModuleObserver { + class CreateOpenGLShader { + OpenGLShaderCache *m_cache; + public: + explicit CreateOpenGLShader(OpenGLShaderCache *cache = 0) + : m_cache(cache) + { + } + + OpenGLShader *construct(const CopiedString &name) + { + OpenGLShader *shader = new OpenGLShader; + if (m_cache->realised()) { + shader->realise(name); + } + return shader; + } + + void destroy(OpenGLShader *shader) + { + if (m_cache->realised()) { + shader->unrealise(); + } + delete shader; + } + }; + + typedef HashedCache, CreateOpenGLShader> Shaders; + Shaders m_shaders; + std::size_t m_unrealised; + + bool m_lightingEnabled; + bool m_lightingSupported; + bool m_useShaderLanguage; public: -OpenGLShaderCache() - : m_shaders( CreateOpenGLShader( this ) ), - m_unrealised( 3 ), // wait until shaders, gl-context and textures are realised before creating any render-states - m_lightingEnabled( true ), - m_lightingSupported( false ), - m_useShaderLanguage( false ), - m_lightsChanged( true ), - m_traverseRenderablesMutex( false ){ -} -~OpenGLShaderCache(){ - for ( Shaders::iterator i = m_shaders.begin(); i != m_shaders.end(); ++i ) - { - globalOutputStream() << "leaked shader: " << makeQuoted( ( *i ).key.c_str() ) << "\n"; - } -} -Shader* capture( const char* name ){ - ASSERT_MESSAGE( name[0] == '$' - || *name == '[' - || *name == '<' - || *name == '(' - || strchr( name, '\\' ) == 0, "shader name contains invalid characters: \"" << name << "\"" ); + OpenGLShaderCache() + : m_shaders(CreateOpenGLShader(this)), + m_unrealised( + 3), // wait until shaders, gl-context and textures are realised before creating any render-states + m_lightingEnabled(true), + m_lightingSupported(false), + m_useShaderLanguage(false), + m_lightsChanged(true), + m_traverseRenderablesMutex(false) + { + } + + ~OpenGLShaderCache() + { + for (Shaders::iterator i = m_shaders.begin(); i != m_shaders.end(); ++i) { + globalOutputStream() << "leaked shader: " << makeQuoted((*i).key.c_str()) << "\n"; + } + } + + Shader *capture(const char *name) + { + ASSERT_MESSAGE(name[0] == '$' + || *name == '[' + || *name == '<' + || *name == '(' + || strchr(name, '\\') == 0, "shader name contains invalid characters: \"" << name << "\""); #if DEBUG_SHADERS - globalOutputStream() << "shaders capture: " << makeQuoted( name ) << '\n'; + globalOutputStream() << "shaders capture: " << makeQuoted( name ) << '\n'; #endif - return m_shaders.capture( name ).get(); -} -void release( const char *name ){ + return m_shaders.capture(name).get(); + } + + void release(const char *name) + { #if DEBUG_SHADERS - globalOutputStream() << "shaders release: " << makeQuoted( name ) << '\n'; + globalOutputStream() << "shaders release: " << makeQuoted( name ) << '\n'; +#endif + m_shaders.release(name); + } + + void + render(RenderStateFlags globalstate, const Matrix4 &modelview, const Matrix4 &projection, const Vector3 &viewer) + { + glMatrixMode(GL_PROJECTION); + glLoadMatrixf(reinterpret_cast( &projection )); +#if 0 + //qglGetFloatv(GL_PROJECTION_MATRIX, reinterpret_cast(&projection)); #endif - m_shaders.release( name ); -} -void render( RenderStateFlags globalstate, const Matrix4& modelview, const Matrix4& projection, const Vector3& viewer ){ - glMatrixMode( GL_PROJECTION ); - glLoadMatrixf( reinterpret_cast( &projection ) ); - #if 0 - //qglGetFloatv(GL_PROJECTION_MATRIX, reinterpret_cast(&projection)); - #endif - - glMatrixMode( GL_MODELVIEW ); - glLoadMatrixf( reinterpret_cast( &modelview ) ); - #if 0 - //qglGetFloatv(GL_MODELVIEW_MATRIX, reinterpret_cast(&modelview)); - #endif - - ASSERT_MESSAGE( realised(), "render states are not realised" ); - - // global settings that are not set in renderstates - glFrontFace( GL_CW ); - glCullFace( GL_BACK ); - glPolygonOffset( -1, 1 ); - { - const GLubyte pattern[132] = { - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55 - }; - glPolygonStipple( pattern ); - } - glEnableClientState( GL_VERTEX_ARRAY ); - g_vertexArray_enabled = true; - glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE ); - - if ( GlobalOpenGL().GL_1_3() ) { - glActiveTexture( GL_TEXTURE0 ); - glClientActiveTexture( GL_TEXTURE0 ); - } - - if ( GlobalOpenGL().ARB_shader_objects() ) { - glUseProgramObjectARB( 0 ); - glDisableVertexAttribArrayARB( c_attr_TexCoord0 ); - glDisableVertexAttribArrayARB( c_attr_Tangent ); - glDisableVertexAttribArrayARB( c_attr_Binormal ); - } - - if ( globalstate & RENDER_TEXTURE ) { - glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); - glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); - } - - OpenGLState current; - OpenGLState_constructDefault( current ); - current.m_sort = OpenGLState::eSortFirst; - - // default renderstate settings - glLineStipple( current.m_linestipple_factor, current.m_linestipple_pattern ); - glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); - glDisable( GL_LIGHTING ); - glDisable( GL_TEXTURE_2D ); - glDisableClientState( GL_TEXTURE_COORD_ARRAY ); - g_texcoordArray_enabled = false; - glDisableClientState( GL_COLOR_ARRAY ); - g_colorArray_enabled = false; - glDisableClientState( GL_NORMAL_ARRAY ); - g_normalArray_enabled = false; - glDisable( GL_BLEND ); - glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); - glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); - glDisable( GL_CULL_FACE ); - glShadeModel( GL_FLAT ); - glDisable( GL_DEPTH_TEST ); - glDepthMask( GL_FALSE ); - glDisable( GL_ALPHA_TEST ); - glDisable( GL_LINE_STIPPLE ); - glDisable( GL_POLYGON_STIPPLE ); - glDisable( GL_POLYGON_OFFSET_LINE ); - - glBindTexture( GL_TEXTURE_2D, 0 ); - glColor4f( 1,1,1,1 ); - glDepthFunc( GL_LESS ); - glAlphaFunc( GL_ALWAYS, 0 ); - glLineWidth( 1 ); - glPointSize( 1 ); - - glHint( GL_FOG_HINT, GL_NICEST ); - glDisable( GL_FOG ); - setFogState( OpenGLFogState() ); - - GlobalOpenGL_debugAssertNoErrors(); - - debug_string( "begin rendering" ); - for ( OpenGLStates::iterator i = g_state_sorted.begin(); i != g_state_sorted.end(); ++i ) - { - ( *i ).second->render( current, globalstate, viewer ); - } - debug_string( "end rendering" ); -} -void realise(){ - if ( --m_unrealised == 0 ) { - if ( lightingSupported() && lightingEnabled() ) { - if ( useShaderLanguage() ) { - g_bumpGLSL.create(); - g_depthFillGLSL.create(); - } - else - { - g_bumpARB.create(); - g_depthFillARB.create(); - } - } - - for ( Shaders::iterator i = m_shaders.begin(); i != m_shaders.end(); ++i ) - { - if ( !( *i ).value.empty() ) { - ( *i ).value->realise( i->key ); - } - } - } -} -void unrealise(){ - if ( ++m_unrealised == 1 ) { - for ( Shaders::iterator i = m_shaders.begin(); i != m_shaders.end(); ++i ) - { - if ( !( *i ).value.empty() ) { - ( *i ).value->unrealise(); - } - } - if ( GlobalOpenGL().contextValid && lightingSupported() && lightingEnabled() ) { - if ( useShaderLanguage() ) { - g_bumpGLSL.destroy(); - g_depthFillGLSL.destroy(); - } - else - { - g_bumpARB.destroy(); - g_depthFillARB.destroy(); - } - } - } -} -bool realised(){ - return m_unrealised == 0; -} - - -bool lightingEnabled() const { - return m_lightingEnabled; -} -bool lightingSupported() const { - return m_lightingSupported; -} -bool useShaderLanguage() const { - return m_useShaderLanguage; -} -void setLighting( bool supported, bool enabled ){ - bool refresh = ( m_lightingSupported && m_lightingEnabled ) != ( supported && enabled ); - if ( refresh ) { - unrealise(); - GlobalShaderSystem().setLightingEnabled( supported && enabled ); - } + glMatrixMode(GL_MODELVIEW); + glLoadMatrixf(reinterpret_cast( &modelview )); +#if 0 + //qglGetFloatv(GL_MODELVIEW_MATRIX, reinterpret_cast(&modelview)); +#endif - m_lightingSupported = supported; - m_lightingEnabled = enabled; - - if ( refresh ) { - realise(); - } -} -void extensionsInitialised(){ - setLighting( GlobalOpenGL().GL_1_3() - && GlobalOpenGL().ARB_vertex_program() - && GlobalOpenGL().ARB_fragment_program() - && GlobalOpenGL().ARB_shader_objects() - && GlobalOpenGL().ARB_vertex_shader() - && GlobalOpenGL().ARB_fragment_shader() - && GlobalOpenGL().ARB_shading_language_100(), - m_lightingEnabled - ); - - if ( !lightingSupported() ) { - globalOutputStream() << "Lighting mode requires OpenGL features not supported by your graphics drivers:\n"; - if ( !GlobalOpenGL().GL_1_3() ) { - globalOutputStream() << " GL version 1.3 or better\n"; - } - if ( !GlobalOpenGL().ARB_vertex_program() ) { - globalOutputStream() << " GL_ARB_vertex_program\n"; - } - if ( !GlobalOpenGL().ARB_fragment_program() ) { - globalOutputStream() << " GL_ARB_fragment_program\n"; - } - if ( !GlobalOpenGL().ARB_shader_objects() ) { - globalOutputStream() << " GL_ARB_shader_objects\n"; - } - if ( !GlobalOpenGL().ARB_vertex_shader() ) { - globalOutputStream() << " GL_ARB_vertex_shader\n"; - } - if ( !GlobalOpenGL().ARB_fragment_shader() ) { - globalOutputStream() << " GL_ARB_fragment_shader\n"; - } - if ( !GlobalOpenGL().ARB_shading_language_100() ) { - globalOutputStream() << " GL_ARB_shading_language_100\n"; - } - } -} -void setLightingEnabled( bool enabled ){ - setLighting( m_lightingSupported, enabled ); -} + ASSERT_MESSAGE(realised(), "render states are not realised"); + + // global settings that are not set in renderstates + glFrontFace(GL_CW); + glCullFace(GL_BACK); + glPolygonOffset(-1, 1); + { + const GLubyte pattern[132] = { + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55 + }; + glPolygonStipple(pattern); + } + glEnableClientState(GL_VERTEX_ARRAY); + g_vertexArray_enabled = true; + glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); + + if (GlobalOpenGL().GL_1_3()) { + glActiveTexture(GL_TEXTURE0); + glClientActiveTexture(GL_TEXTURE0); + } + + if (GlobalOpenGL().ARB_shader_objects()) { + glUseProgramObjectARB(0); + glDisableVertexAttribArrayARB(c_attr_TexCoord0); + glDisableVertexAttribArrayARB(c_attr_Tangent); + glDisableVertexAttribArrayARB(c_attr_Binormal); + } + + if (globalstate & RENDER_TEXTURE) { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + } + + OpenGLState current; + OpenGLState_constructDefault(current); + current.m_sort = OpenGLState::eSortFirst; + + // default renderstate settings + glLineStipple(current.m_linestipple_factor, current.m_linestipple_pattern); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + glDisable(GL_LIGHTING); + glDisable(GL_TEXTURE_2D); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + g_texcoordArray_enabled = false; + glDisableClientState(GL_COLOR_ARRAY); + g_colorArray_enabled = false; + glDisableClientState(GL_NORMAL_ARRAY); + g_normalArray_enabled = false; + glDisable(GL_BLEND); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDisable(GL_CULL_FACE); + glShadeModel(GL_FLAT); + glDisable(GL_DEPTH_TEST); + glDepthMask(GL_FALSE); + glDisable(GL_ALPHA_TEST); + glDisable(GL_LINE_STIPPLE); + glDisable(GL_POLYGON_STIPPLE); + glDisable(GL_POLYGON_OFFSET_LINE); + + glBindTexture(GL_TEXTURE_2D, 0); + glColor4f(1, 1, 1, 1); + glDepthFunc(GL_LESS); + glAlphaFunc(GL_ALWAYS, 0); + glLineWidth(1); + glPointSize(1); + + glHint(GL_FOG_HINT, GL_NICEST); + glDisable(GL_FOG); + setFogState(OpenGLFogState()); + + GlobalOpenGL_debugAssertNoErrors(); + + debug_string("begin rendering"); + for (OpenGLStates::iterator i = g_state_sorted.begin(); i != g_state_sorted.end(); ++i) { + (*i).second->render(current, globalstate, viewer); + } + debug_string("end rendering"); + } + + void realise() + { + if (--m_unrealised == 0) { + if (lightingSupported() && lightingEnabled()) { + if (useShaderLanguage()) { + g_bumpGLSL.create(); + g_depthFillGLSL.create(); + } else { + g_bumpARB.create(); + g_depthFillARB.create(); + } + } + + for (Shaders::iterator i = m_shaders.begin(); i != m_shaders.end(); ++i) { + if (!(*i).value.empty()) { + (*i).value->realise(i->key); + } + } + } + } + + void unrealise() + { + if (++m_unrealised == 1) { + for (Shaders::iterator i = m_shaders.begin(); i != m_shaders.end(); ++i) { + if (!(*i).value.empty()) { + (*i).value->unrealise(); + } + } + if (GlobalOpenGL().contextValid && lightingSupported() && lightingEnabled()) { + if (useShaderLanguage()) { + g_bumpGLSL.destroy(); + g_depthFillGLSL.destroy(); + } else { + g_bumpARB.destroy(); + g_depthFillARB.destroy(); + } + } + } + } + + bool realised() + { + return m_unrealised == 0; + } + + + bool lightingEnabled() const + { + return m_lightingEnabled; + } + + bool lightingSupported() const + { + return m_lightingSupported; + } + + bool useShaderLanguage() const + { + return m_useShaderLanguage; + } + + void setLighting(bool supported, bool enabled) + { + bool refresh = (m_lightingSupported && m_lightingEnabled) != (supported && enabled); + + if (refresh) { + unrealise(); + GlobalShaderSystem().setLightingEnabled(supported && enabled); + } + + m_lightingSupported = supported; + m_lightingEnabled = enabled; + + if (refresh) { + realise(); + } + } + + void extensionsInitialised() + { + setLighting(GlobalOpenGL().GL_1_3() + && GlobalOpenGL().ARB_vertex_program() + && GlobalOpenGL().ARB_fragment_program() + && GlobalOpenGL().ARB_shader_objects() + && GlobalOpenGL().ARB_vertex_shader() + && GlobalOpenGL().ARB_fragment_shader() + && GlobalOpenGL().ARB_shading_language_100(), + m_lightingEnabled + ); + + if (!lightingSupported()) { + globalOutputStream() << "Lighting mode requires OpenGL features not supported by your graphics drivers:\n"; + if (!GlobalOpenGL().GL_1_3()) { + globalOutputStream() << " GL version 1.3 or better\n"; + } + if (!GlobalOpenGL().ARB_vertex_program()) { + globalOutputStream() << " GL_ARB_vertex_program\n"; + } + if (!GlobalOpenGL().ARB_fragment_program()) { + globalOutputStream() << " GL_ARB_fragment_program\n"; + } + if (!GlobalOpenGL().ARB_shader_objects()) { + globalOutputStream() << " GL_ARB_shader_objects\n"; + } + if (!GlobalOpenGL().ARB_vertex_shader()) { + globalOutputStream() << " GL_ARB_vertex_shader\n"; + } + if (!GlobalOpenGL().ARB_fragment_shader()) { + globalOutputStream() << " GL_ARB_fragment_shader\n"; + } + if (!GlobalOpenGL().ARB_shading_language_100()) { + globalOutputStream() << " GL_ARB_shading_language_100\n"; + } + } + } + + void setLightingEnabled(bool enabled) + { + setLighting(m_lightingSupported, enabled); + } // light culling -RendererLights m_lights; -bool m_lightsChanged; -typedef std::map LightLists; -LightLists m_lightLists; - -const LightList& attach( LightCullable& cullable ){ - return ( *m_lightLists.insert( LightLists::value_type( &cullable, LinearLightList( cullable, m_lights, EvaluateChangedCaller( *this ) ) ) ).first ).second; -} -void detach( LightCullable& cullable ){ - m_lightLists.erase( &cullable ); -} -void changed( LightCullable& cullable ){ - LightLists::iterator i = m_lightLists.find( &cullable ); - ASSERT_MESSAGE( i != m_lightLists.end(), "cullable not attached" ); - ( *i ).second.lightsChanged(); -} -void attach( RendererLight& light ){ - ASSERT_MESSAGE( m_lights.find( &light ) == m_lights.end(), "light could not be attached" ); - m_lights.insert( &light ); - changed( light ); -} -void detach( RendererLight& light ){ - ASSERT_MESSAGE( m_lights.find( &light ) != m_lights.end(), "light could not be detached" ); - m_lights.erase( &light ); - changed( light ); -} -void changed( RendererLight& light ){ - m_lightsChanged = true; -} -void evaluateChanged(){ - if ( m_lightsChanged ) { - m_lightsChanged = false; - for ( LightLists::iterator i = m_lightLists.begin(); i != m_lightLists.end(); ++i ) - { - ( *i ).second.lightsChanged(); - } - } -} -typedef MemberCaller EvaluateChangedCaller; - -typedef std::set Renderables; -Renderables m_renderables; -mutable bool m_traverseRenderablesMutex; + RendererLights m_lights; + bool m_lightsChanged; + typedef std::map LightLists; + LightLists m_lightLists; + + const LightList &attach(LightCullable &cullable) + { + return (*m_lightLists.insert(LightLists::value_type(&cullable, LinearLightList(cullable, m_lights, + EvaluateChangedCaller( + *this)))).first).second; + } + + void detach(LightCullable &cullable) + { + m_lightLists.erase(&cullable); + } + + void changed(LightCullable &cullable) + { + LightLists::iterator i = m_lightLists.find(&cullable); + ASSERT_MESSAGE(i != m_lightLists.end(), "cullable not attached"); + (*i).second.lightsChanged(); + } + + void attach(RendererLight &light) + { + ASSERT_MESSAGE(m_lights.find(&light) == m_lights.end(), "light could not be attached"); + m_lights.insert(&light); + changed(light); + } + + void detach(RendererLight &light) + { + ASSERT_MESSAGE(m_lights.find(&light) != m_lights.end(), "light could not be detached"); + m_lights.erase(&light); + changed(light); + } + + void changed(RendererLight &light) + { + m_lightsChanged = true; + } + + void evaluateChanged() + { + if (m_lightsChanged) { + m_lightsChanged = false; + for (LightLists::iterator i = m_lightLists.begin(); i != m_lightLists.end(); ++i) { + (*i).second.lightsChanged(); + } + } + } + + typedef MemberCaller EvaluateChangedCaller; + + typedef std::set Renderables; + Renderables m_renderables; + mutable bool m_traverseRenderablesMutex; // renderables -void attachRenderable( const Renderable& renderable ){ - ASSERT_MESSAGE( !m_traverseRenderablesMutex, "attaching renderable during traversal" ); - ASSERT_MESSAGE( m_renderables.find( &renderable ) == m_renderables.end(), "renderable could not be attached" ); - m_renderables.insert( &renderable ); -} -void detachRenderable( const Renderable& renderable ){ - ASSERT_MESSAGE( !m_traverseRenderablesMutex, "detaching renderable during traversal" ); - ASSERT_MESSAGE( m_renderables.find( &renderable ) != m_renderables.end(), "renderable could not be detached" ); - m_renderables.erase( &renderable ); -} -void forEachRenderable( const RenderableCallback& callback ) const { - ASSERT_MESSAGE( !m_traverseRenderablesMutex, "for-each during traversal" ); - m_traverseRenderablesMutex = true; - for ( Renderables::const_iterator i = m_renderables.begin(); i != m_renderables.end(); ++i ) - { - callback( *( *i ) ); - } - m_traverseRenderablesMutex = false; -} + void attachRenderable(const Renderable &renderable) + { + ASSERT_MESSAGE(!m_traverseRenderablesMutex, "attaching renderable during traversal"); + ASSERT_MESSAGE(m_renderables.find(&renderable) == m_renderables.end(), "renderable could not be attached"); + m_renderables.insert(&renderable); + } + + void detachRenderable(const Renderable &renderable) + { + ASSERT_MESSAGE(!m_traverseRenderablesMutex, "detaching renderable during traversal"); + ASSERT_MESSAGE(m_renderables.find(&renderable) != m_renderables.end(), "renderable could not be detached"); + m_renderables.erase(&renderable); + } + + void forEachRenderable(const RenderableCallback &callback) const + { + ASSERT_MESSAGE(!m_traverseRenderablesMutex, "for-each during traversal"); + m_traverseRenderablesMutex = true; + for (Renderables::const_iterator i = m_renderables.begin(); i != m_renderables.end(); ++i) { + callback(*(*i)); + } + m_traverseRenderablesMutex = false; + } }; -static OpenGLShaderCache* g_ShaderCache; +static OpenGLShaderCache *g_ShaderCache; -void ShaderCache_extensionsInitialised(){ - g_ShaderCache->extensionsInitialised(); +void ShaderCache_extensionsInitialised() +{ + g_ShaderCache->extensionsInitialised(); } -void ShaderCache_setBumpEnabled( bool enabled ){ - g_ShaderCache->setLightingEnabled( enabled ); +void ShaderCache_setBumpEnabled(bool enabled) +{ + g_ShaderCache->setLightingEnabled(enabled); } Vector3 g_DebugShaderColours[256]; -Shader* g_defaultPointLight = 0; +Shader *g_defaultPointLight = 0; -void ShaderCache_Construct(){ - g_ShaderCache = new OpenGLShaderCache; - GlobalTexturesCache().attach( *g_ShaderCache ); - GlobalShaderSystem().attach( *g_ShaderCache ); +void ShaderCache_Construct() +{ + g_ShaderCache = new OpenGLShaderCache; + GlobalTexturesCache().attach(*g_ShaderCache); + GlobalShaderSystem().attach(*g_ShaderCache); - if ( g_pGameDescription->mGameType == "doom3" ) { - g_defaultPointLight = g_ShaderCache->capture( "lights/defaultPointLight" ); - //Shader* overbright = - g_ShaderCache->capture( "$OVERBRIGHT" ); + if (g_pGameDescription->mGameType == "doom3") { + g_defaultPointLight = g_ShaderCache->capture("lights/defaultPointLight"); + //Shader* overbright = + g_ShaderCache->capture("$OVERBRIGHT"); #if LIGHT_SHADER_DEBUG - for ( std::size_t i = 0; i < 256; ++i ) + for ( std::size_t i = 0; i < 256; ++i ) { g_DebugShaderColours[i] = Vector3( i / 256.0, i / 256.0, i / 256.0 ); } @@ -1543,17 +1664,18 @@ void ShaderCache_Construct(){ buffer.clear(); } #endif - } + } } -void ShaderCache_Destroy(){ - if ( g_pGameDescription->mGameType == "doom3" ) { - g_ShaderCache->release( "lights/defaultPointLight" ); - g_ShaderCache->release( "$OVERBRIGHT" ); - g_defaultPointLight = 0; +void ShaderCache_Destroy() +{ + if (g_pGameDescription->mGameType == "doom3") { + g_ShaderCache->release("lights/defaultPointLight"); + g_ShaderCache->release("$OVERBRIGHT"); + g_defaultPointLight = 0; #if LIGHT_SHADER_DEBUG - g_lightDebugShaders.clear(); + g_lightDebugShaders.clear(); StringOutputStream buffer( 256 ); for ( std::size_t i = 0; i < 256; ++i ) { @@ -1561,875 +1683,884 @@ void ShaderCache_Destroy(){ g_ShaderCache->release( buffer.c_str() ); } #endif - } + } - GlobalShaderSystem().detach( *g_ShaderCache ); - GlobalTexturesCache().detach( *g_ShaderCache ); - delete g_ShaderCache; + GlobalShaderSystem().detach(*g_ShaderCache); + GlobalTexturesCache().detach(*g_ShaderCache); + delete g_ShaderCache; } -ShaderCache* GetShaderCache(){ - return g_ShaderCache; +ShaderCache *GetShaderCache() +{ + return g_ShaderCache; } -inline void setTextureState( GLint& current, const GLint& texture, GLenum textureUnit ){ - if ( texture != current ) { - glActiveTexture( textureUnit ); - glClientActiveTexture( textureUnit ); - glBindTexture( GL_TEXTURE_2D, texture ); - GlobalOpenGL_debugAssertNoErrors(); - current = texture; - } +inline void setTextureState(GLint ¤t, const GLint &texture, GLenum textureUnit) +{ + if (texture != current) { + glActiveTexture(textureUnit); + glClientActiveTexture(textureUnit); + glBindTexture(GL_TEXTURE_2D, texture); + GlobalOpenGL_debugAssertNoErrors(); + current = texture; + } } -inline void setTextureState( GLint& current, const GLint& texture ){ - if ( texture != current ) { - glBindTexture( GL_TEXTURE_2D, texture ); - GlobalOpenGL_debugAssertNoErrors(); - current = texture; - } +inline void setTextureState(GLint ¤t, const GLint &texture) +{ + if (texture != current) { + glBindTexture(GL_TEXTURE_2D, texture); + GlobalOpenGL_debugAssertNoErrors(); + current = texture; + } } -inline void setState( unsigned int state, unsigned int delta, unsigned int flag, GLenum glflag ){ - if ( delta & state & flag ) { - glEnable( glflag ); - GlobalOpenGL_debugAssertNoErrors(); - } - else if ( delta & ~state & flag ) { - glDisable( glflag ); - GlobalOpenGL_debugAssertNoErrors(); - } +inline void setState(unsigned int state, unsigned int delta, unsigned int flag, GLenum glflag) +{ + if (delta & state & flag) { + glEnable(glflag); + GlobalOpenGL_debugAssertNoErrors(); + } else if (delta & ~state & flag) { + glDisable(glflag); + GlobalOpenGL_debugAssertNoErrors(); + } } -void OpenGLState_apply( const OpenGLState& self, OpenGLState& current, unsigned int globalstate ){ - debug_int( "sort", int(self.m_sort) ); - debug_int( "texture", self.m_texture ); - debug_int( "state", self.m_state ); - debug_int( "address", int(std::size_t( &self ) ) ); - - count_state(); - - if ( self.m_state & RENDER_OVERRIDE ) { - globalstate |= RENDER_FILL | RENDER_DEPTHWRITE; - } - - const unsigned int state = self.m_state & globalstate; - const unsigned int delta = state ^ current.m_state; - - GlobalOpenGL_debugAssertNoErrors(); - - GLProgram* program = ( state & RENDER_PROGRAM ) != 0 ? self.m_program : 0; - - if ( program != current.m_program ) { - if ( current.m_program != 0 ) { - current.m_program->disable(); - glColor4fv( vector4_to_array( current.m_colour ) ); - debug_colour( "cleaning program" ); - } - - current.m_program = program; - - if ( current.m_program != 0 ) { - current.m_program->enable(); - } - } - - if ( delta & state & RENDER_FILL ) { - //qglPolygonMode (GL_BACK, GL_LINE); - //qglPolygonMode (GL_FRONT, GL_FILL); - glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); - GlobalOpenGL_debugAssertNoErrors(); - } - else if ( delta & ~state & RENDER_FILL ) { - glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); - GlobalOpenGL_debugAssertNoErrors(); - } - - setState( state, delta, RENDER_OFFSETLINE, GL_POLYGON_OFFSET_LINE ); - - if ( delta & state & RENDER_LIGHTING ) { - glEnable( GL_LIGHTING ); - glEnable( GL_COLOR_MATERIAL ); - glEnable( GL_RESCALE_NORMAL ); - glEnableClientState( GL_NORMAL_ARRAY ); - GlobalOpenGL_debugAssertNoErrors(); - g_normalArray_enabled = true; - } - else if ( delta & ~state & RENDER_LIGHTING ) { - glDisable( GL_LIGHTING ); - glDisable( GL_COLOR_MATERIAL ); - glDisable( GL_RESCALE_NORMAL ); - glDisableClientState( GL_NORMAL_ARRAY ); - GlobalOpenGL_debugAssertNoErrors(); - g_normalArray_enabled = false; - } - - if ( delta & state & RENDER_TEXTURE ) { - GlobalOpenGL_debugAssertNoErrors(); - - if ( GlobalOpenGL().GL_1_3() ) { - glActiveTexture( GL_TEXTURE0 ); - glClientActiveTexture( GL_TEXTURE0 ); - } - - glEnable( GL_TEXTURE_2D ); - - glColor4f( 1,1,1,self.m_colour[3] ); - debug_colour( "setting texture" ); - - glEnableClientState( GL_TEXTURE_COORD_ARRAY ); - GlobalOpenGL_debugAssertNoErrors(); - g_texcoordArray_enabled = true; - } - else if ( delta & ~state & RENDER_TEXTURE ) { - if ( GlobalOpenGL().GL_1_3() ) { - glActiveTexture( GL_TEXTURE0 ); - glClientActiveTexture( GL_TEXTURE0 ); - } - - glDisable( GL_TEXTURE_2D ); - glBindTexture( GL_TEXTURE_2D, 0 ); - glDisableClientState( GL_TEXTURE_COORD_ARRAY ); - - GlobalOpenGL_debugAssertNoErrors(); - g_texcoordArray_enabled = false; - } - - if ( delta & state & RENDER_BLEND ) { +void OpenGLState_apply(const OpenGLState &self, OpenGLState ¤t, unsigned int globalstate) +{ + debug_int("sort", int(self.m_sort)); + debug_int("texture", self.m_texture); + debug_int("state", self.m_state); + debug_int("address", int(std::size_t(&self))); + + count_state(); + + if (self.m_state & RENDER_OVERRIDE) { + globalstate |= RENDER_FILL | RENDER_DEPTHWRITE; + } + + const unsigned int state = self.m_state & globalstate; + const unsigned int delta = state ^current.m_state; + + GlobalOpenGL_debugAssertNoErrors(); + + GLProgram *program = (state & RENDER_PROGRAM) != 0 ? self.m_program : 0; + + if (program != current.m_program) { + if (current.m_program != 0) { + current.m_program->disable(); + glColor4fv(vector4_to_array(current.m_colour)); + debug_colour("cleaning program"); + } + + current.m_program = program; + + if (current.m_program != 0) { + current.m_program->enable(); + } + } + + if (delta & state & RENDER_FILL) { + //qglPolygonMode (GL_BACK, GL_LINE); + //qglPolygonMode (GL_FRONT, GL_FILL); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + GlobalOpenGL_debugAssertNoErrors(); + } else if (delta & ~state & RENDER_FILL) { + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + GlobalOpenGL_debugAssertNoErrors(); + } + + setState(state, delta, RENDER_OFFSETLINE, GL_POLYGON_OFFSET_LINE); + + if (delta & state & RENDER_LIGHTING) { + glEnable(GL_LIGHTING); + glEnable(GL_COLOR_MATERIAL); + glEnable(GL_RESCALE_NORMAL); + glEnableClientState(GL_NORMAL_ARRAY); + GlobalOpenGL_debugAssertNoErrors(); + g_normalArray_enabled = true; + } else if (delta & ~state & RENDER_LIGHTING) { + glDisable(GL_LIGHTING); + glDisable(GL_COLOR_MATERIAL); + glDisable(GL_RESCALE_NORMAL); + glDisableClientState(GL_NORMAL_ARRAY); + GlobalOpenGL_debugAssertNoErrors(); + g_normalArray_enabled = false; + } + + if (delta & state & RENDER_TEXTURE) { + GlobalOpenGL_debugAssertNoErrors(); + + if (GlobalOpenGL().GL_1_3()) { + glActiveTexture(GL_TEXTURE0); + glClientActiveTexture(GL_TEXTURE0); + } + + glEnable(GL_TEXTURE_2D); + + glColor4f(1, 1, 1, self.m_colour[3]); + debug_colour("setting texture"); + + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + GlobalOpenGL_debugAssertNoErrors(); + g_texcoordArray_enabled = true; + } else if (delta & ~state & RENDER_TEXTURE) { + if (GlobalOpenGL().GL_1_3()) { + glActiveTexture(GL_TEXTURE0); + glClientActiveTexture(GL_TEXTURE0); + } + + glDisable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, 0); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + + GlobalOpenGL_debugAssertNoErrors(); + g_texcoordArray_enabled = false; + } + + if (delta & state & RENDER_BLEND) { // FIXME: some .TGA are buggy, have a completely empty alpha channel // if such brushes are rendered in this loop they would be totally transparent with GL_MODULATE // so I decided using GL_DECAL instead // if an empty-alpha-channel or nearly-empty texture is used. It will be blank-transparent. // this could get better if you can get glTexEnviv (GL_TEXTURE_ENV, to work .. patches are welcome - glEnable( GL_BLEND ); - if ( GlobalOpenGL().GL_1_3() ) { - glActiveTexture( GL_TEXTURE0 ); - } - glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL ); - GlobalOpenGL_debugAssertNoErrors(); - } - else if ( delta & ~state & RENDER_BLEND ) { - glDisable( GL_BLEND ); - if ( GlobalOpenGL().GL_1_3() ) { - glActiveTexture( GL_TEXTURE0 ); - } - glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); - GlobalOpenGL_debugAssertNoErrors(); - } - - setState( state, delta, RENDER_CULLFACE, GL_CULL_FACE ); - - if ( delta & state & RENDER_SMOOTH ) { - glShadeModel( GL_SMOOTH ); - GlobalOpenGL_debugAssertNoErrors(); - } - else if ( delta & ~state & RENDER_SMOOTH ) { - glShadeModel( GL_FLAT ); - GlobalOpenGL_debugAssertNoErrors(); - } - - setState( state, delta, RENDER_SCALED, GL_NORMALIZE ); // not GL_RESCALE_NORMAL - - setState( state, delta, RENDER_DEPTHTEST, GL_DEPTH_TEST ); - - if ( delta & state & RENDER_DEPTHWRITE ) { - glDepthMask( GL_TRUE ); + glEnable(GL_BLEND); + if (GlobalOpenGL().GL_1_3()) { + glActiveTexture(GL_TEXTURE0); + } + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); + GlobalOpenGL_debugAssertNoErrors(); + } else if (delta & ~state & RENDER_BLEND) { + glDisable(GL_BLEND); + if (GlobalOpenGL().GL_1_3()) { + glActiveTexture(GL_TEXTURE0); + } + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + GlobalOpenGL_debugAssertNoErrors(); + } + + setState(state, delta, RENDER_CULLFACE, GL_CULL_FACE); + + if (delta & state & RENDER_SMOOTH) { + glShadeModel(GL_SMOOTH); + GlobalOpenGL_debugAssertNoErrors(); + } else if (delta & ~state & RENDER_SMOOTH) { + glShadeModel(GL_FLAT); + GlobalOpenGL_debugAssertNoErrors(); + } + + setState(state, delta, RENDER_SCALED, GL_NORMALIZE); // not GL_RESCALE_NORMAL + + setState(state, delta, RENDER_DEPTHTEST, GL_DEPTH_TEST); + + if (delta & state & RENDER_DEPTHWRITE) { + glDepthMask(GL_TRUE); #if DEBUG_RENDER - GLboolean depthEnabled; + GLboolean depthEnabled; glGetBooleanv( GL_DEPTH_WRITEMASK, &depthEnabled ); ASSERT_MESSAGE( depthEnabled, "failed to set depth buffer mask bit" ); #endif - debug_string( "enabled depth-buffer writing" ); + debug_string("enabled depth-buffer writing"); - GlobalOpenGL_debugAssertNoErrors(); - } - else if ( delta & ~state & RENDER_DEPTHWRITE ) { - glDepthMask( GL_FALSE ); + GlobalOpenGL_debugAssertNoErrors(); + } else if (delta & ~state & RENDER_DEPTHWRITE) { + glDepthMask(GL_FALSE); #if DEBUG_RENDER - GLboolean depthEnabled; + GLboolean depthEnabled; glGetBooleanv( GL_DEPTH_WRITEMASK, &depthEnabled ); ASSERT_MESSAGE( !depthEnabled, "failed to set depth buffer mask bit" ); #endif - debug_string( "disabled depth-buffer writing" ); - - GlobalOpenGL_debugAssertNoErrors(); - } - - if ( delta & state & RENDER_COLOURWRITE ) { - glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE ); - GlobalOpenGL_debugAssertNoErrors(); - } - else if ( delta & ~state & RENDER_COLOURWRITE ) { - glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE ); - GlobalOpenGL_debugAssertNoErrors(); - } - - setState( state, delta, RENDER_ALPHATEST, GL_ALPHA_TEST ); - - if ( delta & state & RENDER_COLOURARRAY ) { - glEnableClientState( GL_COLOR_ARRAY ); - GlobalOpenGL_debugAssertNoErrors(); - debug_colour( "enabling color_array" ); - g_colorArray_enabled = true; - } - else if ( delta & ~state & RENDER_COLOURARRAY ) { - glDisableClientState( GL_COLOR_ARRAY ); - glColor4fv( vector4_to_array( self.m_colour ) ); - debug_colour( "cleaning color_array" ); - GlobalOpenGL_debugAssertNoErrors(); - g_colorArray_enabled = false; - } - - if ( delta & ~state & RENDER_COLOURCHANGE ) { - glColor4fv( vector4_to_array( self.m_colour ) ); - GlobalOpenGL_debugAssertNoErrors(); - } - - setState( state, delta, RENDER_LINESTIPPLE, GL_LINE_STIPPLE ); - setState( state, delta, RENDER_LINESMOOTH, GL_LINE_SMOOTH ); - - setState( state, delta, RENDER_POLYGONSTIPPLE, GL_POLYGON_STIPPLE ); - setState( state, delta, RENDER_POLYGONSMOOTH, GL_POLYGON_SMOOTH ); - - setState( state, delta, RENDER_FOG, GL_FOG ); - - if ( ( state & RENDER_FOG ) != 0 ) { - setFogState( self.m_fog ); - GlobalOpenGL_debugAssertNoErrors(); - current.m_fog = self.m_fog; - } - - if ( state & RENDER_DEPTHTEST && self.m_depthfunc != current.m_depthfunc ) { - glDepthFunc( self.m_depthfunc ); - GlobalOpenGL_debugAssertNoErrors(); - current.m_depthfunc = self.m_depthfunc; - } - - if ( state & RENDER_LINESTIPPLE - && ( self.m_linestipple_factor != current.m_linestipple_factor - || self.m_linestipple_pattern != current.m_linestipple_pattern ) ) { - glLineStipple( self.m_linestipple_factor, self.m_linestipple_pattern ); - GlobalOpenGL_debugAssertNoErrors(); - current.m_linestipple_factor = self.m_linestipple_factor; - current.m_linestipple_pattern = self.m_linestipple_pattern; - } - - - if ( state & RENDER_ALPHATEST - && ( self.m_alphafunc != current.m_alphafunc - || self.m_alpharef != current.m_alpharef ) ) { - glAlphaFunc( self.m_alphafunc, self.m_alpharef ); - GlobalOpenGL_debugAssertNoErrors(); - current.m_alphafunc = self.m_alphafunc; - current.m_alpharef = self.m_alpharef; - } - - { - GLint texture0 = 0; - GLint texture1 = 0; - GLint texture2 = 0; - GLint texture3 = 0; - GLint texture4 = 0; - GLint texture5 = 0; - GLint texture6 = 0; - GLint texture7 = 0; - //if(state & RENDER_TEXTURE) != 0) - { - texture0 = self.m_texture; - texture1 = self.m_texture1; - texture2 = self.m_texture2; - texture3 = self.m_texture3; - texture4 = self.m_texture4; - texture5 = self.m_texture5; - texture6 = self.m_texture6; - texture7 = self.m_texture7; - } - - if ( GlobalOpenGL().GL_1_3() ) { - setTextureState( current.m_texture, texture0, GL_TEXTURE0 ); - setTextureState( current.m_texture1, texture1, GL_TEXTURE1 ); - setTextureState( current.m_texture2, texture2, GL_TEXTURE2 ); - setTextureState( current.m_texture3, texture3, GL_TEXTURE3 ); - setTextureState( current.m_texture4, texture4, GL_TEXTURE4 ); - setTextureState( current.m_texture5, texture5, GL_TEXTURE5 ); - setTextureState( current.m_texture6, texture6, GL_TEXTURE6 ); - setTextureState( current.m_texture7, texture7, GL_TEXTURE7 ); - } - else - { - setTextureState( current.m_texture, texture0 ); - } - } - - - if ( state & RENDER_TEXTURE && self.m_colour[3] != current.m_colour[3] ) { - debug_colour( "setting alpha" ); - glColor4f( 1,1,1,self.m_colour[3] ); - GlobalOpenGL_debugAssertNoErrors(); - } - - if ( !( state & RENDER_TEXTURE ) - && ( self.m_colour[0] != current.m_colour[0] - || self.m_colour[1] != current.m_colour[1] - || self.m_colour[2] != current.m_colour[2] - || self.m_colour[3] != current.m_colour[3] ) ) { - glColor4fv( vector4_to_array( self.m_colour ) ); - debug_colour( "setting non-texture" ); - GlobalOpenGL_debugAssertNoErrors(); - } - current.m_colour = self.m_colour; - - if ( state & RENDER_BLEND - && ( self.m_blend_src != current.m_blend_src || self.m_blend_dst != current.m_blend_dst ) ) { - glBlendFunc( self.m_blend_src, self.m_blend_dst ); - GlobalOpenGL_debugAssertNoErrors(); - current.m_blend_src = self.m_blend_src; - current.m_blend_dst = self.m_blend_dst; - } - - if ( !( state & RENDER_FILL ) - && self.m_linewidth != current.m_linewidth ) { - glLineWidth( self.m_linewidth ); - GlobalOpenGL_debugAssertNoErrors(); - current.m_linewidth = self.m_linewidth; - } - - if ( !( state & RENDER_FILL ) - && self.m_pointsize != current.m_pointsize ) { - glPointSize( self.m_pointsize ); - GlobalOpenGL_debugAssertNoErrors(); - current.m_pointsize = self.m_pointsize; - } - - current.m_state = state; - - GlobalOpenGL_debugAssertNoErrors(); -} - -void Renderables_flush( OpenGLStateBucket::Renderables& renderables, OpenGLState& current, unsigned int globalstate, const Vector3& viewer ){ - const Matrix4* transform = 0; - glPushMatrix(); - for ( OpenGLStateBucket::Renderables::const_iterator i = renderables.begin(); i != renderables.end(); ++i ) - { - //qglLoadMatrixf(i->m_transform); - if ( !transform || ( transform != ( *i ).m_transform && !matrix4_affine_equal( *transform, *( *i ).m_transform ) ) ) { - count_transform(); - transform = ( *i ).m_transform; - glPopMatrix(); - glPushMatrix(); - glMultMatrixf( reinterpret_cast( transform ) ); - glFrontFace( ( ( current.m_state & RENDER_CULLFACE ) != 0 && matrix4_handedness( *transform ) == MATRIX4_RIGHTHANDED ) ? GL_CW : GL_CCW ); - } - - count_prim(); - - if ( current.m_program != 0 && ( *i ).m_light != 0 ) { - const IShader& lightShader = static_cast( ( *i ).m_light->getShader() )->getShader(); - if ( lightShader.firstLayer() != 0 ) { - GLuint attenuation_xy = lightShader.firstLayer()->texture()->texture_number; - GLuint attenuation_z = lightShader.lightFalloffImage() != 0 - ? lightShader.lightFalloffImage()->texture_number - : static_cast( g_defaultPointLight )->getShader().lightFalloffImage()->texture_number; - - setTextureState( current.m_texture3, attenuation_xy, GL_TEXTURE3 ); - glActiveTexture( GL_TEXTURE3 ); - glBindTexture( GL_TEXTURE_2D, attenuation_xy ); - glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER ); - glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER ); - - setTextureState( current.m_texture4, attenuation_z, GL_TEXTURE4 ); - glActiveTexture( GL_TEXTURE4 ); - glBindTexture( GL_TEXTURE_2D, attenuation_z ); - glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER ); - glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); - - - AABB lightBounds( ( *i ).m_light->aabb() ); - - Matrix4 world2light( g_matrix4_identity ); - - if ( ( *i ).m_light->isProjected() ) { - world2light = ( *i ).m_light->projection(); - matrix4_multiply_by_matrix4( world2light, matrix4_transposed( ( *i ).m_light->rotation() ) ); - matrix4_translate_by_vec3( world2light, vector3_negated( lightBounds.origin ) ); // world->lightBounds - } - if ( !( *i ).m_light->isProjected() ) { - matrix4_translate_by_vec3( world2light, Vector3( 0.5f, 0.5f, 0.5f ) ); - matrix4_scale_by_vec3( world2light, Vector3( 0.5f, 0.5f, 0.5f ) ); - matrix4_scale_by_vec3( world2light, Vector3( 1.0f / lightBounds.extents.x(), 1.0f / lightBounds.extents.y(), 1.0f / lightBounds.extents.z() ) ); - matrix4_multiply_by_matrix4( world2light, matrix4_transposed( ( *i ).m_light->rotation() ) ); - matrix4_translate_by_vec3( world2light, vector3_negated( lightBounds.origin ) ); // world->lightBounds - } - - current.m_program->setParameters( viewer, *( *i ).m_transform, lightBounds.origin + ( *i ).m_light->offset(), ( *i ).m_light->colour(), world2light ); - debug_string( "set lightBounds parameters" ); - } - } - - ( *i ).m_renderable->render( current.m_state ); - } - glPopMatrix(); - renderables.clear(); -} - -void OpenGLStateBucket::render( OpenGLState& current, unsigned int globalstate, const Vector3& viewer ){ - if ( ( globalstate & m_state.m_state & RENDER_SCREEN ) != 0 ) { - OpenGLState_apply( m_state, current, globalstate ); - debug_colour( "screen fill" ); + debug_string("disabled depth-buffer writing"); + + GlobalOpenGL_debugAssertNoErrors(); + } + + if (delta & state & RENDER_COLOURWRITE) { + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + GlobalOpenGL_debugAssertNoErrors(); + } else if (delta & ~state & RENDER_COLOURWRITE) { + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + GlobalOpenGL_debugAssertNoErrors(); + } + + setState(state, delta, RENDER_ALPHATEST, GL_ALPHA_TEST); + + if (delta & state & RENDER_COLOURARRAY) { + glEnableClientState(GL_COLOR_ARRAY); + GlobalOpenGL_debugAssertNoErrors(); + debug_colour("enabling color_array"); + g_colorArray_enabled = true; + } else if (delta & ~state & RENDER_COLOURARRAY) { + glDisableClientState(GL_COLOR_ARRAY); + glColor4fv(vector4_to_array(self.m_colour)); + debug_colour("cleaning color_array"); + GlobalOpenGL_debugAssertNoErrors(); + g_colorArray_enabled = false; + } + + if (delta & ~state & RENDER_COLOURCHANGE) { + glColor4fv(vector4_to_array(self.m_colour)); + GlobalOpenGL_debugAssertNoErrors(); + } + + setState(state, delta, RENDER_LINESTIPPLE, GL_LINE_STIPPLE); + setState(state, delta, RENDER_LINESMOOTH, GL_LINE_SMOOTH); + + setState(state, delta, RENDER_POLYGONSTIPPLE, GL_POLYGON_STIPPLE); + setState(state, delta, RENDER_POLYGONSMOOTH, GL_POLYGON_SMOOTH); + + setState(state, delta, RENDER_FOG, GL_FOG); + + if ((state & RENDER_FOG) != 0) { + setFogState(self.m_fog); + GlobalOpenGL_debugAssertNoErrors(); + current.m_fog = self.m_fog; + } + + if (state & RENDER_DEPTHTEST && self.m_depthfunc != current.m_depthfunc) { + glDepthFunc(self.m_depthfunc); + GlobalOpenGL_debugAssertNoErrors(); + current.m_depthfunc = self.m_depthfunc; + } + + if (state & RENDER_LINESTIPPLE + && (self.m_linestipple_factor != current.m_linestipple_factor + || self.m_linestipple_pattern != current.m_linestipple_pattern)) { + glLineStipple(self.m_linestipple_factor, self.m_linestipple_pattern); + GlobalOpenGL_debugAssertNoErrors(); + current.m_linestipple_factor = self.m_linestipple_factor; + current.m_linestipple_pattern = self.m_linestipple_pattern; + } + + + if (state & RENDER_ALPHATEST + && (self.m_alphafunc != current.m_alphafunc + || self.m_alpharef != current.m_alpharef)) { + glAlphaFunc(self.m_alphafunc, self.m_alpharef); + GlobalOpenGL_debugAssertNoErrors(); + current.m_alphafunc = self.m_alphafunc; + current.m_alpharef = self.m_alpharef; + } + + { + GLint texture0 = 0; + GLint texture1 = 0; + GLint texture2 = 0; + GLint texture3 = 0; + GLint texture4 = 0; + GLint texture5 = 0; + GLint texture6 = 0; + GLint texture7 = 0; + //if(state & RENDER_TEXTURE) != 0) + { + texture0 = self.m_texture; + texture1 = self.m_texture1; + texture2 = self.m_texture2; + texture3 = self.m_texture3; + texture4 = self.m_texture4; + texture5 = self.m_texture5; + texture6 = self.m_texture6; + texture7 = self.m_texture7; + } + + if (GlobalOpenGL().GL_1_3()) { + setTextureState(current.m_texture, texture0, GL_TEXTURE0); + setTextureState(current.m_texture1, texture1, GL_TEXTURE1); + setTextureState(current.m_texture2, texture2, GL_TEXTURE2); + setTextureState(current.m_texture3, texture3, GL_TEXTURE3); + setTextureState(current.m_texture4, texture4, GL_TEXTURE4); + setTextureState(current.m_texture5, texture5, GL_TEXTURE5); + setTextureState(current.m_texture6, texture6, GL_TEXTURE6); + setTextureState(current.m_texture7, texture7, GL_TEXTURE7); + } else { + setTextureState(current.m_texture, texture0); + } + } + + + if (state & RENDER_TEXTURE && self.m_colour[3] != current.m_colour[3]) { + debug_colour("setting alpha"); + glColor4f(1, 1, 1, self.m_colour[3]); + GlobalOpenGL_debugAssertNoErrors(); + } + + if (!(state & RENDER_TEXTURE) + && (self.m_colour[0] != current.m_colour[0] + || self.m_colour[1] != current.m_colour[1] + || self.m_colour[2] != current.m_colour[2] + || self.m_colour[3] != current.m_colour[3])) { + glColor4fv(vector4_to_array(self.m_colour)); + debug_colour("setting non-texture"); + GlobalOpenGL_debugAssertNoErrors(); + } + current.m_colour = self.m_colour; + + if (state & RENDER_BLEND + && (self.m_blend_src != current.m_blend_src || self.m_blend_dst != current.m_blend_dst)) { + glBlendFunc(self.m_blend_src, self.m_blend_dst); + GlobalOpenGL_debugAssertNoErrors(); + current.m_blend_src = self.m_blend_src; + current.m_blend_dst = self.m_blend_dst; + } + + if (!(state & RENDER_FILL) + && self.m_linewidth != current.m_linewidth) { + glLineWidth(self.m_linewidth); + GlobalOpenGL_debugAssertNoErrors(); + current.m_linewidth = self.m_linewidth; + } + + if (!(state & RENDER_FILL) + && self.m_pointsize != current.m_pointsize) { + glPointSize(self.m_pointsize); + GlobalOpenGL_debugAssertNoErrors(); + current.m_pointsize = self.m_pointsize; + } + + current.m_state = state; + + GlobalOpenGL_debugAssertNoErrors(); +} + +void Renderables_flush(OpenGLStateBucket::Renderables &renderables, OpenGLState ¤t, unsigned int globalstate, + const Vector3 &viewer) +{ + const Matrix4 *transform = 0; + glPushMatrix(); + for (OpenGLStateBucket::Renderables::const_iterator i = renderables.begin(); i != renderables.end(); ++i) { + //qglLoadMatrixf(i->m_transform); + if (!transform || (transform != (*i).m_transform && !matrix4_affine_equal(*transform, *(*i).m_transform))) { + count_transform(); + transform = (*i).m_transform; + glPopMatrix(); + glPushMatrix(); + glMultMatrixf(reinterpret_cast( transform )); + glFrontFace( + ((current.m_state & RENDER_CULLFACE) != 0 && matrix4_handedness(*transform) == MATRIX4_RIGHTHANDED) + ? GL_CW : GL_CCW); + } + + count_prim(); + + if (current.m_program != 0 && (*i).m_light != 0) { + const IShader &lightShader = static_cast((*i).m_light->getShader())->getShader(); + if (lightShader.firstLayer() != 0) { + GLuint attenuation_xy = lightShader.firstLayer()->texture()->texture_number; + GLuint attenuation_z = lightShader.lightFalloffImage() != 0 + ? lightShader.lightFalloffImage()->texture_number + : static_cast( g_defaultPointLight )->getShader().lightFalloffImage()->texture_number; + + setTextureState(current.m_texture3, attenuation_xy, GL_TEXTURE3); + glActiveTexture(GL_TEXTURE3); + glBindTexture(GL_TEXTURE_2D, attenuation_xy); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + + setTextureState(current.m_texture4, attenuation_z, GL_TEXTURE4); + glActiveTexture(GL_TEXTURE4); + glBindTexture(GL_TEXTURE_2D, attenuation_z); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + + AABB lightBounds((*i).m_light->aabb()); + + Matrix4 world2light(g_matrix4_identity); + + if ((*i).m_light->isProjected()) { + world2light = (*i).m_light->projection(); + matrix4_multiply_by_matrix4(world2light, matrix4_transposed((*i).m_light->rotation())); + matrix4_translate_by_vec3(world2light, vector3_negated(lightBounds.origin)); // world->lightBounds + } + if (!(*i).m_light->isProjected()) { + matrix4_translate_by_vec3(world2light, Vector3(0.5f, 0.5f, 0.5f)); + matrix4_scale_by_vec3(world2light, Vector3(0.5f, 0.5f, 0.5f)); + matrix4_scale_by_vec3(world2light, + Vector3(1.0f / lightBounds.extents.x(), 1.0f / lightBounds.extents.y(), + 1.0f / lightBounds.extents.z())); + matrix4_multiply_by_matrix4(world2light, matrix4_transposed((*i).m_light->rotation())); + matrix4_translate_by_vec3(world2light, vector3_negated(lightBounds.origin)); // world->lightBounds + } + + current.m_program->setParameters(viewer, *(*i).m_transform, lightBounds.origin + (*i).m_light->offset(), + (*i).m_light->colour(), world2light); + debug_string("set lightBounds parameters"); + } + } + + (*i).m_renderable->render(current.m_state); + } + glPopMatrix(); + renderables.clear(); +} + +void OpenGLStateBucket::render(OpenGLState ¤t, unsigned int globalstate, const Vector3 &viewer) +{ + if ((globalstate & m_state.m_state & RENDER_SCREEN) != 0) { + OpenGLState_apply(m_state, current, globalstate); + debug_colour("screen fill"); - glMatrixMode( GL_PROJECTION ); - glPushMatrix(); - glLoadMatrixf( reinterpret_cast( &g_matrix4_identity ) ); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadMatrixf(reinterpret_cast( &g_matrix4_identity )); - glMatrixMode( GL_MODELVIEW ); - glPushMatrix(); - glLoadMatrixf( reinterpret_cast( &g_matrix4_identity ) ); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadMatrixf(reinterpret_cast( &g_matrix4_identity )); - glBegin( GL_QUADS ); - glVertex3f( -1, -1, 0 ); - glVertex3f( 1, -1, 0 ); - glVertex3f( 1, 1, 0 ); - glVertex3f( -1, 1, 0 ); - glEnd(); + glBegin(GL_QUADS); + glVertex3f(-1, -1, 0); + glVertex3f(1, -1, 0); + glVertex3f(1, 1, 0); + glVertex3f(-1, 1, 0); + glEnd(); - glMatrixMode( GL_PROJECTION ); - glPopMatrix(); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); - glMatrixMode( GL_MODELVIEW ); - glPopMatrix(); - } - else if ( !m_renderables.empty() ) { - OpenGLState_apply( m_state, current, globalstate ); - Renderables_flush( m_renderables, current, globalstate, viewer ); - } + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + } else if (!m_renderables.empty()) { + OpenGLState_apply(m_state, current, globalstate); + Renderables_flush(m_renderables, current, globalstate, viewer); + } } -class OpenGLStateMap : public OpenGLStateLibrary -{ -typedef std::map States; -States m_states; +class OpenGLStateMap : public OpenGLStateLibrary { + typedef std::map States; + States m_states; public: -~OpenGLStateMap(){ - ASSERT_MESSAGE( m_states.empty(), "OpenGLStateMap::~OpenGLStateMap: not empty" ); -} - -typedef States::iterator iterator; -iterator begin(){ - return m_states.begin(); -} -iterator end(){ - return m_states.end(); -} - -void getDefaultState( OpenGLState& state ) const { - OpenGLState_constructDefault( state ); -} - -void insert( const char* name, const OpenGLState& state ){ - bool inserted = m_states.insert( States::value_type( name, state ) ).second; - ASSERT_MESSAGE( inserted, "OpenGLStateMap::insert: " << name << " already exists" ); -} -void erase( const char* name ){ - std::size_t count = m_states.erase( name ); - ASSERT_MESSAGE( count == 1, "OpenGLStateMap::erase: " << name << " does not exist" ); -} - -iterator find( const char* name ){ - return m_states.find( name ); -} + ~OpenGLStateMap() + { + ASSERT_MESSAGE(m_states.empty(), "OpenGLStateMap::~OpenGLStateMap: not empty"); + } + + typedef States::iterator iterator; + + iterator begin() + { + return m_states.begin(); + } + + iterator end() + { + return m_states.end(); + } + + void getDefaultState(OpenGLState &state) const + { + OpenGLState_constructDefault(state); + } + + void insert(const char *name, const OpenGLState &state) + { + bool inserted = m_states.insert(States::value_type(name, state)).second; + ASSERT_MESSAGE(inserted, "OpenGLStateMap::insert: " << name << " already exists"); + } + + void erase(const char *name) + { + std::size_t count = m_states.erase(name); + ASSERT_MESSAGE(count == 1, "OpenGLStateMap::erase: " << name << " does not exist"); + } + + iterator find(const char *name) + { + return m_states.find(name); + } }; -OpenGLStateMap* g_openglStates = 0; +OpenGLStateMap *g_openglStates = 0; -inline GLenum convertBlendFactor( BlendFactor factor ){ - switch ( factor ) - { - case BLEND_ZERO: - return GL_ZERO; - case BLEND_ONE: - return GL_ONE; - case BLEND_SRC_COLOUR: - return GL_SRC_COLOR; - case BLEND_ONE_MINUS_SRC_COLOUR: - return GL_ONE_MINUS_SRC_COLOR; - case BLEND_SRC_ALPHA: - return GL_SRC_ALPHA; - case BLEND_ONE_MINUS_SRC_ALPHA: - return GL_ONE_MINUS_SRC_ALPHA; - case BLEND_DST_COLOUR: - return GL_DST_COLOR; - case BLEND_ONE_MINUS_DST_COLOUR: - return GL_ONE_MINUS_DST_COLOR; - case BLEND_DST_ALPHA: - return GL_DST_ALPHA; - case BLEND_ONE_MINUS_DST_ALPHA: - return GL_ONE_MINUS_DST_ALPHA; - case BLEND_SRC_ALPHA_SATURATE: - return GL_SRC_ALPHA_SATURATE; - } - return GL_ZERO; +inline GLenum convertBlendFactor(BlendFactor factor) +{ + switch (factor) { + case BLEND_ZERO: + return GL_ZERO; + case BLEND_ONE: + return GL_ONE; + case BLEND_SRC_COLOUR: + return GL_SRC_COLOR; + case BLEND_ONE_MINUS_SRC_COLOUR: + return GL_ONE_MINUS_SRC_COLOR; + case BLEND_SRC_ALPHA: + return GL_SRC_ALPHA; + case BLEND_ONE_MINUS_SRC_ALPHA: + return GL_ONE_MINUS_SRC_ALPHA; + case BLEND_DST_COLOUR: + return GL_DST_COLOR; + case BLEND_ONE_MINUS_DST_COLOUR: + return GL_ONE_MINUS_DST_COLOR; + case BLEND_DST_ALPHA: + return GL_DST_ALPHA; + case BLEND_ONE_MINUS_DST_ALPHA: + return GL_ONE_MINUS_DST_ALPHA; + case BLEND_SRC_ALPHA_SATURATE: + return GL_SRC_ALPHA_SATURATE; + } + return GL_ZERO; } /// \todo Define special-case shaders in a data file. -void OpenGLShader::construct( const char* name ){ - OpenGLState& state = appendDefaultPass(); - switch ( name[0] ) - { - case '(': - sscanf( name, "(%g %g %g)", &state.m_colour[0], &state.m_colour[1], &state.m_colour[2] ); - state.m_colour[3] = 1.0f; - state.m_state = RENDER_FILL | RENDER_LIGHTING | RENDER_DEPTHTEST | RENDER_CULLFACE | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; - state.m_sort = OpenGLState::eSortFullbright; - break; - - case '[': - sscanf( name, "[%g %g %g]", &state.m_colour[0], &state.m_colour[1], &state.m_colour[2] ); - state.m_colour[3] = 0.5f; - state.m_state = RENDER_FILL | RENDER_LIGHTING | RENDER_DEPTHTEST | RENDER_CULLFACE | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_BLEND; - state.m_sort = OpenGLState::eSortTranslucent; - break; - - case '<': - sscanf( name, "<%g %g %g>", &state.m_colour[0], &state.m_colour[1], &state.m_colour[2] ); - state.m_colour[3] = 1; - state.m_state = RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; - state.m_sort = OpenGLState::eSortFullbright; - state.m_depthfunc = GL_LESS; - state.m_linewidth = 1; - state.m_pointsize = 1; - break; - - case '$': - { - OpenGLStateMap::iterator i = g_openglStates->find( name ); - if ( i != g_openglStates->end() ) { - state = ( *i ).second; - break; - } - } - if ( string_equal( name + 1, "POINT" ) ) { - state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; - state.m_sort = OpenGLState::eSortControlFirst; - state.m_pointsize = 4; - } - else if ( string_equal( name + 1, "SELPOINT" ) ) { - state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; - state.m_sort = OpenGLState::eSortControlFirst + 1; - state.m_pointsize = 4; - } - else if ( string_equal( name + 1, "BIGPOINT" ) ) { - state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; - state.m_sort = OpenGLState::eSortControlFirst; - state.m_pointsize = 6; - } - else if ( string_equal( name + 1, "PIVOT" ) ) { - state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHTEST | RENDER_DEPTHWRITE; - state.m_sort = OpenGLState::eSortGUI1; - state.m_linewidth = 2; - state.m_depthfunc = GL_LEQUAL; - - OpenGLState& hiddenLine = appendDefaultPass(); - hiddenLine.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHTEST | RENDER_LINESTIPPLE; - hiddenLine.m_sort = OpenGLState::eSortGUI0; - hiddenLine.m_linewidth = 2; - hiddenLine.m_depthfunc = GL_GREATER; - } - else if ( string_equal( name + 1, "LATTICE" ) ) { - state.m_colour[0] = 1; - state.m_colour[1] = 0.5; - state.m_colour[2] = 0; - state.m_colour[3] = 1; - state.m_state = RENDER_COLOURWRITE | RENDER_DEPTHWRITE; - state.m_sort = OpenGLState::eSortControlFirst; - } - else if ( string_equal( name + 1, "WIREFRAME" ) ) { - state.m_state = RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; - state.m_sort = OpenGLState::eSortFullbright; - } - else if ( string_equal( name + 1, "CAM_HIGHLIGHT" ) ) { - state.m_colour[0] = 1; - state.m_colour[1] = 0; - state.m_colour[2] = 0; - state.m_colour[3] = 0.3f; - state.m_state = RENDER_FILL | RENDER_DEPTHTEST | RENDER_CULLFACE | RENDER_BLEND | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; - state.m_sort = OpenGLState::eSortHighlight; - state.m_depthfunc = GL_LEQUAL; - } - else if ( string_equal( name + 1, "CAM_OVERLAY" ) ) { +void OpenGLShader::construct(const char *name) +{ + OpenGLState &state = appendDefaultPass(); + switch (name[0]) { + case '(': + sscanf(name, "(%g %g %g)", &state.m_colour[0], &state.m_colour[1], &state.m_colour[2]); + state.m_colour[3] = 1.0f; + state.m_state = RENDER_FILL | RENDER_LIGHTING | RENDER_DEPTHTEST | RENDER_CULLFACE | RENDER_COLOURWRITE | + RENDER_DEPTHWRITE; + state.m_sort = OpenGLState::eSortFullbright; + break; + + case '[': + sscanf(name, "[%g %g %g]", &state.m_colour[0], &state.m_colour[1], &state.m_colour[2]); + state.m_colour[3] = 0.5f; + state.m_state = RENDER_FILL | RENDER_LIGHTING | RENDER_DEPTHTEST | RENDER_CULLFACE | RENDER_COLOURWRITE | + RENDER_DEPTHWRITE | RENDER_BLEND; + state.m_sort = OpenGLState::eSortTranslucent; + break; + + case '<': + sscanf(name, "<%g %g %g>", &state.m_colour[0], &state.m_colour[1], &state.m_colour[2]); + state.m_colour[3] = 1; + state.m_state = RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; + state.m_sort = OpenGLState::eSortFullbright; + state.m_depthfunc = GL_LESS; + state.m_linewidth = 1; + state.m_pointsize = 1; + break; + + case '$': { + OpenGLStateMap::iterator i = g_openglStates->find(name); + if (i != g_openglStates->end()) { + state = (*i).second; + break; + } + } + if (string_equal(name + 1, "POINT")) { + state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; + state.m_sort = OpenGLState::eSortControlFirst; + state.m_pointsize = 4; + } else if (string_equal(name + 1, "SELPOINT")) { + state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; + state.m_sort = OpenGLState::eSortControlFirst + 1; + state.m_pointsize = 4; + } else if (string_equal(name + 1, "BIGPOINT")) { + state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; + state.m_sort = OpenGLState::eSortControlFirst; + state.m_pointsize = 6; + } else if (string_equal(name + 1, "PIVOT")) { + state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHTEST | RENDER_DEPTHWRITE; + state.m_sort = OpenGLState::eSortGUI1; + state.m_linewidth = 2; + state.m_depthfunc = GL_LEQUAL; + + OpenGLState &hiddenLine = appendDefaultPass(); + hiddenLine.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHTEST | RENDER_LINESTIPPLE; + hiddenLine.m_sort = OpenGLState::eSortGUI0; + hiddenLine.m_linewidth = 2; + hiddenLine.m_depthfunc = GL_GREATER; + } else if (string_equal(name + 1, "LATTICE")) { + state.m_colour[0] = 1; + state.m_colour[1] = 0.5; + state.m_colour[2] = 0; + state.m_colour[3] = 1; + state.m_state = RENDER_COLOURWRITE | RENDER_DEPTHWRITE; + state.m_sort = OpenGLState::eSortControlFirst; + } else if (string_equal(name + 1, "WIREFRAME")) { + state.m_state = RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; + state.m_sort = OpenGLState::eSortFullbright; + } else if (string_equal(name + 1, "CAM_HIGHLIGHT")) { + state.m_colour[0] = 1; + state.m_colour[1] = 0; + state.m_colour[2] = 0; + state.m_colour[3] = 0.3f; + state.m_state = RENDER_FILL | RENDER_DEPTHTEST | RENDER_CULLFACE | RENDER_BLEND | RENDER_COLOURWRITE | + RENDER_DEPTHWRITE; + state.m_sort = OpenGLState::eSortHighlight; + state.m_depthfunc = GL_LEQUAL; + } else if (string_equal(name + 1, "CAM_OVERLAY")) { #if 0 - state.m_state = RENDER_CULLFACE | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; + state.m_state = RENDER_CULLFACE | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; state.m_sort = OpenGLState::eSortOverlayFirst; #else - state.m_state = RENDER_CULLFACE | RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_OFFSETLINE; - state.m_sort = OpenGLState::eSortOverlayFirst + 1; - state.m_depthfunc = GL_LEQUAL; - - OpenGLState& hiddenLine = appendDefaultPass(); - hiddenLine.m_colour[0] = 0.75; - hiddenLine.m_colour[1] = 0.75; - hiddenLine.m_colour[2] = 0.75; - hiddenLine.m_colour[3] = 1; - hiddenLine.m_state = RENDER_CULLFACE | RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_OFFSETLINE | RENDER_LINESTIPPLE; - hiddenLine.m_sort = OpenGLState::eSortOverlayFirst; - hiddenLine.m_depthfunc = GL_GREATER; - hiddenLine.m_linestipple_factor = 2; + state.m_state = + RENDER_CULLFACE | RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_OFFSETLINE; + state.m_sort = OpenGLState::eSortOverlayFirst + 1; + state.m_depthfunc = GL_LEQUAL; + + OpenGLState &hiddenLine = appendDefaultPass(); + hiddenLine.m_colour[0] = 0.75; + hiddenLine.m_colour[1] = 0.75; + hiddenLine.m_colour[2] = 0.75; + hiddenLine.m_colour[3] = 1; + hiddenLine.m_state = RENDER_CULLFACE | RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_OFFSETLINE | + RENDER_LINESTIPPLE; + hiddenLine.m_sort = OpenGLState::eSortOverlayFirst; + hiddenLine.m_depthfunc = GL_GREATER; + hiddenLine.m_linestipple_factor = 2; #endif - } - else if ( string_equal( name + 1, "XY_OVERLAY" ) ) { - state.m_colour[0] = g_xywindow_globals.color_selbrushes[0]; - state.m_colour[1] = g_xywindow_globals.color_selbrushes[1]; - state.m_colour[2] = g_xywindow_globals.color_selbrushes[2]; - state.m_colour[3] = 1; - state.m_state = RENDER_COLOURWRITE | RENDER_LINESTIPPLE; - state.m_sort = OpenGLState::eSortOverlayFirst; - state.m_linewidth = 2; - state.m_linestipple_factor = 3; - } - else if ( string_equal( name + 1, "DEBUG_CLIPPED" ) ) { - state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; - state.m_sort = OpenGLState::eSortLast; - } - else if ( string_equal( name + 1, "POINTFILE" ) ) { - state.m_colour[0] = 1; - state.m_colour[1] = 0; - state.m_colour[2] = 0; - state.m_colour[3] = 1; - state.m_state = RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; - state.m_sort = OpenGLState::eSortFullbright; - state.m_linewidth = 4; - } - else if ( string_equal( name + 1, "LIGHT_SPHERE" ) ) { - state.m_colour[0] = .15f * .95f; - state.m_colour[1] = .15f * .95f; - state.m_colour[2] = .15f * .95f; - state.m_colour[3] = 1; - state.m_state = RENDER_CULLFACE | RENDER_DEPTHTEST | RENDER_BLEND | RENDER_FILL | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; - state.m_blend_src = GL_ONE; - state.m_blend_dst = GL_ONE; - state.m_sort = OpenGLState::eSortTranslucent; - } - else if ( string_equal( name + 1, "Q3MAP2_LIGHT_SPHERE" ) ) { - state.m_colour[0] = .05f; - state.m_colour[1] = .05f; - state.m_colour[2] = .05f; - state.m_colour[3] = 1; - state.m_state = RENDER_CULLFACE | RENDER_DEPTHTEST | RENDER_BLEND | RENDER_FILL; - state.m_blend_src = GL_ONE; - state.m_blend_dst = GL_ONE; - state.m_sort = OpenGLState::eSortTranslucent; - } - else if ( string_equal( name + 1, "WIRE_OVERLAY" ) ) { + } else if (string_equal(name + 1, "XY_OVERLAY")) { + state.m_colour[0] = g_xywindow_globals.color_selbrushes[0]; + state.m_colour[1] = g_xywindow_globals.color_selbrushes[1]; + state.m_colour[2] = g_xywindow_globals.color_selbrushes[2]; + state.m_colour[3] = 1; + state.m_state = RENDER_COLOURWRITE | RENDER_LINESTIPPLE; + state.m_sort = OpenGLState::eSortOverlayFirst; + state.m_linewidth = 2; + state.m_linestipple_factor = 3; + } else if (string_equal(name + 1, "DEBUG_CLIPPED")) { + state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; + state.m_sort = OpenGLState::eSortLast; + } else if (string_equal(name + 1, "POINTFILE")) { + state.m_colour[0] = 1; + state.m_colour[1] = 0; + state.m_colour[2] = 0; + state.m_colour[3] = 1; + state.m_state = RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; + state.m_sort = OpenGLState::eSortFullbright; + state.m_linewidth = 4; + } else if (string_equal(name + 1, "LIGHT_SPHERE")) { + state.m_colour[0] = .15f * .95f; + state.m_colour[1] = .15f * .95f; + state.m_colour[2] = .15f * .95f; + state.m_colour[3] = 1; + state.m_state = RENDER_CULLFACE | RENDER_DEPTHTEST | RENDER_BLEND | RENDER_FILL | RENDER_COLOURWRITE | + RENDER_DEPTHWRITE; + state.m_blend_src = GL_ONE; + state.m_blend_dst = GL_ONE; + state.m_sort = OpenGLState::eSortTranslucent; + } else if (string_equal(name + 1, "Q3MAP2_LIGHT_SPHERE")) { + state.m_colour[0] = .05f; + state.m_colour[1] = .05f; + state.m_colour[2] = .05f; + state.m_colour[3] = 1; + state.m_state = RENDER_CULLFACE | RENDER_DEPTHTEST | RENDER_BLEND | RENDER_FILL; + state.m_blend_src = GL_ONE; + state.m_blend_dst = GL_ONE; + state.m_sort = OpenGLState::eSortTranslucent; + } else if (string_equal(name + 1, "WIRE_OVERLAY")) { #if 0 - state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE; + state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE; state.m_sort = OpenGLState::eSortOverlayFirst; #else - state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE; - state.m_sort = OpenGLState::eSortGUI1; - state.m_depthfunc = GL_LEQUAL; - - OpenGLState& hiddenLine = appendDefaultPass(); - hiddenLine.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE | RENDER_LINESTIPPLE; - hiddenLine.m_sort = OpenGLState::eSortGUI0; - hiddenLine.m_depthfunc = GL_GREATER; + state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | + RENDER_OVERRIDE; + state.m_sort = OpenGLState::eSortGUI1; + state.m_depthfunc = GL_LEQUAL; + + OpenGLState &hiddenLine = appendDefaultPass(); + hiddenLine.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | + RENDER_OVERRIDE | RENDER_LINESTIPPLE; + hiddenLine.m_sort = OpenGLState::eSortGUI0; + hiddenLine.m_depthfunc = GL_GREATER; #endif - } - else if ( string_equal( name + 1, "FLATSHADE_OVERLAY" ) ) { - state.m_state = RENDER_CULLFACE | RENDER_LIGHTING | RENDER_SMOOTH | RENDER_SCALED | RENDER_COLOURARRAY | RENDER_FILL | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE; - state.m_sort = OpenGLState::eSortGUI1; - state.m_depthfunc = GL_LEQUAL; - - OpenGLState& hiddenLine = appendDefaultPass(); - 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; - hiddenLine.m_sort = OpenGLState::eSortGUI0; - hiddenLine.m_depthfunc = GL_GREATER; - } - else if ( string_equal( name + 1, "CLIPPER_OVERLAY" ) ) { - state.m_colour[0] = g_xywindow_globals.color_clipper[0]; - state.m_colour[1] = g_xywindow_globals.color_clipper[1]; - state.m_colour[2] = g_xywindow_globals.color_clipper[2]; - state.m_colour[3] = 1; - state.m_state = RENDER_CULLFACE | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_FILL | RENDER_POLYGONSTIPPLE; - state.m_sort = OpenGLState::eSortOverlayFirst; - } - else if ( string_equal( name + 1, "OVERBRIGHT" ) ) { - const float lightScale = 2; - state.m_colour[0] = lightScale * 0.5f; - state.m_colour[1] = lightScale * 0.5f; - state.m_colour[2] = lightScale * 0.5f; - state.m_colour[3] = 0.5; - state.m_state = RENDER_FILL | RENDER_BLEND | RENDER_COLOURWRITE | RENDER_SCREEN; - state.m_sort = OpenGLState::eSortOverbrighten; - state.m_blend_src = GL_DST_COLOR; - state.m_blend_dst = GL_SRC_COLOR; - } - else - { - // default to something recognisable.. =) - ERROR_MESSAGE( "hardcoded renderstate not found" ); - state.m_colour[0] = 1; - state.m_colour[1] = 0; - state.m_colour[2] = 1; - state.m_colour[3] = 1; - state.m_state = RENDER_COLOURWRITE | RENDER_DEPTHWRITE; - state.m_sort = OpenGLState::eSortFirst; - } - break; - default: - // construction from IShader - m_shader = QERApp_Shader_ForName( name ); - - if ( g_ShaderCache->lightingSupported() && g_ShaderCache->lightingEnabled() && m_shader->getBump() != 0 && m_shader->getBump()->texture_number != 0 ) { // is a bump shader - state.m_state = RENDER_FILL | RENDER_CULLFACE | RENDER_TEXTURE | RENDER_DEPTHTEST | RENDER_DEPTHWRITE | RENDER_COLOURWRITE | RENDER_PROGRAM; - state.m_colour[0] = 0; - state.m_colour[1] = 0; - state.m_colour[2] = 0; - state.m_colour[3] = 1; - state.m_sort = OpenGLState::eSortOpaque; - - if ( g_ShaderCache->useShaderLanguage() ) { - state.m_program = &g_depthFillGLSL; - } - else - { - state.m_program = &g_depthFillARB; - } - - OpenGLState& bumpPass = appendDefaultPass(); - bumpPass.m_texture = m_shader->getDiffuse()->texture_number; - bumpPass.m_texture1 = m_shader->getBump()->texture_number; - bumpPass.m_texture2 = m_shader->getSpecular()->texture_number; - - bumpPass.m_state = RENDER_BLEND | RENDER_FILL | RENDER_CULLFACE | RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_SMOOTH | RENDER_BUMP | RENDER_PROGRAM; - - if ( g_ShaderCache->useShaderLanguage() ) { - bumpPass.m_state |= RENDER_LIGHTING; - bumpPass.m_program = &g_bumpGLSL; - } - else - { - bumpPass.m_program = &g_bumpARB; - } - - bumpPass.m_depthfunc = GL_LEQUAL; - bumpPass.m_sort = OpenGLState::eSortMultiFirst; - bumpPass.m_blend_src = GL_ONE; - bumpPass.m_blend_dst = GL_ONE; - } - else - { - state.m_texture = m_shader->getTexture()->texture_number; - - state.m_state = RENDER_FILL | RENDER_TEXTURE | RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_LIGHTING | RENDER_SMOOTH; - if ( ( m_shader->getFlags() & QER_CULL ) != 0 ) { - if ( m_shader->getCull() == IShader::eCullBack ) { - state.m_state |= RENDER_CULLFACE; - } - } - else - { - state.m_state |= RENDER_CULLFACE; - } - if ( ( m_shader->getFlags() & QER_ALPHATEST ) != 0 ) { - state.m_state |= RENDER_ALPHATEST; - IShader::EAlphaFunc alphafunc; - m_shader->getAlphaFunc( &alphafunc, &state.m_alpharef ); - switch ( alphafunc ) - { - case IShader::eAlways: - state.m_alphafunc = GL_ALWAYS; - case IShader::eEqual: - state.m_alphafunc = GL_EQUAL; - case IShader::eLess: - state.m_alphafunc = GL_LESS; - case IShader::eGreater: - state.m_alphafunc = GL_GREATER; - case IShader::eLEqual: - state.m_alphafunc = GL_LEQUAL; - case IShader::eGEqual: - state.m_alphafunc = GL_GEQUAL; - } - } - reinterpret_cast( state.m_colour ) = m_shader->getTexture()->color; - state.m_colour[3] = 1.0f; - - if ( ( m_shader->getFlags() & QER_TRANS ) != 0 ) { - state.m_state |= RENDER_BLEND; - state.m_colour[3] = m_shader->getTrans(); - state.m_sort = OpenGLState::eSortTranslucent; - BlendFunc blendFunc = m_shader->getBlendFunc(); - state.m_blend_src = convertBlendFactor( blendFunc.m_src ); - state.m_blend_dst = convertBlendFactor( blendFunc.m_dst ); - if ( state.m_blend_src == GL_SRC_ALPHA || state.m_blend_dst == GL_SRC_ALPHA ) { - state.m_state |= RENDER_DEPTHWRITE; - } - } - else - { - state.m_state |= RENDER_DEPTHWRITE; - state.m_sort = OpenGLState::eSortFullbright; - } - } - } + } else if (string_equal(name + 1, "FLATSHADE_OVERLAY")) { + state.m_state = RENDER_CULLFACE | RENDER_LIGHTING | RENDER_SMOOTH | RENDER_SCALED | RENDER_COLOURARRAY | + RENDER_FILL | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | + RENDER_OVERRIDE; + state.m_sort = OpenGLState::eSortGUI1; + state.m_depthfunc = GL_LEQUAL; + + OpenGLState &hiddenLine = appendDefaultPass(); + 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; + hiddenLine.m_sort = OpenGLState::eSortGUI0; + hiddenLine.m_depthfunc = GL_GREATER; + } else if (string_equal(name + 1, "CLIPPER_OVERLAY")) { + state.m_colour[0] = g_xywindow_globals.color_clipper[0]; + state.m_colour[1] = g_xywindow_globals.color_clipper[1]; + state.m_colour[2] = g_xywindow_globals.color_clipper[2]; + state.m_colour[3] = 1; + state.m_state = + RENDER_CULLFACE | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_FILL | RENDER_POLYGONSTIPPLE; + state.m_sort = OpenGLState::eSortOverlayFirst; + } else if (string_equal(name + 1, "OVERBRIGHT")) { + const float lightScale = 2; + state.m_colour[0] = lightScale * 0.5f; + state.m_colour[1] = lightScale * 0.5f; + state.m_colour[2] = lightScale * 0.5f; + state.m_colour[3] = 0.5; + state.m_state = RENDER_FILL | RENDER_BLEND | RENDER_COLOURWRITE | RENDER_SCREEN; + state.m_sort = OpenGLState::eSortOverbrighten; + state.m_blend_src = GL_DST_COLOR; + state.m_blend_dst = GL_SRC_COLOR; + } else { + // default to something recognisable.. =) + ERROR_MESSAGE("hardcoded renderstate not found"); + state.m_colour[0] = 1; + state.m_colour[1] = 0; + state.m_colour[2] = 1; + state.m_colour[3] = 1; + state.m_state = RENDER_COLOURWRITE | RENDER_DEPTHWRITE; + state.m_sort = OpenGLState::eSortFirst; + } + break; + default: + // construction from IShader + m_shader = QERApp_Shader_ForName(name); + + if (g_ShaderCache->lightingSupported() && g_ShaderCache->lightingEnabled() && m_shader->getBump() != 0 && + m_shader->getBump()->texture_number != 0) { // is a bump shader + state.m_state = RENDER_FILL | RENDER_CULLFACE | RENDER_TEXTURE | RENDER_DEPTHTEST | RENDER_DEPTHWRITE | + RENDER_COLOURWRITE | RENDER_PROGRAM; + state.m_colour[0] = 0; + state.m_colour[1] = 0; + state.m_colour[2] = 0; + state.m_colour[3] = 1; + state.m_sort = OpenGLState::eSortOpaque; + + if (g_ShaderCache->useShaderLanguage()) { + state.m_program = &g_depthFillGLSL; + } else { + state.m_program = &g_depthFillARB; + } + + OpenGLState &bumpPass = appendDefaultPass(); + bumpPass.m_texture = m_shader->getDiffuse()->texture_number; + bumpPass.m_texture1 = m_shader->getBump()->texture_number; + bumpPass.m_texture2 = m_shader->getSpecular()->texture_number; + + bumpPass.m_state = + RENDER_BLEND | RENDER_FILL | RENDER_CULLFACE | RENDER_DEPTHTEST | RENDER_COLOURWRITE | + RENDER_SMOOTH | RENDER_BUMP | RENDER_PROGRAM; + + if (g_ShaderCache->useShaderLanguage()) { + bumpPass.m_state |= RENDER_LIGHTING; + bumpPass.m_program = &g_bumpGLSL; + } else { + bumpPass.m_program = &g_bumpARB; + } + + bumpPass.m_depthfunc = GL_LEQUAL; + bumpPass.m_sort = OpenGLState::eSortMultiFirst; + bumpPass.m_blend_src = GL_ONE; + bumpPass.m_blend_dst = GL_ONE; + } else { + state.m_texture = m_shader->getTexture()->texture_number; + + state.m_state = RENDER_FILL | RENDER_TEXTURE | RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_LIGHTING | + RENDER_SMOOTH; + if ((m_shader->getFlags() & QER_CULL) != 0) { + if (m_shader->getCull() == IShader::eCullBack) { + state.m_state |= RENDER_CULLFACE; + } + } else { + state.m_state |= RENDER_CULLFACE; + } + if ((m_shader->getFlags() & QER_ALPHATEST) != 0) { + state.m_state |= RENDER_ALPHATEST; + IShader::EAlphaFunc alphafunc; + m_shader->getAlphaFunc(&alphafunc, &state.m_alpharef); + switch (alphafunc) { + case IShader::eAlways: + state.m_alphafunc = GL_ALWAYS; + case IShader::eEqual: + state.m_alphafunc = GL_EQUAL; + case IShader::eLess: + state.m_alphafunc = GL_LESS; + case IShader::eGreater: + state.m_alphafunc = GL_GREATER; + case IShader::eLEqual: + state.m_alphafunc = GL_LEQUAL; + case IShader::eGEqual: + state.m_alphafunc = GL_GEQUAL; + } + } + reinterpret_cast( state.m_colour ) = m_shader->getTexture()->color; + state.m_colour[3] = 1.0f; + + if ((m_shader->getFlags() & QER_TRANS) != 0) { + state.m_state |= RENDER_BLEND; + state.m_colour[3] = m_shader->getTrans(); + state.m_sort = OpenGLState::eSortTranslucent; + BlendFunc blendFunc = m_shader->getBlendFunc(); + state.m_blend_src = convertBlendFactor(blendFunc.m_src); + state.m_blend_dst = convertBlendFactor(blendFunc.m_dst); + if (state.m_blend_src == GL_SRC_ALPHA || state.m_blend_dst == GL_SRC_ALPHA) { + state.m_state |= RENDER_DEPTHWRITE; + } + } else { + state.m_state |= RENDER_DEPTHWRITE; + state.m_sort = OpenGLState::eSortFullbright; + } + } + } } #include "modulesystem/singletonmodule.h" #include "modulesystem/moduleregistry.h" -class OpenGLStateLibraryAPI -{ -OpenGLStateMap m_stateMap; +class OpenGLStateLibraryAPI { + OpenGLStateMap m_stateMap; public: -typedef OpenGLStateLibrary Type; -STRING_CONSTANT( Name, "*" ); + typedef OpenGLStateLibrary Type; -OpenGLStateLibraryAPI(){ - g_openglStates = &m_stateMap; -} -~OpenGLStateLibraryAPI(){ - g_openglStates = 0; -} -OpenGLStateLibrary* getTable(){ - return &m_stateMap; -} + STRING_CONSTANT(Name, "*"); + + OpenGLStateLibraryAPI() + { + g_openglStates = &m_stateMap; + } + + ~OpenGLStateLibraryAPI() + { + g_openglStates = 0; + } + + OpenGLStateLibrary *getTable() + { + return &m_stateMap; + } }; typedef SingletonModule OpenGLStateLibraryModule; typedef Static StaticOpenGLStateLibraryModule; -StaticRegisterModule staticRegisterOpenGLStateLibrary( StaticOpenGLStateLibraryModule::instance() ); +StaticRegisterModule staticRegisterOpenGLStateLibrary(StaticOpenGLStateLibraryModule::instance()); -class ShaderCacheDependencies : public GlobalShadersModuleRef, public GlobalTexturesModuleRef, public GlobalOpenGLStateLibraryModuleRef -{ +class ShaderCacheDependencies + : public GlobalShadersModuleRef, public GlobalTexturesModuleRef, public GlobalOpenGLStateLibraryModuleRef { public: -ShaderCacheDependencies() : - GlobalShadersModuleRef( GlobalRadiant().getRequiredGameDescriptionKeyValue( "shaders" ) ){ -} + ShaderCacheDependencies() : + GlobalShadersModuleRef(GlobalRadiant().getRequiredGameDescriptionKeyValue("shaders")) + { + } }; -class ShaderCacheAPI -{ -ShaderCache* m_shaderCache; +class ShaderCacheAPI { + ShaderCache *m_shaderCache; public: -typedef ShaderCache Type; -STRING_CONSTANT( Name, "*" ); + typedef ShaderCache Type; -ShaderCacheAPI(){ - ShaderCache_Construct(); + STRING_CONSTANT(Name, "*"); - m_shaderCache = GetShaderCache(); -} -~ShaderCacheAPI(){ - ShaderCache_Destroy(); -} -ShaderCache* getTable(){ - return m_shaderCache; -} + ShaderCacheAPI() + { + ShaderCache_Construct(); + + m_shaderCache = GetShaderCache(); + } + + ~ShaderCacheAPI() + { + ShaderCache_Destroy(); + } + + ShaderCache *getTable() + { + return m_shaderCache; + } }; typedef SingletonModule ShaderCacheModule; typedef Static StaticShaderCacheModule; -StaticRegisterModule staticRegisterShaderCache( StaticShaderCacheModule::instance() ); +StaticRegisterModule staticRegisterShaderCache(StaticShaderCacheModule::instance());