mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-08-19 13:40:49 +03:00
0032114: Visualization, TKOpenGl - broken PBR LUT on OpenGL ES 2.0
Added image formats Image_Format_RGF_half/Image_Format_RGBAF_half with manual conversion between 32-bit float and 16-bit half-float values. PBR LUT table is now converted into GL_HALF_FLOAT_OES data format in case of OpenGL ES 2.0.
This commit is contained in:
@@ -33,7 +33,9 @@ enum Image_Format
|
||||
Image_Format_BGRF, //!< same as RGBF but with different components order
|
||||
Image_Format_RGBAF, //!< 4 floats (16-bytes) RGBA image plane
|
||||
Image_Format_BGRAF, //!< same as RGBAF but with different components order
|
||||
Image_Format_RGF_half, //!< 2 half-floats (4-bytes) RG image plane
|
||||
Image_Format_RGBAF_half, //!< 4 half-floats (8-bytes) RGBA image plane
|
||||
};
|
||||
enum { Image_Format_NB = Image_Format_BGRAF + 1 };
|
||||
enum { Image_Format_NB = Image_Format_RGBAF_half + 1 };
|
||||
|
||||
#endif // _Image_Format_HeaderFile
|
||||
|
@@ -62,6 +62,8 @@ namespace
|
||||
ImageFormatInfo(BGRF, 3, sizeof(float) * 3),
|
||||
ImageFormatInfo(RGBAF, 4, sizeof(float) * 4),
|
||||
ImageFormatInfo(BGRAF, 4, sizeof(float) * 4),
|
||||
ImageFormatInfo(RGF_half, 2, sizeof(uint16_t) * 2),
|
||||
ImageFormatInfo(RGBAF_half, 4, sizeof(uint16_t) * 4),
|
||||
CompressedImageFormatInfo(RGB_S3TC_DXT1, 3, 1), // DXT1 uses circa half a byte per pixel (64 bits per 4x4 block)
|
||||
CompressedImageFormatInfo(RGBA_S3TC_DXT1, 4, 1),
|
||||
CompressedImageFormatInfo(RGBA_S3TC_DXT3, 4, 1), // DXT3/5 uses circa 1 byte per pixel (128 bits per 4x4 block)
|
||||
@@ -294,6 +296,17 @@ Quantity_ColorRGBA Image_PixMap::PixelColor (const Standard_Integer theX,
|
||||
const Image_ColorBGRF& aPixel = Value<Image_ColorBGRF> (theY, theX);
|
||||
return Quantity_ColorRGBA (NCollection_Vec4<float> (aPixel.r(), aPixel.g(), aPixel.b(), 1.0f)); // opaque
|
||||
}
|
||||
case Image_Format_RGF_half:
|
||||
{
|
||||
const NCollection_Vec2<uint16_t>& aPixel = Value<NCollection_Vec2<uint16_t>> (theY, theX);
|
||||
return Quantity_ColorRGBA (NCollection_Vec4<float> (ConvertFromHalfFloat (aPixel.x()), ConvertFromHalfFloat (aPixel.y()), 0.0f, 1.0f));
|
||||
}
|
||||
case Image_Format_RGBAF_half:
|
||||
{
|
||||
const NCollection_Vec4<uint16_t>& aPixel = Value<NCollection_Vec4<uint16_t>> (theY, theX);
|
||||
return Quantity_ColorRGBA (NCollection_Vec4<float> (ConvertFromHalfFloat (aPixel.r()), ConvertFromHalfFloat (aPixel.g()),
|
||||
ConvertFromHalfFloat (aPixel.b()), ConvertFromHalfFloat (aPixel.a())));
|
||||
}
|
||||
case Image_Format_RGBA:
|
||||
{
|
||||
const Image_ColorRGBA& aPixel = Value<Image_ColorRGBA> (theY, theX);
|
||||
@@ -440,6 +453,22 @@ void Image_PixMap::SetPixelColor (const Standard_Integer theX,
|
||||
aPixel.b() = aColor.b();
|
||||
return;
|
||||
}
|
||||
case Image_Format_RGF_half:
|
||||
{
|
||||
NCollection_Vec2<uint16_t>& aPixel = ChangeValue<NCollection_Vec2<uint16_t>> (theY, theX);
|
||||
aPixel.x() = ConvertToHalfFloat (aColor.r());
|
||||
aPixel.y() = ConvertToHalfFloat (aColor.g());
|
||||
return;
|
||||
}
|
||||
case Image_Format_RGBAF_half:
|
||||
{
|
||||
NCollection_Vec4<uint16_t>& aPixel = ChangeValue<NCollection_Vec4<uint16_t>> (theY, theX);
|
||||
aPixel.r() = ConvertToHalfFloat (aColor.r());
|
||||
aPixel.g() = ConvertToHalfFloat (aColor.g());
|
||||
aPixel.b() = ConvertToHalfFloat (aColor.b());
|
||||
aPixel.a() = ConvertToHalfFloat (aColor.a());
|
||||
return;
|
||||
}
|
||||
case Image_Format_RGBA:
|
||||
{
|
||||
Image_ColorRGBA& aPixel = ChangeValue<Image_ColorRGBA> (theY, theX);
|
||||
|
@@ -303,6 +303,36 @@ public: //! @name low-level API for batch-processing (pixels reading / compariso
|
||||
return myData.ChangeValue (theRow, theCol);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
//! Convert 16-bit half-float value into 32-bit float (simple conversion).
|
||||
static float ConvertFromHalfFloat (const uint16_t theHalf)
|
||||
{
|
||||
union FloatUint32 { float Float32; uint32_t UInt32; };
|
||||
|
||||
const uint32_t e = (theHalf & 0x7C00) >> 10; // exponent
|
||||
const uint32_t m = (theHalf & 0x03FF) << 13; // mantissa
|
||||
FloatUint32 mf, aRes;
|
||||
mf.Float32 = (float )m;
|
||||
const uint32_t v = mf.UInt32 >> 23; // evil log2 bit hack to count leading zeros in denormalized format
|
||||
aRes.UInt32 = (theHalf & 0x8000)<<16 | (e != 0) * ((e + 112) << 23 | m) | ((e == 0) & (m != 0)) * ((v - 37) << 23 | ((m << (150 - v)) & 0x007FE000)); // sign : normalized : denormalized
|
||||
return aRes.Float32;
|
||||
}
|
||||
|
||||
//! Convert 32-bit float value into IEEE-754 16-bit floating-point format without infinity:
|
||||
//! 1-5-10, exp-15, +-131008.0, +-6.1035156E-5, +-5.9604645E-8, 3.311 digits.
|
||||
static uint16_t ConvertToHalfFloat (const float theFloat)
|
||||
{
|
||||
union FloatUint32 { float Float32; uint32_t UInt32; };
|
||||
FloatUint32 anInput;
|
||||
anInput.Float32 = theFloat;
|
||||
const uint32_t b = anInput.UInt32 + 0x00001000; // round-to-nearest-even: add last bit after truncated mantissa
|
||||
const uint32_t e = (b & 0x7F800000) >> 23; // exponent
|
||||
const uint32_t m = b & 0x007FFFFF; // mantissa; in line below: 0x007FF000 = 0x00800000-0x00001000 = decimal indicator flag - initial rounding
|
||||
return (uint16_t)((b & 0x80000000) >> 16 | (e > 112) * ((((e - 112) << 10) & 0x7C00) | m >> 13)
|
||||
| ((e < 113) & (e > 101)) * ((((0x007FF000 + m) >> (125 - e)) + 1) >> 1) | (e > 143) * 0x7FFF); // sign : normalized : denormalized : saturate
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
Image_PixMapData myData; //!< data buffer
|
||||
|
Reference in New Issue
Block a user