From 8e3f4e4890fde6a97d06823ac6e561218a2afe37 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 22 Aug 2005 13:54:43 +0000 Subject: [PATCH] From Fabio Mierlo, "I add a new option in the HDR Reader. The RAW option store the RGBE values into a Image, to use this option you need to decode the RGBE value in the frag- ment shader. Follow the cube map glsl decoder: vec4 textureCubeRGBE( uniform samplerCube sampler, vec3 coords ) { ivec4 rgbe = textureCube( sampler, coords ) * 255. + 0.5; float e = rgbe.a - ( 128 + 8 ); return vec4( rgbe.rgb * exp2( e ), 1.0 ); } This option is usefull for who have a outdate hardware like FX cards and want to do cool things. Finally this patch is need by a new HDR Rendering example that I will put on the Wiki." --- src/osgPlugins/hdr/ReaderWriterHDR.cpp | 44 ++++++++++++++++++++++---- src/osgPlugins/hdr/hdrloader.cpp | 29 ++++++++++++++--- src/osgPlugins/hdr/hdrloader.h | 2 +- 3 files changed, 62 insertions(+), 13 deletions(-) diff --git a/src/osgPlugins/hdr/ReaderWriterHDR.cpp b/src/osgPlugins/hdr/ReaderWriterHDR.cpp index 23a4e503b..edc9c4cb6 100644 --- a/src/osgPlugins/hdr/ReaderWriterHDR.cpp +++ b/src/osgPlugins/hdr/ReaderWriterHDR.cpp @@ -57,6 +57,7 @@ public: float mul = 1.0f; bool bYFlip = false; bool convertToRGB8 = false; + bool rawRGBE = false; if(_opts) { std::istringstream iss(_opts->getOptionString()); @@ -71,6 +72,22 @@ public: { convertToRGB8 = true; } + /* RAW: store the RGBE values into a Image, to use this option you + * need to decode the RGBE value in the fragment shader. Follow + * the cube map glsl decoder: + * + * vec4 textureCubeRGBE( uniform samplerCube sampler, vec3 coords ) + * { + * ivec4 rgbe = textureCube( sampler, coords ) * 255. + 0.5; + * float e = rgbe.a - ( 128 + 8 ); + * return vec4( rgbe.rgb * exp2( e ), 1.0 ); + * } + * + */ + else if(opt == "RAW") + { + rawRGBE = true; + } else if(opt == "YFLIP") { bYFlip = true; // TODO @@ -79,7 +96,7 @@ public: } HDRLoaderResult res; - bool ret = HDRLoader::load(_file.c_str(), res); + bool ret = HDRLoader::load(_file.c_str(), rawRGBE, res); if (!ret) return ReadResult::FILE_NOT_FOUND; @@ -110,8 +127,8 @@ public: int dataType = GL_UNSIGNED_BYTE; img->setFileName(_file.c_str()); - img->setImage( res.width, res.height, 1, - 3, + img->setImage( res.width, res.height, 1, + 3, // Why this value are here? pixelFormat, dataType, (unsigned char*) rgb, @@ -119,18 +136,31 @@ public: } else { - int internalFormat = GL_RGB; - int pixelFormat = GL_RGB; + int internalFormat; + int pixelFormat; int dataType = GL_FLOAT; + if (rawRGBE) + { + internalFormat = GL_RGBA8; + pixelFormat = GL_RGBA; + } else { + // In a perfect world it should be GL_RGB32F_ARB, + // but by default it works fine as GL_RGB8. You + // can set it as GL_RGB32F_ARB in the method + // setInternalFormat of osg::Texture{xD, Rectangle + // and CubeMap} if your GPU support it. + internalFormat = GL_RGB8; + pixelFormat = GL_RGB; + } + img->setFileName(_file.c_str()); - img->setImage( res.width, res.height, 1, + img->setImage( res.width, res.height, 1, internalFormat, pixelFormat, dataType, (unsigned char*) res.cols, osg::Image::USE_NEW_DELETE); - } return img; diff --git a/src/osgPlugins/hdr/hdrloader.cpp b/src/osgPlugins/hdr/hdrloader.cpp index 4d0709fa6..aa80602e3 100644 --- a/src/osgPlugins/hdr/hdrloader.cpp +++ b/src/osgPlugins/hdr/hdrloader.cpp @@ -41,6 +41,7 @@ typedef unsigned char RGBE[4]; #define MINELEN 8 // minimum scanline length for encoding #define MAXELEN 0x7fff // maximum scanline length for encoding +static void rawRGBEData(RGBE *scan, int len, float *cols); static void workOnRGBE(RGBE *scan, int len, float *cols); static bool decrunch(RGBE *scanline, int len, FILE *file); static bool oldDecrunch(RGBE *scanline, int len, FILE *file); @@ -62,7 +63,7 @@ bool HDRLoader::isHDRFile(const char *_fileName) return true; } -bool HDRLoader::load(const char *_fileName, HDRLoaderResult &_res) +bool HDRLoader::load(const char *_fileName, const bool _rawRGBE, HDRLoaderResult &_res) { int i; char str[200]; @@ -112,7 +113,8 @@ bool HDRLoader::load(const char *_fileName, HDRLoaderResult &_res) _res.width = w; _res.height = h; - float *cols = new float[w * h * 3]; + int components = _rawRGBE ? 4 : 3; + float *cols = new float[w * h * components]; _res.cols = cols; RGBE *scanline = new RGBE[w]; @@ -122,12 +124,15 @@ bool HDRLoader::load(const char *_fileName, HDRLoaderResult &_res) } // convert image - cols += (h-1) * w * 3; + cols += (h-1) * w * components; for (int y = h - 1; y >= 0; y--) { if (decrunch(scanline, w, file) == false) break; - workOnRGBE(scanline, w, cols); - cols -= w * 3; + if (_rawRGBE) + rawRGBEData(scanline, w, cols); + else + workOnRGBE(scanline, w, cols); + cols -= w * components; } delete [] scanline; @@ -136,6 +141,20 @@ bool HDRLoader::load(const char *_fileName, HDRLoaderResult &_res) return true; } +void rawRGBEData(RGBE *_scan, int _len, float *_cols) +{ + int ii = 0; + while (_len-- > 0) { + _cols[0] = _scan[0][R] / 255.0; + _cols[1] = _scan[0][G] / 255.0; + _cols[2] = _scan[0][B] / 255.0; + _cols[3] = _scan[0][E] / 255.0; + _cols += 4; + _scan++; + ii++; + } +} + inline float convertComponent(int _expo, int _val) { return ldexp( static_cast(_val), _expo-8); diff --git a/src/osgPlugins/hdr/hdrloader.h b/src/osgPlugins/hdr/hdrloader.h index 85210897b..11a0fac52 100644 --- a/src/osgPlugins/hdr/hdrloader.h +++ b/src/osgPlugins/hdr/hdrloader.h @@ -44,7 +44,7 @@ public: class HDRLoader { public: static bool isHDRFile(const char *fileName); - static bool load(const char *fileName, HDRLoaderResult &res); + static bool load(const char *fileName, const bool rawRGBE, HDRLoaderResult &res); }; #endif