Game Development Community

dev|Pro Game Development Curriculum

Anisotropy Fix

by Joe Doyle · 02/12/2005 (6:46 pm) · 10 comments

Download Code File

The anisotorpy settings seem to be in a state of flux. Half the code is looking for a value between 0 to 1 and the other half is looking for 0 to MaxAnisotropy. This code fix now unifies the $pref::OpenGL::textureAnisotropy setting to be between 0-1, where 1 means use the MaxAnisotropy the video card can handle, and 0 is disabled.

The changes are simple. I have also supplied a patch from HEAD as of 2/12/05.

First, we need to fix a typo that keeps the setting at 0 no matter what we change pref.cs to.
common/client/Canvas.cs - Line 19
setOpenGLAnisotropy( $pref::OpenGL::anisotropy );
Change to:
setOpenGLAnisotropy( $pref::OpenGL::textureAnisotropy );

Now we need to tune up the rest of the code that uses the value.
engine/dgl/gTexManager.cc - Line 135
ConsoleFunction(setOpenGLAnisotropy, void, 2, 2, "setOpenGLAnisotropy(0-1);")
{
   argc;
   F32 val = dAtof(argv[1]);
   if (val < 0.0)
      val = 0.0;
   if (val > dglGetMaxAnisotropy())
      val = dglGetMaxAnisotropy();
   sgTextureAnisotropy = val;

   if(dglDoesSupportTexAnisotropy())
      glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, sgTextureAnisotropy);
}
Change to:
ConsoleFunction(setOpenGLAnisotropy, void, 2, 2, "setOpenGLAnisotropy(0-1);")
{
   argc;
   F32 val = dAtof(argv[1]);
   if (val < 0.0)
      val = 0.0;
   if (val > 1.0)
      val = 1.0;
   sgTextureAnisotropy = val;

   if(dglDoesSupportTexAnisotropy())
      glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, sgTextureAnisotropy * dglGetMaxAnisotropy());
}

engine/dgl/gTexManager.cc - Lines 968
if (dglDoesSupportTexAnisotropy()) {
    F32 val = 1.0f + sgTextureAnisotropy * dglGetMaxAnisotropy();
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, val);
}
Change to:
if (dglDoesSupportTexAnisotropy()) {
    F32 val = sgTextureAnisotropy * dglGetMaxAnisotropy();
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, val);
}


engine/dgl/gTexManager.cc - Lines 1014
if (dglDoesSupportTexAnisotropy()) {
    F32 val = 1.0f + sgTextureAnisotropy * dglGetMaxAnisotropy();
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, val);
}
Change to:
if (dglDoesSupportTexAnisotropy()) {
    F32 val = sgTextureAnisotropy * dglGetMaxAnisotropy();
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, val);
}


Recompile, then we can edit starter.fps/client/prefs.cs to set $pref::OpenGL::textureAnisotropy = "1" to see Anisotropy in effect. Performance and results may vary depending on your video card.

Joe

About the author

Recent Blogs


#1
02/12/2005 (7:06 pm)
Works great. Thanks!
#2
02/12/2005 (10:19 pm)
Will put this into the official branch.
#3
02/13/2005 (4:11 pm)
Thanks Joe!
#4
03/14/2005 (11:55 pm)
Great, it's in. Thank you!
#5
04/23/2005 (7:37 am)
Let's start at the top...

This is not a "typo"...

setOpenGLAnisotropy( $pref::OpenGL::anisotropy );

it was a mistake. Someone commented it out in the engine and replaced it with this...
//Con::addVariable("$Pref::OpenGL::anisotropy", anisotropyCB, "0");
Con::addVariable("$Pref::OpenGL::textureAnisotropy", TypeF32, &sgTextureAnisotropy);

and whoever did it didn't consider that the variable was actually being used for something and thus they didn't make the script update. The funny part is, someone else had to come back and add this line later...

F32 sgTextureAnisotropy = 0.0; // default aniso, when available. not sure why prefs.cs isn't setting.

when all they needed to do was look at the prefs and they would have seen that the variable didn't exist in the prefs.cs and since it was commented out it wasn't being created. The reason it was commented out was because the original code was changed in Release_1_0_0 to the following code...

ConsoleFunction(setOpenGLAnisotropy, void, 2, 2, "setOpenGLAnisotropy(0-1);")
{
   argc;
   F32 val = dAtof(argv[1]);
   if (val < 0.0)
      val = 0.0;
   if (val > 1.0)
      val = 1.0;
   sgTextureAnisotropy = val;
}


and the resulting calls of...


if (dglDoesSupportTexAnisotropy()) {
         F32 val = 1.0 + sgTextureAnisotropy * dglGetMaxAnisotropy();
         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, val);
      }


