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 }