Posted: 8th Dec 2013 22:34
I've seen lots of messages in these forums about anisotropic filtering, and how can you do it in DarkGDK?? People saying it didn't work or one who offered a DBPro .DLL, but with no instructions on using it in DarkGDK. Well it's quite possible in DarkGDK without such a .DLL, using a couple undocumented (but available) DarkGDK functions that provide access to lower-level data.

First of all, there already is an undocumented function available that does it:

+ Code Snippet
dbSetObjectFilter(object, 2);


But it doesn't give you much control. Using that open-source .DLL as a starting point, I wrote another function that provides more control, all within DarkGDK (no third-party stuff or hacks of source code). You can choose the anistropy level yourself (or choose the max supported by your video board). And you can choose which filters you'd like for mipmap selection, minification, and magnification separately.

Such filtering works at an object's texture level rather that a universal environmental level. So I've written a function to apply the filter too all objects up to and including the highest object passed in. I commented within it so you can follow along and easily make any modifications you wish.

Here's the function's prototype:
+ Code Snippet
int FilterObjects(int highestObject, int mipmapFilter, int minificationFilter, int magnificationFilter, int anisotropy);


Here is a call to this function with everything set to match the defaults:
+ Code Snippet
FilterObjects(-1, D3DTEXF_LINEAR, D3DTEXF_LINEAR, D3DTEXF_LINEAR, 0);


Here is a recommended call to this function to enable anisotropic filtering at your card's maximum supported level:
+ Code Snippet
FilterObjects(-1, D3DTEXF_LINEAR, D3DTEXF_ANISOTROPIC, D3DTEXF_LINEAR, -1);


Since anisotropic filtering is heavier on your card's resources than linear, I kept the magnification filter set to linear, but you can do whatever you want. And anisotropic filtering is undefined on mipmap selection.

And here is the function itself:

The constants are defined in d3d9types.h.

+ Code Snippet
// Valid Values for Mipmap       Filter: D3DTEXF_POINT, D3DTEXF_LINEAR
// Valid Values for Minification Filter: D3DTEXF_POINT, D3DTEXF_LINEAR, D3DTEXF_ANISOTROPIC, D3DTEXF_PYRAMIDALQUAD, D3DTEXF_GAUSSIANQUAD

// Will effect all already-created objects up to and including the highestObject passed in (-1 means all objects until it reaches the first invalid object).
// For the 3 Filter values, (-1) means no change what whatever it's currently set to.
// For anisotropy, (-1) means to use the MaxAnisotropy allowed by the video driver.

// Documentation: http://msdn.microsoft.com/en-us/library/windows/desktop/bb172615%28v=vs.85%29.aspx

int FilterObjects (int highestObject, int mipmapFilter, int minificationFilter, int magnificationFilter, int anisotropy)
{
   int               sampler, object, meshIndex, textureIndex;
   bool              quitAtInvalidObject;
   sObject*          objectPtr;
   IDirect3DDevice9* Device;
   D3DCAPS9          caps;


   Device = dbGetDirect3DDevice();
   if ((minificationFilter == D3DTEXF_ANISOTROPIC) || (magnificationFilter == D3DTEXF_ANISOTROPIC))
   {
      // Check Device Capabilities. Assert that anisotropy does not exceed MaxAnisotropy.
      Device->GetDeviceCaps(&caps);
      if ((caps.MaxAnisotropy < anisotropy) || (anisotropy == -1))
      {
         anisotropy = caps.MaxAnisotropy;
      }
   }
   else
   {
      anisotropy = 0;
   }

   // Set the anisotropy
   sampler = 8;
   while (sampler--)
   {
      Device->SetSamplerState(sampler, D3DSAMP_MAXANISOTROPY, anisotropy); 
   }

   if (highestObject == -1)
   {
      highestObject = 22000000;
      quitAtInvalidObject = true;
   }
   else
   {
      quitAtInvalidObject = false;
   }

   // Set object texture filters
   object = -1;
   while (++object <= highestObject)
   {
      // Next object. Check that the object exists.
      if (dbObjectExist(object))
      {
         // Get a pointer to the object's underlying data.
         objectPtr = dbGetObject(object);
         if (objectPtr)
         {
            // Cycle through all the meshes within that object
            meshIndex = objectPtr->iMeshCount;
            while (meshIndex--)
            {
               // Cycle through all the textures within each mesh
               textureIndex = objectPtr->ppMeshList[meshIndex]->dwTextureCount;
               while (textureIndex--)
               {
                  // Apply the Filter Settings, if >= 0
                  if ( minificationFilter >= 0) objectPtr->ppMeshList[meshIndex]->pTextures[textureIndex].dwMinState =  minificationFilter;
                  if (magnificationFilter >= 0) objectPtr->ppMeshList[meshIndex]->pTextures[textureIndex].dwMagState = magnificationFilter;
                  if (       mipmapFilter >= 0) objectPtr->ppMeshList[meshIndex]->pTextures[textureIndex].dwMipState =        mipmapFilter;
               }
            }
         }
      }
      else if (quitAtInvalidObject)
      {
         if (object) object = highestObject;
      }
   }

   // Return the anisotropy used, if used
   return (anisotropy);
}
Posted: 14th Jan 2014 23:08
I tested, it works.
I used a scene with objects that have textures 512x512 and 2048x2048. I see a real difference between D3DTEXF_LINEAR and D3DTEXF_ANISOTROPIC in texture sharpness, FPS decreases only from 463 to 452. Good result for good videocard "NVidia GeForce 660".

But I do not see any difference between anisotropy=2 and anisotropy=4,8,16. No difference in texture sharpness, no difference in FPS. Absolutely. Why?