diff options
Diffstat (limited to 'public/bitmap/float_bm.h')
| -rw-r--r-- | public/bitmap/float_bm.h | 363 |
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 |