Search Unity

Anisotropic textures settings in Quality Settings

Discussion in 'General Graphics' started by ArachnidAnimal, Mar 31, 2017.

  1. ArachnidAnimal

    ArachnidAnimal

    Joined:
    Mar 3, 2015
    Posts:
    1,835
    The manual says this about the "Anisotropic Texture" option in the quality settings:
    Anisotropic Textures This enables if and how anisotropic textures will be used. The options are Disabled, Per Texture and Forced On (ie, always enabled).

    If I choose "Force On",
    Does it set the type of filtering used for all textures. i.e. Bilinear or Trilinear?
    Does it also set a minimum Aniso level per texture by default?

    Thanks.
     
  2. ArachnidAnimal

    ArachnidAnimal

    Joined:
    Mar 3, 2015
    Posts:
    1,835
  3. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    Neither, it's using anisotropic filtering. Anisotropic isn't some additional feature that can be used along side Bilinear or Trilinear, it's the next filtering type after those two options. Unity's texture options kind of hide that fact as you can't choose "Anisotropic" in the same dropdown, but on the graphics API side there's a setting for how to filter a texture during "minification" (when it's being displayed smaller than the actual resolution), and the options are Point, Bilinear, Trilinear, and Anisotropic.

    Anisotropic filtering is basically trilinear on steroids though.

    Point filtering just samples the single nearest pixel on the smallest mip appropriate.
    Bilinear filtering samples four pixels of the mip and linearly interpolates between each pixel pair, and the interpolated values of those pairs.
    Trilinear filtering takes billinear filtered samples from both the smallest mip appropriate and the next mip after and linearly interpolates between them.
    Anisotropic filtering takes multiple offset trilinear filtered samples using a larger mip than the other filtering modes would use. The number of samples depends on the angle of the surface and the max anisotropic level set, and the specific implementation used by the GPU. All of the consumer GPUs are using approximations to reduce the number of anisotropic samples needed, but even with out that if you have 16x aniso set it might only be doing straight trilinear on many surfaces like those facing directly at the camera, it's only those that are nearly edge on that'll ever get the full 16x samples.
     
  4. ArachnidAnimal

    ArachnidAnimal

    Joined:
    Mar 3, 2015
    Posts:
    1,835
    Thanks for explanations.

    I was starting to get under the impression that if you set the aniso level to greater than 1 that you would automatically be using anisotropic filtering. But it sounds like from what you're saying that is not the case. So we need to use the Graphics API to use anisotropic filtering?
     
  5. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    By "graphics API" I mean DirectX, OpenGL, etc.
    https://msdn.microsoft.com/en-us/library/dn642451.aspx

    My understanding of the anisotropic quality level setting is thus:
    0 - Forced off, regardless of quality settings, use texture's filter setting
    1 - Off, quality setting can override, otherwise use texture's filter setting
    Above that I'm not exactly sure exactly what each value signifies, but I assume it to mean roughly (n-1)*2 aniso, so:
    2 - use 2x AF (Anisotropic Filtering) unless overridden by quality settings
    3 - use 4x AF
    4 - use 6x AF
    5 - use 8x AF
    6 - use 10x AF
    7 - use 12x AF
    8 - use 14x AF
    9 - use 16x AF

    2 through 16 - use #x AF (Anisotropic Filtering) unless overriden by quality settings

    Basically everything between 2 and 9 is a guess, though nothing else really makes sense.
    16x AF is the max supported by modern desktop GPUs, some mobile support less (like much older ones only support 2x), but I think most support 16x now as well. The actual APIs don't put any rules on the value you set for the max anisotropic amount (which is what you're actually setting, as explained in my previous post) apart from the value being between 1 (effectively off) and the max allowed by that GPU, but I don't think most GPUs can actually do "12x", but rather do 2, 4, 8, and 16 only, so it's odd to me for Unity to have so many levels to select from.

    Edit: Been a while since I looked at the Aniso Level settings, but it's a straight 0-16 value, so anything 2 or greater maps directly to the "max anisotropic" setting. It appears Unity's documentation here is either wrong, or just out of date.
     
    Last edited: Mar 31, 2017
    ArachnidAnimal likes this.
  6. jvo3dc

    jvo3dc

    Joined:
    Oct 11, 2013
    Posts:
    1,520
    I'm also not aware of any hardware supporting anything else than 2x, 4x, 8x and/or 16x AF. The DirectX 9 API is a bit confusing with three separate filters to set. (Magnification, minification and mipmap.) I see that that has improved a bit with DirectX 11. For who likes to see, these are the (worst case) number of samples per pixel:

    Point: 1
    Bilinear: 4
    Trilinear: 8
    2x AF: 16
    4x AF: 32
    8x AF: 64
    16x AF: 128
     
    ArachnidAnimal likes this.
  7. ArachnidAnimal

    ArachnidAnimal

    Joined:
    Mar 3, 2015
    Posts:
    1,835
    I ran some tests.
    I'm running on AMD R7 260X which only supports aniso 2x, 4x, 8x, 16x.
    I experimented with some different aniso levels and here's what I found:

    0 no filtering
    1 no filtering
    2 improvement (2x AF)
    3 the same results as aniso 2
    4 improvement (4x AF)
    5 the same results as aniso 4
    6 the same results as aniso 4
    7 the same results as aniso 4
    8 improvement (8x AF)
    9 the same results as aniso 8
    10 the same results as aniso 8
    11 the same results as aniso 8
    12 the same results as aniso 8
    13 the same results as aniso 8
    14 the same results as aniso 8
    15 the same results as aniso 8
    16 improvement (16x AF)

    The results were obvious when looking closely at textures at a steep angle.
    It seems that for any aniso level assigned in the import settings, the actual aniso used is the closest lower power-of-two.
    Now it seems to be making sense how this works, just by playing around and noticing what is happening.
     
    glenneroo and bgolus like this.
  8. ArachnidAnimal

    ArachnidAnimal

    Joined:
    Mar 3, 2015
    Posts:
    1,835
    I also ran another experiment.
    When the Anisotropic Filtering is "Forced On", the result is that the aniso level used for textures is 8x (at least on my hardware). But if the texture was set to use 16 AF, then the aniso level used remains 16x for that texture.
     
  9. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    Internally Unity is actually setting the Aniso level to each of those levels, ie: setting it to "7" is actually telling the API to use "7", but as you noticed that really only means 4x is used. Forced On clamps the values it sets to 9-16, so if your texture is set to "1" but Aniso is forced on Unity will tell the graphics API to use "9", which means it'll draw using 8x AF for most hardware. If you set it to "12" it'll tell the graphics API to use "12", but that also just means 8x AF.
     
    DanjelRicci and ArachnidAnimal like this.
  10. ArachnidAnimal

    ArachnidAnimal

    Joined:
    Mar 3, 2015
    Posts:
    1,835
    I was trying to find some hardware that handles non power-of-two AF.
    I ran into this NVIDIA site:
    http://images.nvidia.com/geforce-co...vel-interactive-comparison-001-10x-vs-6x.html
    It tries to compare 6x vs 10x AF. Personally, I don't notice anything different. It's also odd that there comparing non POT AF. Maybe the AF is falling back to 4x vs 8x.
     
  11. ModLunar

    ModLunar

    Joined:
    Oct 16, 2016
    Posts:
    374
    @bgolus wow.. thank you for explaining that, I had no idea what Aniso Level/Anisotropic Textures meant. If I may ask, how did you learn all of this stuff, like specifically about the internal workings of Unity? When it comes to undocumented parts of the engine, there's only so much knowledge I can get from Reflecting on their API haha!
     
  12. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    When it comes to Unity setting the anisotropic value to 9 when forced on, that I figured out by using GPU analysis tools (like RenderDoc) and looking at what values the graphics APIs were getting when setting different aniso levels and quality options.

    This is also how I figured out the anisoLevel was being passed to the GPU straight (when Forced On is not being used), which directly contradicts the documentation for Texture2D.anisoLevel, which does not appear to have been updated since just after Unity 4.0's release in 2012! The current behavior appears to be how it's been since Unity 5.0.

    Knowing about the power-of-two aniso levels comes from prior experience, and just generally being a huge nerd about this kind of thing.

    Anisotropic filtering quality used to be a huge thing for comparing different GPUs, with every major GPU being run through a suite of tests to compare the mip mapping quality between prior and competing GPUs. Every self respecting pc hardware review site in the early to mid 2000's would have an image like this in their GPU reviews:

    (Image from https://www.extremetech.com/extreme/84486-image-quality showing 8x anisotropic filtering with colors mip levels)

    This all stopped in the early 2010's due to there not being any appreciable difference between GPUs anymore in either quality or performance impact. Even in the above image, while there are differences between those two GPUs in terms of the mip level pattern, if you read through the above link you'll see they're having a hard time actually seeing a real visual difference in practice, and that was in 2004.

    These days most people just don't care. The hardcore still force the setting on via the graphics drivers (which you really shouldn't do anymore for various reasons), everyone else just sets their games graphics settings to whatever preset the game runs well enough at. I'd blame that as a big factor for why the documentation is so out of date too; for most people using Unity probably don't even know it's a thing, or if they do they set it to Forced On in the quality settings and never think about it again. For me I've run into cases where I absolutely needed it to be disabled, or maxed out, for specific effects to work as intended, so understanding the actual mechanics of what those setting did was important knowledge.
     
  13. ModLunar

    ModLunar

    Joined:
    Oct 16, 2016
    Posts:
    374
    @bgolus Ahh wow, that's some pretty intense stuff! Haha I traditionally am better at the C#/CPU programming side of things, but have been getting a little better at shaders these past few years. That's interesting stuff though, I didn't realize there was a big difference in earlier GPUs.

    So if I'm understanding correctly, it's generally a bad idea to force Anisotropic Texturing to be on across the board in your game, because that's.. quite expensive, isn't it? (Unless you're just testing/debugging for a moment with it on temporarily)

    Yeah that definitely is great knowledge though, embrace the nerd/geekness! ;)
     
  14. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    On mobile it can be terrible for performance on a lot of hardware. Stick to trilinear, or even bilinear if you can get away with it.

    On desktop you'll be hard pressed to notice a performance difference with it on or off (compared to bilinear or trilinear). It's likely within the margin of error for modern GPUs to enable 8x Anisotropic, or even 16x.

    For example, here's a benchmark between the different quality settings.

    https://www.geforce.com/whats-new/g...-tweaking-guide#titanfall-2-texture-filtering

    Less than 1/8th of a ms of difference between bilinear and 16x aniso. Granted, that's with a GTX 1080 which is a beast, but even then on lesser hardware it's maybe an extra ms to pop on 8x aniso with a decent visual quality increase.
     
  15. CptBertorelli

    CptBertorelli

    Joined:
    Apr 9, 2020
    Posts:
    20
    That's right, thank you for these. Apart from aniso settings, what does the following message mean?
    upload_2020-4-25_17-9-32.png

    I though mipmaps are meant for 3D.
     
  16. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    “POT” means “Power of Two”. Many GPU texture formats require being a power of two resolution for various reasons, resolutions like 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, or 4096. Some formats even require the texture to be square. If a texture isn’t one of those resolutions, it either can’t be compressed, or can’t use certain features, like mip maps in this case.

    The usual solution for this with sprites is to use a sprite atlas.
     
  17. CptBertorelli

    CptBertorelli

    Joined:
    Apr 9, 2020
    Posts:
    20
    My texture size is 256x384. Obviously 384=128+256. Other sprites with the same size are properly displayed and do not feature 'Only POT...' error message.

    After I opened this sprite in photoshop and saved it without any modifications, it was ok. No error message and quality was way increased. I wonder what was the reason for this error.
     
  18. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    It's not "128 + 256", it's 128 or 256. That's 2^7 and 2^8 respectively.
    In other words 256x384 is not a power of two texture resolution, 256x256 or 256x512 would be.

    It's possible something got changed on the import settings when the file got reloaded to fixed it. Sprites are a little odd.
     
    BrandyStarbrite likes this.
  19. CptBertorelli

    CptBertorelli

    Joined:
    Apr 9, 2020
    Posts:
    20
    That's right but how do you explain that other textures with 256x384 got loaded properly? The do not render this error and their quality is excellent. Also why opening the problematic image in photoshop and saving it immediately helped even though the size remained unchaged?
     
  20. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    No idea.

    My best guess is when you resaved the file it changed something in that file that caused Unity to change what format it was using to store the image. You don't show the preview for the image that's at the bottom of the inspector window which shows the format & resolution being used, so I have no idea what format & resolution the texture was actually being stored at original and after.
     
  21. andyz

    andyz

    Joined:
    Jan 5, 2010
    Posts:
    2,276
    So this is still quite bad in Unity - you have aniso level on textures but the warning says enabled for all in settings - OK but what level cuz is just 'enabled'!!
    Thanks for explanations above but clearly Unity could do things better and not mix up trilinear and anisotropic levels

    But note that the docs say "The value range of this variable goes from 1 to 9" which I assume is a mistake. The slider of course makes no change between 0 & 1 which is also like...!
     
    Last edited: Oct 26, 2020
  22. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    Enabled in the Quality settings means it uses whatever value the texture is using, which defaults to 1, which is the same as no anisotropic filtering. If you want a texture to always have anisotropic filtering (at least when Anisotropic Filtering isn't disabled in the quality settings) you need to change it on the texture.

    Yes. That's been noted a few times in this very post. Similarly setting Anisotropic Filtering to Forced On in the quality settings still only sets any texture set to an aniso level between 1 - 9 to 9. Which I can only assume is a legacy thing because 9 used to be the max value, and when that changed to be a direct mapping to the anisotropic filtering level, 8x Anisotropic* was good enough that no one complained. Though realistically the performance difference between 8x and 16x is almost non-existent, but the visual difference isn't. I really think it just comes down to it's something almost no one notices is wrong, and no one complains about, so no one at Unity has ever taken the time to fix it.

    * Many devices only actually support power of 2, or multiple of 2 anisotropic levels. So an aniso level of 9x for a lot of hardware is visually identical to 8x. What levels a GPU are actually supports changes from generation to generation and maker to maker.
     
  23. andyz

    andyz

    Joined:
    Jan 5, 2010
    Posts:
    2,276
    Are you sure you have to set the aniso level on each texture, setting on in quality should be enough?

    The shader graph manages to forget about anisotropic in its sampler states!
     
  24. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    As long as the textures haven't been set to an aniso level of 0, or you're using a sample function that doesn't support it (Sample Texture 2D LOD), or you're overriding the sampler state with a custom one.

    For Shader Graph the correct way to do it is to not set an explicit sampler state for a Sample Texture node. All textures have an implicit sampler state already, and that will be used automatically for any Sample Texture nodes that don't have it overridden. Sampling textures in a custom function makes things a little more difficult since Unity doesn't expose a Texture object's implicit sampler state to Shader Graph, but it can be worked around by just typing the sampler state's name in the code directly.
     
    andyz likes this.
  25. Ziflin

    Ziflin

    Joined:
    Mar 12, 2013
    Posts:
    132
    @bgolus Do you know if Unity is planning to expose the Aniso Level on the Shader Graph Sampler State nodes? I'm doing some terrain blending in a custom function and only need one sampler state, but there's no way to set the Aniso Level. I tried using an "Inline Sampler State" from Unity's Docs (https://docs.unity3d.com/2020.2/Documentation/Manual/SL-SamplerStates.html) hoping that since we have Anisotropic Textures set to "Forced On" that they would expose the samplers with it, but I can't tell any difference vs. using the one from my shader graph.

    Any hints at how to get to an anisotropic sampler from a custom function?
     
  26. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    The Forced On option only affects the textures' implicit sampler states. Inline sampler states original exist to be able to forcibly override the ones from the texture asset, so it wouldn't make sense for the Forced On option to affect them.

    The work around is to use the texture's own sampler state. To do that you have to use a Custom Function node and manually, explicitly write out the sampler state's variable name. Like this:
    upload_2020-12-20_16-34-29.png
    Note the reference name for the texture is
    _TestTexture
    , and the sampler in the Custom Function is
    sampler_TestTexture
    . Unity always adds an implicit sampler state for texture properties with that naming scheme. One note of warning: until you have the texture and custom function node connected to a Master node input the Custom Function may show a warning that "sampler_texturename" doesn't exist, because Unity doesn't add the texture uniform, or its sampler, to the shader code until it thinks it's in use, and thus it doesn't exist until it's all connected.

    It's tempting to have a Custom Function node that outputs just the texture's sampler state so you don't have to have fully custom code like this for every texture, but that's not an option as you can't actually use a Sampler State as a Custom Function output. I mean, you can, but it'll never actually work due to how they have the generated code setup.
     
    lilacsky824 likes this.
  27. Ziflin

    Ziflin

    Joined:
    Mar 12, 2013
    Posts:
    132
    Thanks @bgolus! I was just about to try this since I stumbled across the "Using Sampler States' doc that mentioned it. It would certainly be better if they would expose the Anisotropic setting in the Sampler State node though as hardcoding the name seems pretty bad and apparently generates warnings like you mention.

    Now if I can just figure out how to get ddx_fine() to work in my custom shader, which seems to be just returning ddx() as someone else mentioned 2 years ago with no answer from Unity.

    Thanks for the help. I read through your 'Generating Perfect Normal Maps for Unity' article this morning. Very helpful!
     
    bgolus likes this.
  28. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    Yep. They really need to add anisotropic settings to the Sampler State node, and expose the texture’s own sampler state. They already have the Texel Size node which works exactly the same way a texture sampler state node would need to (takes a texture as an input, outputs the texel size by combining the texture’s name with
    _TexelSize
    suffix). I really don’t understand why it’s not something that’s been fixed yet.
     
    Ziflin likes this.
  29. Ziflin

    Ziflin

    Joined:
    Mar 12, 2013
    Posts:
    132
    Hehe, yeah, I just stumbled across another one of your posts from I think 2 years ago mentioning the anisotropic issue way back then. I'd even settle for them making an "inline sampler state" with a 8x default.. Something like sampler_anisotropic8_repeat would be fine.
     
  30. lejean

    lejean

    Joined:
    Jul 4, 2013
    Posts:
    392
    Is it advised to set the aniso level to 0 for stuff like normal, spec, ao maps?
    Does that improve the performance?

    I feel like the only texture that has any impact on the visuals is the diffuse texture.
     
  31. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    To the question of if it improves performance ... it depends on if anisotropic filtering perceptibly affects performance or not at all. And if you're forcing it on in the quality settings or not.

    On desktop GPUs, as noted above, it doesn't really have any affect on performance one way or the other. So it's unlikely disabling anisotropic filtering on some textures would have any real performance benefit.

    On mobile, it's not a bad idea. But you're also probably not forcing anisotropic filtering on to begin with so there's no difference between it being 1 or 0 since both are the same when not forcing it on in the quality settings. More realistically, you probably want to leave anisotropic filtering quality setting to Per Texture, and setting the aniso filtering level on individual textures you feel need the help.

    So that brings us to the first question.
    The answer here is ... maybe?
    You're right that anisotropic filtering mainly benefits diffuse textures. It's where its affects are the most obvious, and what it was primarily designed to deal with.

    Using anisotropic filtering on normal maps isn't technically correct, but normal maps themselves are a big lie that aren't ever actually correct. Anisotropic filtering mainly affects how a texture is sampled when viewing a surface at an oblique angle, especially when closer to parallel with the view direction. I.E..: like a floor. The lighting you get from a detailed normal map using anisotropic filtering won't match the lighting you'd get if using super sampling, but that's also true of mip maps of normal maps in general. Neither will match what the original high poly source model would have looked like either, though the anisotropic filtered one may actually end up looking closer. The same is true for anisotropic filtering on specular or metal maps. They won't quite match a super sampled equivalent, but neither do mip maps anyway. The main benefit is sharp details will remain clear when using anisotropic filtering is used, regardless of if it's "correct" or not.

    Smoothness / roughness and AO maps however probably look pretty good, and mip maps do actually work properly with these (mostly). AO maps, like normal maps, may actually look closer to a high poly source model without anisotropic filtering enabled, but you'll loose some sharp details you may want to keep.