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 extern void R_InitBubble();
25
26 /*
27 ==================
28 R_InitTextures
29 ==================
30 */
R_InitTextures(void)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 = 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 };
R_InitParticleTexture(void)70 void R_InitParticleTexture (void)
71 {
72 int x,y;
73 byte data[8][8][4];
74
75 //
76 // particle texture
77 //
78 particletexture = texture_extension_number++;
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 /*
100 ===============
101 R_Envmap_f
102
103 Grab six views for environment mapping tests
104 ===============
105 */
R_Envmap_f(void)106 void R_Envmap_f (void)
107 {
108 #ifdef USE_OPENGLES
109 // Not implemented
110 #else
111 byte buffer[256*256*4];
112
113 glDrawBuffer (GL_FRONT);
114 glReadBuffer (GL_FRONT);
115 envmap = true;
116
117 r_refdef.vrect.x = 0;
118 r_refdef.vrect.y = 0;
119 r_refdef.vrect.width = 256;
120 r_refdef.vrect.height = 256;
121
122 r_refdef.viewangles[0] = 0;
123 r_refdef.viewangles[1] = 0;
124 r_refdef.viewangles[2] = 0;
125 GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
126 R_RenderView ();
127 glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
128 COM_WriteFile ("env0.rgb", buffer, sizeof(buffer));
129
130 r_refdef.viewangles[1] = 90;
131 GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
132 R_RenderView ();
133 glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
134 COM_WriteFile ("env1.rgb", buffer, sizeof(buffer));
135
136 r_refdef.viewangles[1] = 180;
137 GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
138 R_RenderView ();
139 glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
140 COM_WriteFile ("env2.rgb", buffer, sizeof(buffer));
141
142 r_refdef.viewangles[1] = 270;
143 GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
144 R_RenderView ();
145 glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
146 COM_WriteFile ("env3.rgb", buffer, sizeof(buffer));
147
148 r_refdef.viewangles[0] = -90;
149 r_refdef.viewangles[1] = 0;
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 ("env4.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 ("env5.rgb", buffer, sizeof(buffer));
161
162 envmap = false;
163 glDrawBuffer (GL_BACK);
164 glReadBuffer (GL_BACK);
165 GL_EndRendering ();
166 #endif
167 }
168
169 /*
170 ===============
171 R_Init
172 ===============
173 */
R_Init(void)174 void R_Init (void)
175 {
176 Cmd_AddCommand ("timerefresh", R_TimeRefresh_f);
177 Cmd_AddCommand ("envmap", R_Envmap_f);
178 Cmd_AddCommand ("pointfile", R_ReadPointFile_f);
179
180 Cvar_RegisterVariable (&r_norefresh);
181 Cvar_RegisterVariable (&r_lightmap);
182 Cvar_RegisterVariable (&r_fullbright);
183 Cvar_RegisterVariable (&r_drawentities);
184 Cvar_RegisterVariable (&r_drawviewmodel);
185 Cvar_RegisterVariable (&r_shadows);
186 Cvar_RegisterVariable (&r_mirroralpha);
187 Cvar_RegisterVariable (&r_wateralpha);
188 Cvar_RegisterVariable (&r_dynamic);
189 Cvar_RegisterVariable (&r_novis);
190 Cvar_RegisterVariable (&r_speeds);
191 Cvar_RegisterVariable (&r_netgraph);
192
193 Cvar_RegisterVariable (&gl_clear);
194 Cvar_RegisterVariable (&gl_texsort);
195
196 if (gl_mtexable)
197 Cvar_SetValue ("gl_texsort", 0.0);
198
199 Cvar_RegisterVariable (&gl_cull);
200 Cvar_RegisterVariable (&gl_smoothmodels);
201 Cvar_RegisterVariable (&gl_affinemodels);
202 Cvar_RegisterVariable (&gl_polyblend);
203 Cvar_RegisterVariable (&gl_flashblend);
204 Cvar_RegisterVariable (&gl_playermip);
205 Cvar_RegisterVariable (&gl_nocolors);
206 Cvar_RegisterVariable (&gl_finish);
207
208 Cvar_RegisterVariable (&gl_keeptjunctions);
209 Cvar_RegisterVariable (&gl_reporttjunctions);
210
211 R_InitBubble();
212
213 R_InitParticles ();
214 R_InitParticleTexture ();
215
216 #ifdef GLTEST
217 Test_Init ();
218 #endif
219
220 netgraphtexture = texture_extension_number;
221 texture_extension_number++;
222
223 playertextures = texture_extension_number;
224 texture_extension_number += MAX_CLIENTS;
225 }
226
227 /*
228 ===============
229 R_TranslatePlayerSkin
230
231 Translates a skin texture by the per-player color lookup
232 ===============
233 */
R_TranslatePlayerSkin(int playernum)234 void R_TranslatePlayerSkin (int playernum)
235 {
236 int top, bottom;
237 byte translate[256];
238 unsigned translate32[256];
239 int i, j;
240 byte *original;
241 unsigned pixels[512*256], *out;
242 unsigned scaled_width, scaled_height;
243 int inwidth, inheight;
244 int tinwidth, tinheight;
245 byte *inrow;
246 unsigned frac, fracstep;
247 player_info_t *player;
248 extern byte player_8bit_texels[320*200];
249 char s[512];
250
251 GL_DisableMultitexture();
252
253 player = &cl.players[playernum];
254 if (!player->name[0])
255 return;
256
257 strcpy(s, Info_ValueForKey(player->userinfo, "skin"));
258 COM_StripExtension(s, s);
259 if (player->skin && !stricmp(s, player->skin->name))
260 player->skin = NULL;
261
262 if (player->_topcolor != player->topcolor ||
263 player->_bottomcolor != player->bottomcolor || !player->skin) {
264 player->_topcolor = player->topcolor;
265 player->_bottomcolor = player->bottomcolor;
266
267 top = player->topcolor;
268 bottom = player->bottomcolor;
269 top = (top < 0) ? 0 : ((top > 13) ? 13 : top);
270 bottom = (bottom < 0) ? 0 : ((bottom > 13) ? 13 : bottom);
271 top *= 16;
272 bottom *= 16;
273
274 for (i=0 ; i<256 ; i++)
275 translate[i] = i;
276
277 for (i=0 ; i<16 ; i++)
278 {
279 if (top < 128) // the artists made some backwards ranges. sigh.
280 translate[TOP_RANGE+i] = top+i;
281 else
282 translate[TOP_RANGE+i] = top+15-i;
283
284 if (bottom < 128)
285 translate[BOTTOM_RANGE+i] = bottom+i;
286 else
287 translate[BOTTOM_RANGE+i] = bottom+15-i;
288 }
289
290 //
291 // locate the original skin pixels
292 //
293 // real model width
294 tinwidth = 296;
295 tinheight = 194;
296
297 if (!player->skin)
298 Skin_Find(player);
299 if ((original = Skin_Cache(player->skin)) != NULL) {
300 //skin data width
301 inwidth = 320;
302 inheight = 200;
303 } else {
304 original = player_8bit_texels;
305 inwidth = 296;
306 inheight = 194;
307 }
308
309
310 // because this happens during gameplay, do it fast
311 // instead of sending it through gl_upload 8
312 GL_Bind(playertextures + playernum);
313
314 #if 0
315 s = 320*200;
316 byte translated[320*200];
317
318 for (i=0 ; i<s ; i+=4)
319 {
320 translated[i] = translate[original[i]];
321 translated[i+1] = translate[original[i+1]];
322 translated[i+2] = translate[original[i+2]];
323 translated[i+3] = translate[original[i+3]];
324 }
325
326
327 // don't mipmap these, because it takes too long
328 GL_Upload8 (translated, paliashdr->skinwidth, paliashdr->skinheight,
329 false, false, true);
330 #endif
331
332 scaled_width = gl_max_size.value < 512 ? gl_max_size.value : 512;
333 scaled_height = gl_max_size.value < 256 ? gl_max_size.value : 256;
334 // allow users to crunch sizes down even more if they want
335 scaled_width >>= (int)gl_playermip.value;
336 scaled_height >>= (int)gl_playermip.value;
337
338 if (VID_Is8bit()) { // 8bit texture upload
339 byte *out2;
340
341 out2 = (byte *)pixels;
342 memset(pixels, 0, sizeof(pixels));
343 fracstep = tinwidth*0x10000/scaled_width;
344 for (i=0 ; i< (int) scaled_height ; i++, out2 += scaled_width)
345 {
346 inrow = original + inwidth*(i*tinheight/scaled_height);
347 frac = fracstep >> 1;
348 for (j=0 ; j< (int) scaled_width ; j+=4)
349 {
350 out2[j] = translate[inrow[frac>>16]];
351 frac += fracstep;
352 out2[j+1] = translate[inrow[frac>>16]];
353 frac += fracstep;
354 out2[j+2] = translate[inrow[frac>>16]];
355 frac += fracstep;
356 out2[j+3] = translate[inrow[frac>>16]];
357 frac += fracstep;
358 }
359 }
360
361 GL_Upload8_EXT ((byte *)pixels, scaled_width, scaled_height, false, false);
362 return;
363 }
364
365 for (i=0 ; i<256 ; i++)
366 translate32[i] = d_8to24table[translate[i]];
367
368 out = pixels;
369 memset(pixels, 0, sizeof(pixels));
370 fracstep = tinwidth*0x10000/scaled_width;
371 for (i=0 ; i< (int) scaled_height ; i++, out += scaled_width)
372 {
373 inrow = original + inwidth*(i*tinheight/scaled_height);
374 frac = fracstep >> 1;
375 for (j=0 ; j< (int) scaled_width ; j+=4)
376 {
377 out[j] = translate32[inrow[frac>>16]];
378 frac += fracstep;
379 out[j+1] = translate32[inrow[frac>>16]];
380 frac += fracstep;
381 out[j+2] = translate32[inrow[frac>>16]];
382 frac += fracstep;
383 out[j+3] = translate32[inrow[frac>>16]];
384 frac += fracstep;
385 }
386 }
387
388 glTexImage2DHelper (GL_TEXTURE_2D, 0, gl_solid_format,
389 scaled_width, scaled_height, 0, GL_RGBA,
390 GL_UNSIGNED_BYTE, pixels);
391
392 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
393 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
394 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
395 }
396 }
397
398 /*
399 ===============
400 R_NewMap
401 ===============
402 */
R_NewMap(void)403 void R_NewMap (void)
404 {
405 int i;
406
407 for (i=0 ; i<256 ; i++)
408 d_lightstylevalue[i] = 264; // normal light value
409
410 memset (&r_worldentity, 0, sizeof(r_worldentity));
411 r_worldentity.model = cl.worldmodel;
412
413 // clear out efrags in case the level hasn't been reloaded
414 // FIXME: is this one short?
415 for (i=0 ; i<cl.worldmodel->numleafs ; i++)
416 cl.worldmodel->leafs[i].efrags = NULL;
417
418 r_viewleaf = NULL;
419 R_ClearParticles ();
420
421 GL_BuildLightmaps ();
422
423 // identify sky texture
424 skytexturenum = -1;
425 mirrortexturenum = -1;
426 for (i=0 ; i<cl.worldmodel->numtextures ; i++)
427 {
428 if (!cl.worldmodel->textures[i])
429 continue;
430 if (!Q_strncmp(cl.worldmodel->textures[i]->name,"sky",3) )
431 skytexturenum = i;
432 if (!Q_strncmp(cl.worldmodel->textures[i]->name,"window02_1",10) )
433 mirrortexturenum = i;
434 cl.worldmodel->textures[i]->texturechain = NULL;
435 }
436 #ifdef QUAKE2
437 R_LoadSkys ();
438 #endif
439 }
440
441
442 /*
443 ====================
444 R_TimeRefresh_f
445
446 For program optimization
447 ====================
448 */
R_TimeRefresh_f(void)449 void R_TimeRefresh_f (void)
450 {
451 #ifdef USE_OPENGLES
452 // Not implemented
453 Con_Printf("TimeRefresh not implemented.\n");
454 #else
455 int i;
456 float start, stop, time;
457
458 glDrawBuffer (GL_FRONT);
459 glFinish ();
460
461 start = Sys_DoubleTime ();
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_DoubleTime ();
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
D_FlushCaches(void)478 void D_FlushCaches (void)
479 {
480 }
481
482
483