I think keeping the data in cache as sRGB and then having to linearize every individual texel access before it is used in any math is likely to add dramatically to the cost of each filtered texture lookup. Many texels are touched for every texture call.
I would recommend linearizing the source files as they come into maketx and having all of your mipmapped textures be linear. That may mean that 8 bits are often not enough for texture, and you want uint16 (I don't think we ever use 8 bit textures, unless they represent simple masks). I don't think that's as bad as you might guess, but partly it depends on how incoherent your texture access is and if your cache size is currently at the limit of what you can afford as well as right on the borderline of thrashing. If you're at the edge, where you just can't increase the cache size at all because there's no physical RAM to spare on your renders, and if your tile cache miss rate increases even a little bit your perf will plummet, then you're in trouble. But if only a portion of your textures are these 8 bit files, and you are getting a decent cache hit rate, and you can spare enough RAM to raise the max_memory_MB by another GB or two, then maybe you should just do that, store your textures as linear uint16, and won't notice any perf change (or maybe perf will be better for not needing the extra math to linearize in the shaders). But you won't know for sure until you try it. -- lg > On Jan 11, 2021, at 8:34 AM, Søren Ragsdale <sor...@gmail.com> wrote: > > I think your understanding and mine are in sync. > > At this step I'm looking for (1): a way to "truly save sRGB" rather than just > save filtered values derived from samples which were once converted to RGB. > > I hadn't thought of (2) but that's a really good point; "true sRGB" texture > data isn't a fully correct solution without linearization before filtering. > > I'm not overly concerned about (3) because we've got a proprietary solution > called "texture bundles" which explicitly specify the linearizing LUT for our > textures. > > Can (4) be avoided by keeping the texture cache as a cache of the actual > texture data, and re-linearizing every time we need the values? Whether this > is a good idea probably depends how many textures we want to fit in RAM. > (Answer: so, so many. Probably worthwhile for us.) > > > On Mon, 11 Jan 2021 at 00:30, Larry Gritz <l...@larrygritz.com > <mailto:l...@larrygritz.com>> wrote: > OH, I get it. > > --colorconvert in out means "Convert the source image from `in` to `out` > before turning it into a MIP-map." > > It does NOT mean "convert the source from `in` to linear, and then when > writing the MIPmap convert it to `out`." > > So your source texture, the checkerboard, has values 0.0 and 1.0 only, and > when you convert those from linear to "sRGB", they are still 0.0 and 1.0, > respectively, so the rest proceeds apace, and your 1x1 fully filtered layer > ends up pretty darned close to 0.5. > > It assumes that you write a linear file. Maybe because the texture system > assumes all its input is linear. Using linear math for the downsizing when > creating the MIPmap is not enough. ALL the math inside the texture system for > blending between pixels (the filtering of the individual texture lookups) is > also linear, and will be wrong if the map is sRGB. > > You could make an argument, I suppose, that this is all not as flexible as > you'd want, and that you want to store nonlinear textures. You'd need a > number of changes: > > (1) a way to instruct maketx to do a second color conversion upon output to > the color space of your choice (i.e. truly save sRGB). > > (2) to have an option in the texture system to color convert BACK to a linear > space upon reading tiles, so that the filtering math will be correct, because > it's not correct to convert sRGB->linear in the shader itself after the > filter math is done, the conversion has to be upstream of the filter math. > > (3) to figure out how you're going to be able to tell, for a TIFF texture, > whether it's intended to be linear or in some other color space, because TIFF > doesn't directly say this anywhere. (Maybe you could rely on the file naming > convention, like maybe you seem to with checker_uint8_sRGB.tx?) > > (4) If you have a uint8 sRGB texture on disk, and you want to be converting > to linear as the tiles are read into the texture cache... ugh, you don't want > those tiles to be uint8 or you'll lose a lot of precision in the darks. So in > addition to converting sRGB to linear, you also want to convert from uint8 > to, I dunno, maybe uint16 or half for storage in the cache? Which also makes > it consume twice as much cache space? > > (By the way, `info -a -stats foo.tx` is also your friend for inspecting value > ranges.) > > >> On Jan 10, 2021, at 4:09 PM, Larry Gritz <l...@larrygritz.com >> <mailto:l...@larrygritz.com>> wrote: >> >> That's right, the FLOAT here just means "give me the values as floats", and >> it does not imply any color space conversion. >> >> So, the question is why the --colorconvert linear sRGB doesn't end up with a >> 1x1 miplevel that's farther from 0.5. I also would have the same expectation >> as you. >> >> Let me look a bit through the code... >> >> >>> On Jan 10, 2021, at 3:41 PM, Søren Ragsdale <sor...@gmail.com >>> <mailto:sor...@gmail.com>> wrote: >>> >>> I assumed oiio.FLOAT describes the data type and that script wouldn't know >>> whether the texture it was reading was UINT8 linear, gamma22, or sRGB. >>> >>> That assumption seems to be correct. I changed the script to UINT8 and I'm >>> still getting basically the same result. Black is 0 and white is 255 but >>> 50% gray should be higher than 128 due to the nonlinear sRGB LUT: >>> >>> $ python ~/scripts-dev/miplevels.py checker_uint8_sRGB.tx >>> 0 512x512=262144 min=0 med=255 max=255 >>> 1 256x256=65536 min=0 med=255 max=255 >>> 2 128x128=16384 min=0 med=255 max=255 >>> 3 64x64=4096 min=0 med=255 max=255 >>> 4 32x32=1024 min=127 med=127 max=155 >>> 5 16x16=256 min=127 med=127 max=142 >>> 6 8x8=64 min=127 med=127 max=135 >>> 7 4x4=16 min=127 med=129 max=131 >>> 8 2x2=4 min=128 med=129 max=129 >>> 9 1x1=1 min=129 med=129 max=129 >>> >>> As a sanity check I made a uniform 50% grey texture and the values are at >>> 188, consistent with sRGB 50% grey: >>> >>> $ iinfo --stats grey_float32_lin.tif >>> grey_float32_lin.tif : 512 x 512, 3 channel, float tiff >>> Stats Min: 0.500000 0.500000 0.500000 (float) >>> Stats Max: 0.500000 0.500000 0.500000 (float) >>> Stats Avg: 0.500000 0.500000 0.500000 (float) >>> Stats StdDev: 0.000000 0.000000 0.000000 (float) >>> Stats NanCount: 0 0 0 >>> Stats InfCount: 0 0 0 >>> Stats FiniteCount: 262144 262144 262144 >>> Constant: Yes >>> Constant Color: 0.500000 0.500000 0.500000 (float) >>> Monochrome: Yes >>> >>> $ maketx --oiio -d uint8 --unpremult --colorconvert linear sRGB >>> grey_float32_lin.tif -o grey_uint8_sRGB.tx >>> >>> $ python ~/scripts-dev/miplevels.py grey_uint8_sRGB.tx >>> 0 512x512=262144 min=188 med=188 max=188 >>> 1 256x256=65536 min=188 med=188 max=188 >>> 2 128x128=16384 min=188 med=188 max=188 >>> 3 64x64=4096 min=188 med=188 max=188 >>> 4 32x32=1024 min=188 med=188 max=188 >>> 5 16x16=256 min=188 med=188 max=188 >>> 6 8x8=64 min=188 med=188 max=188 >>> 7 4x4=16 min=188 med=188 max=188 >>> 8 2x2=4 min=188 med=188 max=188 >>> 9 1x1=1 min=188 med=188 max=188 >>> >>> On Sun, 10 Jan 2021 at 18:48, Solomon Boulos <bou...@cs.stanford.edu >>> <mailto:bou...@cs.stanford.edu>> wrote: >>> Doesn’t get as float convert from sRGB to Linear in your miplevels.py? If >>> you don’t want conversion, open it as int8. >>> >>> On Sun, Jan 10, 2021 at 10:39 Søren Ragsdale <sor...@gmail.com >>> <mailto:sor...@gmail.com>> wrote: >>> I have "checker_float32_lin.tif", a simple RGBA black and white >>> checkerboard. Each black or white square is 8 pixels wide, and every pixel >>> value is either 0.0 or 1.0. >>> >>> I'm using OIIO to turn this float32 scene-linear TIFF into a uint8 sRGB >>> albedo texture: >>> >>> maketx --oiio -d uint8 --unpremult --colorconvert linear sRGB >>> checker_float32_lin.tif -o checker_uint8_sRGB.tx >>> >>> I've written miplevels.py (see attached) which prints the min, median, and >>> max values of the first color channel for each mipmap level of the texture. >>> Here's the output: >>> >>> $ python ~/scripts-dev/miplevels.py checker_uint8_sRGB.tx >>> 0 512x512=262144 min=0.0 med=1.0 max=1.0 >>> 1 256x256=65536 min=0.0 med=1.0 max=1.0 >>> 2 128x128=16384 min=0.0 med=1.0 max=1.0 >>> 3 64x64=4096 min=0.0 med=1.0 max=1.0 >>> 4 32x32=1024 min=0.498039245605 med=0.498039245605 max=0.607843160629 >>> 5 16x16=256 min=0.498039245605 med=0.498039245605 max=0.556862771511 >>> 6 8x8=64 min=0.498039245605 med=0.498039245605 max=0.529411792755 >>> 7 4x4=16 min=0.498039245605 med=0.505882382393 max=0.51372551918 >>> 8 2x2=4 min=0.501960813999 med=0.505882382393 max=0.505882382393 >>> 9 1x1=1 min=0.505882382393 med=0.505882382393 max=0.505882382393 >>> >>> As the mipmaps decrease in size the median value converges on 0.5. Except >>> this is a sRGB texture. The value for 50% grey should be around 0.737 in >>> sRGB space. >>> >>> It appears maketx is converting the values from linear to sRGB then scaling >>> to create the mipmaps. When the source and destination color space are >>> specified I think maketx should scale in scene linear color space, then >>> convert to sRGB before saving each mipmap. >>> >>> Is this a bug? Is there a flag or workaround that I should know about? >>> >>> https://paroj.github.io/gltut/Texturing/Tut16%20Mipmaps%20and%20Linearity.html >>> >>> <https://paroj.github.io/gltut/Texturing/Tut16%20Mipmaps%20and%20Linearity.html> >>> _______________________________________________ >>> Oiio-dev mailing list >>> Oiio-dev@lists.openimageio.org <mailto:Oiio-dev@lists.openimageio.org> >>> http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org >>> <http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org> >>> _______________________________________________ >>> Oiio-dev mailing list >>> Oiio-dev@lists.openimageio.org <mailto:Oiio-dev@lists.openimageio.org> >>> http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org >>> <http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org> >>> <miplevels.py>_______________________________________________ >>> Oiio-dev mailing list >>> Oiio-dev@lists.openimageio.org <mailto:Oiio-dev@lists.openimageio.org> >>> http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org >>> <http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org> >> >> -- >> Larry Gritz >> l...@larrygritz.com <mailto:l...@larrygritz.com> >> >> >> >> >> _______________________________________________ >> Oiio-dev mailing list >> Oiio-dev@lists.openimageio.org <mailto:Oiio-dev@lists.openimageio.org> >> http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org >> <http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org> > > -- > Larry Gritz > l...@larrygritz.com <mailto:l...@larrygritz.com> > > > > > _______________________________________________ > Oiio-dev mailing list > Oiio-dev@lists.openimageio.org <mailto:Oiio-dev@lists.openimageio.org> > http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org > <http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org> > _______________________________________________ > Oiio-dev mailing list > Oiio-dev@lists.openimageio.org > http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org -- Larry Gritz l...@larrygritz.com
_______________________________________________ Oiio-dev mailing list Oiio-dev@lists.openimageio.org http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org