1 /* 2 Copyright (C) 1996-1997 Id Software, Inc. 3 4 This program is free software; you can redistribute it and/or 5 modify it under the terms of the GNU General Public License 6 as published by the Free Software Foundation; either version 2 7 of the License, or (at your option) any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 13 See the GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, write to the Free Software 17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 19 */ 20 // r_misc.c 21 22 #include "quakedef.h" 23 24 25 26 /* 27 ================== 28 R_InitTextures 29 ================== 30 */ 31 void R_InitTextures (void) 32 { 33 int x,y, m; 34 byte *dest; 35 36 // create a simple checkerboard texture for the default 37 r_notexture_mip = (texture_t*) Hunk_AllocName (sizeof(texture_t) + 16*16+8*8+4*4+2*2, "notexture"); 38 39 r_notexture_mip->width = r_notexture_mip->height = 16; 40 r_notexture_mip->offsets[0] = sizeof(texture_t); 41 r_notexture_mip->offsets[1] = r_notexture_mip->offsets[0] + 16*16; 42 r_notexture_mip->offsets[2] = r_notexture_mip->offsets[1] + 8*8; 43 r_notexture_mip->offsets[3] = r_notexture_mip->offsets[2] + 4*4; 44 45 for (m=0 ; m<4 ; m++) 46 { 47 dest = (byte *)r_notexture_mip + r_notexture_mip->offsets[m]; 48 for (y=0 ; y< (16>>m) ; y++) 49 for (x=0 ; x< (16>>m) ; x++) 50 { 51 if ( (y< (8>>m) ) ^ (x< (8>>m) ) ) 52 *dest++ = 0; 53 else 54 *dest++ = 0xff; 55 } 56 } 57 } 58 59 byte dottexture[8][8] = 60 { 61 {0,1,1,0,0,0,0,0}, 62 {1,1,1,1,0,0,0,0}, 63 {1,1,1,1,0,0,0,0}, 64 {0,1,1,0,0,0,0,0}, 65 {0,0,0,0,0,0,0,0}, 66 {0,0,0,0,0,0,0,0}, 67 {0,0,0,0,0,0,0,0}, 68 {0,0,0,0,0,0,0,0}, 69 }; 70 // Initialize particle texture, can be called multiple times. 71 void R_InitParticleTexture2 (void) 72 { 73 int x,y; 74 byte data[8][8][4]; 75 76 // 77 // particle texture 78 // 79 GL_Bind(particletexture); 80 81 for (x=0 ; x<8 ; x++) 82 { 83 for (y=0 ; y<8 ; y++) 84 { 85 data[y][x][0] = 255; 86 data[y][x][1] = 255; 87 data[y][x][2] = 255; 88 data[y][x][3] = dottexture[x][y]*255; 89 } 90 } 91 glTexImage2DHelper (GL_TEXTURE_2D, 0, gl_alpha_format, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); 92 93 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 94 95 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 96 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 97 } 98 99 void R_InitParticleTexture (void) 100 { 101 particletexture = texture_extension_number++; 102 R_InitParticleTexture2(); 103 } 104 105 /* 106 =============== 107 R_Envmap_f 108 109 Grab six views for environment mapping tests 110 =============== 111 */ 112 void R_Envmap_f (void) 113 { 114 #ifdef USE_OPENGLES 115 // Not implemented 116 #else 117 byte buffer[256*256*4]; 118 char name[1024]; 119 120 glDrawBuffer (GL_FRONT); 121 glReadBuffer (GL_FRONT); 122 envmap = true; 123 124 r_refdef.vrect.x = 0; 125 r_refdef.vrect.y = 0; 126 r_refdef.vrect.width = 256; 127 r_refdef.vrect.height = 256; 128 129 r_refdef.viewangles[0] = 0; 130 r_refdef.viewangles[1] = 0; 131 r_refdef.viewangles[2] = 0; 132 GL_BeginRendering (&glx, &gly, &glwidth, &glheight); 133 R_RenderView (); 134 glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer); 135 COM_WriteFile ("env0.rgb", buffer, sizeof(buffer)); 136 137 r_refdef.viewangles[1] = 90; 138 GL_BeginRendering (&glx, &gly, &glwidth, &glheight); 139 R_RenderView (); 140 glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer); 141 COM_WriteFile ("env1.rgb", buffer, sizeof(buffer)); 142 143 r_refdef.viewangles[1] = 180; 144 GL_BeginRendering (&glx, &gly, &glwidth, &glheight); 145 R_RenderView (); 146 glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer); 147 COM_WriteFile ("env2.rgb", buffer, sizeof(buffer)); 148 149 r_refdef.viewangles[1] = 270; 150 GL_BeginRendering (&glx, &gly, &glwidth, &glheight); 151 R_RenderView (); 152 glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer); 153 COM_WriteFile ("env3.rgb", buffer, sizeof(buffer)); 154 155 r_refdef.viewangles[0] = -90; 156 r_refdef.viewangles[1] = 0; 157 GL_BeginRendering (&glx, &gly, &glwidth, &glheight); 158 R_RenderView (); 159 glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer); 160 COM_WriteFile ("env4.rgb", buffer, sizeof(buffer)); 161 162 r_refdef.viewangles[0] = 90; 163 r_refdef.viewangles[1] = 0; 164 GL_BeginRendering (&glx, &gly, &glwidth, &glheight); 165 R_RenderView (); 166 glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer); 167 COM_WriteFile ("env5.rgb", buffer, sizeof(buffer)); 168 169 envmap = false; 170 glDrawBuffer (GL_BACK); 171 glReadBuffer (GL_BACK); 172 GL_EndRendering (); 173 #endif 174 } 175 176 /* 177 =============== 178 R_Init 179 =============== 180 */ 181 void R_Init (void) 182 { 183 extern byte *hunk_base; 184 extern cvar_t gl_finish; 185 186 Cmd_AddCommand ("timerefresh", R_TimeRefresh_f); 187 Cmd_AddCommand ("envmap", R_Envmap_f); 188 Cmd_AddCommand ("pointfile", R_ReadPointFile_f); 189 190 Cvar_RegisterVariable (&r_norefresh); 191 Cvar_RegisterVariable (&r_lightmap); 192 Cvar_RegisterVariable (&r_fullbright); 193 Cvar_RegisterVariable (&r_drawentities); 194 Cvar_RegisterVariable (&r_drawviewmodel); 195 Cvar_RegisterVariable (&r_shadows); 196 Cvar_RegisterVariable (&r_mirroralpha); 197 Cvar_RegisterVariable (&r_wateralpha); 198 Cvar_RegisterVariable (&r_dynamic); 199 Cvar_RegisterVariable (&r_novis); 200 Cvar_RegisterVariable (&r_speeds); 201 202 Cvar_RegisterVariable (&gl_finish); 203 Cvar_RegisterVariable (&gl_clear); 204 Cvar_RegisterVariable (&gl_texsort); 205 206 if (gl_mtexable) 207 Cvar_SetValue ("gl_texsort", 0.0); 208 209 Cvar_RegisterVariable (&gl_cull); 210 Cvar_RegisterVariable (&gl_smoothmodels); 211 Cvar_RegisterVariable (&gl_affinemodels); 212 Cvar_RegisterVariable (&gl_polyblend); 213 Cvar_RegisterVariable (&gl_flashblend); 214 Cvar_RegisterVariable (&gl_playermip); 215 Cvar_RegisterVariable (&gl_nocolors); 216 217 Cvar_RegisterVariable (&gl_keeptjunctions); 218 Cvar_RegisterVariable (&gl_reporttjunctions); 219 220 Cvar_RegisterVariable (&gl_doubleeyes); 221 222 R_InitParticles (); 223 R_InitParticleTexture (); 224 225 #ifdef GLTEST 226 Test_Init (); 227 #endif 228 229 playertextures = texture_extension_number; 230 texture_extension_number += 16; 231 } 232 233 /* 234 =============== 235 R_TranslatePlayerSkin 236 237 Translates a skin texture by the per-player color lookup 238 =============== 239 */ 240 void R_TranslatePlayerSkin (int playernum) 241 { 242 int top, bottom; 243 byte translate[256]; 244 unsigned translate32[256]; 245 int i, j, s; 246 model_t *model; 247 aliashdr_t *paliashdr; 248 byte *original; 249 unsigned* pixels; 250 unsigned *out; 251 unsigned scaled_width, scaled_height; 252 int inwidth, inheight; 253 byte *inrow; 254 unsigned frac, fracstep; 255 extern byte **player_8bit_texels_tbl; 256 257 GL_DisableMultitexture(); 258 259 top = cl.scores[playernum].colors & 0xf0; 260 bottom = (cl.scores[playernum].colors &15)<<4; 261 262 for (i=0 ; i<256 ; i++) 263 translate[i] = i; 264 265 for (i=0 ; i<16 ; i++) 266 { 267 if (top < 128) // the artists made some backwards ranges. sigh. 268 translate[TOP_RANGE+i] = top+i; 269 else 270 translate[TOP_RANGE+i] = top+15-i; 271 272 if (bottom < 128) 273 translate[BOTTOM_RANGE+i] = bottom+i; 274 else 275 translate[BOTTOM_RANGE+i] = bottom+15-i; 276 } 277 278 // 279 // locate the original skin pixels 280 // 281 currententity = &cl_entities[1+playernum]; 282 model = currententity->model; 283 if (!model) 284 return; // player doesn't have a model yet 285 if (model->type != mod_alias) 286 return; // only translate skins on alias models 287 288 paliashdr = (aliashdr_t *)Mod_Extradata (model); 289 s = paliashdr->skinwidth * paliashdr->skinheight; 290 if (currententity->skinnum < 0 || currententity->skinnum >= paliashdr->numskins) { 291 Con_Printf("(%d): Invalid player skin #%d\n", playernum, currententity->skinnum); 292 original = (byte *)paliashdr + paliashdr->texels[0]; 293 } else 294 original = (byte *)paliashdr + paliashdr->texels[currententity->skinnum]; 295 if (s & 3) 296 Sys_Error ("R_TranslateSkin: s&3"); 297 298 inwidth = paliashdr->skinwidth; 299 inheight = paliashdr->skinheight; 300 301 // because this happens during gameplay, do it fast 302 // instead of sending it through gl_upload 8 303 GL_Bind(playertextures + playernum); 304 305 #if 0 306 byte translated[320*200]; 307 308 for (i=0 ; i<s ; i+=4) 309 { 310 translated[i] = translate[original[i]]; 311 translated[i+1] = translate[original[i+1]]; 312 translated[i+2] = translate[original[i+2]]; 313 translated[i+3] = translate[original[i+3]]; 314 } 315 316 317 // don't mipmap these, because it takes too long 318 GL_Upload8 (translated, paliashdr->skinwidth, paliashdr->skinheight, false, false, true); 319 #else 320 scaled_width = (unsigned int) (gl_max_size.value < 512 ? gl_max_size.value : 512); 321 scaled_height = (unsigned int) (gl_max_size.value < 256 ? gl_max_size.value : 256); 322 323 // allow users to crunch sizes down even more if they want 324 scaled_width >>= (int)gl_playermip.value; 325 scaled_height >>= (int)gl_playermip.value; 326 327 #define PIXEL_COUNT (512*256) 328 #define PIXELS_SIZE (PIXEL_COUNT * sizeof(unsigned)) 329 330 pixels = (unsigned*) malloc(PIXELS_SIZE); 331 if(!pixels) 332 { 333 Sys_Error("Out of memory."); 334 } 335 336 if (VID_Is8bit()) { // 8bit texture upload 337 byte *out2; 338 339 out2 = (byte *)pixels; 340 memset(pixels, 0, PIXELS_SIZE); 341 fracstep = inwidth*0x10000/scaled_width; 342 for (i=0 ; i< (int) scaled_height ; i++, out2 += scaled_width) 343 { 344 inrow = original + inwidth*(i*inheight/scaled_height); 345 frac = fracstep >> 1; 346 for (j=0 ; j< (int) scaled_width ; j+=4) 347 { 348 out2[j] = translate[inrow[frac>>16]]; 349 frac += fracstep; 350 out2[j+1] = translate[inrow[frac>>16]]; 351 frac += fracstep; 352 out2[j+2] = translate[inrow[frac>>16]]; 353 frac += fracstep; 354 out2[j+3] = translate[inrow[frac>>16]]; 355 frac += fracstep; 356 } 357 } 358 359 GL_Upload8_EXT ((byte *)pixels, scaled_width, scaled_height, false, false); 360 } 361 else 362 { 363 364 for (i=0 ; i<256 ; i++) 365 translate32[i] = d_8to24table[translate[i]]; 366 367 out = pixels; 368 fracstep = inwidth*0x10000/scaled_width; 369 for (i=0 ; i< (int) scaled_height ; i++, out += scaled_width) 370 { 371 inrow = original + inwidth*(i*inheight/scaled_height); 372 frac = fracstep >> 1; 373 for (j=0 ; j< (int) scaled_width ; j+=4) 374 { 375 out[j] = translate32[inrow[frac>>16]]; 376 frac += fracstep; 377 out[j+1] = translate32[inrow[frac>>16]]; 378 frac += fracstep; 379 out[j+2] = translate32[inrow[frac>>16]]; 380 frac += fracstep; 381 out[j+3] = translate32[inrow[frac>>16]]; 382 frac += fracstep; 383 } 384 } 385 glTexImage2DHelper (GL_TEXTURE_2D, 0, gl_solid_format, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); 386 387 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 388 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 389 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 390 } 391 #endif 392 free(pixels); 393 } 394 395 396 /* 397 =============== 398 R_NewMap 399 =============== 400 */ 401 void R_NewMap (void) 402 { 403 int i; 404 405 for (i=0 ; i<256 ; i++) 406 d_lightstylevalue[i] = 264; // normal light value 407 408 memset (&r_worldentity, 0, sizeof(r_worldentity)); 409 r_worldentity.model = cl.worldmodel; 410 411 // clear out efrags in case the level hasn't been reloaded 412 // FIXME: is this one short? 413 for (i=0 ; i<cl.worldmodel->numleafs ; i++) 414 cl.worldmodel->leafs[i].efrags = NULL; 415 416 r_viewleaf = NULL; 417 R_ClearParticles (); 418 419 GL_BuildLightmaps (); 420 421 // identify sky texture 422 skytexturenum = -1; 423 mirrortexturenum = -1; 424 for (i=0 ; i<cl.worldmodel->numtextures ; i++) 425 { 426 if (!cl.worldmodel->textures[i]) 427 continue; 428 if (!Q_strncmp(cl.worldmodel->textures[i]->name,"sky",3) ) 429 skytexturenum = i; 430 if (!Q_strncmp(cl.worldmodel->textures[i]->name,"window02_1",10) ) 431 mirrortexturenum = i; 432 cl.worldmodel->textures[i]->texturechain = NULL; 433 } 434 #ifdef QUAKE2 435 R_LoadSkys (); 436 #endif 437 } 438 439 440 /* 441 ==================== 442 R_TimeRefresh_f 443 444 For program optimization 445 ==================== 446 */ 447 void R_TimeRefresh_f (void) 448 { 449 #ifdef USE_OPENGLES 450 // Not implemented 451 Con_Printf("TimeRefresh not implemented.\n"); 452 #else 453 int i; 454 float start, stop, time; 455 int startangle; 456 vrect_t vr; 457 458 glDrawBuffer (GL_FRONT); 459 glFinish (); 460 461 start = Sys_FloatTime (); 462 for (i=0 ; i<128 ; i++) 463 { 464 r_refdef.viewangles[1] = i/128.0*360.0; 465 R_RenderView (); 466 } 467 468 glFinish (); 469 stop = Sys_FloatTime (); 470 time = stop-start; 471 Con_Printf ("%f seconds (%f fps)\n", time, 128/time); 472 473 glDrawBuffer (GL_BACK); 474 GL_EndRendering (); 475 #endif 476 } 477 478 void D_FlushCaches (void) 479 { 480 } 481