diff --git a/include/iglrender.h b/include/iglrender.h index 04b4a807..2c079052 100644 --- a/include/iglrender.h +++ b/include/iglrender.h @@ -61,8 +61,8 @@ enum ESort eSortMultiLast = 1023, eSortOverbrighten = 1024, eSortFullbright = 1025, - eSortHighlight = 1026, - eSortTranslucent = 1027, + eSortTranslucent = 1026, + eSortHighlight = 1027, eSortOverlayFirst = 1028, eSortOverlayLast = 2047, eSortControlFirst = 2048, diff --git a/libs/eclasslib.h b/libs/eclasslib.h index d2730d62..08367ae0 100644 --- a/libs/eclasslib.h +++ b/libs/eclasslib.h @@ -159,6 +159,10 @@ inline EntityClassAttributePair& EntityClass_insertAttribute( EntityClass& entit } +inline void buffer_write_colour_add( char buffer[128], const Colour3& colour ){ + sprintf( buffer, "{%g %g %g}", colour[0], colour[1], colour[2] ); +} + inline void buffer_write_colour_fill( char buffer[128], const Colour3& colour ){ sprintf( buffer, "(%g %g %g)", colour[0], colour[1], colour[2] ); } @@ -171,6 +175,18 @@ inline void buffer_write_colour_blend( char buffer[128], const Colour3& colour ) sprintf( buffer, "[%g %g %g]", colour[0], colour[1], colour[2] ); } +inline Shader* colour_capture_state_add( const Colour3& colour ){ + char buffer[128]; + buffer_write_colour_add( buffer, colour ); + return GlobalShaderCache().capture( buffer ); +} + +inline void colour_release_state_add( const Colour3& colour ){ + char buffer[128]; + buffer_write_colour_add( buffer, colour ); + GlobalShaderCache().release( buffer ); +} + inline Shader* colour_capture_state_fill( const Colour3& colour ){ char buffer[128]; buffer_write_colour_fill( buffer, colour ); diff --git a/plugins/entity/colour.h b/plugins/entity/colour.h index e0b42ad7..159703e0 100644 --- a/plugins/entity/colour.h +++ b/plugins/entity/colour.h @@ -49,12 +49,15 @@ class Colour { Callback m_colourChanged; Shader* m_state; +Shader* m_state_additive; void capture_state(){ m_state = colour_capture_state_fill( m_colour ); + m_state_additive = colour_capture_state_add( m_colour ); } void release_state(){ colour_release_state_fill( m_colour ); + colour_release_state_add( m_colour ); } public: @@ -86,6 +89,9 @@ void write( Entity* entity ) const { Shader* state() const { return m_state; } +Shader* state_additive() const { + return m_state_additive; +} }; #endif diff --git a/plugins/entity/light.cpp b/plugins/entity/light.cpp index db625fa6..55c2033e 100644 --- a/plugins/entity/light.cpp +++ b/plugins/entity/light.cpp @@ -66,7 +66,61 @@ #include "entity.h" extern bool g_newLightDraw; +#define SPHERE_FILL_SIDES 16 +#define SPHERE_FILL_POINTS SPHERE_FILL_SIDES * (SPHERE_FILL_SIDES - 1) * 6 + SPHERE_FILL_SIDES * 3 +#define SPHERE_WIRE_SIDES 24 +#define SPHERE_WIRE_POINTS SPHERE_WIRE_SIDES * 3 + +void sphere_construct_fill( Vector3 (&radiiPoints)[SPHERE_FILL_POINTS] ){ + + const double dt = c_2pi / static_cast( SPHERE_FILL_SIDES ); + const double dp = c_pi / static_cast( SPHERE_FILL_SIDES ); + int k = 0; + + for ( int i = 0; i <= SPHERE_FILL_SIDES - 1; ++i ) + { + for ( int j = 0; j <= SPHERE_FILL_SIDES - 2; ++j ) + { + const double t = i * dt; + const double p = ( j * dp ) - ( c_pi / 2.0 ); + + radiiPoints[k++] = vector3_for_spherical( t, p ); + radiiPoints[k++] = vector3_for_spherical( t, p + dp ); + radiiPoints[k++] = vector3_for_spherical( t + dt, p + dp ); + radiiPoints[k++] = vector3_for_spherical( t, p ); + radiiPoints[k++] = vector3_for_spherical( t + dt, p + dp ); + radiiPoints[k++] = vector3_for_spherical( t + dt, p ); + } + } + + { + const double p = ( SPHERE_FILL_SIDES - 1 ) * dp - ( c_pi / 2.0 ); + for ( int i = 0; i <= SPHERE_FILL_SIDES - 1; ++i ) + { + const double t = i * dt; + + radiiPoints[k++] = vector3_for_spherical( t, p ); + radiiPoints[k++] = vector3_for_spherical( t + dt, p + dp ); + radiiPoints[k++] = vector3_for_spherical( t + dt, p ); + } + } +} + +void sphere_draw_fill_( const Vector3& origin, float radius, const Vector3 (&radiiPoints)[SPHERE_FILL_POINTS] ){ + if ( radius <= 0 ) { + return; + } + + glBegin( GL_TRIANGLES ); + for ( int i = 0; i < SPHERE_FILL_POINTS; ++i ) + { + glVertex3fv( vector3_to_array( vector3_added( origin, vector3_scaled( radiiPoints[i], radius ) ) ) ); + } + glEnd(); +} + +#if 0 void sphere_draw_fill( const Vector3& origin, float radius, int sides ){ if ( radius <= 0 ) { return; @@ -195,6 +249,67 @@ void sphere_draw_wire( const Vector3& origin, float radius, int sides ){ glEnd(); } } +#endif // 0 + +void sphere_construct_wire( Vector3 (&radiiPoints)[SPHERE_WIRE_POINTS] ){ + int k = 0; + + for ( int i = 0; i < SPHERE_WIRE_SIDES; i++ ) + { + double ds = sin( ( i * 2 * c_pi ) / SPHERE_WIRE_SIDES ); + double dc = cos( ( i * 2 * c_pi ) / SPHERE_WIRE_SIDES ); + + radiiPoints[k++] = + Vector3( + static_cast( dc ), + static_cast( ds ), + 0.f + ); + } + + for ( int i = 0; i < SPHERE_WIRE_SIDES; i++ ) + { + double ds = sin( ( i * 2 * c_pi ) / SPHERE_WIRE_SIDES ); + double dc = cos( ( i * 2 * c_pi ) / SPHERE_WIRE_SIDES ); + + radiiPoints[k++] = + Vector3( + static_cast( dc ), + 0.f, + static_cast( ds ) + ); + } + + for ( int i = 0; i < SPHERE_WIRE_SIDES; i++ ) + { + double ds = sin( ( i * 2 * c_pi ) / SPHERE_WIRE_SIDES ); + double dc = cos( ( i * 2 * c_pi ) / SPHERE_WIRE_SIDES ); + + radiiPoints[k++] = + Vector3( + 0.f, + static_cast( dc ), + static_cast( ds ) + ); + } + +} + + +void sphere_draw_wire_( const Vector3& origin, float radius, const Vector3 (&radiiPoints)[SPHERE_WIRE_POINTS] ){ + int k = 0; + for( int j = 0; j < 3; j++ ) + { + glBegin( GL_LINE_LOOP ); + + for ( int i = 0; i < SPHERE_WIRE_SIDES; i++ ) + { + glVertex3fv( vector3_to_array( vector3_added( origin, vector3_scaled( radiiPoints[k++], radius ) ) ) ); + } + + glEnd(); + } +} void light_draw_box_lines( const Vector3& origin, const Vector3 points[8] ){ //draw lines from the center of the bbox to the corners @@ -226,7 +341,7 @@ void light_draw_box_lines( const Vector3& origin, const Vector3 points[8] ){ glEnd(); } - +#if 0 void light_draw_radius_wire( const Vector3& origin, const float envelope[3] ){ if ( envelope[0] > 0 ) { sphere_draw_wire( origin, envelope[0], 24 ); @@ -238,7 +353,19 @@ void light_draw_radius_wire( const Vector3& origin, const float envelope[3] ){ sphere_draw_wire( origin, envelope[2], 24 ); } } - +#endif // 0 +void light_draw_radius_wire_( const Vector3& origin, const float envelope[3], const Vector3 (&radiiPoints)[SPHERE_WIRE_POINTS] ){ + if ( envelope[0] > 0 ) { + sphere_draw_wire_( origin, envelope[0], radiiPoints ); + } + if ( envelope[1] > 0 ) { + sphere_draw_wire_( origin, envelope[1], radiiPoints ); + } + if ( envelope[2] > 0 ) { + sphere_draw_wire_( origin, envelope[2], radiiPoints ); + } +} +#if 0 void light_draw_radius_fill( const Vector3& origin, const float envelope[3] ){ if ( envelope[0] > 0 ) { sphere_draw_fill( origin, envelope[0], 16 ); @@ -250,6 +377,18 @@ void light_draw_radius_fill( const Vector3& origin, const float envelope[3] ){ sphere_draw_fill( origin, envelope[2], 16 ); } } +#endif // 0 +void light_draw_radius_fill_( const Vector3& origin, const float envelope[3], const Vector3 (&radiiPoints)[SPHERE_FILL_POINTS] ){ + if ( envelope[0] > 0 ) { + sphere_draw_fill_( origin, envelope[0], radiiPoints ); + } + if ( envelope[1] > 0 ) { + sphere_draw_fill_( origin, envelope[1], radiiPoints ); + } + if ( envelope[2] > 0 ) { + sphere_draw_fill_( origin, envelope[2], radiiPoints ); + } +} void light_vertices( const AABB& aabb_light, Vector3 points[6] ){ Vector3 max( vector3_added( aabb_light.origin, aabb_light.extents ) ); @@ -533,7 +672,7 @@ bool m_useCenterKey; Doom3LightRadius( const char* defaultRadius ) : m_defaultRadius( 300, 300, 300 ), m_center( 0, 0, 0 ), m_useCenterKey( false ){ if ( g_lightType == LIGHTTYPE_DOOM3 ){ if ( !string_parse_vector3( defaultRadius, m_defaultRadius ) ) { - globalErrorStream() << "Doom3LightRadius: failed to parse default light radius\n"; + globalErrorStream() << "Doom3LightRadius: failed to parse default light radius\n"; } m_radius = m_defaultRadius; } @@ -564,33 +703,41 @@ class RenderLightRadiiWire : public OpenGLRenderable LightRadii& m_radii; const Vector3& m_origin; public: +static Vector3 m_radiiPoints[SPHERE_WIRE_POINTS]; + RenderLightRadiiWire( LightRadii& radii, const Vector3& origin ) : m_radii( radii ), m_origin( origin ){ } void render( RenderStateFlags state ) const { - light_draw_radius_wire( m_origin, m_radii.m_radii ); + //light_draw_radius_wire( m_origin, m_radii.m_radii ); + light_draw_radius_wire_( m_origin, m_radii.m_radii, m_radiiPoints ); } }; +Vector3 RenderLightRadiiWire::m_radiiPoints[SPHERE_WIRE_POINTS] = {g_vector3_identity}; class RenderLightRadiiFill : public OpenGLRenderable { LightRadii& m_radii; const Vector3& m_origin; public: -static Shader* m_state; +//static Shader* m_state; +static Vector3 m_radiiPoints[SPHERE_FILL_POINTS]; RenderLightRadiiFill( LightRadii& radii, const Vector3& origin ) : m_radii( radii ), m_origin( origin ){ } void render( RenderStateFlags state ) const { - light_draw_radius_fill( m_origin, m_radii.m_radii ); + //light_draw_radius_fill( m_origin, m_radii.m_radii ); + light_draw_radius_fill_( m_origin, m_radii.m_radii, m_radiiPoints ); } }; +//Shader* RenderLightRadiiFill::m_state = 0; +Vector3 RenderLightRadiiFill::m_radiiPoints[SPHERE_FILL_POINTS] = {g_vector3_identity}; class RenderLightRadiiBox : public OpenGLRenderable { const Vector3& m_origin; public: mutable Vector3 m_points[8]; -static Shader* m_state; +//static Shader* m_state; RenderLightRadiiBox( const Vector3& origin ) : m_origin( origin ){ } @@ -610,8 +757,6 @@ void render( RenderStateFlags state ) const { } }; -Shader* RenderLightRadiiFill::m_state = 0; - class RenderLightCenter : public OpenGLRenderable { const Vector3& m_center; @@ -1104,18 +1249,20 @@ const AABB& localAABB() const { mutable Matrix4 m_projectionOrientation; void renderSolid( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, bool selected ) const { - renderer.SetState( m_entity.getEntityClass().m_state_wire, Renderer::eWireframeOnly ); + renderer.SetState( m_colour.state(), Renderer::eWireframeOnly ); renderer.SetState( m_colour.state(), Renderer::eFullMaterials ); renderer.addRenderable( *this, localToWorld ); if ( selected && g_lightRadii && string_empty( m_entity.getKeyValue( "target" ) ) ) { if ( renderer.getStyle() == Renderer::eFullMaterials ) { - renderer.SetState( RenderLightRadiiFill::m_state, Renderer::eFullMaterials ); + renderer.SetState( m_colour.state_add(), Renderer::eFullMaterials ); renderer.Highlight( Renderer::ePrimitive, false ); + renderer.Highlight( Renderer::eFace, false ); renderer.addRenderable( m_radii_fill, localToWorld ); } else { + renderer.Highlight( Renderer::ePrimitive, false ); renderer.addRenderable( m_radii_wire, localToWorld ); } } @@ -1709,11 +1856,13 @@ void Light_Construct( LightType lightType ){ LightShader::m_defaultShader = "lights/defaultProjectedLight"; #endif } - RenderLightRadiiFill::m_state = GlobalShaderCache().capture( "$Q3MAP2_LIGHT_SPHERE" ); + //RenderLightRadiiFill::m_state = GlobalShaderCache().capture( "$Q3MAP2_LIGHT_SPHERE" ); RenderLightCenter::m_state = GlobalShaderCache().capture( "$BIGPOINT" ); + sphere_construct_fill( RenderLightRadiiFill::m_radiiPoints ); + sphere_construct_wire( RenderLightRadiiWire::m_radiiPoints ); } void Light_Destroy(){ - GlobalShaderCache().release( "$Q3MAP2_LIGHT_SPHERE" ); + //GlobalShaderCache().release( "$Q3MAP2_LIGHT_SPHERE" ); GlobalShaderCache().release( "$BIGPOINT" ); } diff --git a/radiant/renderstate.cpp b/radiant/renderstate.cpp index b17342db..924688a6 100644 --- a/radiant/renderstate.cpp +++ b/radiant/renderstate.cpp @@ -1192,6 +1192,7 @@ Shader* capture( const char* name ){ || *name == '[' || *name == '<' || *name == '(' + || *name == '{' || strchr( name, '\\' ) == 0, "shader name contains invalid characters: \"" << name << "\"" ); #if DEBUG_SHADERS globalOutputStream() << "shaders capture: " << makeQuoted( name ) << '\n'; @@ -2080,21 +2081,30 @@ void OpenGLShader::construct( const char* name ){ OpenGLState& state = appendDefaultPass(); switch ( name[0] ) { - case '(': + case '{': //add + 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_CULLFACE | RENDER_DEPTHTEST | RENDER_BLEND | RENDER_FILL | RENDER_COLOURWRITE /*| RENDER_DEPTHWRITE*/ | RENDER_LIGHTING; + state.m_blend_src = GL_ONE; + state.m_blend_dst = GL_ONE; + state.m_sort = OpenGLState::eSortTranslucent; + break; + + case '(': //fill 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 '[': + case '[': //blend 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 '<': + case '<': //wire 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; @@ -2156,7 +2166,7 @@ void OpenGLShader::construct( const char* name ){ state.m_colour[1] = g_camwindow_globals.color_selbrushes3d[1]; state.m_colour[2] = g_camwindow_globals.color_selbrushes3d[2]; state.m_colour[3] = 0.3f; - state.m_state = RENDER_FILL | RENDER_DEPTHTEST | RENDER_CULLFACE | RENDER_BLEND | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; + 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; } @@ -2203,6 +2213,7 @@ void OpenGLShader::construct( const char* name ){ state.m_sort = OpenGLState::eSortFullbright; state.m_linewidth = 4; } +#if 0 else if ( string_equal( name + 1, "LIGHT_SPHERE" ) ) { state.m_colour[0] = .15f * .95f; state.m_colour[1] = .15f * .95f; @@ -2223,6 +2234,7 @@ void OpenGLShader::construct( const char* name ){ state.m_blend_dst = GL_ONE; state.m_sort = OpenGLState::eSortTranslucent; } +#endif // 0 else if ( string_equal( name + 1, "WIRE_OVERLAY" ) ) { #if 0 state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE; @@ -2365,9 +2377,9 @@ void OpenGLShader::construct( const char* name ){ state.m_blend_src = convertBlendFactor( blendFunc.m_src ); state.m_blend_dst = convertBlendFactor( blendFunc.m_dst ); state.m_depthfunc = GL_LEQUAL; - if ( state.m_blend_src == GL_SRC_ALPHA || state.m_blend_dst == GL_SRC_ALPHA ) { - state.m_state |= RENDER_DEPTHWRITE; - } +// if ( state.m_blend_src == GL_SRC_ALPHA || state.m_blend_dst == GL_SRC_ALPHA ) { +// state.m_state |= RENDER_DEPTHWRITE; +// } } else { diff --git a/radiant/textures.cpp b/radiant/textures.cpp index c0477d92..7f5e5a94 100644 --- a/radiant/textures.cpp +++ b/radiant/textures.cpp @@ -49,7 +49,6 @@ enum ETexturesMode eTextures_LINEAR = 3, eTextures_LINEAR_MIPMAP_NEAREST = 4, eTextures_LINEAR_MIPMAP_LINEAR = 5, - eTextures_MAX_ANISOTROPY = 6, }; enum TextureCompressionFormat @@ -89,15 +88,6 @@ struct texture_globals_t texture_globals_t g_texture_globals( GL_RGBA ); void SetTexParameters( ETexturesMode mode ){ - float maxAniso = QGL_maxTextureAnisotropy(); - if ( maxAniso > 1 ) { - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f ); - } - else - if ( mode == eTextures_MAX_ANISOTROPY ) { - mode = eTextures_LINEAR_MIPMAP_LINEAR; - } - switch ( mode ) { case eTextures_NEAREST: @@ -124,15 +114,20 @@ void SetTexParameters( ETexturesMode mode ){ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); break; - case eTextures_MAX_ANISOTROPY: - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, maxAniso ); - break; default: globalOutputStream() << "invalid texture mode\n"; } } +void SetTexAnisotropy( bool anisotropy ){ + float maxAniso = QGL_maxTextureAnisotropy(); + if ( maxAniso > 1 ) { + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy ? maxAniso : 1.f ); + } +} + ETexturesMode g_texture_mode = eTextures_LINEAR_MIPMAP_LINEAR; +bool g_TextureAnisotropy = true; @@ -206,6 +201,7 @@ void LoadTextureRGBA( qtexture_t* q, unsigned char* pPixels, int nWidth, int nHe glBindTexture( GL_TEXTURE_2D, q->texture_number ); SetTexParameters( g_texture_mode ); + SetTexAnisotropy( g_TextureAnisotropy ); int gl_width = 1; while ( gl_width < nWidth ) @@ -557,11 +553,13 @@ void Textures_setModeChangedNotify( const Callback& notify ){ void Textures_ModeChanged(){ if ( g_texturesmap->realised() ) { SetTexParameters( g_texture_mode ); + SetTexAnisotropy( g_TextureAnisotropy ); for ( TexturesMap::iterator i = g_texturesmap->begin(); i != g_texturesmap->end(); ++i ) { glBindTexture( GL_TEXTURE_2D, ( *i ).value->texture_number ); SetTexParameters( g_texture_mode ); + SetTexAnisotropy( g_TextureAnisotropy ); } glBindTexture( GL_TEXTURE_2D, 0 ); @@ -577,6 +575,14 @@ void Textures_SetMode( ETexturesMode mode ){ } } +void Textures_SetAnisotropy( bool anisotropy ){ + if ( g_TextureAnisotropy != anisotropy ) { + g_TextureAnisotropy = anisotropy; + + Textures_ModeChanged(); + } +} + void Textures_setTextureComponents( GLint texture_components ){ if ( g_texture_globals.texture_components != texture_components ) { Textures_Unrealise(); @@ -677,9 +683,6 @@ void TextureModeImport( ETexturesMode& self, int value ){ break; case 5: Textures_SetMode( eTextures_LINEAR_MIPMAP_LINEAR ); - break; - case 6: - Textures_SetMode( eTextures_MAX_ANISOTROPY ); } } typedef ReferenceCaller1 TextureModeImportCaller; @@ -705,9 +708,6 @@ void TextureModeExport( ETexturesMode& self, const IntImportCallback& importer ) case eTextures_LINEAR_MIPMAP_LINEAR: importer( 5 ); break; - case eTextures_MAX_ANISOTROPY: - importer( 6 ); - break; default: importer( 4 ); } @@ -733,7 +733,7 @@ void Textures_constructPreferences( PreferencesPage& page ){ FloatExportCallback( FloatExportCaller( g_texture_globals.fGamma ) ) ); { - const char* texture_mode[] = { "Nearest", "Nearest Mipmap", "Linear", "Bilinear", "Bilinear Mipmap", "Trilinear", "Anisotropy" }; + const char* texture_mode[] = { "Nearest", "Nearest Mipmap", "Linear", "Bilinear", "Bilinear Mipmap", "Trilinear" }; page.appendCombo( "Texture Render Mode", STRING_ARRAY_RANGE( texture_mode ), @@ -762,6 +762,9 @@ void Textures_constructPreferences( PreferencesPage& page ){ IntExportCaller( reinterpret_cast( g_texture_globals.m_nTextureCompressionFormat ) ) ); } + page.appendCheckBox( "", "Anisotropy", + FreeCaller1(), + BoolExportCaller( g_TextureAnisotropy ) ); } void Textures_constructPage( PreferenceGroup& group ){ PreferencesPage page( group.createPage( "Textures", "Texture Settings" ) ); @@ -783,6 +786,7 @@ void Textures_Construct(){ GlobalPreferenceSystem().registerPreference( "TextureCompressionFormat", TextureCompressionImportStringCaller(), IntExportStringCaller( reinterpret_cast( g_texture_globals.m_nTextureCompressionFormat ) ) ); GlobalPreferenceSystem().registerPreference( "TextureFiltering", IntImportStringCaller( reinterpret_cast( g_texture_mode ) ), IntExportStringCaller( reinterpret_cast( g_texture_mode ) ) ); + GlobalPreferenceSystem().registerPreference( "TextureAnisotropy", BoolImportStringCaller( g_TextureAnisotropy ), BoolExportStringCaller( g_TextureAnisotropy ) ); GlobalPreferenceSystem().registerPreference( "TextureQuality", IntImportStringCaller( g_Textures_textureQuality.m_latched ), IntExportStringCaller( g_Textures_textureQuality.m_latched ) ); GlobalPreferenceSystem().registerPreference( "SI_Gamma", FloatImportStringCaller( g_texture_globals.fGamma ), FloatExportStringCaller( g_texture_globals.fGamma ) );