Add rygorous's float->srgb8 conversion routine to the stdlib.
Issue #230
This commit is contained in:
@@ -147,6 +147,7 @@ Contents:
|
|||||||
|
|
||||||
* `Converting Between Array-of-Structures and Structure-of-Arrays Layout`_
|
* `Converting Between Array-of-Structures and Structure-of-Arrays Layout`_
|
||||||
* `Conversions To and From Half-Precision Floats`_
|
* `Conversions To and From Half-Precision Floats`_
|
||||||
|
* `Converting to sRGB8`_
|
||||||
|
|
||||||
+ `Systems Programming Support`_
|
+ `Systems Programming Support`_
|
||||||
|
|
||||||
@@ -3691,6 +3692,22 @@ precise.
|
|||||||
uniform int16 float_to_half_fast(uniform float f)
|
uniform int16 float_to_half_fast(uniform float f)
|
||||||
|
|
||||||
|
|
||||||
|
Converting to sRGB8
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
The sRGB color space is used in many applications in graphics and imaging;
|
||||||
|
see the `Wikipedia page on sRGB`_ for more information. The ``ispc``
|
||||||
|
standard library provides two functions for converting floating-point color
|
||||||
|
values to 8-bit values in the sRGB space.
|
||||||
|
|
||||||
|
.. _Wikipedia page on sRGB: http://en.wikipedia.org/wiki/SRGB
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
int float_to_srgb8(float v)
|
||||||
|
uniform int float_to_srgb8(uniform float v)
|
||||||
|
|
||||||
|
|
||||||
Systems Programming Support
|
Systems Programming Support
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
|
|||||||
127
stdlib.ispc
127
stdlib.ispc
@@ -3829,6 +3829,133 @@ static inline int16 float_to_half_fast(float f) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// float -> srgb8
|
||||||
|
|
||||||
|
// https://gist.github.com/2246678, from Fabian "rygorous" Giesen.
|
||||||
|
//
|
||||||
|
// The basic ideas are still the same, only this time, we squeeze
|
||||||
|
// everything into the table, even the linear part of the range; since we
|
||||||
|
// are approximating the function as piecewise linear anyway, this is
|
||||||
|
// fairly easy.
|
||||||
|
//
|
||||||
|
// In the exact version of the conversion, any value that produces an
|
||||||
|
// output float less than 0.5 will be rounded to an integer of
|
||||||
|
// zero. Inverting the linear part of the transform, we get:
|
||||||
|
//
|
||||||
|
// log2(0.5 / (255 * 12.92)) =~ -12.686
|
||||||
|
//
|
||||||
|
// which in turn means that any value smaller than about 2^(-12.687) will
|
||||||
|
// return 0. What this means is that we can adapt the clamping code to
|
||||||
|
// just clamp to [2^(-13), 1-eps] and we're covered. This means our table
|
||||||
|
// needs to cover a range of 13 different exponents from -13 to -1.
|
||||||
|
//
|
||||||
|
// The table lookup, storage and interpolation works exactly the same way
|
||||||
|
// as in the code above.
|
||||||
|
//
|
||||||
|
// Max error for the whole function (integer-rounded result minus "exact"
|
||||||
|
// value, as computed in floats using the official formula): 0.544403 at
|
||||||
|
// 0x3e9f8000
|
||||||
|
|
||||||
|
__declspec(safe)
|
||||||
|
static inline int
|
||||||
|
float_to_srgb8(float in)
|
||||||
|
{
|
||||||
|
static const uniform unsigned int table[104] = {
|
||||||
|
0x0073000d, 0x007a000d, 0x0080000d, 0x0087000d,
|
||||||
|
0x008d000d, 0x0094000d, 0x009a000d, 0x00a1000d,
|
||||||
|
0x00a7001a, 0x00b4001a, 0x00c1001a, 0x00ce001a,
|
||||||
|
0x00da001a, 0x00e7001a, 0x00f4001a, 0x0101001a,
|
||||||
|
0x010e0033, 0x01280033, 0x01410033, 0x015b0033,
|
||||||
|
0x01750033, 0x018f0033, 0x01a80033, 0x01c20033,
|
||||||
|
0x01dc0067, 0x020f0067, 0x02430067, 0x02760067,
|
||||||
|
0x02aa0067, 0x02dd0067, 0x03110067, 0x03440067,
|
||||||
|
0x037800ce, 0x03df00ce, 0x044600ce, 0x04ad00ce,
|
||||||
|
0x051400ce, 0x057b00c5, 0x05dd00bc, 0x063b00b5,
|
||||||
|
0x06970158, 0x07420142, 0x07e30130, 0x087b0120,
|
||||||
|
0x090b0112, 0x09940106, 0x0a1700fc, 0x0a9500f2,
|
||||||
|
0x0b0f01cb, 0x0bf401ae, 0x0ccb0195, 0x0d950180,
|
||||||
|
0x0e56016e, 0x0f0d015e, 0x0fbc0150, 0x10630143,
|
||||||
|
0x11070264, 0x1238023e, 0x1357021d, 0x14660201,
|
||||||
|
0x156601e9, 0x165a01d3, 0x174401c0, 0x182401af,
|
||||||
|
0x18fe0331, 0x1a9602fe, 0x1c1502d2, 0x1d7e02ad,
|
||||||
|
0x1ed4028d, 0x201a0270, 0x21520256, 0x227d0240,
|
||||||
|
0x239f0443, 0x25c003fe, 0x27bf03c4, 0x29a10392,
|
||||||
|
0x2b6a0367, 0x2d1d0341, 0x2ebe031f, 0x304d0300,
|
||||||
|
0x31d105b0, 0x34a80555, 0x37520507, 0x39d504c5,
|
||||||
|
0x3c37048b, 0x3e7c0458, 0x40a8042a, 0x42bd0401,
|
||||||
|
0x44c20798, 0x488e071e, 0x4c1c06b6, 0x4f76065d,
|
||||||
|
0x52a50610, 0x55ac05cc, 0x5892058f, 0x5b590559,
|
||||||
|
0x5e0c0a23, 0x631c0980, 0x67db08f6, 0x6c55087f,
|
||||||
|
0x70940818, 0x74a007bd, 0x787d076c, 0x7c330723,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uniform unsigned int almost_one = 0x3f7fffff;
|
||||||
|
|
||||||
|
// Clamp to [2^(-13), 1-eps]; these two values map to 0 and 1, respectively.
|
||||||
|
in = max(in, 0.0f);
|
||||||
|
in = min(in, floatbits(almost_one));
|
||||||
|
|
||||||
|
// Do the table lookup and unpack bias, scale
|
||||||
|
unsigned int tab = table[(intbits(in) - 0x39000000u) >> 20];
|
||||||
|
unsigned int bias = (tab >> 16) << 9;
|
||||||
|
unsigned int scale = tab & 0xffff;
|
||||||
|
|
||||||
|
// Grab next-highest mantissa bits and perform linear interpolation
|
||||||
|
unsigned int t = (intbits(in) >> 12) & 0xff;
|
||||||
|
return (bias + scale*t) >> 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
__declspec(safe)
|
||||||
|
static inline uniform int
|
||||||
|
float_to_srgb8(uniform float in)
|
||||||
|
{
|
||||||
|
static const uniform unsigned int table[104] = {
|
||||||
|
0x0073000d, 0x007a000d, 0x0080000d, 0x0087000d,
|
||||||
|
0x008d000d, 0x0094000d, 0x009a000d, 0x00a1000d,
|
||||||
|
0x00a7001a, 0x00b4001a, 0x00c1001a, 0x00ce001a,
|
||||||
|
0x00da001a, 0x00e7001a, 0x00f4001a, 0x0101001a,
|
||||||
|
0x010e0033, 0x01280033, 0x01410033, 0x015b0033,
|
||||||
|
0x01750033, 0x018f0033, 0x01a80033, 0x01c20033,
|
||||||
|
0x01dc0067, 0x020f0067, 0x02430067, 0x02760067,
|
||||||
|
0x02aa0067, 0x02dd0067, 0x03110067, 0x03440067,
|
||||||
|
0x037800ce, 0x03df00ce, 0x044600ce, 0x04ad00ce,
|
||||||
|
0x051400ce, 0x057b00c5, 0x05dd00bc, 0x063b00b5,
|
||||||
|
0x06970158, 0x07420142, 0x07e30130, 0x087b0120,
|
||||||
|
0x090b0112, 0x09940106, 0x0a1700fc, 0x0a9500f2,
|
||||||
|
0x0b0f01cb, 0x0bf401ae, 0x0ccb0195, 0x0d950180,
|
||||||
|
0x0e56016e, 0x0f0d015e, 0x0fbc0150, 0x10630143,
|
||||||
|
0x11070264, 0x1238023e, 0x1357021d, 0x14660201,
|
||||||
|
0x156601e9, 0x165a01d3, 0x174401c0, 0x182401af,
|
||||||
|
0x18fe0331, 0x1a9602fe, 0x1c1502d2, 0x1d7e02ad,
|
||||||
|
0x1ed4028d, 0x201a0270, 0x21520256, 0x227d0240,
|
||||||
|
0x239f0443, 0x25c003fe, 0x27bf03c4, 0x29a10392,
|
||||||
|
0x2b6a0367, 0x2d1d0341, 0x2ebe031f, 0x304d0300,
|
||||||
|
0x31d105b0, 0x34a80555, 0x37520507, 0x39d504c5,
|
||||||
|
0x3c37048b, 0x3e7c0458, 0x40a8042a, 0x42bd0401,
|
||||||
|
0x44c20798, 0x488e071e, 0x4c1c06b6, 0x4f76065d,
|
||||||
|
0x52a50610, 0x55ac05cc, 0x5892058f, 0x5b590559,
|
||||||
|
0x5e0c0a23, 0x631c0980, 0x67db08f6, 0x6c55087f,
|
||||||
|
0x70940818, 0x74a007bd, 0x787d076c, 0x7c330723,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uniform unsigned int almost_one = 0x3f7fffff;
|
||||||
|
|
||||||
|
// Clamp to [2^(-13), 1-eps]; these two values map to 0 and 1, respectively.
|
||||||
|
in = max(in, 0.0f);
|
||||||
|
in = min(in, floatbits(almost_one));
|
||||||
|
|
||||||
|
// Do the table lookup and unpack bias, scale
|
||||||
|
uniform unsigned int tab = table[(intbits(in) - 0x39000000u) >> 20];
|
||||||
|
uniform unsigned int bias = (tab >> 16) << 9;
|
||||||
|
uniform unsigned int scale = tab & 0xffff;
|
||||||
|
|
||||||
|
// Grab next-highest mantissa bits and perform linear interpolation
|
||||||
|
uniform unsigned int t = (intbits(in) >> 12) & 0xff;
|
||||||
|
return (bias + scale*t) >> 16;
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// RNG stuff
|
// RNG stuff
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user