were I believe someones attempt to give you some variable pref control of your anisotropy. The implementation was bad because if you use it at all, you should start at 2 to 1 and go up. The code above would obviously not guaranteed a 2-1 or better ratio and if your pref was zero you would still do anistropy of 1 + 0 * x = 1 on every texture in question. A complete waste of resources. And of course if your max was 4 and you used 1 you would have 1 + 1 * 4 = 5 which is an incorrect setting being fed directly to OpenGL functions and completely surpasses the original 0-1 checks that were designed to keep it all in check.


So in Release_1_1_1 someone else comes along and finds the non-updating value...

F32    sgTextureAnisotropy    = 0.0; // default aniso, when available.  [b]not sure why prefs.cs isn't setting.[/b]


And after a little debugging they stumble upon the problem somehow and almost solved by inserting...


Con::addVariable("$pref::OpenGL::textureAnisotropy",    TypeF32,  &sgTextureAnisotropy);

And when it didn't work they thought "Oh yeah, gotta set it!!!" and they typed the command into the console and it worked and they just knew they were done. But still no pref update had been done and the canvas was still sending the wrong pref. So it sat there, thought to be fixed, yet still broken untill Release_1_3_0 when someone else tried the "Get a bigger hammer" approach and put in this...

ConsoleFunction(setOpenGLAnisotropy, void, 2, 2, "setOpenGLAnisotropy(0-1);")
{
   argc;
   F32 val = dAtof(argv[1]);
   if (val < 0.0)
      val = 0.0;
   if (val > dglGetMaxAnisotropy())
      val = dglGetMaxAnisotropy();
   sgTextureAnisotropy = val;

   if(dglDoesSupportTexAnisotropy())
      glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, sgTextureAnisotropy);
}


Which was a radical shift and would result in some really wrong settings. On my card, with a max anisotropy of 8, I could set it to 8, and the new results would be 1 + 8 * 8 = 65 which is definately not a correct value. And just for good measure, they threw in an OpenGl call that was totally useless. I guess cuz it looked good. And yet even STILL no update to the prefs.cs or the canvas.cs so it still would only use a CPU wasting 1 untill someone tried to set it manually and then it went even more haywire than ever.

And now we have the newly upcoming Release_1_4_0 which is going to butcher it yet even more with the above patch. Sad. LOL ;-)


How about this, first...

Change line 68 to...

F32 sgTextureAnisotropy = NULL; // SSP - Gonzo

Cont...
#6
04/23/2005 (7:38 am)
If you want the user to have All or Nothing via 1/0 pref then use the following console function...

//  SSP - Gonzo - All or Nothing
ConsoleFunction(setOpenGLAnisotropy, void, 2, 2, "setOpenGLAnisotropy(0-1);")
{
	if(!dglDoesSupportTexAnisotropy()){ return; }
	
	argc;

	F32 val = dAtof(argv[1]);

	if(val < 1.0){ return; }
	
	sgTextureAnisotropy = dglGetMaxAnisotropy();
}
//  End Gonzo


Otherwise, for a variable control via 1-0 pref use this console function...


//  SSP - Gonzo - Variable Anisotropy
ConsoleFunction(setOpenGLAnisotropy, void, 2, 2, "setOpenGLAnisotropy(0-1);")
{
	if(!dglDoesSupportTexAnisotropy()){ return; }
	
	argc;

	F32 val = dAtof(argv[1]) * dglGetMaxAnisotropy();

	if(val < 2.0){ return; }
	if(val > dglGetMaxAnisotropy()){ val = dglGetMaxAnisotropy(); }
	
	sgTextureAnisotropy = val;
}
//  End Gonzo


Change the lines at 968-971...

if (dglDoesSupportTexAnisotropy()) {
                F32 val = 1.0f + sgTextureAnisotropy * dglGetMaxAnisotropy();
                glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, val);
            }


and the lines at 1014-1017 from this...


if (dglDoesSupportTexAnisotropy()) {
         F32 val = 1.0f + sgTextureAnisotropy * dglGetMaxAnisotropy();
         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, val);
      }


to this....


if (sgTextureAnisotropy != NULL) {  //  SSP - Gonzo - save those resources

         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, sgTextureAnisotropy);
      }  //  End Gonzo





If you want to do away with all the console support and force the user to use the max amount his card can support then skip all that and take out line 68, take out the console function completely, then take out line 204?...

Con::addVariable("$Pref::OpenGL::textureAnisotropy", TypeF32, &sgTextureAnisotropy);

take out the "setOpenGLanisotropy()" function in canvas.cs at line 18, and finally use the following code at lines 968-971 and 1014-1017 instead...


if (gGLState.maxAnisotropy != 0.0f) {  //  SSP - Gonzo - force max always
         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, gGLState.maxAnisotropy);
      }


Note: I ran some tests with various settings and got the following results...

FPS were directly affected by the amount of Anisotropy(as were the graphics) and in the simplest of terms it worked out like this...


Off = highest FPS

Full ON = Lowest FPS

Variable ON = variable FPS between highest and lowest.


