mirror of
https://github.com/dhewm/dhewm3.git
synced 2024-11-23 21:02:11 +00:00
736ec20d4d
Don't include the lazy precompiled.h everywhere, only what's required for the compilation unit. platform.h needs to be included instead to provide all essential defines and types. All includes use the relative path to the neo or the game specific root. Move all idlib related includes from idlib/Lib.h to precompiled.h. precompiled.h still exists for the MFC stuff in tools/. Add some missing header guards.
505 lines
20 KiB
C++
505 lines
20 KiB
C++
/*
|
|
===========================================================================
|
|
|
|
Doom 3 GPL Source Code
|
|
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
|
|
|
This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code").
|
|
|
|
Doom 3 Source Code is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
Doom 3 Source Code is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
|
|
|
|
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
|
|
|
===========================================================================
|
|
*/
|
|
|
|
#ifndef __IMAGE_H__
|
|
#define __IMAGE_H__
|
|
|
|
#include "idlib/containers/List.h"
|
|
#include "framework/FileSystem.h"
|
|
#include "renderer/Material.h"
|
|
#include "renderer/qgl.h"
|
|
|
|
/*
|
|
====================================================================
|
|
|
|
IMAGE
|
|
|
|
idImage have a one to one correspondance with OpenGL textures.
|
|
|
|
No texture is ever used that does not have a corresponding idImage.
|
|
|
|
no code outside this unit should call any of these OpenGL functions:
|
|
|
|
qglGenTextures
|
|
qglDeleteTextures
|
|
qglBindTexture
|
|
|
|
qglTexParameter
|
|
|
|
qglTexImage
|
|
qglTexSubImage
|
|
|
|
qglCopyTexImage
|
|
qglCopyTexSubImage
|
|
|
|
qglEnable( GL_TEXTURE_* )
|
|
qglDisable( GL_TEXTURE_* )
|
|
|
|
====================================================================
|
|
*/
|
|
|
|
typedef enum {
|
|
IS_UNLOADED, // no gl texture number
|
|
IS_PARTIAL, // has a texture number and the low mip levels loaded
|
|
IS_LOADED // has a texture number and the full mip hierarchy
|
|
} imageState_t;
|
|
|
|
static const int MAX_TEXTURE_LEVELS = 14;
|
|
|
|
// surface description flags
|
|
const unsigned int DDSF_CAPS = 0x00000001l;
|
|
const unsigned int DDSF_HEIGHT = 0x00000002l;
|
|
const unsigned int DDSF_WIDTH = 0x00000004l;
|
|
const unsigned int DDSF_PITCH = 0x00000008l;
|
|
const unsigned int DDSF_PIXELFORMAT = 0x00001000l;
|
|
const unsigned int DDSF_MIPMAPCOUNT = 0x00020000l;
|
|
const unsigned int DDSF_LINEARSIZE = 0x00080000l;
|
|
const unsigned int DDSF_DEPTH = 0x00800000l;
|
|
|
|
// pixel format flags
|
|
const unsigned int DDSF_ALPHAPIXELS = 0x00000001l;
|
|
const unsigned int DDSF_FOURCC = 0x00000004l;
|
|
const unsigned int DDSF_RGB = 0x00000040l;
|
|
const unsigned int DDSF_RGBA = 0x00000041l;
|
|
|
|
// our extended flags
|
|
const unsigned int DDSF_ID_INDEXCOLOR = 0x10000000l;
|
|
const unsigned int DDSF_ID_MONOCHROME = 0x20000000l;
|
|
|
|
// dwCaps1 flags
|
|
const unsigned int DDSF_COMPLEX = 0x00000008l;
|
|
const unsigned int DDSF_TEXTURE = 0x00001000l;
|
|
const unsigned int DDSF_MIPMAP = 0x00400000l;
|
|
|
|
#define DDS_MAKEFOURCC(a, b, c, d) ((a) | ((b) << 8) | ((c) << 16) | ((d) << 24))
|
|
|
|
typedef struct {
|
|
unsigned int dwSize;
|
|
unsigned int dwFlags;
|
|
unsigned int dwFourCC;
|
|
unsigned int dwRGBBitCount;
|
|
unsigned int dwRBitMask;
|
|
unsigned int dwGBitMask;
|
|
unsigned int dwBBitMask;
|
|
unsigned int dwABitMask;
|
|
} ddsFilePixelFormat_t;
|
|
|
|
typedef struct
|
|
{
|
|
unsigned int dwSize;
|
|
unsigned int dwFlags;
|
|
unsigned int dwHeight;
|
|
unsigned int dwWidth;
|
|
unsigned int dwPitchOrLinearSize;
|
|
unsigned int dwDepth;
|
|
unsigned int dwMipMapCount;
|
|
unsigned int dwReserved1[11];
|
|
ddsFilePixelFormat_t ddspf;
|
|
unsigned int dwCaps1;
|
|
unsigned int dwCaps2;
|
|
unsigned int dwReserved2[3];
|
|
} ddsFileHeader_t;
|
|
|
|
|
|
// increasing numeric values imply more information is stored
|
|
typedef enum {
|
|
TD_SPECULAR, // may be compressed, and always zeros the alpha channel
|
|
TD_DIFFUSE, // may be compressed
|
|
TD_DEFAULT, // will use compressed formats when possible
|
|
TD_BUMP, // may be compressed with 8 bit lookup
|
|
TD_HIGH_QUALITY // either 32 bit or a component format, no loss at all
|
|
} textureDepth_t;
|
|
|
|
typedef enum {
|
|
TT_DISABLED,
|
|
TT_2D,
|
|
TT_3D,
|
|
TT_CUBIC,
|
|
TT_RECT
|
|
} textureType_t;
|
|
|
|
typedef enum {
|
|
CF_2D, // not a cube map
|
|
CF_NATIVE, // _px, _nx, _py, etc, directly sent to GL
|
|
CF_CAMERA // _forward, _back, etc, rotated and flipped as needed before sending to GL
|
|
} cubeFiles_t;
|
|
|
|
#define MAX_IMAGE_NAME 256
|
|
|
|
class idImage {
|
|
public:
|
|
idImage();
|
|
|
|
// Makes this image active on the current GL texture unit.
|
|
// automatically enables or disables cube mapping or texture3D
|
|
// May perform file loading if the image was not preloaded.
|
|
// May start a background image read.
|
|
void Bind();
|
|
|
|
// for use with fragment programs, doesn't change any enable2D/3D/cube states
|
|
void BindFragment();
|
|
|
|
// deletes the texture object, but leaves the structure so it can be reloaded
|
|
void PurgeImage();
|
|
|
|
// used by callback functions to specify the actual data
|
|
// data goes from the bottom to the top line of the image, as OpenGL expects it
|
|
// These perform an implicit Bind() on the current texture unit
|
|
// FIXME: should we implement cinematics this way, instead of with explicit calls?
|
|
void GenerateImage( const byte *pic, int width, int height,
|
|
textureFilter_t filter, bool allowDownSize,
|
|
textureRepeat_t repeat, textureDepth_t depth );
|
|
void Generate3DImage( const byte *pic, int width, int height, int depth,
|
|
textureFilter_t filter, bool allowDownSize,
|
|
textureRepeat_t repeat, textureDepth_t minDepth );
|
|
void GenerateCubeImage( const byte *pic[6], int size,
|
|
textureFilter_t filter, bool allowDownSize,
|
|
textureDepth_t depth );
|
|
|
|
void CopyFramebuffer( int x, int y, int width, int height, bool useOversizedBuffer );
|
|
|
|
void CopyDepthbuffer( int x, int y, int width, int height );
|
|
|
|
void UploadScratch( const byte *pic, int width, int height );
|
|
|
|
// just for resource tracking
|
|
void SetClassification( int tag );
|
|
|
|
// estimates size of the GL image based on dimensions and storage type
|
|
int StorageSize() const;
|
|
|
|
// print a one line summary of the image
|
|
void Print() const;
|
|
|
|
// check for changed timestamp on disk and reload if necessary
|
|
void Reload( bool checkPrecompressed, bool force );
|
|
|
|
void AddReference() { refCount++; };
|
|
|
|
//==========================================================
|
|
|
|
void GetDownsize( int &scaled_width, int &scaled_height ) const;
|
|
void MakeDefault(); // fill with a grid pattern
|
|
void SetImageFilterAndRepeat() const;
|
|
bool ShouldImageBePartialCached();
|
|
void WritePrecompressedImage();
|
|
bool CheckPrecompressedImage( bool fullLoad );
|
|
void UploadPrecompressedImage( byte *data, int len );
|
|
void ActuallyLoadImage( bool checkForPrecompressed, bool fromBackEnd );
|
|
void StartBackgroundImageLoad();
|
|
int BitsForInternalFormat( int internalFormat ) const;
|
|
void UploadCompressedNormalMap( int width, int height, const byte *rgba, int mipLevel );
|
|
GLenum SelectInternalFormat( const byte **dataPtrs, int numDataPtrs, int width, int height,
|
|
textureDepth_t minimumDepth, bool *monochromeResult ) const;
|
|
void ImageProgramStringToCompressedFileName( const char *imageProg, char *fileName ) const;
|
|
int NumLevelsForImageSize( int width, int height ) const;
|
|
|
|
// data commonly accessed is grouped here
|
|
static const int TEXTURE_NOT_LOADED = -1;
|
|
GLuint texnum; // gl texture binding, will be TEXTURE_NOT_LOADED if not loaded
|
|
textureType_t type;
|
|
int frameUsed; // for texture usage in frame statistics
|
|
int bindCount; // incremented each bind
|
|
|
|
// background loading information
|
|
idImage *partialImage; // shrunken, space-saving version
|
|
bool isPartialImage; // true if this is pointed to by another image
|
|
bool backgroundLoadInProgress; // true if another thread is reading the complete d3t file
|
|
backgroundDownload_t bgl;
|
|
idImage * bglNext; // linked from tr.backgroundImageLoads
|
|
|
|
// parameters that define this image
|
|
idStr imgName; // game path, including extension (except for cube maps), may be an image program
|
|
void (*generatorFunction)( idImage *image ); // NULL for files
|
|
bool allowDownSize; // this also doubles as a don't-partially-load flag
|
|
textureFilter_t filter;
|
|
textureRepeat_t repeat;
|
|
textureDepth_t depth;
|
|
cubeFiles_t cubeFiles; // determines the naming and flipping conventions for the six images
|
|
|
|
bool referencedOutsideLevelLoad;
|
|
bool levelLoadReferenced; // for determining if it needs to be purged
|
|
bool precompressedFile; // true when it was loaded from a .d3t file
|
|
bool defaulted; // true if the default image was generated because a file couldn't be loaded
|
|
bool isMonochrome; // so the NV20 path can use a reduced pass count
|
|
ID_TIME_T timestamp; // the most recent of all images used in creation, for reloadImages command
|
|
|
|
int imageHash; // for identical-image checking
|
|
|
|
int classification; // just for resource profiling
|
|
|
|
// data for listImages
|
|
int uploadWidth, uploadHeight, uploadDepth; // after power of two, downsample, and MAX_TEXTURE_SIZE
|
|
int internalFormat;
|
|
|
|
idImage *cacheUsagePrev, *cacheUsageNext; // for dynamic cache purging of old images
|
|
|
|
idImage * hashNext; // for hash chains to speed lookup
|
|
|
|
int refCount; // overall ref count
|
|
};
|
|
|
|
ID_INLINE idImage::idImage() {
|
|
texnum = TEXTURE_NOT_LOADED;
|
|
partialImage = NULL;
|
|
type = TT_DISABLED;
|
|
isPartialImage = false;
|
|
frameUsed = 0;
|
|
classification = 0;
|
|
backgroundLoadInProgress = false;
|
|
bgl.opcode = DLTYPE_FILE;
|
|
bgl.f = NULL;
|
|
bglNext = NULL;
|
|
imgName[0] = '\0';
|
|
generatorFunction = NULL;
|
|
allowDownSize = false;
|
|
filter = TF_DEFAULT;
|
|
repeat = TR_REPEAT;
|
|
depth = TD_DEFAULT;
|
|
cubeFiles = CF_2D;
|
|
referencedOutsideLevelLoad = false;
|
|
levelLoadReferenced = false;
|
|
precompressedFile = false;
|
|
defaulted = false;
|
|
timestamp = 0;
|
|
bindCount = 0;
|
|
uploadWidth = uploadHeight = uploadDepth = 0;
|
|
internalFormat = 0;
|
|
cacheUsagePrev = cacheUsageNext = NULL;
|
|
hashNext = NULL;
|
|
isMonochrome = false;
|
|
refCount = 0;
|
|
}
|
|
|
|
|
|
// data is RGBA
|
|
void R_WriteTGA( const char *filename, const byte *data, int width, int height, bool flipVertical = false );
|
|
// data is an 8 bit index into palette, which is RGB (no A)
|
|
void R_WritePalTGA( const char *filename, const byte *data, const byte *palette, int width, int height, bool flipVertical = false );
|
|
// data is in top-to-bottom raster order unless flipVertical is set
|
|
|
|
|
|
class idImageManager {
|
|
public:
|
|
void Init();
|
|
void Shutdown();
|
|
|
|
// If the exact combination of parameters has been asked for already, an existing
|
|
// image will be returned, otherwise a new image will be created.
|
|
// Be careful not to use the same image file with different filter / repeat / etc parameters
|
|
// if possible, because it will cause a second copy to be loaded.
|
|
// If the load fails for any reason, the image will be filled in with the default
|
|
// grid pattern.
|
|
// Will automatically resample non-power-of-two images and execute image programs if needed.
|
|
idImage * ImageFromFile( const char *name,
|
|
textureFilter_t filter, bool allowDownSize,
|
|
textureRepeat_t repeat, textureDepth_t depth, cubeFiles_t cubeMap = CF_2D );
|
|
|
|
// look for a loaded image, whatever the parameters
|
|
idImage * GetImage( const char *name ) const;
|
|
|
|
// The callback will be issued immediately, and later if images are reloaded or vid_restart
|
|
// The callback function should call one of the idImage::Generate* functions to fill in the data
|
|
idImage * ImageFromFunction( const char *name, void (*generatorFunction)( idImage *image ));
|
|
|
|
// called once a frame to allow any background loads that have been completed
|
|
// to turn into textures.
|
|
void CompleteBackgroundImageLoads();
|
|
|
|
// returns the number of bytes of image data bound in the previous frame
|
|
int SumOfUsedImages();
|
|
|
|
// called each frame to allow some cvars to automatically force changes
|
|
void CheckCvars();
|
|
|
|
// purges all the images before a vid_restart
|
|
void PurgeAllImages();
|
|
|
|
// reloads all apropriate images after a vid_restart
|
|
void ReloadAllImages();
|
|
|
|
// disable the active texture unit
|
|
void BindNull();
|
|
|
|
// Mark all file based images as currently unused,
|
|
// but don't free anything. Calls to ImageFromFile() will
|
|
// either mark the image as used, or create a new image without
|
|
// loading the actual data.
|
|
// Called only by renderSystem::BeginLevelLoad
|
|
void BeginLevelLoad();
|
|
|
|
// Free all images marked as unused, and load all images that are necessary.
|
|
// This architecture prevents us from having the union of two level's
|
|
// worth of data present at one time.
|
|
// Called only by renderSystem::EndLevelLoad
|
|
void EndLevelLoad();
|
|
|
|
// used to clear and then write the dds conversion batch file
|
|
void StartBuild();
|
|
void FinishBuild( bool removeDups = false );
|
|
void AddDDSCommand( const char *cmd );
|
|
|
|
void PrintMemInfo( MemInfo_t *mi );
|
|
|
|
// cvars
|
|
static idCVar image_roundDown; // round bad sizes down to nearest power of two
|
|
static idCVar image_colorMipLevels; // development aid to see texture mip usage
|
|
static idCVar image_downSize; // controls texture downsampling
|
|
static idCVar image_useCompression; // 0 = force everything to high quality
|
|
static idCVar image_filter; // changes texture filtering on mipmapped images
|
|
static idCVar image_anisotropy; // set the maximum texture anisotropy if available
|
|
static idCVar image_lodbias; // change lod bias on mipmapped images
|
|
static idCVar image_useAllFormats; // allow alpha/intensity/luminance/luminance+alpha
|
|
static idCVar image_usePrecompressedTextures; // use .dds files if present
|
|
static idCVar image_writePrecompressedTextures; // write .dds files if necessary
|
|
static idCVar image_writeNormalTGA; // debug tool to write out .tgas of the final normal maps
|
|
static idCVar image_writeNormalTGAPalletized; // debug tool to write out palletized versions of the final normal maps
|
|
static idCVar image_writeTGA; // debug tool to write out .tgas of the non normal maps
|
|
static idCVar image_useNormalCompression; // 1 = use 256 color compression for normal maps if available, 2 = use rxgb compression
|
|
static idCVar image_useOffLineCompression; // will write a batch file with commands for the offline compression
|
|
static idCVar image_preload; // if 0, dynamically load all images
|
|
static idCVar image_cacheMinK; // maximum K of precompressed files to read at specification time,
|
|
// the remainder will be dynamically cached
|
|
static idCVar image_cacheMegs; // maximum bytes set aside for temporary loading of full-sized precompressed images
|
|
static idCVar image_useCache; // 1 = do background load image caching
|
|
static idCVar image_showBackgroundLoads; // 1 = print number of outstanding background loads
|
|
static idCVar image_forceDownSize; // allows the ability to force a downsize
|
|
static idCVar image_downSizeSpecular; // downsize specular
|
|
static idCVar image_downSizeSpecularLimit;// downsize specular limit
|
|
static idCVar image_downSizeBump; // downsize bump maps
|
|
static idCVar image_downSizeBumpLimit; // downsize bump limit
|
|
static idCVar image_ignoreHighQuality; // ignore high quality on materials
|
|
static idCVar image_downSizeLimit; // downsize diffuse limit
|
|
|
|
// built-in images
|
|
idImage * defaultImage;
|
|
idImage * flatNormalMap; // 128 128 255 in all pixels
|
|
idImage * ambientNormalMap; // tr.ambientLightVector encoded in all pixels
|
|
idImage * rampImage; // 0-255 in RGBA in S
|
|
idImage * alphaRampImage; // 0-255 in alpha, 255 in RGB
|
|
idImage * alphaNotchImage; // 2x1 texture with just 1110 and 1111 with point sampling
|
|
idImage * whiteImage; // full of 0xff
|
|
idImage * blackImage; // full of 0x00
|
|
idImage * normalCubeMapImage; // cube map to normalize STR into RGB
|
|
idImage * noFalloffImage; // all 255, but zero clamped
|
|
idImage * fogImage; // increasing alpha is denser fog
|
|
idImage * fogEnterImage; // adjust fogImage alpha based on terminator plane
|
|
idImage * cinematicImage;
|
|
idImage * scratchImage;
|
|
idImage * scratchImage2;
|
|
idImage * accumImage;
|
|
idImage * currentRenderImage; // for SS_POST_PROCESS shaders
|
|
idImage * scratchCubeMapImage;
|
|
idImage * specularTableImage; // 1D intensity texture with our specular function
|
|
idImage * specular2DTableImage; // 2D intensity texture with our specular function with variable specularity
|
|
idImage * borderClampImage; // white inside, black outside
|
|
|
|
//--------------------------------------------------------
|
|
|
|
idImage * AllocImage( const char *name );
|
|
void SetNormalPalette();
|
|
void ChangeTextureFilter();
|
|
|
|
idList<idImage*> images;
|
|
idStrList ddsList;
|
|
idHashIndex ddsHash;
|
|
|
|
bool insideLevelLoad; // don't actually load images now
|
|
|
|
byte originalToCompressed[256]; // maps normal maps to 8 bit textures
|
|
byte compressedPalette[768]; // the palette that normal maps use
|
|
|
|
// default filter modes for images
|
|
GLenum textureMinFilter;
|
|
GLenum textureMaxFilter;
|
|
float textureAnisotropy;
|
|
float textureLODBias;
|
|
|
|
idImage * imageHashTable[FILE_HASH_SIZE];
|
|
|
|
idImage * backgroundImageLoads; // chain of images that have background file loads active
|
|
idImage cacheLRU; // head/tail of doubly linked list
|
|
int totalCachedImageSize; // for determining when something should be purged
|
|
|
|
int numActiveBackgroundImageLoads;
|
|
const static int MAX_BACKGROUND_IMAGE_LOADS = 8;
|
|
};
|
|
|
|
extern idImageManager *globalImages; // pointer to global list for the rest of the system
|
|
|
|
int MakePowerOfTwo( int num );
|
|
|
|
/*
|
|
====================================================================
|
|
|
|
IMAGEPROCESS
|
|
|
|
FIXME: make an "imageBlock" type to hold byte*,width,height?
|
|
====================================================================
|
|
*/
|
|
|
|
byte *R_Dropsample( const byte *in, int inwidth, int inheight,
|
|
int outwidth, int outheight );
|
|
byte *R_ResampleTexture( const byte *in, int inwidth, int inheight,
|
|
int outwidth, int outheight );
|
|
byte *R_MipMapWithAlphaSpecularity( const byte *in, int width, int height );
|
|
byte *R_MipMap( const byte *in, int width, int height, bool preserveBorder );
|
|
byte *R_MipMap3D( const byte *in, int width, int height, int depth, bool preserveBorder );
|
|
|
|
// these operate in-place on the provided pixels
|
|
void R_SetBorderTexels( byte *inBase, int width, int height, const byte border[4] );
|
|
void R_SetBorderTexels3D( byte *inBase, int width, int height, int depth, const byte border[4] );
|
|
void R_BlendOverTexture( byte *data, int pixelCount, const byte blend[4] );
|
|
void R_HorizontalFlip( byte *data, int width, int height );
|
|
void R_VerticalFlip( byte *data, int width, int height );
|
|
void R_RotatePic( byte *data, int width );
|
|
|
|
/*
|
|
====================================================================
|
|
|
|
IMAGEFILES
|
|
|
|
====================================================================
|
|
*/
|
|
|
|
void R_LoadImage( const char *name, byte **pic, int *width, int *height, ID_TIME_T *timestamp, bool makePowerOf2 );
|
|
// pic is in top to bottom raster format
|
|
bool R_LoadCubeImages( const char *cname, cubeFiles_t extensions, byte *pic[6], int *size, ID_TIME_T *timestamp );
|
|
|
|
/*
|
|
====================================================================
|
|
|
|
IMAGEPROGRAM
|
|
|
|
====================================================================
|
|
*/
|
|
|
|
void R_LoadImageProgram( const char *name, byte **pic, int *width, int *height, ID_TIME_T *timestamp, textureDepth_t *depth = NULL );
|
|
const char *R_ParsePastImageProgram( idLexer &src );
|
|
|
|
#endif
|