From 0d782993f9e7acda5e1fd728911a746d1e23d35c Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 27 Oct 2012 17:46:13 +0200 Subject: [PATCH] Fixed #1: Implement anisotropic filtering for textures --- code/nel/include/nel/3d/driver.h | 5 +++ code/nel/include/nel/3d/driver_user.h | 1 + code/nel/include/nel/3d/u_driver.h | 5 +++ code/nel/src/3d/driver.cpp | 2 +- .../3d/driver/direct3d/driver_direct3d.cpp | 35 +++++++++++++++++++ .../src/3d/driver/direct3d/driver_direct3d.h | 8 +++++ .../direct3d/driver_direct3d_texture.cpp | 13 +++++++ .../src/3d/driver/opengl/driver_opengl.cpp | 2 ++ code/nel/src/3d/driver/opengl/driver_opengl.h | 3 ++ .../driver/opengl/driver_opengl_extension.h | 2 +- .../driver/opengl/driver_opengl_texture.cpp | 25 +++++++++++++ code/nel/src/3d/driver_user.cpp | 9 +++++ code/ryzom/client/src/client_cfg.cpp | 3 ++ code/ryzom/client/src/client_cfg.h | 2 ++ code/ryzom/client/src/init.cpp | 3 ++ 15 files changed, 116 insertions(+), 2 deletions(-) diff --git a/code/nel/include/nel/3d/driver.h b/code/nel/include/nel/3d/driver.h index 630cbcb01..d090d77da 100644 --- a/code/nel/include/nel/3d/driver.h +++ b/code/nel/include/nel/3d/driver.h @@ -293,6 +293,11 @@ public: */ virtual void forceDXTCCompression(bool dxtcComp)=0; + /** if different from 0, enable anisotropic filter on textures. -1 enables max value. + * Default is 0. + */ + virtual void setAnisotropicFilter(sint filter)=0; + /** if !=1, force mostly all the textures (but TextureFonts lightmaps, interfaces etc..) * to be divided by Divisor (2, 4, 8...) * Default is 1. diff --git a/code/nel/include/nel/3d/driver_user.h b/code/nel/include/nel/3d/driver_user.h index a7f6ac7a5..bfe4c1755 100644 --- a/code/nel/include/nel/3d/driver_user.h +++ b/code/nel/include/nel/3d/driver_user.h @@ -471,6 +471,7 @@ public: virtual void delete3dMouseListener (U3dMouseListener *listener); virtual TPolygonMode getPolygonMode (); virtual void forceDXTCCompression(bool dxtcComp); + virtual void setAnisotropicFilter(sint filter); virtual void forceTextureResize(uint divisor); virtual void forceNativeFragmentPrograms(bool nativeOnly); virtual bool setMonitorColorProperties (const CMonitorColorProperties &properties); diff --git a/code/nel/include/nel/3d/u_driver.h b/code/nel/include/nel/3d/u_driver.h index 9b9eac656..d66a72e47 100644 --- a/code/nel/include/nel/3d/u_driver.h +++ b/code/nel/include/nel/3d/u_driver.h @@ -660,6 +660,11 @@ public: */ virtual void forceDXTCCompression(bool dxtcComp)=0; + /** if different from 0, enable anisotropic filter on textures. -1 enables max value. + * Default is 0. + */ + virtual void setAnisotropicFilter(sint filter)=0; + /** if !=1, force mostly all the textures (but TextureFonts lightmaps, interfaces etc..) * to be divided by Divisor (2, 4, 8...) * Default is 1. diff --git a/code/nel/src/3d/driver.cpp b/code/nel/src/3d/driver.cpp index 13e76cfa1..fa48649ae 100644 --- a/code/nel/src/3d/driver.cpp +++ b/code/nel/src/3d/driver.cpp @@ -33,7 +33,7 @@ namespace NL3D { // *************************************************************************** -const uint32 IDriver::InterfaceVersion = 0x6a; // added cursors methods +const uint32 IDriver::InterfaceVersion = 0x6b; // added anisotropic filter // *************************************************************************** IDriver::IDriver() : _SyncTexDrvInfos( "IDriver::_SyncTexDrvInfos" ) diff --git a/code/nel/src/3d/driver/direct3d/driver_direct3d.cpp b/code/nel/src/3d/driver/direct3d/driver_direct3d.cpp index 2b18c8698..412cb52da 100644 --- a/code/nel/src/3d/driver/direct3d/driver_direct3d.cpp +++ b/code/nel/src/3d/driver/direct3d/driver_direct3d.cpp @@ -292,6 +292,11 @@ CDriverD3D::CDriverD3D() _CurrIndexBufferFormat = CIndexBuffer::IndicesUnknownFormat; _IsGeforce = false; _NonPowerOfTwoTexturesSupported = false; + _MaxAnisotropy = 0; + _AnisotropicMinSupported = false; + _AnisotropicMagSupported = false; + _AnisotropicMinCubeSupported = false; + _AnisotropicMagCubeSupported = false; _FrustumLeft= -1.f; _FrustumRight= 1.f; @@ -1493,6 +1498,11 @@ bool CDriverD3D::setDisplay(nlWindow wnd, const GfxMode& mode, bool show, bool r _MaxVertexIndex = caps.MaxVertexIndex; _IsGeforce = !(caps.DevCaps & D3DDEVCAPS_NPATCHES) && (caps.PixelShaderVersion >= D3DPS_VERSION(2, 0) || caps.PixelShaderVersion < D3DPS_VERSION(1, 4)); _NonPowerOfTwoTexturesSupported = !(caps.TextureCaps & D3DPTEXTURECAPS_POW2) || (caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL); + _MaxAnisotropy = caps.MaxAnisotropy; + _AnisotropicMinSupported = (caps.TextureFilterCaps & D3DPTFILTERCAPS_MINFANISOTROPIC) != 0; + _AnisotropicMagSupported = (caps.TextureFilterCaps & D3DPTFILTERCAPS_MAGFANISOTROPIC) != 0; + _AnisotropicMinCubeSupported = (caps.CubeTextureFilterCaps & D3DPTFILTERCAPS_MINFANISOTROPIC) != 0; + _AnisotropicMagCubeSupported = (caps.CubeTextureFilterCaps & D3DPTFILTERCAPS_MAGFANISOTROPIC) != 0; } else { @@ -1506,6 +1516,11 @@ bool CDriverD3D::setDisplay(nlWindow wnd, const GfxMode& mode, bool show, bool r _MaxVertexIndex = 0xffff; _IsGeforce = false; _NonPowerOfTwoTexturesSupported = false; + _MaxAnisotropy = 0; + _AnisotropicMinSupported = false; + _AnisotropicMagSupported = false; + _AnisotropicMinCubeSupported = false; + _AnisotropicMagCubeSupported = false; } // If 16 bits vertices only, build a vb for quads rendering if (_MaxVertexIndex <= 0xffff) @@ -1607,6 +1622,7 @@ bool CDriverD3D::setDisplay(nlWindow wnd, const GfxMode& mode, bool show, bool r // Init some variables _ForceDXTCCompression = false; + _AnisotropicFilter = 0; _ForceTextureResizePower = 0; _FogEnabled = false; @@ -2049,6 +2065,25 @@ void CDriverD3D::forceDXTCCompression(bool dxtcComp) // *************************************************************************** +void CDriverD3D::setAnisotropicFilter(sint filter) +{ + H_AUTO_D3D(CDriverD3D_setAnisotropicFilter); + + // anisotropic filter not supported + if (_MaxAnisotropy < 2) return; + + if (filter < 0 || filter > _MaxAnisotropy) + { + _AnisotropicFilter = _MaxAnisotropy; + } + else + { + _AnisotropicFilter = filter; + } +} + +// *************************************************************************** + void CDriverD3D::forceTextureResize(uint divisor) { H_AUTO_D3D(CDriverD3D_forceTextureResize); diff --git a/code/nel/src/3d/driver/direct3d/driver_direct3d.h b/code/nel/src/3d/driver/direct3d/driver_direct3d.h index c1b05cc67..351cf10d0 100644 --- a/code/nel/src/3d/driver/direct3d/driver_direct3d.h +++ b/code/nel/src/3d/driver/direct3d/driver_direct3d.h @@ -777,6 +777,7 @@ public: virtual void disableHardwareVertexArrayAGP(); virtual void disableHardwareTextureShader(); virtual void forceDXTCCompression(bool dxtcComp); + virtual void setAnisotropicFilter(sint filter); virtual void forceTextureResize(uint divisor); virtual void forceNativeFragmentPrograms(bool /* nativeOnly */) {} // ignored @@ -1521,6 +1522,7 @@ public: setSamplerState (stage, D3DSAMP_MAGFILTER, d3dtext->MagFilter); setSamplerState (stage, D3DSAMP_MINFILTER, d3dtext->MinFilter); setSamplerState (stage, D3DSAMP_MIPFILTER, d3dtext->MipFilter); + setSamplerState (stage, D3DSAMP_MAXANISOTROPY, _AnisotropicFilter); // Profile, log the use of this texture if (_SumTextureMemoryUsed) @@ -2205,6 +2207,11 @@ private: bool _CubbedMipMapSupported; bool _IsGeforce; bool _NonPowerOfTwoTexturesSupported; + uint _MaxAnisotropy; + bool _AnisotropicMinSupported; + bool _AnisotropicMagSupported; + bool _AnisotropicMinCubeSupported; + bool _AnisotropicMagCubeSupported; uint _NbNeLTextureStages; // Number of texture stage for NeL (max IDRV_MAT_MAXTEXTURES) uint _MaxVerticesByVertexBufferHard; uint _MaxLight; @@ -2411,6 +2418,7 @@ private: bool _MustRestoreLight; D3DXMATRIX _D3DMatrixIdentity; DWORD _FogColor; + uint _AnisotropicFilter; // stencil buffer bool _CurStencilTest; diff --git a/code/nel/src/3d/driver/direct3d/driver_direct3d_texture.cpp b/code/nel/src/3d/driver/direct3d/driver_direct3d_texture.cpp index cfafaf5f9..d413bd847 100644 --- a/code/nel/src/3d/driver/direct3d/driver_direct3d_texture.cpp +++ b/code/nel/src/3d/driver/direct3d/driver_direct3d_texture.cpp @@ -506,6 +506,19 @@ inline void CDriverD3D::setupTextureWrapMode(ITexture& tex) d3dtext->MagFilter = RemapMagTextureFilterTypeNeL2D3D[tex.getMagFilter()]; d3dtext->MinFilter = RemapMinTextureFilterTypeNeL2D3D[tex.getMinFilter()]; d3dtext->MipFilter = RemapMipTextureFilterTypeNeL2D3D[tex.getMinFilter()]; + + // only enable for min filter, because it's never supported for mag filter + if (_AnisotropicFilter > 1 && tex.getMinFilter() > ITexture::NearestMipMapLinear) + { + if (tex.isTextureCube()) + { + if (_AnisotropicMinCubeSupported) d3dtext->MinFilter = D3DTEXF_ANISOTROPIC; + } + else + { + if (_AnisotropicMinSupported) d3dtext->MinFilter = D3DTEXF_ANISOTROPIC; + } + } } diff --git a/code/nel/src/3d/driver/opengl/driver_opengl.cpp b/code/nel/src/3d/driver/opengl/driver_opengl.cpp index e8cae3530..c00c8aece 100644 --- a/code/nel/src/3d/driver/opengl/driver_opengl.cpp +++ b/code/nel/src/3d/driver/opengl/driver_opengl.cpp @@ -305,6 +305,8 @@ CDriverGL::CDriverGL() _NVTextureShaderEnabled = false; + _AnisotropicFilter = 0.f; + // Compute the Flag which say if one texture has been changed in CMaterial. _MaterialAllTextureTouchedFlag= 0; for(i=0; i < IDRV_MAT_MAXTEXTURES; i++) diff --git a/code/nel/src/3d/driver/opengl/driver_opengl.h b/code/nel/src/3d/driver/opengl/driver_opengl.h index 66e0b1325..bfe73492d 100644 --- a/code/nel/src/3d/driver/opengl/driver_opengl.h +++ b/code/nel/src/3d/driver/opengl/driver_opengl.h @@ -364,6 +364,7 @@ public: virtual bool uploadTextureCube (ITexture& tex, NLMISC::CRect& rect, uint8 nNumMipMap, uint8 nNumFace); virtual void forceDXTCCompression(bool dxtcComp); + virtual void setAnisotropicFilter(sint filter); virtual void forceTextureResize(uint divisor); @@ -955,6 +956,8 @@ private: bool _NVTextureShaderEnabled; // Which stages support EMBM bool _StageSupportEMBM[IDRV_MAT_MAXTEXTURES]; + // Anisotropic filtering value + float _AnisotropicFilter; // Prec settings for material. CDriverGLStates _DriverGLStates; diff --git a/code/nel/src/3d/driver/opengl/driver_opengl_extension.h b/code/nel/src/3d/driver/opengl/driver_opengl_extension.h index 792555947..9d28a15ab 100644 --- a/code/nel/src/3d/driver/opengl/driver_opengl_extension.h +++ b/code/nel/src/3d/driver/opengl/driver_opengl_extension.h @@ -157,7 +157,7 @@ public: NVTextureRectangle = false; EXTTextureRectangle = false; EXTTextureFilterAnisotropic = false; - EXTTextureFilterAnisotropicMaximum = 1.f; + EXTTextureFilterAnisotropicMaximum = 0.f; ARBTextureRectangle = false; ARBTextureNonPowerOfTwo = false; ARBMultisample = false; diff --git a/code/nel/src/3d/driver/opengl/driver_opengl_texture.cpp b/code/nel/src/3d/driver/opengl/driver_opengl_texture.cpp index 3e11f5651..77954a8e3 100644 --- a/code/nel/src/3d/driver/opengl/driver_opengl_texture.cpp +++ b/code/nel/src/3d/driver/opengl/driver_opengl_texture.cpp @@ -823,6 +823,9 @@ void CDriverGL::setupTextureBasicParameters(ITexture &tex) #endif glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB,GL_TEXTURE_MAG_FILTER, translateMagFilterToGl(gltext)); glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB,GL_TEXTURE_MIN_FILTER, translateMinFilterToGl(gltext)); + + if (_AnisotropicFilter > 1.f && gltext->MinFilter > ITexture::NearestMipMapLinear) + glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAX_ANISOTROPY_EXT, _AnisotropicFilter); } } else @@ -831,6 +834,9 @@ void CDriverGL::setupTextureBasicParameters(ITexture &tex) glTexParameteri(gltext->TextureMode,GL_TEXTURE_WRAP_T, translateWrapToGl(gltext->WrapT, _Extensions)); glTexParameteri(gltext->TextureMode,GL_TEXTURE_MAG_FILTER, translateMagFilterToGl(gltext)); glTexParameteri(gltext->TextureMode,GL_TEXTURE_MIN_FILTER, translateMinFilterToGl(gltext)); + + if (_AnisotropicFilter > 1.f && gltext->MinFilter > ITexture::NearestMipMapLinear) + glTexParameteri(gltext->TextureMode, GL_TEXTURE_MAX_ANISOTROPY_EXT, _AnisotropicFilter); } // tex.clearFilterOrWrapModeTouched(); @@ -2184,6 +2190,25 @@ void CDriverGL::forceDXTCCompression(bool dxtcComp) _ForceDXTCCompression= dxtcComp; } +// *************************************************************************** +void CDriverGL::setAnisotropicFilter(sint filtering) +{ + H_AUTO_OGL(CDriverGL_setAnisotropicFiltering); + + if (!_Extensions.EXTTextureFilterAnisotropic) return; + + if (filtering < 0 || filtering > _Extensions.EXTTextureFilterAnisotropicMaximum) + { + // set maximum value for anisotropic filter + _AnisotropicFilter = _Extensions.EXTTextureFilterAnisotropicMaximum; + } + else + { + // set specified value for anisotropic filter + _AnisotropicFilter = filtering; + } +} + // *************************************************************************** void CDriverGL::forceTextureResize(uint divisor) { diff --git a/code/nel/src/3d/driver_user.cpp b/code/nel/src/3d/driver_user.cpp index df66f99d0..b45ebbd37 100644 --- a/code/nel/src/3d/driver_user.cpp +++ b/code/nel/src/3d/driver_user.cpp @@ -1469,12 +1469,21 @@ UDriver::TPolygonMode CDriverUser::getPolygonMode () return umode; } + void CDriverUser::forceDXTCCompression(bool dxtcComp) { NL3D_HAUTO_UI_DRIVER; _Driver->forceDXTCCompression(dxtcComp); } + +void CDriverUser::setAnisotropicFilter(sint filter) +{ + NL3D_HAUTO_UI_DRIVER; + + _Driver->setAnisotropicFilter(filter); +} + void CDriverUser::forceTextureResize(uint divisor) { NL3D_HAUTO_UI_DRIVER; diff --git a/code/ryzom/client/src/client_cfg.cpp b/code/ryzom/client/src/client_cfg.cpp index 61cfbf9ad..916e907b7 100644 --- a/code/ryzom/client/src/client_cfg.cpp +++ b/code/ryzom/client/src/client_cfg.cpp @@ -380,6 +380,7 @@ CClientConfig::CClientConfig() ScreenAspectRatio = 0.f; // Default commmon Screen Aspect Ratio (no relation with the resolution) - 0.f = auto FoV = 75.f; // Default value for the FoV. ForceDXTC = false; // Default is no DXTC Compression. + AnisotropicFilter = 0; // Default is disabled (-1 = maximum value, 0 = disabled, 1+ = enabled) DivideTextureSizeBy2= false; // Divide texture by 2 DisableVtxProgram = false; // Disable Hardware Vertex Program. DisableVtxAGP = false; // Disable Hardware Vertex AGP. @@ -979,6 +980,8 @@ void CClientConfig::setValues() READ_FLOAT_FV(FoV) // ForceDXTC READ_BOOL_FV(ForceDXTC) + // AnisotropicFilter + READ_INT_FV(AnisotropicFilter) // DivideTextureSizeBy2 READ_BOOL_FV(DivideTextureSizeBy2) // DisableVtxProgram diff --git a/code/ryzom/client/src/client_cfg.h b/code/ryzom/client/src/client_cfg.h index 2c448bac0..ebb972f05 100644 --- a/code/ryzom/client/src/client_cfg.h +++ b/code/ryzom/client/src/client_cfg.h @@ -230,6 +230,8 @@ struct CClientConfig float FoV; /// Force the DXTC Compression. bool ForceDXTC; + /// Set the anisotropic filter + sint AnisotropicFilter; /// Divide texture size by 2 bool DivideTextureSizeBy2; /// Disable Hardware Vertex Program. diff --git a/code/ryzom/client/src/init.cpp b/code/ryzom/client/src/init.cpp index ce6aa535c..f8ea4aa04 100644 --- a/code/ryzom/client/src/init.cpp +++ b/code/ryzom/client/src/init.cpp @@ -1067,6 +1067,9 @@ void prelogInit() // Init the DXTCCompression. Driver->forceDXTCCompression(ClientCfg.ForceDXTC); + // Set the anisotropic filter + Driver->setAnisotropicFilter(ClientCfg.AnisotropicFilter); + // Divide the texture size. if (ClientCfg.DivideTextureSizeBy2) Driver->forceTextureResize(2);