summaryrefslogtreecommitdiff
path: root/public/bitmap/float_bm.h
diff options
context:
space:
mode:
Diffstat (limited to 'public/bitmap/float_bm.h')
-rw-r--r--public/bitmap/float_bm.h363
1 files changed, 363 insertions, 0 deletions
diff --git a/public/bitmap/float_bm.h b/public/bitmap/float_bm.h
new file mode 100644
index 0000000..a80722d
--- /dev/null
+++ b/public/bitmap/float_bm.h
@@ -0,0 +1,363 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $Header: $
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef FLOAT_BM_H
+#define FLOAT_BM_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include <tier0/platform.h>
+#include "tier0/dbg.h"
+#include <mathlib/mathlib.h>
+
+struct PixRGBAF
+{
+ float Red;
+ float Green;
+ float Blue;
+ float Alpha;
+};
+
+struct PixRGBA8
+{
+ unsigned char Red;
+ unsigned char Green;
+ unsigned char Blue;
+ unsigned char Alpha;
+};
+
+inline PixRGBAF PixRGBA8_to_F( PixRGBA8 const &x )
+{
+ PixRGBAF f;
+ f.Red = x.Red / 255.f;
+ f.Green = x.Green / 255.f;
+ f.Blue = x.Blue / 255.f;
+ f.Alpha = x.Alpha / 255.f;
+ return f;
+}
+
+inline PixRGBA8 PixRGBAF_to_8( PixRGBAF const &f )
+{
+ PixRGBA8 x;
+ x.Red = max( 0.f, min( 255.f,255.f*f.Red ) );
+ x.Green = max( 0.f, min( 255.f,255.f*f.Green ) );
+ x.Blue = max( 0.f, min( 255.f,255.f*f.Blue ) );
+ x.Alpha = max( 0.f, min( 255.f,255.f*f.Alpha ) );
+ return x;
+}
+
+#define SPFLAGS_MAXGRADIENT 1
+
+// bit flag options for ComputeSelfShadowedBumpmapFromHeightInAlphaChannel:
+#define SSBUMP_OPTION_NONDIRECTIONAL 1 // generate ambient occlusion only
+#define SSBUMP_MOD2X_DETAIL_TEXTURE 2 // scale so that a flat unshadowed
+ // value is 0.5, and bake rgb luminance
+ // in.
+
+
+
+class FloatBitMap_t
+{
+public:
+ int Width, Height; // bitmap dimensions
+ float *RGBAData; // actual data
+
+ FloatBitMap_t(void) // empty one
+ {
+ Width=Height=0;
+ RGBAData=0;
+ }
+
+
+
+ FloatBitMap_t(int width, int height); // make one and allocate space
+ FloatBitMap_t(char const *filename); // read one from a file (tga or pfm)
+ FloatBitMap_t(FloatBitMap_t const *orig);
+ // quantize one to 8 bits
+ bool WriteTGAFile(char const *filename) const;
+
+ bool LoadFromPFM(char const *filename); // load from floating point pixmap (.pfm) file
+ bool WritePFM(char const *filename); // save to floating point pixmap (.pfm) file
+
+
+ void InitializeWithRandomPixelsFromAnotherFloatBM(FloatBitMap_t const &other);
+
+ inline float & Pixel(int x, int y, int comp) const
+ {
+ Assert((x>=0) && (x<Width));
+ Assert((y>=0) && (y<Height));
+ return RGBAData[4*(x+Width*y)+comp];
+ }
+
+ inline float & PixelWrapped(int x, int y, int comp) const
+ {
+ // like Pixel except wraps around to other side
+ if (x < 0)
+ x+=Width;
+ else
+ if (x>= Width)
+ x -= Width;
+
+ if ( y < 0 )
+ y+=Height;
+ else
+ if ( y >= Height )
+ y -= Height;
+
+ return RGBAData[4*(x+Width*y)+comp];
+ }
+
+ inline float & PixelClamped(int x, int y, int comp) const
+ {
+ // like Pixel except wraps around to other side
+ x=clamp(x,0,Width-1);
+ y=clamp(y,0,Height-1);
+ return RGBAData[4*(x+Width*y)+comp];
+ }
+
+
+ inline float & Alpha(int x, int y) const
+ {
+ Assert((x>=0) && (x<Width));
+ Assert((y>=0) && (y<Height));
+ return RGBAData[3+4*(x+Width*y)];
+ }
+
+
+ // look up a pixel value with bilinear interpolation
+ float InterpolatedPixel(float x, float y, int comp) const;
+
+ inline PixRGBAF PixelRGBAF(int x, int y) const
+ {
+ Assert((x>=0) && (x<Width));
+ Assert((y>=0) && (y<Height));
+
+ PixRGBAF RetPix;
+ int RGBoffset= 4*(x+Width*y);
+ RetPix.Red= RGBAData[RGBoffset+0];
+ RetPix.Green= RGBAData[RGBoffset+1];
+ RetPix.Blue= RGBAData[RGBoffset+2];
+ RetPix.Alpha= RGBAData[RGBoffset+3];
+
+ return RetPix;
+ }
+
+
+ inline void WritePixelRGBAF(int x, int y, PixRGBAF value) const
+ {
+ Assert((x>=0) && (x<Width));
+ Assert((y>=0) && (y<Height));
+
+ int RGBoffset= 4*(x+Width*y);
+ RGBAData[RGBoffset+0]= value.Red;
+ RGBAData[RGBoffset+1]= value.Green;
+ RGBAData[RGBoffset+2]= value.Blue;
+ RGBAData[RGBoffset+3]= value.Alpha;
+
+ }
+
+
+ inline void WritePixel(int x, int y, int comp, float value)
+ {
+ Assert((x>=0) && (x<Width));
+ Assert((y>=0) && (y<Height));
+ RGBAData[4*(x+Width*y)+comp]= value;
+ }
+
+ // paste, performing boundary matching. Alpha channel can be used to make
+ // brush shape irregular
+ void SmartPaste(FloatBitMap_t const &brush, int xofs, int yofs, uint32 flags);
+
+ // force to be tileable using poisson formula
+ void MakeTileable(void);
+
+ void ReSize(int NewXSize, int NewYSize);
+
+ // find the bounds of the area that has non-zero alpha.
+ void GetAlphaBounds(int &minx, int &miny, int &maxx,int &maxy);
+
+ // Solve the poisson equation for an image. The alpha channel of the image controls which
+ // pixels are "modifiable", and can be used to set boundary conditions. Alpha=0 means the pixel
+ // 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)
+ void Poisson(FloatBitMap_t *deltas[4],
+ int n_iters,
+ uint32 flags // SPF_xxx
+ );
+
+ FloatBitMap_t *QuarterSize(void) const; // get a new one downsampled
+ FloatBitMap_t *QuarterSizeBlocky(void) const; // get a new one downsampled
+
+ FloatBitMap_t *QuarterSizeWithGaussian(void) const; // downsample 2x using a gaussian
+
+
+ void RaiseToPower(float pow);
+ void ScaleGradients(void);
+ void Logize(void); // pix=log(1+pix)
+ void UnLogize(void); // pix=exp(pix)-1
+
+ // compress to 8 bits converts the hdr texture to an 8 bit texture, encoding a scale factor
+ // in the alpha channel. upon return, the original pixel can be (approximately) recovered
+ // by the formula rgb*alpha*overbright.
+ // this function performs special numerical optimization on the texture to minimize the error
+ // when using bilinear filtering to read the texture.
+ void CompressTo8Bits(float overbright);
+ // decompress a bitmap converted by CompressTo8Bits
+ void Uncompress(float overbright);
+
+
+ Vector AverageColor(void); // average rgb value of all pixels
+ float BrightestColor(void); // highest vector magnitude
+
+ void Clear(float r, float g, float b, float alpha); // set all pixels to speicifed values (0..1 nominal)
+
+ void ScaleRGB(float scale_factor); // for all pixels, r,g,b*=scale_factor
+
+ // given a bitmap with height stored in the alpha channel, generate vector positions and normals
+ void ComputeVertexPositionsAndNormals( float flHeightScale, Vector **ppPosOut, Vector **ppNormalOut ) const;
+
+ // generate a normal map with height stored in alpha. uses hl2 tangent basis to support baked
+ // self shadowing. the bump scale maps the height of a pixel relative to the edges of the
+ // pixel. This function may take a while - many millions of rays may be traced. applications
+ // using this method need to link w/ raytrace.lib
+ FloatBitMap_t *ComputeSelfShadowedBumpmapFromHeightInAlphaChannel(
+ float bump_scale, int nrays_to_trace_per_pixel=100,
+ uint32 nOptionFlags = 0 // SSBUMP_OPTION_XXX
+ ) const;
+
+
+ // generate a conventional normal map from a source with height stored in alpha.
+ FloatBitMap_t *ComputeBumpmapFromHeightInAlphaChannel( float bump_scale ) const ;
+
+
+ // bilateral (edge preserving) smoothing filter. edge_threshold_value defines the difference in
+ // values over which filtering will not occur. Each channel is filtered independently. large
+ // radii will run slow, since the bilateral filter is neither separable, nor is it a
+ // convolution that can be done via fft.
+ void TileableBilateralFilter( int radius_in_pixels, float edge_threshold_value );
+
+ ~FloatBitMap_t();
+
+ void AllocateRGB(int w, int h)
+ {
+ if (RGBAData) delete[] RGBAData;
+ RGBAData=new float[w*h*4];
+ Width=w;
+ Height=h;
+ }
+};
+
+
+// a FloatCubeMap_t holds the floating point bitmaps for 6 faces of a cube map
+class FloatCubeMap_t
+{
+public:
+ FloatBitMap_t face_maps[6];
+
+ FloatCubeMap_t(int xfsize, int yfsize)
+ {
+ // make an empty one with face dimensions xfsize x yfsize
+ for(int f=0;f<6;f++)
+ face_maps[f].AllocateRGB(xfsize,yfsize);
+ }
+
+ // load basenamebk,pfm, basenamedn.pfm, basenameft.pfm, ...
+ FloatCubeMap_t(char const *basename);
+
+ // save basenamebk,pfm, basenamedn.pfm, basenameft.pfm, ...
+ void WritePFMs(char const *basename);
+
+ Vector AverageColor(void)
+ {
+ Vector ret(0,0,0);
+ int nfaces=0;
+ for(int f=0;f<6;f++)
+ if (face_maps[f].RGBAData)
+ {
+ nfaces++;
+ ret+=face_maps[f].AverageColor();
+ }
+ if (nfaces)
+ ret*=(1.0/nfaces);
+ return ret;
+ }
+
+ float BrightestColor(void)
+ {
+ float ret=0.0;
+ int nfaces=0;
+ for(int f=0;f<6;f++)
+ if (face_maps[f].RGBAData)
+ {
+ nfaces++;
+ ret=max(ret,face_maps[f].BrightestColor());
+ }
+ return ret;
+ }
+
+
+ // resample a cubemap to one of possibly a lower resolution, using a given phong exponent.
+ // dot-product weighting will be used for the filtering operation.
+ void Resample(FloatCubeMap_t &dest, float flPhongExponent);
+
+ // returns the normalized direciton vector through a given pixel of a given face
+ Vector PixelDirection(int face, int x, int y);
+
+ // returns the direction vector throught the center of a cubemap face
+ Vector FaceNormal( int nFaceNumber );
+};
+
+
+static inline float FLerp(float f1, float f2, float t)
+{
+ return f1+(f2-f1)*t;
+}
+
+
+// Image Pyramid class.
+#define MAX_IMAGE_PYRAMID_LEVELS 16 // up to 64kx64k
+
+enum ImagePyramidMode_t
+{
+ PYRAMID_MODE_GAUSSIAN,
+};
+
+class FloatImagePyramid_t
+{
+public:
+ int m_nLevels;
+ FloatBitMap_t *m_pLevels[MAX_IMAGE_PYRAMID_LEVELS]; // level 0 is highest res
+
+ FloatImagePyramid_t(void)
+ {
+ m_nLevels=0;
+ memset(m_pLevels,0,sizeof(m_pLevels));
+ }
+
+ // build one. clones data from src for level 0.
+ FloatImagePyramid_t(FloatBitMap_t const &src, ImagePyramidMode_t mode);
+
+ // read or write a Pixel from a given level. All coordinates are specified in the same domain as the base level.
+ float &Pixel(int x, int y, int component, int level) const;
+
+ FloatBitMap_t *Level(int lvl) const
+ {
+ Assert(lvl<m_nLevels);
+ Assert(lvl<ARRAYSIZE(m_pLevels));
+ return m_pLevels[lvl];
+ }
+ // rebuild all levels above the specified level
+ void ReconstructLowerResolutionLevels(int starting_level);
+
+ ~FloatImagePyramid_t(void);
+
+ void WriteTGAs(char const *basename) const; // outputs name_00.tga, name_01.tga,...
+};
+
+#endif