In a heavy scene the full anisotropy reduced my FPS from average 46 to average 37. A loss of 9 FPS or almost 20% of my FPS but the graphics looked great versus not so great.

In a light scene the full on reduced my FPS from average 145 to average 102. A loss of 43 FPS or almost 30% of my FPS and once again the graphics were of course better.

Conclusion is: The more you use, the more you lose. At the heavily populated scene the 20% loss(9 FPS) is not a huge deal but at that range of FPS it's treading on dangerous. The light scene loss of almost 30%(43 FPS) seems like a major loss but the bottom line is that I was still at 102 FPS with that loss and the graphics were by far the best. You'll need to decide what's best for your game or use the variable till you have tested and know what your needs are then lock that in via whatever method you feel best.


The moral of this story is: Do your research BEFORE you do your fix!
#7
04/27/2005 (8:16 am)
I'm not sure I understand your complaint with the fix. This fix allows the user to set the percentage of anisotropy from 0 (off) to 1 (maximum the card can handle). It aligns any previous attmepts to change this value with the current codebase. While using anisotropy does eat FPS, my fix allows someone to make a GUI slider to allow the end user control how much they use. Do you not like that option to be available?
#8
04/27/2005 (8:20 am)
He seems to have stated the same thing in his "conclusion"
#9
04/27/2005 (8:38 pm)
Joe,


I didn't mean to sound condescending or negative towards your efforts at all. I was just commenting as a whole on what I learned(perceived) via an extensive review of every TGE release all the way back to 1_0_0. However, in all fairness, I do feel that "aligning with previous attempts" was a bad approach because the previous attempts were a mess. That's not your fault, you obviously didn't create this mess, lol.

Also, if you get to know a little about me over time you'll eventually figure out I'm a tweak freak that loves to use only as much code as it takes and nothing more. That's why I provided 3 different options that were "All or Nothing", "Variable Anisotropy", or "Full on if exists". It's important to note here that everyone will benifit from this modification differently. Some will get great results from it, some will get next to nothing. For example, if you are going to create a racing game with center lines that are scrolling towards you, this fix is a must and the more Anisotropy you can use the better. But if your making a space based game or something where your primary textures and viewpoints are vertical, then your not going to get that much help from this IMO. It won't really matter in the long run because once it's fixec in the HEAD everyone will have access to it and can use it as they see fit.


Quote:
While using anisotropy does eat FPS, my fix allows someone to make a GUI slider to allow the end user control how much they use. Do you not like that option to be available?


I have no problem with it personally. I can only offer 2 cents worth of learned experience that you can test against others if you like. Being a guy, I'm willing to bet good money that you are just like me in the respect that when you buy a game, you come home, rip it out of the box, and play. Read the manual? What the heck is a manual? Most guys could care less about a manual. And when it comes to settings it's easy to assume that guys like you and I want all the control we can get. We also tend to think that others will as well. But my experience has shown me that this is simply not the case. Most people could care less about having an Anisotropy slider. The majority of players don't even know how to pronounce it, much less tell you what it does, so they tend to not even bother with such things. If I had to speak for those people, I would say "Just make it work, I don't care about messing with it". A buddy of mine played Tribes for 6 months before I was turned onto it. When he showed it to me the first thing I did was switch him from Software to Hardware rendering(3 seconds in the options) and I thought his head was going to explode when he saw the graphics. He was blown away by how good it looked in OpenGL on a TNT2 and didn't know if should be happy with the new graphics or incredibly frustrated by the fact that he had wasted months on crappy software graphics when it could have been that way all along. It just never occured to him to change ANY settings at all and Tibes had plenty of settings to toy with. Most of my close friends will fire up a game, set the resolution to their favorite res, and then just dive in. They have usually accepted the way a game looks right out of the box and I guess in their minds it doesn't even click that it COULD look better if they screwed around with it.

Long story short, not everybody cares about settings. Some people are even itimidated by them. Too many settings can be a bad thing. Also, you have developers to consider. The reason I'm even on this resource was because a customer asked me to evaluate your patch for their application. But for their particular needs they wanted "Full on if Exists". They want their product represented by the best graphics possible at all times. They do not want their clients touching ANY settings. What one client see's they want all to see the same way if possible. It's about quality control with them. And while we cannot make their clients systems do things they aren't capable of doing, we have worked the entire build around discovering their exact abilities and taking full advantage of them. So if their client's vidcard supports Anisotropy then it gets set to full no matter what. They like it that way, the clients like it that way, who am I to argue, lol.


FWIW, I was the only other person to rate your resource, and I gave it a 4 not because you didn't do a good job, but because I do not believe that everybody can or will benifit from this change and I feel that everybody pumping out 5's as a rating tends to lead less knowledgable users into assuming that it's a "Must Have" resource. And my opinion is, if you don't know exactly what this resource does, chances are you don't need it yet.

Many Thanks

Gonzo
#10
05/06/2006 (3:23 am)
Thanks for this :)