Team Fortress 2 Source Code as on 22/4/2020
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.

363 lines
9.9 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $Header: $
  6. // $NoKeywords: $
  7. //=============================================================================//
  8. #ifndef FLOAT_BM_H
  9. #define FLOAT_BM_H
  10. #ifdef _WIN32
  11. #pragma once
  12. #endif
  13. #include <tier0/platform.h>
  14. #include "tier0/dbg.h"
  15. #include <mathlib/mathlib.h>
  16. struct PixRGBAF
  17. {
  18. float Red;
  19. float Green;
  20. float Blue;
  21. float Alpha;
  22. };
  23. struct PixRGBA8
  24. {
  25. unsigned char Red;
  26. unsigned char Green;
  27. unsigned char Blue;
  28. unsigned char Alpha;
  29. };
  30. inline PixRGBAF PixRGBA8_to_F( PixRGBA8 const &x )
  31. {
  32. PixRGBAF f;
  33. f.Red = x.Red / 255.f;
  34. f.Green = x.Green / 255.f;
  35. f.Blue = x.Blue / 255.f;
  36. f.Alpha = x.Alpha / 255.f;
  37. return f;
  38. }
  39. inline PixRGBA8 PixRGBAF_to_8( PixRGBAF const &f )
  40. {
  41. PixRGBA8 x;
  42. x.Red = max( 0.f, min( 255.f,255.f*f.Red ) );
  43. x.Green = max( 0.f, min( 255.f,255.f*f.Green ) );
  44. x.Blue = max( 0.f, min( 255.f,255.f*f.Blue ) );
  45. x.Alpha = max( 0.f, min( 255.f,255.f*f.Alpha ) );
  46. return x;
  47. }
  48. #define SPFLAGS_MAXGRADIENT 1
  49. // bit flag options for ComputeSelfShadowedBumpmapFromHeightInAlphaChannel:
  50. #define SSBUMP_OPTION_NONDIRECTIONAL 1 // generate ambient occlusion only
  51. #define SSBUMP_MOD2X_DETAIL_TEXTURE 2 // scale so that a flat unshadowed
  52. // value is 0.5, and bake rgb luminance
  53. // in.
  54. class FloatBitMap_t
  55. {
  56. public:
  57. int Width, Height; // bitmap dimensions
  58. float *RGBAData; // actual data
  59. FloatBitMap_t(void) // empty one
  60. {
  61. Width=Height=0;
  62. RGBAData=0;
  63. }
  64. FloatBitMap_t(int width, int height); // make one and allocate space
  65. FloatBitMap_t(char const *filename); // read one from a file (tga or pfm)
  66. FloatBitMap_t(FloatBitMap_t const *orig);
  67. // quantize one to 8 bits
  68. bool WriteTGAFile(char const *filename) const;
  69. bool LoadFromPFM(char const *filename); // load from floating point pixmap (.pfm) file
  70. bool WritePFM(char const *filename); // save to floating point pixmap (.pfm) file
  71. void InitializeWithRandomPixelsFromAnotherFloatBM(FloatBitMap_t const &other);
  72. inline float & Pixel(int x, int y, int comp) const
  73. {
  74. Assert((x>=0) && (x<Width));
  75. Assert((y>=0) && (y<Height));
  76. return RGBAData[4*(x+Width*y)+comp];
  77. }
  78. inline float & PixelWrapped(int x, int y, int comp) const
  79. {
  80. // like Pixel except wraps around to other side
  81. if (x < 0)
  82. x+=Width;
  83. else
  84. if (x>= Width)
  85. x -= Width;
  86. if ( y < 0 )
  87. y+=Height;
  88. else
  89. if ( y >= Height )
  90. y -= Height;
  91. return RGBAData[4*(x+Width*y)+comp];
  92. }
  93. inline float & PixelClamped(int x, int y, int comp) const
  94. {
  95. // like Pixel except wraps around to other side
  96. x=clamp(x,0,Width-1);
  97. y=clamp(y,0,Height-1);
  98. return RGBAData[4*(x+Width*y)+comp];
  99. }
  100. inline float & Alpha(int x, int y) const
  101. {
  102. Assert((x>=0) && (x<Width));
  103. Assert((y>=0) && (y<Height));
  104. return RGBAData[3+4*(x+Width*y)];
  105. }
  106. // look up a pixel value with bilinear interpolation
  107. float InterpolatedPixel(float x, float y, int comp) const;
  108. inline PixRGBAF PixelRGBAF(int x, int y) const
  109. {
  110. Assert((x>=0) && (x<Width));
  111. Assert((y>=0) && (y<Height));
  112. PixRGBAF RetPix;
  113. int RGBoffset= 4*(x+Width*y);
  114. RetPix.Red= RGBAData[RGBoffset+0];
  115. RetPix.Green= RGBAData[RGBoffset+1];
  116. RetPix.Blue= RGBAData[RGBoffset+2];
  117. RetPix.Alpha= RGBAData[RGBoffset+3];
  118. return RetPix;
  119. }
  120. inline void WritePixelRGBAF(int x, int y, PixRGBAF value) const
  121. {
  122. Assert((x>=0) && (x<Width));
  123. Assert((y>=0) && (y<Height));
  124. int RGBoffset= 4*(x+Width*y);
  125. RGBAData[RGBoffset+0]= value.Red;
  126. RGBAData[RGBoffset+1]= value.Green;
  127. RGBAData[RGBoffset+2]= value.Blue;
  128. RGBAData[RGBoffset+3]= value.Alpha;
  129. }
  130. inline void WritePixel(int x, int y, int comp, float value)
  131. {
  132. Assert((x>=0) && (x<Width));
  133. Assert((y>=0) && (y<Height));
  134. RGBAData[4*(x+Width*y)+comp]= value;
  135. }
  136. // paste, performing boundary matching. Alpha channel can be used to make
  137. // brush shape irregular
  138. void SmartPaste(FloatBitMap_t const &brush, int xofs, int yofs, uint32 flags);
  139. // force to be tileable using poisson formula
  140. void MakeTileable(void);
  141. void ReSize(int NewXSize, int NewYSize);
  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. FloatBitMap_t *QuarterSize(void) const; // get a new one downsampled
  152. FloatBitMap_t *QuarterSizeBlocky(void) const; // get a new one downsampled
  153. FloatBitMap_t *QuarterSizeWithGaussian(void) const; // downsample 2x using a gaussian
  154. void RaiseToPower(float pow);
  155. void ScaleGradients(void);
  156. void Logize(void); // pix=log(1+pix)
  157. void UnLogize(void); // pix=exp(pix)-1
  158. // compress to 8 bits converts the hdr texture to an 8 bit texture, encoding a scale factor
  159. // in the alpha channel. upon return, the original pixel can be (approximately) recovered
  160. // by the formula rgb*alpha*overbright.
  161. // this function performs special numerical optimization on the texture to minimize the error
  162. // when using bilinear filtering to read the texture.
  163. void CompressTo8Bits(float overbright);
  164. // decompress a bitmap converted by CompressTo8Bits
  165. void Uncompress(float overbright);
  166. Vector AverageColor(void); // average rgb value of all pixels
  167. float BrightestColor(void); // highest vector magnitude
  168. void Clear(float r, float g, float b, float alpha); // set all pixels to speicifed values (0..1 nominal)
  169. void ScaleRGB(float scale_factor); // for all pixels, r,g,b*=scale_factor
  170. // given a bitmap with height stored in the alpha channel, generate vector positions and normals
  171. void ComputeVertexPositionsAndNormals( float flHeightScale, Vector **ppPosOut, Vector **ppNormalOut ) const;
  172. // generate a normal map with height stored in alpha. uses hl2 tangent basis to support baked
  173. // self shadowing. the bump scale maps the height of a pixel relative to the edges of the
  174. // pixel. This function may take a while - many millions of rays may be traced. applications
  175. // using this method need to link w/ raytrace.lib
  176. FloatBitMap_t *ComputeSelfShadowedBumpmapFromHeightInAlphaChannel(
  177. float bump_scale, int nrays_to_trace_per_pixel=100,
  178. uint32 nOptionFlags = 0 // SSBUMP_OPTION_XXX
  179. ) const;
  180. // generate a conventional normal map from a source with height stored in alpha.
  181. FloatBitMap_t *ComputeBumpmapFromHeightInAlphaChannel( float bump_scale ) const ;
  182. // bilateral (edge preserving) smoothing filter. edge_threshold_value defines the difference in
  183. // values over which filtering will not occur. Each channel is filtered independently. large
  184. // radii will run slow, since the bilateral filter is neither separable, nor is it a
  185. // convolution that can be done via fft.
  186. void TileableBilateralFilter( int radius_in_pixels, float edge_threshold_value );
  187. ~FloatBitMap_t();
  188. void AllocateRGB(int w, int h)
  189. {
  190. if (RGBAData) delete[] RGBAData;
  191. RGBAData=new float[w*h*4];
  192. Width=w;
  193. Height=h;
  194. }
  195. };
  196. // a FloatCubeMap_t holds the floating point bitmaps for 6 faces of a cube map
  197. class FloatCubeMap_t
  198. {
  199. public:
  200. FloatBitMap_t face_maps[6];
  201. FloatCubeMap_t(int xfsize, int yfsize)
  202. {
  203. // make an empty one with face dimensions xfsize x yfsize
  204. for(int f=0;f<6;f++)
  205. face_maps[f].AllocateRGB(xfsize,yfsize);
  206. }
  207. // load basenamebk,pfm, basenamedn.pfm, basenameft.pfm, ...
  208. FloatCubeMap_t(char const *basename);
  209. // save basenamebk,pfm, basenamedn.pfm, basenameft.pfm, ...
  210. void WritePFMs(char const *basename);
  211. Vector AverageColor(void)
  212. {
  213. Vector ret(0,0,0);
  214. int nfaces=0;
  215. for(int f=0;f<6;f++)
  216. if (face_maps[f].RGBAData)
  217. {
  218. nfaces++;
  219. ret+=face_maps[f].AverageColor();
  220. }
  221. if (nfaces)
  222. ret*=(1.0/nfaces);
  223. return ret;
  224. }
  225. float BrightestColor(void)
  226. {
  227. float ret=0.0;
  228. int nfaces=0;
  229. for(int f=0;f<6;f++)
  230. if (face_maps[f].RGBAData)
  231. {
  232. nfaces++;
  233. ret=max(ret,face_maps[f].BrightestColor());
  234. }
  235. return ret;
  236. }
  237. // resample a cubemap to one of possibly a lower resolution, using a given phong exponent.
  238. // dot-product weighting will be used for the filtering operation.
  239. void Resample(FloatCubeMap_t &dest, float flPhongExponent);
  240. // returns the normalized direciton vector through a given pixel of a given face
  241. Vector PixelDirection(int face, int x, int y);
  242. // returns the direction vector throught the center of a cubemap face
  243. Vector FaceNormal( int nFaceNumber );
  244. };
  245. static inline float FLerp(float f1, float f2, float t)
  246. {
  247. return f1+(f2-f1)*t;
  248. }
  249. // Image Pyramid class.
  250. #define MAX_IMAGE_PYRAMID_LEVELS 16 // up to 64kx64k
  251. enum ImagePyramidMode_t
  252. {
  253. PYRAMID_MODE_GAUSSIAN,
  254. };
  255. class FloatImagePyramid_t
  256. {
  257. public:
  258. int m_nLevels;
  259. FloatBitMap_t *m_pLevels[MAX_IMAGE_PYRAMID_LEVELS]; // level 0 is highest res
  260. FloatImagePyramid_t(void)
  261. {
  262. m_nLevels=0;
  263. memset(m_pLevels,0,sizeof(m_pLevels));
  264. }
  265. // build one. clones data from src for level 0.
  266. FloatImagePyramid_t(FloatBitMap_t const &src, ImagePyramidMode_t mode);
  267. // read or write a Pixel from a given level. All coordinates are specified in the same domain as the base level.
  268. float &Pixel(int x, int y, int component, int level) const;
  269. FloatBitMap_t *Level(int lvl) const
  270. {
  271. Assert(lvl<m_nLevels);
  272. Assert(lvl<ARRAYSIZE(m_pLevels));
  273. return m_pLevels[lvl];
  274. }
  275. // rebuild all levels above the specified level
  276. void ReconstructLowerResolutionLevels(int starting_level);
  277. ~FloatImagePyramid_t(void);
  278. void WriteTGAs(char const *basename) const; // outputs name_00.tga, name_01.tga,...
  279. };
  280. #endif