-
- 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<LightCullable*, LinearLightList> 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<OpenGLShaderCache, &OpenGLShaderCache::evaluateChanged> EvaluateChangedCaller;
-
- typedef std::set<const Renderable*> 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;
- }
+
+ 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<LightCullable*, LinearLightList> 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<OpenGLShaderCache, void(), &OpenGLShaderCache::evaluateChanged> EvaluateChangedCaller;
+
+typedef std::set<const Renderable*> 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;
+}