Alright, I implemented support for generating mipmaps in CIELAB and CIELUV space.
Though I probably posted this before, the motivation is based on this
paper by Burger pointing out that performing linear filtering in neither sRGB nor linearized sRGB is actually a good choice while at the same time suggesting to use CIELAB or CIELUV.
Comparission:http://coding.hanfling.de/MipsFilter.bmpLegend:a) Mips generated in sRGB space, filtered in sRGB space ingame
b) Mips generated in linear (sRGB) space, filter in linear (sRGB) space ingame.
c) Mips generated in CIELAB, filtered in linear (sRGB) space ingame.
d) Mips generated in CIELUV, filtered in linear (sRGB) space ingame.
I haven't done any excessive testing yet, but wanted to give some road with a white stripe a test as this usually always ends up in some bloating of the white stripe after anisotropic filtering gives up (I guess my driver settings enforced 8x anisotropic filtering for this shot).
The differences are certainly just minor, but imho the white bloating is slighty reduced when generating the mipmaps in CIELAB or CIELUV space, so I'm curious to try out if storing the texture data in CIELAB to make the GPU filter it linear in CIELAB space, and afterwards convert it to (linearized) sRGB inside the fragment shader will further reduce this effect *and* whether this will hopefully provide more pleasant texture magnification.
One further note towards a), which doesn't seem far off towards b). Especially in case the diffuse textures are rather dark like in Deus Ex, a) will cause a clearly noticable and odd darkening in the distance effect, while b) works fine.
However, CIELUV is a bitch. Take a look at the CIEXYZ<=>CIELUV transformations on Bruce Lindblooms really helpful site:
http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_Luv.htmlhttp://www.brucelindbloom.com/index.html?Eqn_Luv_to_XYZ.htmlFor XYZ -> LUV: In case of (X+15Y+3Z)==0 you get divide by zero errors for u' and v'. My current workaround is to set LUV=(0,0,0) in case (X+15Y+3Z)<SMALL_VALUE, however just L=0 makes sense in this case, for U and V this is more like some "what else" kind of choice. I think one approach for selecting UV in this particular case would be on some sort of what would provide the the most desireble results for a texture filtered towards a black hole.
For LUV -> XYZ: In case of (u+14*L*u0)==0 and/or (v+14*L*v0)==0 you get a divide by zero for a and/or d respectivly. My (not bulletproof) current solution is to check whether L<SMALL_NUMBER and -- as this is black -- set the XYZ values to (0,0,0). This seems to be sufficient for my two test textures so far. To make it bulletproof one could just clamp (L,U,V) into [0,1]x[0,1]x[0,1] and afterwards do the L<SMALL_NUMBER check. This is probably required for filters like
Lanczos as values get weighted with a negative sign, so L could become negative. But I should actually add that straight ahead to be safe. However, I'll keep CIELUV for filtering unless it causes more troubles, recommend CIELAB over it and for textures storage and shader code I'll not consider it at all.
So much for now.. oh and hey.. looks like my ideal of Nerf beeing in sRGB starts to crack. For me a great amount of especially the player skins seem more right in AdobeRGB space compared to sRGB and other people I asked also can't really tell what would be more right, so at least the difference for Nerf doesnt seem that large...