6 #include "cl_collision.h"
9 cvar_t scr_viewsize = {CVAR_SAVE, "viewsize","100", "how large the view should be, 110 disables inventory bar, 120 disables status bar"};
10 cvar_t scr_fov = {CVAR_SAVE, "fov","90", "field of vision, 1-170 degrees, default 90, some players use 110-130"}; // 1 - 170
11 cvar_t scr_conalpha = {CVAR_SAVE, "scr_conalpha", "1", "opacity of console background"};
12 cvar_t scr_conbrightness = {CVAR_SAVE, "scr_conbrightness", "1", "brightness of console background (0 = black, 1 = image)"};
13 cvar_t scr_conforcewhiledisconnected = {0, "scr_conforcewhiledisconnected", "1", "forces fullscreen console while disconnected"};
14 cvar_t scr_menuforcewhiledisconnected = {0, "scr_menuforcewhiledisconnected", "0", "forces menu while disconnected"};
15 cvar_t scr_centertime = {0, "scr_centertime","2", "how long centerprint messages show"};
16 cvar_t scr_showram = {CVAR_SAVE, "showram","1", "show ram icon if low on surface cache memory (not used)"};
17 cvar_t scr_showturtle = {CVAR_SAVE, "showturtle","0", "show turtle icon when framerate is too low (not used)"};
18 cvar_t scr_showpause = {CVAR_SAVE, "showpause","1", "show pause icon when game is paused"};
19 cvar_t scr_showbrand = {0, "showbrand","0", "shows gfx/brand.tga in a corner of the screen (different values select different positions, including centered)"};
20 cvar_t scr_printspeed = {0, "scr_printspeed","8", "speed of intermission printing (episode end texts)"};
21 cvar_t vid_conwidth = {CVAR_SAVE, "vid_conwidth", "640", "virtual width of 2D graphics system"};
22 cvar_t vid_conheight = {CVAR_SAVE, "vid_conheight", "480", "virtual height of 2D graphics system"};
23 cvar_t vid_pixelheight = {CVAR_SAVE, "vid_pixelheight", "1", "adjusts vertical field of vision to account for non-square pixels (1280x1024 on a CRT monitor for example)"};
24 cvar_t scr_screenshot_jpeg = {CVAR_SAVE, "scr_screenshot_jpeg","1", "save jpeg instead of targa"};
25 cvar_t scr_screenshot_jpeg_quality = {CVAR_SAVE, "scr_screenshot_jpeg_quality","0.9", "image quality of saved jpeg"};
26 cvar_t scr_screenshot_gammaboost = {CVAR_SAVE, "scr_screenshot_gammaboost","1", "gamma correction on saved screenshots and videos, 1.0 saves unmodified images"};
27 // scr_screenshot_name is defined in fs.c
28 cvar_t cl_capturevideo = {0, "cl_capturevideo", "0", "enables saving of video to a file or files (default is .tga files, if scr_screenshot_jpeg is on it saves .jpg files (VERY SLOW), if any rawrgb or rawyv12 are on it saves those formats instead, note that scr_screenshot_gammaboost affects the brightness of the output)"};
29 cvar_t cl_capturevideo_sound = {0, "cl_capturevideo_sound", "0", "enables saving of sound to a .wav file (warning: this requires exact sync, if your hard drive can't keep up it will abort, if your graphics can't keep up it will save duplicate frames to maintain sound sync)"};
30 cvar_t cl_capturevideo_fps = {0, "cl_capturevideo_fps", "30", "how many frames per second to save (29.97 for NTSC, 30 for typical PC video, 15 can be useful)"};
31 cvar_t cl_capturevideo_rawrgb = {0, "cl_capturevideo_rawrgb", "0", "saves a single .rgb video file containing raw RGB images (you'll need special processing tools to encode this to something more useful)"};
32 cvar_t cl_capturevideo_rawyv12 = {0, "cl_capturevideo_rawyv12", "0", "saves a single .yv12 video file containing raw YV12 (luma plane, then half resolution chroma planes, first chroma blue then chroma red, this is the format used internally by many encoders, some tools can read it directly)"};
33 cvar_t r_letterbox = {0, "r_letterbox", "0", "reduces vertical height of view to simulate a letterboxed movie effect (can be used by mods for cutscenes)"};
34 cvar_t r_stereo_separation = {0, "r_stereo_separation", "4", "separation of eyes in the world (try negative values too)"};
35 cvar_t r_stereo_sidebyside = {0, "r_stereo_sidebyside", "0", "side by side views (for those who can't afford glasses but can afford eye strain)"};
36 cvar_t r_stereo_redblue = {0, "r_stereo_redblue", "0", "red/blue anaglyph stereo glasses (note: most of these glasses are actually red/cyan, try that one too)"};
37 cvar_t r_stereo_redcyan = {0, "r_stereo_redcyan", "0", "red/cyan anaglyph stereo glasses, the kind given away at drive-in movies like Creature From The Black Lagoon In 3D"};
38 cvar_t r_stereo_redgreen = {0, "r_stereo_redgreen", "0", "red/green anaglyph stereo glasses (for those who don't mind yellow)"};
39 cvar_t scr_zoomwindow = {CVAR_SAVE, "scr_zoomwindow", "0", "displays a zoomed in overlay window"};
40 cvar_t scr_zoomwindow_viewsizex = {CVAR_SAVE, "scr_zoomwindow_viewsizex", "20", "horizontal viewsize of zoom window"};
41 cvar_t scr_zoomwindow_viewsizey = {CVAR_SAVE, "scr_zoomwindow_viewsizey", "20", "vertical viewsize of zoom window"};
42 cvar_t scr_zoomwindow_fov = {CVAR_SAVE, "scr_zoomwindow_fov", "20", "fov of zoom window"};
45 int jpeg_supported = false;
47 qboolean scr_initialized; // ready to draw
49 float scr_con_current;
51 extern int con_vislines;
53 void DrawCrosshair(int num);
54 static void SCR_ScreenShot_f (void);
55 static void R_Envmap_f (void);
58 void R_ClearScreen(void);
61 ===============================================================================
65 ===============================================================================
68 char scr_centerstring[MAX_INPUTLINE];
69 float scr_centertime_start; // for slow victory printing
70 float scr_centertime_off;
79 Called for important messages that should stay in the center of the screen
83 void SCR_CenterPrint(char *str)
85 strlcpy (scr_centerstring, str, sizeof (scr_centerstring));
86 scr_centertime_off = scr_centertime.value;
87 scr_centertime_start = cl.time;
89 // count the number of lines for centering
100 void SCR_DrawCenterString (void)
108 // the finale prints the characters one at a time
110 remaining = (int)(scr_printspeed.value * (cl.time - scr_centertime_start));
114 scr_erase_center = 0;
115 start = scr_centerstring;
120 if (scr_center_lines <= 4)
121 y = (int)(vid_conheight.integer*0.35);
128 // scan the width of the line
129 for (l=0 ; l<vid_conwidth.integer/8 ; l++)
130 if (start[l] == '\n' || !start[l])
132 x = (vid_conwidth.integer - l*8)/2;
137 DrawQ_ColoredString(x, y, start, l, 8, 8, 1, 1, 1, 1, 0, &color);
145 while (*start && *start != '\n')
150 start++; // skip the \n
154 void SCR_CheckDrawCenterString (void)
156 if (scr_center_lines > scr_erase_lines)
157 scr_erase_lines = scr_center_lines;
159 scr_centertime_off -= cl.realframetime;
161 // don't draw if this is a normal stats-screen intermission,
162 // only if it is not an intermission, or a finale intermission
163 if (cl.intermission == 1)
165 if (scr_centertime_off <= 0 && !cl.intermission)
167 if (key_dest != key_game)
170 SCR_DrawCenterString ();
178 void SCR_DrawTurtle (void)
182 if (cls.state != ca_connected)
185 if (!scr_showturtle.integer)
188 if (cl.realframetime < 0.1)
198 DrawQ_Pic (0, 0, Draw_CachePic("gfx/turtle", true), 0, 0, 1, 1, 1, 1, 0);
206 void SCR_DrawNet (void)
208 if (cls.state != ca_connected)
210 if (realtime - cl.last_received_message < 0.3)
212 if (cls.demoplayback)
215 DrawQ_Pic (64, 0, Draw_CachePic("gfx/net", true), 0, 0, 1, 1, 1, 1, 0);
223 void SCR_DrawPause (void)
227 if (cls.state != ca_connected)
230 if (!scr_showpause.integer) // turn off for screenshots
236 pic = Draw_CachePic ("gfx/pause", true);
237 DrawQ_Pic ((vid_conwidth.integer - pic->width)/2, (vid_conheight.integer - pic->height)/2, pic, 0, 0, 1, 1, 1, 1, 0);
245 void SCR_DrawBrand (void)
250 if (!scr_showbrand.value)
253 pic = Draw_CachePic ("gfx/brand", true);
255 switch ((int)scr_showbrand.value)
257 case 1: // bottom left
259 y = vid_conheight.integer - pic->height;
261 case 2: // bottom centre
262 x = (vid_conwidth.integer - pic->width) / 2;
263 y = vid_conheight.integer - pic->height;
265 case 3: // bottom right
266 x = vid_conwidth.integer - pic->width;
267 y = vid_conheight.integer - pic->height;
269 case 4: // centre right
270 x = vid_conwidth.integer - pic->width;
271 y = (vid_conheight.integer - pic->height) / 2;
274 x = vid_conwidth.integer - pic->width;
277 case 6: // top centre
278 x = (vid_conwidth.integer - pic->width) / 2;
285 case 8: // centre left
287 y = (vid_conheight.integer - pic->height) / 2;
293 DrawQ_Pic (x, y, pic, 0, 0, 1, 1, 1, 1, 0);
301 static void SCR_DrawDownload(void)
307 if (!cls.qw_downloadname[0])
309 dpsnprintf(temp, sizeof(temp), "Downloading %s ... %3i%%\n", cls.qw_downloadname, cls.qw_downloadpercent);
310 len = (int)strlen(temp);
311 x = (vid_conwidth.integer - len*size) / 2;
312 y = vid_conheight.integer - size;
313 DrawQ_Pic(0, y, NULL, vid_conwidth.integer, size, 0, 0, 0, 0.5, 0);
314 DrawQ_String(x, y, temp, len, size, size, 1, 1, 1, 1, 0);
317 //=============================================================================
322 SCR_SetUpToDrawConsole
325 void SCR_SetUpToDrawConsole (void)
327 // lines of console to display
329 static int framecounter = 0;
333 if (scr_menuforcewhiledisconnected.integer && key_dest == key_game && cls.state == ca_disconnected)
335 if (framecounter >= 2)
343 if (scr_conforcewhiledisconnected.integer && key_dest == key_game && cls.signon != SIGNONS)
344 key_consoleactive |= KEY_CONSOLEACTIVE_FORCED;
346 key_consoleactive &= ~KEY_CONSOLEACTIVE_FORCED;
348 // decide on the height of the console
349 if (key_consoleactive & KEY_CONSOLEACTIVE_USER)
350 conlines = vid_conheight.integer/2; // half screen
352 conlines = 0; // none visible
354 scr_con_current = conlines;
362 void SCR_DrawConsole (void)
364 if (key_consoleactive & KEY_CONSOLEACTIVE_FORCED)
367 Con_DrawConsole (vid_conheight.integer);
369 else if (scr_con_current)
370 Con_DrawConsole ((int)scr_con_current);
374 if (key_dest == key_game || key_dest == key_message)
375 Con_DrawNotify (); // only draw notify in game
381 SCR_BeginLoadingPlaque
385 void SCR_BeginLoadingPlaque (void)
387 // save console log up to this point to log_file if it was set by configs
392 SCR_UpdateLoadingScreen();
395 //=============================================================================
397 char r_speeds_string[1024];
398 int speedstringcount, r_timereport_active;
399 double r_timereport_temp = 0, r_timereport_current = 0, r_timereport_start = 0;
401 void R_TimeReport(char *desc)
407 if (r_speeds.integer < 2 || !r_timereport_active)
411 qglFinish();CHECKGLERROR
412 r_timereport_temp = r_timereport_current;
413 r_timereport_current = Sys_DoubleTime();
414 t = (int) ((r_timereport_current - r_timereport_temp) * 1000000.0 + 0.5);
416 dpsnprintf(tempbuf, sizeof(tempbuf), "%8i %-11s", t, desc);
417 length = (int)strlen(tempbuf);
418 if (speedstringcount + length > (vid_conwidth.integer / 8))
420 strlcat(r_speeds_string, "\n", sizeof(r_speeds_string));
421 speedstringcount = 0;
423 strlcat(r_speeds_string, tempbuf, sizeof(r_speeds_string));
424 speedstringcount += length;
427 void R_TimeReport_Frame(void)
431 if (r_speeds_string[0])
433 if (r_timereport_active)
435 r_timereport_current = r_timereport_start;
436 R_TimeReport("total");
439 if (r_speeds_string[strlen(r_speeds_string)-1] == '\n')
440 r_speeds_string[strlen(r_speeds_string)-1] = 0;
442 for (i = 0;r_speeds_string[i];i++)
443 if (r_speeds_string[i] == '\n')
445 y = vid_conheight.integer - sb_lines - lines * 8;
447 DrawQ_Pic(0, y, NULL, vid_conwidth.integer, lines * 8, 0, 0, 0, 0.5, 0);
448 while (r_speeds_string[i])
451 while (r_speeds_string[i] && r_speeds_string[i] != '\n')
454 DrawQ_String(0, y, r_speeds_string + j, i - j, 8, 8, 1, 1, 1, 1, 0);
455 if (r_speeds_string[i] == '\n')
459 r_speeds_string[0] = 0;
460 r_timereport_active = false;
462 if (r_speeds.integer && cls.signon == SIGNONS && cls.state == ca_connected)
464 speedstringcount = 0;
465 r_speeds_string[0] = 0;
466 r_timereport_active = false;
467 sprintf(r_speeds_string + strlen(r_speeds_string), "org:'%+8.2f %+8.2f %+8.2f' dir:'%+2.3f %+2.3f %+2.3f'\n", r_vieworigin[0], r_vieworigin[1], r_vieworigin[2], r_viewforward[0], r_viewforward[1], r_viewforward[2]);
468 sprintf(r_speeds_string + strlen(r_speeds_string), "%5i entities%6i surfaces%6i triangles%5i leafs%5i portals%6i particles\n", renderstats.entities, renderstats.entities_surfaces, renderstats.entities_triangles, renderstats.world_leafs, renderstats.world_portals, renderstats.particles);
469 sprintf(r_speeds_string + strlen(r_speeds_string), "%4i lights%4i clears%4i scissored%7i light%7i shadow%7i dynamic\n", renderstats.lights, renderstats.lights_clears, renderstats.lights_scissored, renderstats.lights_lighttriangles, renderstats.lights_shadowtriangles, renderstats.lights_dynamicshadowtriangles);
470 if (renderstats.bloom)
471 sprintf(r_speeds_string + strlen(r_speeds_string), "rendered%6i meshes%8i triangles bloompixels%8i copied%8i drawn\n", renderstats.meshes, renderstats.meshes_elements / 3, renderstats.bloom_copypixels, renderstats.bloom_drawpixels);
473 sprintf(r_speeds_string + strlen(r_speeds_string), "rendered%6i meshes%8i triangles\n", renderstats.meshes, renderstats.meshes_elements / 3);
475 memset(&renderstats, 0, sizeof(renderstats));
477 if (r_speeds.integer >= 2)
479 r_timereport_active = true;
480 r_timereport_start = r_timereport_current = Sys_DoubleTime();
492 void SCR_SizeUp_f (void)
494 Cvar_SetValue ("viewsize",scr_viewsize.value+10);
505 void SCR_SizeDown_f (void)
507 Cvar_SetValue ("viewsize",scr_viewsize.value-10);
510 void CL_Screen_Init(void)
512 Cvar_RegisterVariable (&scr_fov);
513 Cvar_RegisterVariable (&scr_viewsize);
514 Cvar_RegisterVariable (&scr_conalpha);
515 Cvar_RegisterVariable (&scr_conbrightness);
516 Cvar_RegisterVariable (&scr_conforcewhiledisconnected);
517 Cvar_RegisterVariable (&scr_menuforcewhiledisconnected);
518 Cvar_RegisterVariable (&scr_showram);
519 Cvar_RegisterVariable (&scr_showturtle);
520 Cvar_RegisterVariable (&scr_showpause);
521 Cvar_RegisterVariable (&scr_showbrand);
522 Cvar_RegisterVariable (&scr_centertime);
523 Cvar_RegisterVariable (&scr_printspeed);
524 Cvar_RegisterVariable (&vid_conwidth);
525 Cvar_RegisterVariable (&vid_conheight);
526 Cvar_RegisterVariable (&vid_pixelheight);
527 Cvar_RegisterVariable (&scr_screenshot_jpeg);
528 Cvar_RegisterVariable (&scr_screenshot_jpeg_quality);
529 Cvar_RegisterVariable (&scr_screenshot_gammaboost);
530 Cvar_RegisterVariable (&cl_capturevideo);
531 Cvar_RegisterVariable (&cl_capturevideo_sound);
532 Cvar_RegisterVariable (&cl_capturevideo_fps);
533 Cvar_RegisterVariable (&cl_capturevideo_rawrgb);
534 Cvar_RegisterVariable (&cl_capturevideo_rawyv12);
535 Cvar_RegisterVariable (&r_letterbox);
536 Cvar_RegisterVariable(&r_stereo_separation);
537 Cvar_RegisterVariable(&r_stereo_sidebyside);
538 Cvar_RegisterVariable(&r_stereo_redblue);
539 Cvar_RegisterVariable(&r_stereo_redcyan);
540 Cvar_RegisterVariable(&r_stereo_redgreen);
541 Cvar_RegisterVariable(&scr_zoomwindow);
542 Cvar_RegisterVariable(&scr_zoomwindow_viewsizex);
543 Cvar_RegisterVariable(&scr_zoomwindow_viewsizey);
544 Cvar_RegisterVariable(&scr_zoomwindow_fov);
546 Cmd_AddCommand ("sizeup",SCR_SizeUp_f, "increase view size (increases viewsize cvar)");
547 Cmd_AddCommand ("sizedown",SCR_SizeDown_f, "decrease view size (decreases viewsize cvar)");
548 Cmd_AddCommand ("screenshot",SCR_ScreenShot_f, "takes a screenshot of the next rendered frame");
549 Cmd_AddCommand ("envmap", R_Envmap_f, "render a cubemap (skybox) of the current scene");
551 scr_initialized = true;
559 void SCR_ScreenShot_f (void)
561 static int shotnumber;
562 static char oldname[MAX_QPATH];
563 char base[MAX_QPATH];
564 char filename[MAX_QPATH];
565 unsigned char *buffer1;
566 unsigned char *buffer2;
567 unsigned char *buffer3;
568 qboolean jpeg = (scr_screenshot_jpeg.integer != 0);
570 sprintf (base, "screenshots/%s", scr_screenshot_name.string);
572 if (strcmp (oldname, scr_screenshot_name.string))
574 sprintf(oldname, "%s", scr_screenshot_name.string);
578 // find a file name to save it to
579 for (;shotnumber < 1000000;shotnumber++)
580 if (!FS_SysFileExists(va("%s/%s%06d.tga", fs_gamedir, base, shotnumber)) && !FS_SysFileExists(va("%s/%s%06d.jpg", fs_gamedir, base, shotnumber)))
582 if (shotnumber >= 1000000)
584 Con_Print("SCR_ScreenShot_f: Couldn't create the image file\n");
588 sprintf(filename, "%s%06d.%s", base, shotnumber, jpeg ? "jpg" : "tga");
590 buffer1 = (unsigned char *)Mem_Alloc(tempmempool, vid.width * vid.height * 3);
591 buffer2 = (unsigned char *)Mem_Alloc(tempmempool, vid.width * vid.height * 3);
592 buffer3 = (unsigned char *)Mem_Alloc(tempmempool, vid.width * vid.height * 3 + 18);
594 if (SCR_ScreenShot (filename, buffer1, buffer2, buffer3, 0, 0, vid.width, vid.height, false, false, false, jpeg, true))
595 Con_Printf("Wrote %s\n", filename);
597 Con_Printf("unable to write %s\n", filename);
606 void SCR_CaptureVideo_BeginVideo(void)
610 unsigned char out[44];
611 if (cls.capturevideo_active)
613 // soundrate is figured out on the first SoundFrame
614 cls.capturevideo_active = true;
615 cls.capturevideo_starttime = Sys_DoubleTime();
616 cls.capturevideo_framerate = bound(1, cl_capturevideo_fps.value, 1000);
617 cls.capturevideo_soundrate = 0;
618 cls.capturevideo_frame = 0;
619 cls.capturevideo_buffer = (unsigned char *)Mem_Alloc(tempmempool, vid.width * vid.height * (3+3+3) + 18);
620 gamma = 1.0/scr_screenshot_gammaboost.value;
623 for (i = 0;i < 256;i++)
625 unsigned char j = (unsigned char)bound(0, 255*pow(i/255.0, gamma), 255);
626 cls.capturevideo_rgbgammatable[0][i] = j;
627 cls.capturevideo_rgbgammatable[1][i] = j;
628 cls.capturevideo_rgbgammatable[2][i] = j;
632 R = Y + 1.4075 * (Cr - 128);
633 G = Y + -0.3455 * (Cb - 128) + -0.7169 * (Cr - 128);
634 B = Y + 1.7790 * (Cb - 128);
635 Y = R * .299 + G * .587 + B * .114;
636 Cb = R * -.169 + G * -.332 + B * .500 + 128.;
637 Cr = R * .500 + G * -.419 + B * -.0813 + 128.;
639 for (i = 0;i < 256;i++)
641 g = 255*pow(i/255.0, gamma);
642 // Y weights from RGB
643 cls.capturevideo_rgbtoyuvscaletable[0][0][i] = (short)(g * 0.299);
644 cls.capturevideo_rgbtoyuvscaletable[0][1][i] = (short)(g * 0.587);
645 cls.capturevideo_rgbtoyuvscaletable[0][2][i] = (short)(g * 0.114);
646 // Cb weights from RGB
647 cls.capturevideo_rgbtoyuvscaletable[1][0][i] = (short)(g * -0.169);
648 cls.capturevideo_rgbtoyuvscaletable[1][1][i] = (short)(g * -0.332);
649 cls.capturevideo_rgbtoyuvscaletable[1][2][i] = (short)(g * 0.500);
650 // Cr weights from RGB
651 cls.capturevideo_rgbtoyuvscaletable[2][0][i] = (short)(g * 0.500);
652 cls.capturevideo_rgbtoyuvscaletable[2][1][i] = (short)(g * -0.419);
653 cls.capturevideo_rgbtoyuvscaletable[2][2][i] = (short)(g * -0.0813);
654 // range reduction of YCbCr to valid signal range
655 cls.capturevideo_yuvnormalizetable[0][i] = 16 + i * (236-16) / 256;
656 cls.capturevideo_yuvnormalizetable[1][i] = 16 + i * (240-16) / 256;
657 cls.capturevideo_yuvnormalizetable[2][i] = 16 + i * (240-16) / 256;
660 if (cl_capturevideo_rawrgb.integer)
662 cls.capturevideo_format = CAPTUREVIDEOFORMAT_RAWRGB;
663 cls.capturevideo_videofile = FS_Open ("video/dpvideo.rgb", "wb", false, true);
665 else if (cl_capturevideo_rawyv12.integer)
667 cls.capturevideo_format = CAPTUREVIDEOFORMAT_RAWYV12;
668 cls.capturevideo_videofile = FS_Open ("video/dpvideo.yv12", "wb", false, true);
670 else if (scr_screenshot_jpeg.integer)
672 cls.capturevideo_format = CAPTUREVIDEOFORMAT_JPEG;
673 cls.capturevideo_videofile = NULL;
677 cls.capturevideo_format = CAPTUREVIDEOFORMAT_TARGA;
678 cls.capturevideo_videofile = NULL;
681 if (cl_capturevideo_sound.integer)
683 cls.capturevideo_soundfile = FS_Open ("video/dpvideo.wav", "wb", false, true);
684 // wave header will be filled out when video ends
686 FS_Write (cls.capturevideo_soundfile, out, 44);
689 cls.capturevideo_soundfile = NULL;
692 void SCR_CaptureVideo_EndVideo(void)
695 unsigned char out[44];
696 if (!cls.capturevideo_active)
698 cls.capturevideo_active = false;
700 if (cls.capturevideo_videofile)
702 FS_Close(cls.capturevideo_videofile);
703 cls.capturevideo_videofile = NULL;
706 // finish the wave file
707 if (cls.capturevideo_soundfile)
709 i = (int)FS_Tell (cls.capturevideo_soundfile);
710 //"RIFF", (int) unknown (chunk size), "WAVE",
711 //"fmt ", (int) 16 (chunk size), (short) format 1 (uncompressed PCM), (short) 2 channels, (int) unknown rate, (int) unknown bytes per second, (short) 4 bytes per sample (channels * bytes per channel), (short) 16 bits per channel
712 //"data", (int) unknown (chunk size)
713 memcpy (out, "RIFF****WAVEfmt \x10\x00\x00\x00\x01\x00\x02\x00********\x04\x00\x10\0data****", 44);
714 // the length of the whole RIFF chunk
717 out[5] = (n >> 8) & 0xFF;
718 out[6] = (n >> 16) & 0xFF;
719 out[7] = (n >> 24) & 0xFF;
721 n = cls.capturevideo_soundrate;
722 out[24] = (n) & 0xFF;
723 out[25] = (n >> 8) & 0xFF;
724 out[26] = (n >> 16) & 0xFF;
725 out[27] = (n >> 24) & 0xFF;
726 // bytes per second (rate * channels * bytes per channel)
727 n = cls.capturevideo_soundrate * 2 * 2;
728 out[28] = (n) & 0xFF;
729 out[29] = (n >> 8) & 0xFF;
730 out[30] = (n >> 16) & 0xFF;
731 out[31] = (n >> 24) & 0xFF;
732 // the length of the data chunk
734 out[40] = (n) & 0xFF;
735 out[41] = (n >> 8) & 0xFF;
736 out[42] = (n >> 16) & 0xFF;
737 out[43] = (n >> 24) & 0xFF;
738 FS_Seek (cls.capturevideo_soundfile, 0, SEEK_SET);
739 FS_Write (cls.capturevideo_soundfile, out, 44);
740 FS_Close (cls.capturevideo_soundfile);
741 cls.capturevideo_soundfile = NULL;
744 if (cls.capturevideo_buffer)
746 Mem_Free (cls.capturevideo_buffer);
747 cls.capturevideo_buffer = NULL;
750 cls.capturevideo_starttime = 0;
751 cls.capturevideo_framerate = 0;
752 cls.capturevideo_frame = 0;
755 qboolean SCR_CaptureVideo_VideoFrame(int newframenum)
757 int x = 0, y = 0, width = vid.width, height = vid.height;
758 unsigned char *b, *out;
760 int outoffset = (width/2)*(height/2);
762 //return SCR_ScreenShot(filename, cls.capturevideo_buffer, cls.capturevideo_buffer + vid.width * vid.height * 3, cls.capturevideo_buffer + vid.width * vid.height * 6, 0, 0, vid.width, vid.height, false, false, false, jpeg, true);
763 // speed is critical here, so do saving as directly as possible
764 switch (cls.capturevideo_format)
766 case CAPTUREVIDEOFORMAT_RAWYV12:
767 // FIXME: width/height must be multiple of 2, enforce this?
768 qglReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, cls.capturevideo_buffer);CHECKGLERROR
769 // process one line at a time, and CbCr every other line at 2 pixel intervals
770 for (y = 0;y < height;y++)
773 for (b = cls.capturevideo_buffer + (height-1-y)*width*3, out = cls.capturevideo_buffer + width*height*3 + y*width, x = 0;x < width;x++, b += 3, out++)
774 *out = cls.capturevideo_yuvnormalizetable[0][cls.capturevideo_rgbtoyuvscaletable[0][0][b[0]] + cls.capturevideo_rgbtoyuvscaletable[0][1][b[1]] + cls.capturevideo_rgbtoyuvscaletable[0][2][b[2]]];
777 // 2x2 Cb and Cr planes
779 // low quality, no averaging
780 for (b = cls.capturevideo_buffer + (height-2-y)*width*3, out = cls.capturevideo_buffer + width*height*3 + width*height + (y/2)*(width/2), x = 0;x < width/2;x++, b += 6, out++)
783 out[0 ] = cls.capturevideo_yuvnormalizetable[2][cls.capturevideo_rgbtoyuvscaletable[2][0][b[0]] + cls.capturevideo_rgbtoyuvscaletable[2][1][b[1]] + cls.capturevideo_rgbtoyuvscaletable[2][2][b[2]] + 128];
785 out[outoffset] = cls.capturevideo_yuvnormalizetable[1][cls.capturevideo_rgbtoyuvscaletable[1][0][b[0]] + cls.capturevideo_rgbtoyuvscaletable[1][1][b[1]] + cls.capturevideo_rgbtoyuvscaletable[1][2][b[2]] + 128];
788 // high quality, averaging
789 int inpitch = width*3;
790 for (b = cls.capturevideo_buffer + (height-2-y)*width*3, out = cls.capturevideo_buffer + width*height*3 + width*height + (y/2)*(width/2), x = 0;x < width/2;x++, b += 6, out++)
792 int blockr, blockg, blockb;
793 blockr = (b[0] + b[3] + b[inpitch+0] + b[inpitch+3]) >> 2;
794 blockg = (b[1] + b[4] + b[inpitch+1] + b[inpitch+4]) >> 2;
795 blockb = (b[2] + b[5] + b[inpitch+2] + b[inpitch+5]) >> 2;
797 out[0 ] = cls.capturevideo_yuvnormalizetable[2][cls.capturevideo_rgbtoyuvscaletable[2][0][blockr] + cls.capturevideo_rgbtoyuvscaletable[2][1][blockg] + cls.capturevideo_rgbtoyuvscaletable[2][2][blockb] + 128];
799 out[outoffset] = cls.capturevideo_yuvnormalizetable[1][cls.capturevideo_rgbtoyuvscaletable[1][0][blockr] + cls.capturevideo_rgbtoyuvscaletable[1][1][blockg] + cls.capturevideo_rgbtoyuvscaletable[1][2][blockb] + 128];
804 for (;cls.capturevideo_frame < newframenum;cls.capturevideo_frame++)
805 if (!FS_Write (cls.capturevideo_videofile, cls.capturevideo_buffer + width*height*3, width*height+(width/2)*(height/2)*2))
808 case CAPTUREVIDEOFORMAT_RAWRGB:
809 qglReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, cls.capturevideo_buffer);CHECKGLERROR
810 for (;cls.capturevideo_frame < newframenum;cls.capturevideo_frame++)
811 if (!FS_Write (cls.capturevideo_videofile, cls.capturevideo_buffer, width*height*3))
814 case CAPTUREVIDEOFORMAT_JPEG:
815 qglReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, cls.capturevideo_buffer);CHECKGLERROR
816 for (;cls.capturevideo_frame < newframenum;cls.capturevideo_frame++)
818 sprintf(filename, "video/dp%06d.jpg", cls.capturevideo_frame);
819 if (!JPEG_SaveImage_preflipped (filename, width, height, cls.capturevideo_buffer))
823 case CAPTUREVIDEOFORMAT_TARGA:
824 //return Image_WriteTGARGB_preflipped (filename, width, height, cls.capturevideo_buffer, cls.capturevideo_buffer + vid.width * vid.height * 3, );
825 memset (cls.capturevideo_buffer, 0, 18);
826 cls.capturevideo_buffer[2] = 2; // uncompressed type
827 cls.capturevideo_buffer[12] = (width >> 0) & 0xFF;
828 cls.capturevideo_buffer[13] = (width >> 8) & 0xFF;
829 cls.capturevideo_buffer[14] = (height >> 0) & 0xFF;
830 cls.capturevideo_buffer[15] = (height >> 8) & 0xFF;
831 cls.capturevideo_buffer[16] = 24; // pixel size
832 qglReadPixels (x, y, width, height, GL_BGR, GL_UNSIGNED_BYTE, cls.capturevideo_buffer + 18);CHECKGLERROR
833 for (;cls.capturevideo_frame < newframenum;cls.capturevideo_frame++)
835 sprintf(filename, "video/dp%06d.tga", cls.capturevideo_frame);
836 if (!FS_WriteFile (filename, cls.capturevideo_buffer, width*height*3 + 18))
845 void SCR_CaptureVideo_SoundFrame(unsigned char *bufstereo16le, size_t length, int rate)
847 if (!cls.capturevideo_soundfile)
849 cls.capturevideo_soundrate = rate;
850 if (FS_Write (cls.capturevideo_soundfile, bufstereo16le, 4 * length) < (fs_offset_t)(4 * length))
852 Cvar_SetValueQuick(&cl_capturevideo, 0);
853 Con_Printf("video sound saving failed on frame %i, out of disk space? stopping video capture.\n", cls.capturevideo_frame);
854 SCR_CaptureVideo_EndVideo();
858 void SCR_CaptureVideo(void)
861 if (cl_capturevideo.integer && r_render.integer)
863 if (!cls.capturevideo_active)
864 SCR_CaptureVideo_BeginVideo();
865 if (cls.capturevideo_framerate != cl_capturevideo_fps.value)
867 Con_Printf("You can not change the video framerate while recording a video.\n");
868 Cvar_SetValueQuick(&cl_capturevideo_fps, cls.capturevideo_framerate);
870 if (cls.capturevideo_soundfile)
872 // preserve sound sync by duplicating frames when running slow
873 newframenum = (int)((Sys_DoubleTime() - cls.capturevideo_starttime) * cls.capturevideo_framerate);
876 newframenum = cls.capturevideo_frame + 1;
877 // if falling behind more than one second, stop
878 if (newframenum - cls.capturevideo_frame > (int)ceil(cls.capturevideo_framerate))
880 Cvar_SetValueQuick(&cl_capturevideo, 0);
881 Con_Printf("video saving failed on frame %i, your machine is too slow for this capture speed.\n", cls.capturevideo_frame);
882 SCR_CaptureVideo_EndVideo();
886 if (!SCR_CaptureVideo_VideoFrame(newframenum))
888 Cvar_SetValueQuick(&cl_capturevideo, 0);
889 Con_Printf("video saving failed on frame %i, out of disk space? stopping video capture.\n", cls.capturevideo_frame);
890 SCR_CaptureVideo_EndVideo();
893 else if (cls.capturevideo_active)
894 SCR_CaptureVideo_EndVideo();
901 Grab six views for environment mapping tests
908 qboolean flipx, flipy, flipdiagonaly;
912 {{ 0, 0, 0}, "rt", false, false, false},
913 {{ 0, 270, 0}, "ft", false, false, false},
914 {{ 0, 180, 0}, "lf", false, false, false},
915 {{ 0, 90, 0}, "bk", false, false, false},
916 {{-90, 180, 0}, "up", true, true, false},
917 {{ 90, 180, 0}, "dn", true, true, false},
919 {{ 0, 0, 0}, "px", true, true, true},
920 {{ 0, 90, 0}, "py", false, true, false},
921 {{ 0, 180, 0}, "nx", false, false, true},
922 {{ 0, 270, 0}, "ny", true, false, false},
923 {{-90, 180, 0}, "pz", false, false, true},
924 {{ 90, 180, 0}, "nz", false, false, true}
927 static void R_Envmap_f (void)
930 char filename[MAX_QPATH], basename[MAX_QPATH];
931 unsigned char *buffer1;
932 unsigned char *buffer2;
933 unsigned char *buffer3;
937 Con_Print("envmap <basename> <size>: save out 6 cubic environment map images, usable with loadsky, note that size must one of 128, 256, 512, or 1024 and can't be bigger than your current resolution\n");
941 strlcpy (basename, Cmd_Argv(1), sizeof (basename));
942 size = atoi(Cmd_Argv(2));
943 if (size != 128 && size != 256 && size != 512 && size != 1024)
945 Con_Print("envmap: size must be one of 128, 256, 512, or 1024\n");
948 if (size > vid.width || size > vid.height)
950 Con_Print("envmap: your resolution is not big enough to render that size\n");
958 r_refdef.width = size;
959 r_refdef.height = size;
961 r_refdef.frustum_x = tan(90 * M_PI / 360.0);
962 r_refdef.frustum_y = tan(90 * M_PI / 360.0);
964 buffer1 = (unsigned char *)Mem_Alloc(tempmempool, size * size * 3);
965 buffer2 = (unsigned char *)Mem_Alloc(tempmempool, size * size * 3);
966 buffer3 = (unsigned char *)Mem_Alloc(tempmempool, size * size * 3 + 18);
968 for (j = 0;j < 12;j++)
970 sprintf(filename, "env/%s%s.tga", basename, envmapinfo[j].name);
971 Matrix4x4_CreateFromQuakeEntity(&r_refdef.viewentitymatrix, r_vieworigin[0], r_vieworigin[1], r_vieworigin[2], envmapinfo[j].angles[0], envmapinfo[j].angles[1], envmapinfo[j].angles[2], 1);
976 SCR_ScreenShot(filename, buffer1, buffer2, buffer3, 0, vid.height - (r_refdef.y + r_refdef.height), size, size, envmapinfo[j].flipx, envmapinfo[j].flipy, envmapinfo[j].flipdiagonaly, false, false);
986 //=============================================================================
988 // LordHavoc: SHOWLMP stuff
989 #define SHOWLMP_MAXLABELS 256
990 typedef struct showlmp_s
1000 showlmp_t showlmp[SHOWLMP_MAXLABELS];
1002 void SHOWLMP_decodehide(void)
1006 lmplabel = MSG_ReadString();
1007 for (i = 0;i < SHOWLMP_MAXLABELS;i++)
1008 if (showlmp[i].isactive && strcmp(showlmp[i].label, lmplabel) == 0)
1010 showlmp[i].isactive = false;
1015 void SHOWLMP_decodeshow(void)
1018 char lmplabel[256], picname[256];
1020 strlcpy (lmplabel,MSG_ReadString(), sizeof (lmplabel));
1021 strlcpy (picname, MSG_ReadString(), sizeof (picname));
1022 if (gamemode == GAME_NEHAHRA) // LordHavoc: nasty old legacy junk
1029 x = MSG_ReadShort();
1030 y = MSG_ReadShort();
1033 for (i = 0;i < SHOWLMP_MAXLABELS;i++)
1034 if (showlmp[i].isactive)
1036 if (strcmp(showlmp[i].label, lmplabel) == 0)
1039 break; // drop out to replace it
1042 else if (k < 0) // find first empty one to replace
1045 return; // none found to replace
1046 // change existing one
1047 showlmp[k].isactive = true;
1048 strlcpy (showlmp[k].label, lmplabel, sizeof (showlmp[k].label));
1049 strlcpy (showlmp[k].pic, picname, sizeof (showlmp[k].pic));
1054 void SHOWLMP_drawall(void)
1057 for (i = 0;i < SHOWLMP_MAXLABELS;i++)
1058 if (showlmp[i].isactive)
1059 DrawQ_Pic(showlmp[i].x, showlmp[i].y, Draw_CachePic(showlmp[i].pic, true), 0, 0, 1, 1, 1, 1, 0);
1062 void SHOWLMP_clear(void)
1065 for (i = 0;i < SHOWLMP_MAXLABELS;i++)
1066 showlmp[i].isactive = false;
1070 ==============================================================================
1074 ==============================================================================
1077 qboolean SCR_ScreenShot(char *filename, unsigned char *buffer1, unsigned char *buffer2, unsigned char *buffer3, int x, int y, int width, int height, qboolean flipx, qboolean flipy, qboolean flipdiagonal, qboolean jpeg, qboolean gammacorrect)
1079 int indices[3] = {0,1,2};
1082 if (!r_render.integer)
1086 qglReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer1);CHECKGLERROR
1088 if (scr_screenshot_gammaboost.value != 1 && gammacorrect)
1091 double igamma = 1.0 / scr_screenshot_gammaboost.value;
1092 unsigned char ramp[256];
1093 for (i = 0;i < 256;i++)
1094 ramp[i] = (unsigned char) (pow(i * (1.0 / 255.0), igamma) * 255.0);
1095 for (i = 0;i < width*height*3;i++)
1096 buffer1[i] = ramp[buffer1[i]];
1099 Image_CopyMux (buffer2, buffer1, width, height, flipx, flipy, flipdiagonal, 3, 3, indices);
1102 ret = JPEG_SaveImage_preflipped (filename, width, height, buffer2);
1104 ret = Image_WriteTGARGB_preflipped (filename, width, height, buffer2, buffer3);
1109 //=============================================================================
1111 void R_ClearScreen(void)
1113 if (r_render.integer)
1119 qglClearColor(fogcolor[0],fogcolor[1],fogcolor[2],0);CHECKGLERROR
1123 qglClearColor(0,0,0,0);CHECKGLERROR
1125 qglClearDepth(1);CHECKGLERROR
1128 // LordHavoc: we use a stencil centered around 128 instead of 0,
1129 // to avoid clamping interfering with strange shadow volume
1131 qglClearStencil(128);CHECKGLERROR
1134 GL_Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | (gl_stencil ? GL_STENCIL_BUFFER_BIT : 0));
1135 // set dithering mode
1136 if (gl_dither.integer)
1138 qglEnable(GL_DITHER);CHECKGLERROR
1142 qglDisable(GL_DITHER);CHECKGLERROR
1147 qboolean CL_VM_UpdateView (void);
1148 void SCR_DrawConsole (void);
1149 void R_Shadow_EditLights_DrawSelectedLightProperties(void);
1153 void SCR_DrawScreen (void)
1157 if (r_timereport_active)
1158 R_TimeReport("setup");
1160 if (cls.signon == SIGNONS)
1164 size = scr_viewsize.value * (1.0 / 100.0);
1165 size = min(size, 1);
1167 if (r_stereo_sidebyside.integer)
1169 r_refdef.width = (int)(vid.width * size / 2.5);
1170 r_refdef.height = (int)(vid.height * size / 2.5 * (1 - bound(0, r_letterbox.value, 100) / 100));
1171 r_refdef.x = (int)((vid.width - r_refdef.width * 2.5) * 0.5);
1172 r_refdef.y = (int)((vid.height - r_refdef.height)/2);
1174 r_refdef.x += (int)(r_refdef.width * 1.5);
1178 r_refdef.width = (int)(vid.width * size);
1179 r_refdef.height = (int)(vid.height * size * (1 - bound(0, r_letterbox.value, 100) / 100));
1180 r_refdef.x = (int)((vid.width - r_refdef.width)/2);
1181 r_refdef.y = (int)((vid.height - r_refdef.height)/2);
1184 // LordHavoc: viewzoom (zoom in for sniper rifles, etc)
1185 // LordHavoc: this is designed to produce widescreen fov values
1186 // when the screen is wider than 4/3 width/height aspect, to do
1187 // this it simply assumes the requested fov is the vertical fov
1188 // for a 4x3 display, if the ratio is not 4x3 this makes the fov
1189 // higher/lower according to the ratio
1190 r_refdef.frustum_y = tan(scr_fov.value * cl.viewzoom * M_PI / 360.0) * (3.0/4.0);
1191 r_refdef.frustum_x = r_refdef.frustum_y * (float)r_refdef.width / (float)r_refdef.height / vid_pixelheight.value;
1193 r_refdef.frustum_x *= r_refdef.frustumscale_x;
1194 r_refdef.frustum_y *= r_refdef.frustumscale_y;
1196 if(!CL_VM_UpdateView())
1201 if (scr_zoomwindow.integer)
1203 float sizex = bound(10, scr_zoomwindow_viewsizex.value, 100) / 100.0;
1204 float sizey = bound(10, scr_zoomwindow_viewsizey.value, 100) / 100.0;
1205 r_refdef.width = (int)(vid.width * sizex);
1206 r_refdef.height = (int)(vid.height * sizey);
1207 r_refdef.x = (int)((vid.width - r_refdef.width)/2);
1210 r_refdef.frustum_y = tan(scr_zoomwindow_fov.value * cl.viewzoom * M_PI / 360.0) * (3.0/4.0);
1211 r_refdef.frustum_x = r_refdef.frustum_y * vid_pixelheight.value * (float)r_refdef.width / (float)r_refdef.height;
1213 r_refdef.frustum_x *= r_refdef.frustumscale_x;
1214 r_refdef.frustum_y *= r_refdef.frustumscale_y;
1216 if(!CL_VM_UpdateView())
1221 if (!r_stereo_sidebyside.integer)
1223 r_refdef.width = vid.width;
1224 r_refdef.height = vid.height;
1232 //FIXME: force menu if nothing else to look at?
1233 //if (key_dest == key_game && cls.signon != SIGNONS && cls.state == ca_disconnected)
1235 if (cls.signon == SIGNONS)
1240 if (!r_letterbox.value)
1243 SCR_CheckDrawCenterString();
1247 R_Shadow_EditLights_DrawSelectedLightProperties();
1256 if (r_timereport_active)
1259 if (cls.signon == SIGNONS)
1260 R_TimeReport_Frame();
1268 if (r_timereport_active)
1269 R_TimeReport("meshfinish");
1272 void SCR_UpdateLoadingScreen (void)
1277 float texcoord2f[8];
1278 // don't do anything if not initialized yet
1282 qglViewport(0, 0, vid.width, vid.height);CHECKGLERROR
1283 //qglDisable(GL_SCISSOR_TEST);CHECKGLERROR
1284 //qglDepthMask(1);CHECKGLERROR
1285 qglColorMask(1,1,1,1);CHECKGLERROR
1286 //qglClearColor(0,0,0,0);CHECKGLERROR
1287 //qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1288 //qglCullFace(GL_FRONT);CHECKGLERROR
1289 //qglDisable(GL_CULL_FACE);CHECKGLERROR
1292 GL_SetupView_Mode_Ortho(0, 0, vid_conwidth.integer, vid_conheight.integer, -10, 100);
1294 R_Mesh_Matrix(&identitymatrix);
1295 // draw the loading plaque
1296 pic = Draw_CachePic("gfx/loading", true);
1297 x = (vid_conwidth.integer - pic->width)/2;
1298 y = (vid_conheight.integer - pic->height)/2;
1300 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1301 GL_DepthTest(false);
1302 R_Mesh_VertexPointer(vertex3f);
1303 R_Mesh_ColorPointer(NULL);
1304 R_Mesh_ResetTextureState();
1305 R_Mesh_TexBind(0, R_GetTexture(pic->tex));
1306 R_Mesh_TexCoordPointer(0, 2, texcoord2f);
1307 vertex3f[2] = vertex3f[5] = vertex3f[8] = vertex3f[11] = 0;
1308 vertex3f[0] = vertex3f[9] = x;
1309 vertex3f[1] = vertex3f[4] = y;
1310 vertex3f[3] = vertex3f[6] = x + pic->width;
1311 vertex3f[7] = vertex3f[10] = y + pic->height;
1312 texcoord2f[0] = 0;texcoord2f[1] = 0;
1313 texcoord2f[2] = 1;texcoord2f[3] = 0;
1314 texcoord2f[4] = 1;texcoord2f[5] = 1;
1315 texcoord2f[6] = 0;texcoord2f[7] = 1;
1316 R_Mesh_Draw(0, 4, 2, polygonelements);
1322 void CL_UpdateScreen(void)
1324 float conwidth, conheight;
1329 if (!scr_initialized || !con_initialized || vid_hidden)
1330 return; // not initialized yet
1332 // don't allow cheats in multiplayer
1333 if (!cl.islocalgame && cl.worldmodel)
1335 if (r_fullbright.integer != 0)
1336 Cvar_Set ("r_fullbright", "0");
1337 if (r_ambient.value != 0)
1338 Cvar_Set ("r_ambient", "0");
1341 conwidth = bound(320, vid_conwidth.value, 2048);
1342 conheight = bound(200, vid_conheight.value, 1536);
1343 if (vid_conwidth.value != conwidth)
1344 Cvar_SetValue("vid_conwidth", conwidth);
1345 if (vid_conheight.value != conheight)
1346 Cvar_SetValue("vid_conheight", conheight);
1349 if (scr_viewsize.value < 30)
1350 Cvar_Set ("viewsize","30");
1351 if (scr_viewsize.value > 120)
1352 Cvar_Set ("viewsize","120");
1354 // bound field of view
1355 if (scr_fov.value < 1)
1356 Cvar_Set ("fov","1");
1357 if (scr_fov.value > 170)
1358 Cvar_Set ("fov","170");
1360 // validate r_textureunits cvar
1361 if (r_textureunits.integer > gl_textureunits)
1362 Cvar_SetValueQuick(&r_textureunits, gl_textureunits);
1363 if (r_textureunits.integer < 1)
1364 Cvar_SetValueQuick(&r_textureunits, 1);
1366 // validate gl_combine cvar
1367 if (gl_combine.integer && !gl_combine_extension)
1368 Cvar_SetValueQuick(&gl_combine, 0);
1370 // intermission is always full screen
1371 if (cl.intermission)
1375 if (scr_viewsize.value >= 120)
1376 sb_lines = 0; // no status bar at all
1377 else if (scr_viewsize.value >= 110)
1378 sb_lines = 24; // no inventory
1383 r_refdef.colormask[0] = 1;
1384 r_refdef.colormask[1] = 1;
1385 r_refdef.colormask[2] = 1;
1387 if (r_timereport_active)
1388 R_TimeReport("other");
1390 SCR_SetUpToDrawConsole();
1392 if (r_timereport_active)
1393 R_TimeReport("start");
1396 qglViewport(0, 0, vid.width, vid.height);CHECKGLERROR
1397 qglDisable(GL_SCISSOR_TEST);CHECKGLERROR
1398 qglDepthMask(1);CHECKGLERROR
1399 qglColorMask(1,1,1,1);CHECKGLERROR
1400 qglClearColor(0,0,0,0);CHECKGLERROR
1401 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1403 if (r_timereport_active)
1404 R_TimeReport("clear");
1406 if (r_stereo_redblue.integer || r_stereo_redgreen.integer || r_stereo_redcyan.integer || r_stereo_sidebyside.integer)
1408 matrix4x4_t originalmatrix = r_refdef.viewentitymatrix;
1409 r_refdef.viewentitymatrix.m[0][3] = originalmatrix.m[0][3] + r_stereo_separation.value * -0.5f * r_refdef.viewentitymatrix.m[0][1];
1410 r_refdef.viewentitymatrix.m[1][3] = originalmatrix.m[1][3] + r_stereo_separation.value * -0.5f * r_refdef.viewentitymatrix.m[1][1];
1411 r_refdef.viewentitymatrix.m[2][3] = originalmatrix.m[2][3] + r_stereo_separation.value * -0.5f * r_refdef.viewentitymatrix.m[2][1];
1413 if (r_stereo_sidebyside.integer)
1416 if (r_stereo_redblue.integer || r_stereo_redgreen.integer || r_stereo_redcyan.integer)
1418 r_refdef.colormask[0] = 1;
1419 r_refdef.colormask[1] = 0;
1420 r_refdef.colormask[2] = 0;
1425 r_refdef.viewentitymatrix.m[0][3] = originalmatrix.m[0][3] + r_stereo_separation.value * 0.5f * r_refdef.viewentitymatrix.m[0][1];
1426 r_refdef.viewentitymatrix.m[1][3] = originalmatrix.m[1][3] + r_stereo_separation.value * 0.5f * r_refdef.viewentitymatrix.m[1][1];
1427 r_refdef.viewentitymatrix.m[2][3] = originalmatrix.m[2][3] + r_stereo_separation.value * 0.5f * r_refdef.viewentitymatrix.m[2][1];
1429 if (r_stereo_sidebyside.integer)
1432 if (r_stereo_redblue.integer || r_stereo_redgreen.integer || r_stereo_redcyan.integer)
1434 r_refdef.colormask[0] = 0;
1435 r_refdef.colormask[1] = r_stereo_redcyan.integer || r_stereo_redgreen.integer;
1436 r_refdef.colormask[2] = r_stereo_redcyan.integer || r_stereo_redblue.integer;
1441 r_refdef.viewentitymatrix = originalmatrix;
1449 if (r_timereport_active)
1450 R_TimeReport("finish");
1453 void CL_Screen_NewMap(void)