Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

833 lines
27 KiB

  1. //======= Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose:
  4. //
  5. // $Header: $
  6. // $NoKeywords: $
  7. //=============================================================================//
  8. #ifndef FLOATBITMAP_H
  9. #define FLOATBITMAP_H
  10. #ifdef _WIN32
  11. #pragma once
  12. #endif
  13. #include "tier0/platform.h"
  14. #include "tier0/dbg.h"
  15. #include "tier1/utlsoacontainer.h"
  16. #include "mathlib/mathlib.h"
  17. #include "bitmap/imageformat.h"
  18. class IThreadPool;
  19. struct PixRGBAF
  20. {
  21. float Red;
  22. float Green;
  23. float Blue;
  24. float Alpha;
  25. };
  26. struct PixRGBA8
  27. {
  28. unsigned char Red;
  29. unsigned char Green;
  30. unsigned char Blue;
  31. unsigned char Alpha;
  32. };
  33. inline PixRGBAF PixRGBA8_to_F( PixRGBA8 const &x )
  34. {
  35. PixRGBAF f;
  36. f.Red = x.Red / float( 255.0f );
  37. f.Green = x.Green / float( 255.0f );
  38. f.Blue = x.Blue / float( 255.0f );
  39. f.Alpha = x.Alpha / float( 255.0f );
  40. return f;
  41. }
  42. inline PixRGBA8 PixRGBAF_to_8( PixRGBAF const &f )
  43. {
  44. PixRGBA8 x;
  45. x.Red = ( unsigned char )MAX( 0, MIN( 255.0,255.0*f.Red ) );
  46. x.Green = ( unsigned char )MAX( 0, MIN( 255.0,255.0*f.Green ) );
  47. x.Blue = ( unsigned char )MAX( 0, MIN( 255.0,255.0*f.Blue ) );
  48. x.Alpha = ( unsigned char )MAX( 0, MIN( 255.0,255.0*f.Alpha ) );
  49. return x;
  50. }
  51. #define SPFLAGS_MAXGRADIENT 1
  52. // bit flag options for ComputeSelfShadowedBumpmapFromHeightInAlphaChannel:
  53. #define SSBUMP_OPTION_NONDIRECTIONAL 1 // generate ambient occlusion only
  54. #define SSBUMP_MOD2X_DETAIL_TEXTURE 2 // scale so that a flat unshadowed
  55. // value is 0.5, and bake rgb luminance
  56. // in.
  57. // attributes for csoaa container
  58. enum FBMAttribute_t
  59. {
  60. FBM_ATTR_RED = 0,
  61. FBM_ATTR_GREEN = 1,
  62. FBM_ATTR_BLUE = 2,
  63. FBM_ATTR_ALPHA = 3,
  64. FBM_ATTR_COUNT
  65. };
  66. enum FBMAttributeMask_t
  67. {
  68. FBM_ATTR_RED_MASK = ( 1 << FBM_ATTR_RED ),
  69. FBM_ATTR_GREEN_MASK = ( 1 << FBM_ATTR_GREEN ),
  70. FBM_ATTR_BLUE_MASK = ( 1 << FBM_ATTR_BLUE ),
  71. FBM_ATTR_ALPHA_MASK = ( 1 << FBM_ATTR_ALPHA ),
  72. FBM_ATTR_RGB_MASK = FBM_ATTR_RED_MASK | FBM_ATTR_GREEN_MASK | FBM_ATTR_BLUE_MASK,
  73. FBM_ATTR_RGBA_MASK = FBM_ATTR_RED_MASK | FBM_ATTR_GREEN_MASK | FBM_ATTR_BLUE_MASK | FBM_ATTR_ALPHA_MASK,
  74. };
  75. enum DownsampleFlags_t
  76. {
  77. DOWNSAMPLE_CLAMPS = 0x1,
  78. DOWNSAMPLE_CLAMPT = 0x2,
  79. DOWNSAMPLE_CLAMPU = 0x4,
  80. DOWNSAMPLE_ALPHATEST = 0x10,
  81. };
  82. struct DownsampleInfo_t
  83. {
  84. int m_nFlags; // see DownsampleFlags_t
  85. float m_flAlphaThreshhold;
  86. float m_flAlphaHiFreqThreshhold;
  87. };
  88. //-----------------------------------------------------------------------------
  89. // Float bitmap
  90. //-----------------------------------------------------------------------------
  91. class FloatBitMap_t : public CSOAContainer
  92. {
  93. typedef CSOAContainer BaseClass;
  94. public:
  95. FloatBitMap_t();
  96. FloatBitMap_t( int nWidth, int nHeight, int nDepth = 1, int nAttributeMask = FBM_ATTR_RGBA_MASK ); // make one and allocate space
  97. FloatBitMap_t( const char *pFilename ); // read one from a file (tga or pfm)
  98. FloatBitMap_t( const FloatBitMap_t *pOrig );
  99. // Initialize, shutdown
  100. void Init( int nWidth, int nHeight, int nDepth = 1, int nAttributeMask = FBM_ATTR_RGBA_MASK );
  101. void Shutdown();
  102. // Computes the attribute mask
  103. int GetAttributeMask() const;
  104. // Does the bitmap have data for a particular component?
  105. bool HasAttributeData( FBMAttribute_t a ) const;
  106. // Compute valid attribute list
  107. int ComputeValidAttributeList( int pIndex[4] ) const;
  108. // Methods to initialize bitmap data
  109. bool LoadFromPFM( const char *pFilename ); // load from floating point pixmap (.pfm) file
  110. bool LoadFromPSD( const char *pFilename ); // load from psd file
  111. void InitializeWithRandomPixelsFromAnotherFloatBM( const FloatBitMap_t &other );
  112. void Clear( float r, float g, float b, float alpha ); // set all pixels to speicifed values (0..1 nominal)
  113. void LoadFromBuffer( const void *pBuffer, size_t nBufSize, ImageFormat fmt, float flGamma ); // Assumes dimensions match the bitmap size
  114. void LoadFromFloatBitmap( const FloatBitMap_t *pOrig );
  115. // Methods to write bitmap data to files
  116. bool WriteTGAFile( const char *pFilename ) const;
  117. bool WritePFM( const char *pFilename ); // save to floating point pixmap (.pfm) file
  118. void WriteToBuffer( void *pBuffer, size_t nBufSize, ImageFormat fmt, float flGamma ) const; // Assumes dimensions match the bitmap size
  119. // Methods to read + write constant values
  120. const float &ConstantValue( int comp ) const;
  121. // Methods to read + write individual pixels
  122. float &Pixel( int x, int y, int z, int comp ) const;
  123. float &PixelWrapped( int x, int y, int z, int comp ) const;
  124. float &PixelClamped( int x, int y, int z, int comp ) const;
  125. float &Alpha( int x, int y, int z ) const;
  126. // look up a pixel value with bilinear interpolation
  127. float InterpolatedPixel( float x, float y, int comp ) const;
  128. float InterpolatedPixel( float x, float y, float z, int comp ) const;
  129. PixRGBAF PixelRGBAF( int x, int y, int z ) const;
  130. void WritePixelRGBAF(int x, int y, int z, PixRGBAF value) const;
  131. void WritePixel(int x, int y, int z, int comp, float value);
  132. // Method to slam a particular channel to always be the same value
  133. void SetChannel( int comp, float flValue );
  134. // paste, performing boundary matching. Alpha channel can be used to make
  135. // brush shape irregular
  136. void SmartPaste( const FloatBitMap_t &brush, int xofs, int yofs, uint32 flags );
  137. // force to be tileable using poisson formula
  138. void MakeTileable( void );
  139. void ReSize( int NewXSize, int NewYSize );
  140. // Makes the image be a sub-range of the current image
  141. void Crop( int x, int y, int z, int nWidth, int nHeight, int nDepth );
  142. // find the bounds of the area that has non-zero alpha.
  143. void GetAlphaBounds( int &minx, int &miny, int &maxx, int &maxy );
  144. // Solve the poisson equation for an image. The alpha channel of the image controls which
  145. // pixels are "modifiable", and can be used to set boundary conditions. Alpha=0 means the pixel
  146. // is locked. deltas are in the order [(x,y)-(x,y-1),(x,y)-(x-1,y),(x,y)-(x+1,y),(x,y)-(x,y+1)
  147. void Poisson( FloatBitMap_t * deltas[4],
  148. int n_iters,
  149. uint32 flags // SPF_xxx
  150. );
  151. void QuarterSize( FloatBitMap_t *pBitmap ); // get a new one downsampled
  152. void QuarterSizeBlocky( FloatBitMap_t *pBitmap ); // get a new one downsampled
  153. void QuarterSizeWithGaussian( FloatBitMap_t *pBitmap ); // downsample 2x using a gaussian
  154. // Downsample using nice filter (NOTE: Dest bitmap needs to have been initialized w/ final size)
  155. void DownsampleNiceFiltered( const DownsampleInfo_t& info, FloatBitMap_t *pBitmap );
  156. void RaiseToPower( float pow );
  157. void ScaleGradients( void );
  158. void Logize( void ); // pix=log(1+pix)
  159. void UnLogize( void ); // pix=exp(pix)-1
  160. // compress to 8 bits converts the hdr texture to an 8 bit texture, encoding a scale factor
  161. // in the alpha channel. upon return, the original pixel can be (approximately) recovered
  162. // by the formula rgb*alpha*overbright.
  163. // this function performs special numerical optimization on the texture to minimize the error
  164. // when using bilinear filtering to read the texture.
  165. void CompressTo8Bits( float overbright );
  166. // decompress a bitmap converted by CompressTo8Bits
  167. void Uncompress( float overbright );
  168. Vector AverageColor( void ); // average rgb value of all pixels
  169. float BrightestColor( void ); // highest vector magnitude
  170. void ScaleRGB( float scale_factor ); // for all pixels, r,g,b*=scale_factor
  171. // given a bitmap with height stored in the alpha channel, generate vector positions and normals
  172. void ComputeVertexPositionsAndNormals( float flHeightScale, Vector ** ppPosOut, Vector ** ppNormalOut ) const;
  173. // generate a normal map with height stored in alpha. uses hl2 tangent basis to support baked
  174. // self shadowing. the bump scale maps the height of a pixel relative to the edges of the
  175. // pixel. This function may take a while - many millions of rays may be traced. applications
  176. // using this method need to link w/ raytrace.lib
  177. FloatBitMap_t * ComputeSelfShadowedBumpmapFromHeightInAlphaChannel(
  178. float bump_scale, int nrays_to_trace_per_pixel = 100,
  179. uint32 nOptionFlags = 0 // SSBUMP_OPTION_XXX
  180. ) const;
  181. // generate a conventional normal map from a source with height stored in alpha.
  182. FloatBitMap_t *ComputeBumpmapFromHeightInAlphaChannel( float bump_scale ) const ;
  183. // bilateral (edge preserving) smoothing filter. edge_threshold_value defines the difference in
  184. // values over which filtering will not occur. Each channel is filtered independently. large
  185. // radii will run slow, since the bilateral filter is neither separable, nor is it a
  186. // convolution that can be done via fft.
  187. void TileableBilateralFilter( int radius_in_pixels, float edge_threshold_value );
  188. // Sets a thread pool for all float bitmap work to be done on
  189. static void SetThreadPool( IThreadPool* pPool );
  190. protected:
  191. void QuarterSize2D( FloatBitMap_t *pDest, int nStart, int nCount );
  192. void QuarterSize3D( FloatBitMap_t *pDest, int nStart, int nCount );
  193. void QuarterSizeBlocky2D( FloatBitMap_t *pDest, int nStart, int nCount );
  194. void QuarterSizeBlocky3D( FloatBitMap_t *pDest, int nStart, int nCount );
  195. template< class T > void LoadFromBufferRGBFloat( const T *pBuffer, int nPixelCount );
  196. template< class T > void LoadFromBufferRGB( const T *pBuffer, int nPixelCount, const float *pGammaTable );
  197. template< class T > void LoadFromBufferRGBAFloat( const T *pBuffer, int nPixelCount );
  198. template< class T > void LoadFromBufferRGBA( const T *pBuffer, int nPixelCount, const float *pGammaTable );
  199. template< class T > void LoadFromBufferUV( const T *pBuffer, int nPixelCount );
  200. template< class T > void LoadFromBufferUVWQ( const T *pBuffer, int nPixelCount );
  201. template< class T > void LoadFromBufferUVLX( const T *pBuffer, int nPixelCount );
  202. template< class T > void WriteToBufferRGB( T *pBuffer, int nPixelCount, const uint16 *pInvGammaTable ) const;
  203. template< class T > void WriteToBufferRGBFloat( T *pBuffer, int nPixelCount ) const;
  204. template< class T > void WriteToBufferRGBA( T *pBuffer, int nPixelCount, const uint16 *pInvGammaTable ) const;
  205. template< class T > void WriteToBufferRGBAFloat( T *pBuffer, int nPixelCount ) const;
  206. template< class T > void WriteToBufferUV( T *pBuffer, int nPixelCount ) const;
  207. template< class T > void WriteToBufferUVWQ( T *pBuffer, int nPixelCount ) const;
  208. template< class T > void WriteToBufferUVLX( T *pBuffer, int nPixelCount ) const;
  209. static int CoordWrap( int nC, int nLimit );
  210. static IThreadPool *sm_pFBMThreadPool;
  211. };
  212. //-----------------------------------------------------------------------------
  213. // Inline methods
  214. //-----------------------------------------------------------------------------
  215. inline FloatBitMap_t::FloatBitMap_t(void)
  216. {
  217. }
  218. inline void FloatBitMap_t::Init( int nXSize, int nYSize, int nZSize, int nAttributeMask )
  219. {
  220. PurgeData();
  221. SetAttributeType( FBM_ATTR_RED, ATTRDATATYPE_FLOAT, ( nAttributeMask & FBM_ATTR_RED_MASK ) != 0 );
  222. SetAttributeType( FBM_ATTR_GREEN, ATTRDATATYPE_FLOAT, ( nAttributeMask & FBM_ATTR_GREEN_MASK ) != 0 );
  223. SetAttributeType( FBM_ATTR_BLUE, ATTRDATATYPE_FLOAT, ( nAttributeMask & FBM_ATTR_BLUE_MASK ) != 0 );
  224. SetAttributeType( FBM_ATTR_ALPHA, ATTRDATATYPE_FLOAT, ( nAttributeMask & FBM_ATTR_ALPHA_MASK ) != 0 );
  225. AllocateData( nXSize, nYSize, nZSize );
  226. // Default alpha to white. All others default to 0.0 by default
  227. if ( ( nAttributeMask & FBM_ATTR_ALPHA_MASK ) == 0 )
  228. {
  229. FillAttr( FBM_ATTR_ALPHA, 1.0f );
  230. }
  231. }
  232. //-----------------------------------------------------------------------------
  233. // Computes the attribute mask
  234. //-----------------------------------------------------------------------------
  235. inline int FloatBitMap_t::GetAttributeMask() const
  236. {
  237. int nMask = 0;
  238. if ( HasAllocatedMemory( FBM_ATTR_RED ) )
  239. nMask |= FBM_ATTR_RED_MASK;
  240. if ( HasAllocatedMemory( FBM_ATTR_GREEN ) )
  241. nMask |= FBM_ATTR_GREEN_MASK;
  242. if ( HasAllocatedMemory( FBM_ATTR_BLUE ) )
  243. nMask |= FBM_ATTR_BLUE_MASK;
  244. if ( HasAllocatedMemory( FBM_ATTR_ALPHA ) )
  245. nMask |= FBM_ATTR_ALPHA_MASK;
  246. return nMask;
  247. }
  248. //-----------------------------------------------------------------------------
  249. // Compute valid attribute list
  250. //-----------------------------------------------------------------------------
  251. inline int FloatBitMap_t::ComputeValidAttributeList( int pIndex[4] ) const
  252. {
  253. int nCount = 0;
  254. if ( HasAllocatedMemory( FBM_ATTR_RED ) )
  255. pIndex[ nCount++ ] = FBM_ATTR_RED;
  256. if ( HasAllocatedMemory( FBM_ATTR_GREEN ) )
  257. pIndex[ nCount++ ] = FBM_ATTR_GREEN;
  258. if ( HasAllocatedMemory( FBM_ATTR_BLUE ) )
  259. pIndex[ nCount++ ] = FBM_ATTR_BLUE;
  260. if ( HasAllocatedMemory( FBM_ATTR_ALPHA ) )
  261. pIndex[ nCount++ ] = FBM_ATTR_ALPHA;
  262. return nCount;
  263. }
  264. //-----------------------------------------------------------------------------
  265. // Does the bitmap have data for a particular component?
  266. //-----------------------------------------------------------------------------
  267. inline bool FloatBitMap_t::HasAttributeData( FBMAttribute_t a ) const
  268. {
  269. return HasAllocatedMemory( a );
  270. }
  271. inline int FloatBitMap_t::CoordWrap( int nC, int nLimit )
  272. {
  273. if ( nC >= nLimit )
  274. {
  275. nC %= nLimit;
  276. }
  277. else if ( nC < 0 )
  278. {
  279. nC += nLimit * ( ( -nC + nLimit-1 ) / nLimit );
  280. }
  281. return nC;
  282. }
  283. inline float &FloatBitMap_t::Pixel(int x, int y, int z, int comp) const
  284. {
  285. Assert( (x >= 0 ) && (x < NumCols() ) );
  286. Assert( (y >= 0) && (y < NumRows() ) );
  287. Assert( (z >= 0) && (z < NumSlices() ) );
  288. float *pData = ElementPointer<float>( comp, x, y, z );
  289. return *pData;
  290. }
  291. inline const float &FloatBitMap_t::ConstantValue( int comp ) const
  292. {
  293. Assert( !HasAllocatedMemory( comp ) );
  294. return Pixel( 0, 0, 0, comp );
  295. }
  296. inline float &FloatBitMap_t::PixelWrapped(int x, int y, int z, int comp) const
  297. {
  298. // like Pixel except wraps around to other side
  299. x = CoordWrap( x, NumCols() );
  300. y = CoordWrap( y, NumRows() );
  301. z = CoordWrap( z, NumSlices() );
  302. return Pixel( x, y, z, comp );
  303. }
  304. inline float &FloatBitMap_t::PixelClamped(int x, int y, int z, int comp) const
  305. {
  306. // like Pixel except wraps around to other side
  307. x = clamp( x, 0, NumCols() - 1 );
  308. y = clamp( y, 0, NumRows() - 1 );
  309. z = clamp( z, 0, NumSlices() - 1 );
  310. return Pixel( x, y, z, comp );
  311. }
  312. inline float &FloatBitMap_t::Alpha( int x, int y, int z ) const
  313. {
  314. Assert( ( x >= 0 ) && ( x < NumCols() ) );
  315. Assert( ( y >= 0 ) && ( y < NumRows() ) );
  316. Assert( ( z >= 0 ) && ( z < NumSlices() ) );
  317. return Pixel( x, y, z, FBM_ATTR_ALPHA );
  318. }
  319. inline PixRGBAF FloatBitMap_t::PixelRGBAF( int x, int y, int z ) const
  320. {
  321. Assert( ( x >= 0 ) && ( x < NumCols() ) );
  322. Assert( ( y >= 0 ) && ( y < NumRows() ) );
  323. Assert( ( z >= 0 ) && ( z < NumSlices() ) );
  324. PixRGBAF RetPix;
  325. RetPix.Red = Pixel( x, y, z, FBM_ATTR_RED );
  326. RetPix.Green = Pixel( x, y, z, FBM_ATTR_GREEN );
  327. RetPix.Blue = Pixel( x, y, z, FBM_ATTR_BLUE );
  328. RetPix.Alpha = Pixel( x, y, z, FBM_ATTR_ALPHA );
  329. return RetPix;
  330. }
  331. inline void FloatBitMap_t::WritePixelRGBAF( int x, int y, int z, PixRGBAF value ) const
  332. {
  333. Pixel( x, y, z, FBM_ATTR_RED ) = value.Red;
  334. Pixel( x, y, z, FBM_ATTR_GREEN ) = value.Green;
  335. Pixel( x, y, z, FBM_ATTR_BLUE ) = value.Blue;
  336. Pixel( x, y, z, FBM_ATTR_ALPHA ) = value.Alpha;
  337. }
  338. inline void FloatBitMap_t::WritePixel(int x, int y, int z, int comp, float value)
  339. {
  340. Pixel( x, y, z, comp ) = value;
  341. }
  342. //-----------------------------------------------------------------------------
  343. // Loads an array of image data into a buffer
  344. //-----------------------------------------------------------------------------
  345. template< class T > void FloatBitMap_t::LoadFromBufferRGBFloat( const T *pBuffer, int nPixelCount )
  346. {
  347. Assert( nPixelCount == NumCols() * NumRows() * NumSlices() );
  348. for( int z = 0; z < NumSlices(); ++z )
  349. {
  350. for( int y = 0; y < NumRows(); ++y )
  351. {
  352. for( int x = 0; x < NumCols(); ++x )
  353. {
  354. Pixel( x, y, z, FBM_ATTR_RED ) = pBuffer[x].r;
  355. Pixel( x, y, z, FBM_ATTR_GREEN ) = pBuffer[x].g;
  356. Pixel( x, y, z, FBM_ATTR_BLUE ) = pBuffer[x].b;
  357. Pixel( x, y, z, FBM_ATTR_ALPHA ) = 1.0f;
  358. }
  359. pBuffer += NumCols();
  360. }
  361. }
  362. }
  363. template< class T > void FloatBitMap_t::LoadFromBufferRGB( const T *pBuffer, int nPixelCount, const float *pGammaTable )
  364. {
  365. Assert( nPixelCount == NumCols() * NumRows() * NumSlices() );
  366. for( int z = 0; z < NumSlices(); ++z )
  367. {
  368. for( int y = 0; y < NumRows(); ++y )
  369. {
  370. for( int x = 0; x < NumCols(); ++x )
  371. {
  372. Pixel( x, y, z, FBM_ATTR_RED ) = pGammaTable[ pBuffer[x].RTo10Bit( ) ];
  373. Pixel( x, y, z, FBM_ATTR_GREEN ) = pGammaTable[ pBuffer[x].GTo10Bit( ) ];
  374. Pixel( x, y, z, FBM_ATTR_BLUE ) = pGammaTable[ pBuffer[x].BTo10Bit( ) ];
  375. Pixel( x, y, z, FBM_ATTR_ALPHA ) = 1.0f;
  376. }
  377. pBuffer += NumCols();
  378. }
  379. }
  380. }
  381. template< class T > void FloatBitMap_t::LoadFromBufferRGBAFloat( const T *pBuffer, int nPixelCount )
  382. {
  383. Assert( nPixelCount == NumCols() * NumRows() * NumSlices() );
  384. for( int z = 0; z < NumSlices(); ++z )
  385. {
  386. for( int y = 0; y < NumRows(); ++y )
  387. {
  388. for( int x = 0; x < NumCols(); ++x )
  389. {
  390. Pixel( x, y, z, FBM_ATTR_RED ) = pBuffer[x].r;
  391. Pixel( x, y, z, FBM_ATTR_GREEN ) = pBuffer[x].g;
  392. Pixel( x, y, z, FBM_ATTR_BLUE ) = pBuffer[x].b;
  393. Pixel( x, y, z, FBM_ATTR_ALPHA ) = pBuffer[x].a;
  394. }
  395. pBuffer += NumCols();
  396. }
  397. }
  398. }
  399. template< class T > void FloatBitMap_t::LoadFromBufferRGBA( const T *pBuffer, int nPixelCount, const float *pGammaTable )
  400. {
  401. float flOO1023 = 1.0f / 1023.0f;
  402. Assert( nPixelCount == NumCols() * NumRows() * NumSlices() );
  403. for( int z = 0; z < NumSlices(); ++z )
  404. {
  405. for( int y = 0; y < NumRows(); ++y )
  406. {
  407. for( int x = 0; x < NumCols(); ++x )
  408. {
  409. Pixel( x, y, z, FBM_ATTR_RED ) = pGammaTable[ pBuffer[x].RTo10Bit( ) ];
  410. Pixel( x, y, z, FBM_ATTR_GREEN ) = pGammaTable[ pBuffer[x].GTo10Bit( ) ];
  411. Pixel( x, y, z, FBM_ATTR_BLUE ) = pGammaTable[ pBuffer[x].BTo10Bit( ) ];
  412. Pixel( x, y, z, FBM_ATTR_ALPHA ) = pBuffer[x].ATo10Bit( ) * flOO1023;
  413. }
  414. pBuffer += NumCols();
  415. }
  416. }
  417. }
  418. //-----------------------------------------------------------------------------
  419. // Loads from UV buffers
  420. //-----------------------------------------------------------------------------
  421. template< class T > void FloatBitMap_t::LoadFromBufferUV( const T *pBuffer, int nPixelCount )
  422. {
  423. float fl2O255 = 2.0f / 255.0f;
  424. for( int z = 0; z < NumSlices(); ++z )
  425. {
  426. for( int y = 0; y < NumRows(); ++y )
  427. {
  428. for( int x = 0; x < NumCols(); ++x )
  429. {
  430. Pixel( x, y, z, FBM_ATTR_RED ) = ( pBuffer[x].u + 128 ) * fl2O255 - 1.0f;
  431. Pixel( x, y, z, FBM_ATTR_GREEN ) = ( pBuffer[x].v + 128 ) * fl2O255 - 1.0f;
  432. Pixel( x, y, z, FBM_ATTR_BLUE ) = 0.0f;
  433. Pixel( x, y, z, FBM_ATTR_ALPHA ) = 1.0f;
  434. }
  435. pBuffer += NumCols();
  436. }
  437. }
  438. }
  439. template< class T > void FloatBitMap_t::LoadFromBufferUVWQ( const T *pBuffer, int nPixelCount )
  440. {
  441. float fl2O255 = 2.0f / 255.0f;
  442. for( int z = 0; z < NumSlices(); ++z )
  443. {
  444. for( int y = 0; y < NumRows(); ++y )
  445. {
  446. for( int x = 0; x < NumCols(); ++x )
  447. {
  448. Pixel( x, y, z, FBM_ATTR_RED ) = ( pBuffer[x].u + 128 ) * fl2O255 - 1.0f;
  449. Pixel( x, y, z, FBM_ATTR_GREEN ) = ( pBuffer[x].v + 128 ) * fl2O255 - 1.0f;
  450. Pixel( x, y, z, FBM_ATTR_BLUE ) = ( pBuffer[x].w + 128 ) * fl2O255 - 1.0f;
  451. Pixel( x, y, z, FBM_ATTR_ALPHA ) = ( pBuffer[x].q + 128 ) * fl2O255 - 1.0f;
  452. }
  453. pBuffer += NumCols();
  454. }
  455. }
  456. }
  457. template< class T > void FloatBitMap_t::LoadFromBufferUVLX( const T *pBuffer, int nPixelCount )
  458. {
  459. float flOO255 = 1.0f / 255.0f;
  460. for( int z = 0; z < NumSlices(); ++z )
  461. {
  462. for( int y = 0; y < NumRows(); ++y )
  463. {
  464. for( int x = 0; x < NumCols(); ++x )
  465. {
  466. Pixel( x, y, z, FBM_ATTR_RED ) = ( pBuffer[x].u + 128 ) * 2.0f * flOO255 - 1.0f;
  467. Pixel( x, y, z, FBM_ATTR_GREEN ) = ( pBuffer[x].v + 128 ) * 2.0f * flOO255 - 1.0f;
  468. Pixel( x, y, z, FBM_ATTR_BLUE ) = pBuffer[x].l * flOO255;
  469. Pixel( x, y, z, FBM_ATTR_ALPHA ) = 1.0f;
  470. }
  471. pBuffer += NumCols();
  472. }
  473. }
  474. }
  475. //-----------------------------------------------------------------------------
  476. // Writes an array of image data into a buffer
  477. //-----------------------------------------------------------------------------
  478. template< class T > void FloatBitMap_t::WriteToBufferRGBFloat( T *pBuffer, int nPixelCount ) const
  479. {
  480. Assert( nPixelCount == NumCols() * NumRows() * NumSlices() );
  481. for( int z = 0; z < NumSlices(); ++z )
  482. {
  483. for( int y = 0; y < NumRows(); ++y )
  484. {
  485. for( int x = 0; x < NumCols(); ++x )
  486. {
  487. pBuffer[x].r = Pixel( x, y, z, FBM_ATTR_RED );
  488. pBuffer[x].g = Pixel( x, y, z, FBM_ATTR_GREEN );
  489. pBuffer[x].b = Pixel( x, y, z, FBM_ATTR_BLUE );
  490. }
  491. pBuffer += NumCols();
  492. }
  493. }
  494. }
  495. template< class T > void FloatBitMap_t::WriteToBufferRGB( T *pBuffer, int nPixelCount, const uint16 *pInvGammaTable ) const
  496. {
  497. int c;
  498. Assert( nPixelCount == NumCols() * NumRows() * NumSlices() );
  499. for( int z = 0; z < NumSlices(); ++z )
  500. {
  501. for( int y = 0; y < NumRows(); ++y )
  502. {
  503. for( int x = 0; x < NumCols(); ++x )
  504. {
  505. c = ( int )( 1023.0f * Pixel( x, y, z, FBM_ATTR_RED ) + 0.5f );
  506. pBuffer[x].RFrom10Bit( pInvGammaTable[ clamp( c, 0, 1023 ) ] );
  507. c = ( int )( 1023.0f * Pixel( x, y, z, FBM_ATTR_GREEN ) + 0.5f );
  508. pBuffer[x].GFrom10Bit( pInvGammaTable[ clamp( c, 0, 1023 ) ] );
  509. c = ( int )( 1023.0f * Pixel( x, y, z, FBM_ATTR_BLUE ) + 0.5f );
  510. pBuffer[x].BFrom10Bit( pInvGammaTable[ clamp( c, 0, 1023 ) ] );
  511. }
  512. pBuffer += NumCols();
  513. }
  514. }
  515. }
  516. template< class T > void FloatBitMap_t::WriteToBufferRGBAFloat( T *pBuffer, int nPixelCount ) const
  517. {
  518. Assert( nPixelCount == NumCols() * NumRows() * NumSlices() );
  519. for( int z = 0; z < NumSlices(); ++z )
  520. {
  521. for( int y = 0; y < NumRows(); ++y )
  522. {
  523. for( int x = 0; x < NumCols(); ++x )
  524. {
  525. pBuffer[x].r = Pixel( x, y, z, FBM_ATTR_RED );
  526. pBuffer[x].g = Pixel( x, y, z, FBM_ATTR_GREEN );
  527. pBuffer[x].b = Pixel( x, y, z, FBM_ATTR_BLUE );
  528. pBuffer[x].a = Pixel( x, y, z, FBM_ATTR_ALPHA );
  529. }
  530. pBuffer += NumCols();
  531. }
  532. }
  533. }
  534. template< class T > void FloatBitMap_t::WriteToBufferRGBA( T *pBuffer, int nPixelCount, const uint16 *pInvGammaTable ) const
  535. {
  536. int c;
  537. Assert( nPixelCount == NumCols() * NumRows() * NumSlices() );
  538. for( int z = 0; z < NumSlices(); ++z )
  539. {
  540. for( int y = 0; y < NumRows(); ++y )
  541. {
  542. for( int x = 0; x < NumCols(); ++x )
  543. {
  544. c = ( int )( 1023.0f * Pixel( x, y, z, FBM_ATTR_RED ) + 0.5f );
  545. pBuffer[x].RFrom10Bit( pInvGammaTable[ clamp( c, 0, 1023 ) ] );
  546. c = ( int )( 1023.0f * Pixel( x, y, z, FBM_ATTR_GREEN ) + 0.5f );
  547. pBuffer[x].GFrom10Bit( pInvGammaTable[ clamp( c, 0, 1023 ) ] );
  548. c = ( int )( 1023.0f * Pixel( x, y, z, FBM_ATTR_BLUE ) + 0.5f );
  549. pBuffer[x].BFrom10Bit( pInvGammaTable[ clamp( c, 0, 1023 ) ] );
  550. c = ( int )( 1023.0f * Pixel( x, y, z, FBM_ATTR_ALPHA ) + 0.5f );
  551. pBuffer[x].AFrom10Bit( clamp( c, 0, 1023 ) );
  552. }
  553. pBuffer += NumCols();
  554. }
  555. }
  556. }
  557. //-----------------------------------------------------------------------------
  558. // Writes to UV buffers
  559. //-----------------------------------------------------------------------------
  560. template< class T > void FloatBitMap_t::WriteToBufferUV( T *pBuffer, int nPixelCount ) const
  561. {
  562. int c;
  563. float fl255O2 = 255.0f / 2.0f;
  564. for( int z = 0; z < NumSlices(); ++z )
  565. {
  566. for( int y = 0; y < NumRows(); ++y )
  567. {
  568. for( int x = 0; x < NumCols(); ++x )
  569. {
  570. c = ( int )( fl255O2 * ( Pixel( x, y, z, FBM_ATTR_RED ) + 1.0f ) );
  571. pBuffer[x].u = clamp( c, 0, 255 ) - 128;
  572. c = ( int )( fl255O2 * ( Pixel( x, y, z, FBM_ATTR_GREEN ) + 1.0f ) );
  573. pBuffer[x].v = clamp( c, 0, 255 ) - 128;
  574. }
  575. pBuffer += NumCols();
  576. }
  577. }
  578. }
  579. template< class T > void FloatBitMap_t::WriteToBufferUVWQ( T *pBuffer, int nPixelCount ) const
  580. {
  581. int c;
  582. float fl255O2 = 255.0f / 2.0f;
  583. for( int z = 0; z < NumSlices(); ++z )
  584. {
  585. for( int y = 0; y < NumRows(); ++y )
  586. {
  587. for( int x = 0; x < NumCols(); ++x )
  588. {
  589. c = ( int )( fl255O2 * ( Pixel( x, y, z, FBM_ATTR_RED ) + 1.0f ) );
  590. pBuffer[x].u = clamp( c, 0, 255 ) - 128;
  591. c = ( int )( fl255O2 * ( Pixel( x, y, z, FBM_ATTR_GREEN ) + 1.0f ) );
  592. pBuffer[x].v = clamp( c, 0, 255 ) - 128;
  593. c = ( int )( fl255O2 * ( Pixel( x, y, z, FBM_ATTR_BLUE ) + 1.0f ) );
  594. pBuffer[x].w = clamp( c, 0, 255 ) - 128;
  595. c = ( int )( fl255O2 * ( Pixel( x, y, z, FBM_ATTR_ALPHA ) + 1.0f ) );
  596. pBuffer[x].q = clamp( c, 0, 255 ) - 128;
  597. }
  598. pBuffer += NumCols();
  599. }
  600. }
  601. }
  602. template< class T > void FloatBitMap_t::WriteToBufferUVLX( T *pBuffer, int nPixelCount ) const
  603. {
  604. int c;
  605. float fl255O2 = 255.0f / 2.0f;
  606. for( int z = 0; z < NumSlices(); ++z )
  607. {
  608. for( int y = 0; y < NumRows(); ++y )
  609. {
  610. for( int x = 0; x < NumCols(); ++x )
  611. {
  612. c = ( int )( fl255O2 * ( Pixel( x, y, z, FBM_ATTR_RED ) + 1.0f ) );
  613. pBuffer[x].u = clamp( c, 0, 255 ) - 128;
  614. c = ( int )( fl255O2 * ( Pixel( x, y, z, FBM_ATTR_GREEN ) + 1.0f ) );
  615. pBuffer[x].v = clamp( c, 0, 255 ) - 128;
  616. c = ( int )( 255.0f * Pixel( x, y, z, FBM_ATTR_BLUE ) );
  617. pBuffer[x].l = clamp( c, 0, 255 );
  618. pBuffer[x].x = 255;
  619. }
  620. pBuffer += NumCols();
  621. }
  622. }
  623. }
  624. // a FloatCubeMap_t holds the floating point bitmaps for 6 faces of a cube map
  625. class FloatCubeMap_t
  626. {
  627. public:
  628. FloatBitMap_t face_maps[6];
  629. FloatCubeMap_t(int xfsize, int yfsize)
  630. {
  631. // make an empty one with face dimensions xfsize x yfsize
  632. for(int f=0;f<6;f++)
  633. {
  634. face_maps[f].Init(xfsize,yfsize);
  635. }
  636. }
  637. // load basenamebk,pfm, basenamedn.pfm, basenameft.pfm, ...
  638. FloatCubeMap_t(const char *basename);
  639. // save basenamebk,pfm, basenamedn.pfm, basenameft.pfm, ...
  640. void WritePFMs(const char *basename);
  641. Vector AverageColor(void)
  642. {
  643. Vector ret(0,0,0);
  644. int nfaces = 0;
  645. for( int f = 0;f < 6;f ++ )
  646. if ( face_maps[f].NumElements() )
  647. {
  648. nfaces++;
  649. ret += face_maps[f].AverageColor();
  650. }
  651. if ( nfaces )
  652. ret *= ( 1.0 / nfaces );
  653. return ret;
  654. }
  655. float BrightestColor( void )
  656. {
  657. float ret = 0.0;
  658. for( int f = 0;f < 6;f ++ )
  659. if ( face_maps[f].NumElements() )
  660. {
  661. ret = MAX( ret, face_maps[f].BrightestColor() );
  662. }
  663. return ret;
  664. }
  665. // generate the N-order spherical harmonic coeffcients to approxiamte this cubemap.
  666. // for order N, this will fill in 1 + 2 * N + N^2 vectors ( 0 = 0, 1 = 4, 2 = 9 .. )
  667. // vectors are used to hold the r,g,b coeffs
  668. void CalculateSphericalHarmonicApproximation( int nOrder, Vector *flCoeffs );
  669. // inverse of above
  670. void GenerateFromSphericalHarmonics( int nOrder, Vector const *flCoeffs );
  671. // resample a cubemap to one of possibly a lower resolution, using a given phong exponent.
  672. // dot-product weighting will be used for the filtering operation.
  673. void Resample(FloatCubeMap_t &dest, float flPhongExponent);
  674. // returns the normalized direciton vector through a given pixel of a given face
  675. Vector PixelDirection(int face, int x, int y);
  676. // returns the direction vector throught the center of a cubemap face
  677. Vector FaceNormal( int nFaceNumber );
  678. };
  679. // Image Pyramid class.
  680. #define MAX_IMAGE_PYRAMID_LEVELS 16 // up to 64kx64k
  681. enum ImagePyramidMode_t
  682. {
  683. PYRAMID_MODE_GAUSSIAN,
  684. };
  685. class FloatImagePyramid_t
  686. {
  687. public:
  688. int m_nLevels;
  689. FloatBitMap_t *m_pLevels[MAX_IMAGE_PYRAMID_LEVELS]; // level 0 is highest res
  690. FloatImagePyramid_t(void)
  691. {
  692. m_nLevels = 0;
  693. memset( m_pLevels, 0, sizeof( m_pLevels ));
  694. }
  695. // build one. clones data from src for level 0.
  696. FloatImagePyramid_t(const FloatBitMap_t &src, ImagePyramidMode_t mode);
  697. // read or write a Pixel from a given level. All coordinates are specified in the same domain as the base level.
  698. float &Pixel(int x, int y, int component, int level) const;
  699. FloatBitMap_t *Level(int lvl) const
  700. {
  701. Assert( lvl < m_nLevels );
  702. return m_pLevels[lvl];
  703. }
  704. // rebuild all levels above the specified level
  705. void ReconstructLowerResolutionLevels(int starting_level);
  706. ~FloatImagePyramid_t(void);
  707. void WriteTGAs(const char *basename) const; // outputs name_00.tga, name_01.tga,...
  708. };
  709. #endif