DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

Image_intrinsic.cpp (11289B)


      1 /*
      2 ===========================================================================
      3 
      4 Doom 3 BFG Edition GPL Source Code
      5 Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. 
      6 
      7 This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").  
      8 
      9 Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
     10 it under the terms of the GNU General Public License as published by
     11 the Free Software Foundation, either version 3 of the License, or
     12 (at your option) any later version.
     13 
     14 Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
     15 but WITHOUT ANY WARRANTY; without even the implied warranty of
     16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17 GNU General Public License for more details.
     18 
     19 You should have received a copy of the GNU General Public License
     20 along with Doom 3 BFG Edition Source Code.  If not, see <http://www.gnu.org/licenses/>.
     21 
     22 In addition, the Doom 3 BFG Edition 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 BFG Edition Source Code.  If not, please request a copy in writing from id Software at the address below.
     23 
     24 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.
     25 
     26 ===========================================================================
     27 */
     28 
     29 #pragma hdrstop
     30 #include "../idlib/precompiled.h"
     31 
     32 
     33 #include "tr_local.h"
     34 
     35 #define	DEFAULT_SIZE	16
     36 
     37 /*
     38 ==================
     39 idImage::MakeDefault
     40 
     41 the default image will be grey with a white box outline
     42 to allow you to see the mapping coordinates on a surface
     43 ==================
     44 */
     45 void idImage::MakeDefault() {
     46 	int		x, y;
     47 	byte	data[DEFAULT_SIZE][DEFAULT_SIZE][4];
     48 
     49 	if ( com_developer.GetBool() ) {
     50 		// grey center
     51 		for ( y = 0 ; y < DEFAULT_SIZE ; y++ ) {
     52 			for ( x = 0 ; x < DEFAULT_SIZE ; x++ ) {
     53 				data[y][x][0] = 32;
     54 				data[y][x][1] = 32;
     55 				data[y][x][2] = 32;
     56 				data[y][x][3] = 255;
     57 			}
     58 		}
     59 
     60 		// white border
     61 		for ( x = 0 ; x < DEFAULT_SIZE ; x++ ) {
     62 			data[0][x][0] =
     63 				data[0][x][1] =
     64 				data[0][x][2] =
     65 				data[0][x][3] = 255;
     66 
     67 			data[x][0][0] =
     68 				data[x][0][1] =
     69 				data[x][0][2] =
     70 				data[x][0][3] = 255;
     71 
     72 			data[DEFAULT_SIZE-1][x][0] =
     73 				data[DEFAULT_SIZE-1][x][1] =
     74 				data[DEFAULT_SIZE-1][x][2] =
     75 				data[DEFAULT_SIZE-1][x][3] = 255;
     76 
     77 			data[x][DEFAULT_SIZE-1][0] =
     78 				data[x][DEFAULT_SIZE-1][1] =
     79 				data[x][DEFAULT_SIZE-1][2] =
     80 				data[x][DEFAULT_SIZE-1][3] = 255;
     81 		}
     82 	} else {
     83 		for ( y = 0 ; y < DEFAULT_SIZE ; y++ ) {
     84 			for ( x = 0 ; x < DEFAULT_SIZE ; x++ ) {
     85 				data[y][x][0] = 0;
     86 				data[y][x][1] = 0;
     87 				data[y][x][2] = 0;
     88 				data[y][x][3] = 0;
     89 			}
     90 		}
     91 	}
     92 
     93 	GenerateImage( (byte *)data, 
     94 		DEFAULT_SIZE, DEFAULT_SIZE, 
     95 		TF_DEFAULT, TR_REPEAT, TD_DEFAULT );
     96 
     97 	defaulted = true;
     98 }
     99 
    100 static void R_DefaultImage( idImage *image ) {
    101 	image->MakeDefault();
    102 }
    103 
    104 static void R_WhiteImage( idImage *image ) {
    105 	byte	data[DEFAULT_SIZE][DEFAULT_SIZE][4];
    106 
    107 	// solid white texture
    108 	memset( data, 255, sizeof( data ) );
    109 	image->GenerateImage( (byte *)data, DEFAULT_SIZE, DEFAULT_SIZE, 
    110 		TF_DEFAULT, TR_REPEAT, TD_DEFAULT );
    111 }
    112 
    113 static void R_BlackImage( idImage *image ) {
    114 	byte	data[DEFAULT_SIZE][DEFAULT_SIZE][4];
    115 
    116 	// solid black texture
    117 	memset( data, 0, sizeof( data ) );
    118 	image->GenerateImage( (byte *)data, DEFAULT_SIZE, DEFAULT_SIZE, 
    119 		TF_DEFAULT, TR_REPEAT, TD_DEFAULT );
    120 }
    121 
    122 static void R_RGBA8Image( idImage *image ) {
    123 	byte	data[DEFAULT_SIZE][DEFAULT_SIZE][4];
    124 
    125 	memset( data, 0, sizeof( data ) );
    126 	data[0][0][0] = 16;
    127 	data[0][0][1] = 32;
    128 	data[0][0][2] = 48;
    129 	data[0][0][3] = 96;
    130 
    131 	image->GenerateImage( (byte *)data, DEFAULT_SIZE, DEFAULT_SIZE, TF_DEFAULT, TR_REPEAT, TD_LOOKUP_TABLE_RGBA );
    132 }
    133 
    134 static void R_DepthImage( idImage *image ) {
    135 	byte	data[DEFAULT_SIZE][DEFAULT_SIZE][4];
    136 
    137 	memset( data, 0, sizeof( data ) );
    138 	data[0][0][0] = 16;
    139 	data[0][0][1] = 32;
    140 	data[0][0][2] = 48;
    141 	data[0][0][3] = 96;
    142 
    143 	image->GenerateImage( (byte *)data, DEFAULT_SIZE, DEFAULT_SIZE, TF_NEAREST, TR_CLAMP, TD_DEPTH );
    144 }
    145 
    146 static void R_AlphaNotchImage( idImage *image ) {
    147 	byte	data[2][4];
    148 
    149 	// this is used for alpha test clip planes
    150 
    151 	data[0][0] = data[0][1] = data[0][2] = 255;
    152 	data[0][3] = 0;
    153 	data[1][0] = data[1][1] = data[1][2] = 255;
    154 	data[1][3] = 255;
    155 
    156 	image->GenerateImage( (byte *)data, 2, 1, TF_NEAREST, TR_CLAMP, TD_LOOKUP_TABLE_ALPHA );
    157 }
    158 
    159 static void R_FlatNormalImage( idImage *image ) {
    160 	byte	data[DEFAULT_SIZE][DEFAULT_SIZE][4];
    161 
    162 	// flat normal map for default bunp mapping
    163 	for ( int i = 0 ; i < 4 ; i++ ) {
    164 		data[0][i][0] = 128;
    165 		data[0][i][1] = 128;
    166 		data[0][i][2] = 255;
    167 		data[0][i][3] = 255;
    168 	}
    169 	image->GenerateImage( (byte *)data, 2, 2, TF_DEFAULT, TR_REPEAT, TD_BUMP );
    170 }
    171 
    172 /*
    173 ================
    174 R_CreateNoFalloffImage
    175 
    176 This is a solid white texture that is zero clamped.
    177 ================
    178 */
    179 static void R_CreateNoFalloffImage( idImage *image ) {
    180 	int		x,y;
    181 	byte	data[16][FALLOFF_TEXTURE_SIZE][4];
    182 
    183 	memset( data, 0, sizeof( data ) );
    184 	for (x=1 ; x<FALLOFF_TEXTURE_SIZE-1 ; x++) {
    185 		for (y=1 ; y<15 ; y++) {
    186 			data[y][x][0] = 255;
    187 			data[y][x][1] = 255;
    188 			data[y][x][2] = 255;
    189 			data[y][x][3] = 255;
    190 		}
    191 	}
    192 	image->GenerateImage( (byte *)data, FALLOFF_TEXTURE_SIZE, 16, TF_DEFAULT, TR_CLAMP_TO_ZERO, TD_LOOKUP_TABLE_MONO );
    193 }
    194 
    195 /*
    196 ================
    197 R_FogImage
    198 
    199 We calculate distance correctly in two planes, but the
    200 third will still be projection based
    201 ================
    202 */
    203 const int	FOG_SIZE = 128;
    204 
    205 void R_FogImage( idImage *image ) {
    206 	int		x,y;
    207 	byte	data[FOG_SIZE][FOG_SIZE][4];
    208 	int		b;
    209 
    210 	float	step[256];
    211 	int		i;
    212 	float	remaining = 1.0;
    213 	for ( i = 0 ; i < 256 ; i++ ) {
    214 		step[i] = remaining;
    215 		remaining *= 0.982f;
    216 	}
    217 
    218 	for (x=0 ; x<FOG_SIZE ; x++) {
    219 		for (y=0 ; y<FOG_SIZE ; y++) {
    220 			float	d;
    221 
    222 			d = idMath::Sqrt( (x - FOG_SIZE/2) * (x - FOG_SIZE/2) 
    223 				+ (y - FOG_SIZE/2) * (y - FOG_SIZE / 2) );
    224 			d /= FOG_SIZE/2-1;
    225 
    226 			b = (byte)(d * 255);
    227 			if ( b <= 0 ) {
    228 				b = 0;
    229 			} else if ( b > 255 ) {
    230 				b = 255;
    231 			}
    232 			b = (byte)(255 * ( 1.0 - step[b] ));
    233 			if ( x == 0 || x == FOG_SIZE-1 || y == 0 || y == FOG_SIZE-1 ) {
    234 				b = 255;		// avoid clamping issues
    235 			}
    236 			data[y][x][0] =
    237 			data[y][x][1] =
    238 			data[y][x][2] = 255;
    239 			data[y][x][3] = b;
    240 		}
    241 	}
    242 
    243 	image->GenerateImage( (byte *)data, FOG_SIZE, FOG_SIZE, TF_LINEAR, TR_CLAMP, TD_LOOKUP_TABLE_ALPHA );
    244 }
    245 
    246 
    247 /*
    248 ================
    249 FogFraction
    250 
    251 Height values below zero are inside the fog volume
    252 ================
    253 */
    254 static const float	RAMP_RANGE =	8;
    255 static const float	DEEP_RANGE =	-30;
    256 static float	FogFraction( float viewHeight, float targetHeight ) {
    257 	float	total = idMath::Fabs( targetHeight - viewHeight );
    258 
    259 //	return targetHeight >= 0 ? 0 : 1.0;
    260 
    261 	// only ranges that cross the ramp range are special
    262 	if ( targetHeight > 0 && viewHeight > 0 ) {
    263 		return 0.0;
    264 	}
    265 	if ( targetHeight < -RAMP_RANGE && viewHeight < -RAMP_RANGE ) {
    266 		return 1.0;
    267 	}
    268 
    269 	float	above;
    270 	if ( targetHeight > 0 ) {
    271 		above = targetHeight;
    272 	} else if ( viewHeight > 0 ) {
    273 		above = viewHeight;
    274 	} else {
    275 		above = 0;
    276 	}
    277 
    278 	float	rampTop, rampBottom;
    279 
    280 	if ( viewHeight > targetHeight ) {
    281 		rampTop = viewHeight;
    282 		rampBottom = targetHeight;
    283 	} else {
    284 		rampTop = targetHeight;
    285 		rampBottom = viewHeight;
    286 	}
    287 	if ( rampTop > 0 ) {
    288 		rampTop = 0;
    289 	}
    290 	if ( rampBottom < -RAMP_RANGE ) {
    291 		rampBottom = -RAMP_RANGE;
    292 	}
    293 
    294 	float	rampSlope = 1.0 / RAMP_RANGE;
    295 
    296 	if ( !total ) {
    297 		return -viewHeight * rampSlope;
    298 	}
    299 
    300 	float ramp = ( 1.0 - ( rampTop * rampSlope + rampBottom * rampSlope ) * -0.5 ) * ( rampTop - rampBottom );
    301 
    302 	float	frac = ( total - above - ramp ) / total;
    303 
    304 	// after it gets moderately deep, always use full value
    305 	float deepest = viewHeight < targetHeight ? viewHeight : targetHeight;
    306 
    307 	float	deepFrac = deepest / DEEP_RANGE;
    308 	if ( deepFrac >= 1.0 ) {
    309 		return 1.0;
    310 	}
    311 
    312 	frac = frac * ( 1.0 - deepFrac ) + deepFrac;
    313 
    314 	return frac;
    315 }
    316 
    317 /*
    318 ================
    319 R_FogEnterImage
    320 
    321 Modulate the fog alpha density based on the distance of the
    322 start and end points to the terminator plane
    323 ================
    324 */
    325 void R_FogEnterImage( idImage *image ) {
    326 	int		x,y;
    327 	byte	data[FOG_ENTER_SIZE][FOG_ENTER_SIZE][4];
    328 	int		b;
    329 
    330 	for (x=0 ; x<FOG_ENTER_SIZE ; x++) {
    331 		for (y=0 ; y<FOG_ENTER_SIZE ; y++) {
    332 			float	d;
    333 
    334 			d = FogFraction( x - (FOG_ENTER_SIZE / 2), y - (FOG_ENTER_SIZE / 2) );
    335 
    336 			b = (byte)(d * 255);
    337 			if ( b <= 0 ) {
    338 				b = 0;
    339 			} else if ( b > 255 ) {
    340 				b = 255;
    341 			}
    342 			data[y][x][0] =
    343 			data[y][x][1] =
    344 			data[y][x][2] = 255;
    345 			data[y][x][3] = b;
    346 		}
    347 	}
    348 
    349 	// if mipmapped, acutely viewed surfaces fade wrong
    350 	image->GenerateImage( (byte *)data, FOG_ENTER_SIZE, FOG_ENTER_SIZE, TF_LINEAR, TR_CLAMP, TD_LOOKUP_TABLE_ALPHA );
    351 }
    352 
    353 
    354 /*
    355 ================
    356 R_QuadraticImage
    357 
    358 ================
    359 */
    360 static const int	QUADRATIC_WIDTH = 32;
    361 static const int	QUADRATIC_HEIGHT = 4;
    362 
    363 void R_QuadraticImage( idImage *image ) {
    364 	int		x,y;
    365 	byte	data[QUADRATIC_HEIGHT][QUADRATIC_WIDTH][4];
    366 	int		b;
    367 
    368 
    369 	for (x=0 ; x<QUADRATIC_WIDTH ; x++) {
    370 		for (y=0 ; y<QUADRATIC_HEIGHT ; y++) {
    371 			float	d;
    372 
    373 			d = x - (QUADRATIC_WIDTH/2 - 0.5);
    374 			d = idMath::Fabs( d );
    375 			d -= 0.5;
    376 			d /= QUADRATIC_WIDTH/2;
    377 		
    378 			d = 1.0 - d;
    379 			d = d * d;
    380 
    381 			b = (byte)(d * 255);
    382 			if ( b <= 0 ) {
    383 				b = 0;
    384 			} else if ( b > 255 ) {
    385 				b = 255;
    386 			}
    387 			data[y][x][0] =
    388 			data[y][x][1] =
    389 			data[y][x][2] = b;
    390 			data[y][x][3] = 255;
    391 		}
    392 	}
    393 
    394 	image->GenerateImage( (byte *)data, QUADRATIC_WIDTH, QUADRATIC_HEIGHT, TF_DEFAULT, TR_CLAMP, TD_LOOKUP_TABLE_RGB1 );
    395 }
    396 
    397 /*
    398 ================
    399 idImageManager::CreateIntrinsicImages
    400 ================
    401 */
    402 void idImageManager::CreateIntrinsicImages() {
    403 	// create built in images
    404 	defaultImage = ImageFromFunction( "_default", R_DefaultImage );
    405 	whiteImage = ImageFromFunction( "_white", R_WhiteImage );
    406 	blackImage = ImageFromFunction( "_black", R_BlackImage );
    407 	flatNormalMap = ImageFromFunction( "_flat", R_FlatNormalImage );
    408 	alphaNotchImage = ImageFromFunction( "_alphaNotch", R_AlphaNotchImage );
    409 	fogImage = ImageFromFunction( "_fog", R_FogImage );
    410 	fogEnterImage = ImageFromFunction( "_fogEnter", R_FogEnterImage );
    411 	noFalloffImage = ImageFromFunction( "_noFalloff", R_CreateNoFalloffImage );
    412 	ImageFromFunction( "_quadratic", R_QuadraticImage );
    413 
    414 	// scratchImage is used for screen wipes/doublevision etc..
    415 	scratchImage = ImageFromFunction("_scratch", R_RGBA8Image );
    416 	scratchImage2 = ImageFromFunction("_scratch2", R_RGBA8Image );
    417 	accumImage = ImageFromFunction("_accum", R_RGBA8Image );
    418 	currentRenderImage = ImageFromFunction("_currentRender", R_RGBA8Image );
    419 	currentDepthImage = ImageFromFunction("_currentDepth", R_DepthImage );
    420 
    421 	// save a copy of this for material comparison, because currentRenderImage may get
    422 	// reassigned during stereo rendering
    423 	originalCurrentRenderImage = currentRenderImage;
    424 
    425 	loadingIconImage = ImageFromFile("textures/loadingicon2", TF_DEFAULT, TR_CLAMP, TD_DEFAULT, CF_2D );
    426 	hellLoadingIconImage = ImageFromFile("textures/loadingicon3", TF_DEFAULT, TR_CLAMP, TD_DEFAULT, CF_2D );
    427 
    428 	release_assert( loadingIconImage->referencedOutsideLevelLoad );
    429 	release_assert( hellLoadingIconImage->referencedOutsideLevelLoad );
    430 }