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_conspeed = {CVAR_SAVE, "scr_conspeed","900", "speed of console open/close"}; // LordHavoc: quake used 300
12 cvar_t scr_conalpha = {CVAR_SAVE, "scr_conalpha", "1", "opacity of console background"};
13 cvar_t scr_conbrightness = {CVAR_SAVE, "scr_conbrightness", "0.2", "brightness of console background (0 = black, 1 = image)"};
14 cvar_t scr_conforcewhiledisconnected = {0, "scr_conforcewhiledisconnected", "1", "forces fullscreen console while disconnected"};
15 cvar_t scr_menuforcewhiledisconnected = {0, "scr_menuforcewhiledisconnected", "0", "forces menu while disconnected"};
16 cvar_t scr_centertime = {0, "scr_centertime","2", "how long centerprint messages show"};
17 cvar_t scr_showram = {CVAR_SAVE, "showram","1", "show ram icon if low on surface cache memory (not used)"};
18 cvar_t scr_showturtle = {CVAR_SAVE, "showturtle","0", "show turtle icon when framerate is too low (not used)"};
19 cvar_t scr_showpause = {CVAR_SAVE, "showpause","1", "show pause icon when game is paused"};
20 cvar_t scr_showbrand = {0, "showbrand","0", "shows gfx/brand.tga in a corner of the screen (different values select different positions, including centered)"};
21 cvar_t scr_printspeed = {0, "scr_printspeed","8", "speed of intermission printing (episode end texts)"};
22 cvar_t vid_conwidth = {CVAR_SAVE, "vid_conwidth", "640", "virtual width of 2D graphics system"};
23 cvar_t vid_conheight = {CVAR_SAVE, "vid_conheight", "480", "virtual height of 2D graphics system"};
24 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)"};
25 cvar_t scr_screenshot_jpeg = {CVAR_SAVE, "scr_screenshot_jpeg","1", "save jpeg instead of targa"};
26 cvar_t scr_screenshot_jpeg_quality = {CVAR_SAVE, "scr_screenshot_jpeg_quality","0.9", "image quality of saved jpeg"};
27 cvar_t scr_screenshot_gamma = {CVAR_SAVE, "scr_screenshot_gamma","2.2", "gamma correction on saved screenshots and videos, 1.0 saves unmodified images"};
28 // scr_screenshot_name is defined in fs.c
29 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_gamma affects the brightness of the output)"};
30 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)"};
31 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)"};
32 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)"};
33 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)"};
34 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)"};
35 cvar_t r_stereo_separation = {0, "r_stereo_separation", "4", "separation of eyes in the world (try negative values too)"};
36 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)"};
37 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)"};
38 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"};
39 cvar_t r_stereo_redgreen = {0, "r_stereo_redgreen", "0", "red/green anaglyph stereo glasses (for those who don't mind yellow)"};
40 cvar_t scr_zoomwindow = {CVAR_SAVE, "scr_zoomwindow", "0", "displays a zoomed in overlay window"};
41 cvar_t scr_zoomwindow_viewsizex = {CVAR_SAVE, "scr_zoomwindow_viewsizex", "20", "horizontal viewsize of zoom window"};
42 cvar_t scr_zoomwindow_viewsizey = {CVAR_SAVE, "scr_zoomwindow_viewsizey", "20", "vertical viewsize of zoom window"};
43 cvar_t scr_zoomwindow_fov = {CVAR_SAVE, "scr_zoomwindow_fov", "20", "fov of zoom window"};
46 int jpeg_supported = false;
48 qboolean scr_initialized; // ready to draw
50 float scr_con_current;
52 extern int con_vislines;
54 void DrawCrosshair(int num);
55 static void SCR_ScreenShot_f (void);
56 static void R_Envmap_f (void);
59 void R_ClearScreen(void);
62 ===============================================================================
66 ===============================================================================
69 char scr_centerstring[MAX_INPUTLINE];
70 float scr_centertime_start; // for slow victory printing
71 float scr_centertime_off;
80 Called for important messages that should stay in the center of the screen
84 void SCR_CenterPrint(char *str)
86 strlcpy (scr_centerstring, str, sizeof (scr_centerstring));
87 scr_centertime_off = scr_centertime.value;
88 scr_centertime_start = cl.time;
90 // count the number of lines for centering
101 void SCR_DrawCenterString (void)
109 // the finale prints the characters one at a time
111 remaining = scr_printspeed.value * (cl.time - scr_centertime_start);
115 scr_erase_center = 0;
116 start = scr_centerstring;
121 if (scr_center_lines <= 4)
122 y = vid_conheight.integer*0.35;
129 // scan the width of the line
130 for (l=0 ; l<vid_conwidth.integer/8 ; l++)
131 if (start[l] == '\n' || !start[l])
133 x = (vid_conwidth.integer - l*8)/2;
138 DrawQ_ColoredString(x, y, start, l, 8, 8, 1, 1, 1, 1, 0, &color);
146 while (*start && *start != '\n')
151 start++; // skip the \n
155 void SCR_CheckDrawCenterString (void)
157 if (scr_center_lines > scr_erase_lines)
158 scr_erase_lines = scr_center_lines;
160 scr_centertime_off -= host_frametime;
162 // don't draw if this is a normal stats-screen intermission,
163 // only if it is not an intermission, or a finale intermission
164 if (cl.intermission == 1)
166 if (scr_centertime_off <= 0 && !cl.intermission)
168 if (key_dest != key_game)
171 SCR_DrawCenterString ();
179 void SCR_DrawTurtle (void)
183 if (cls.state != ca_connected)
186 if (!scr_showturtle.integer)
189 if (host_frametime < 0.1)
199 DrawQ_Pic (0, 0, Draw_CachePic("gfx/turtle", true), 0, 0, 1, 1, 1, 1, 0);
207 void SCR_DrawNet (void)
209 if (cls.state != ca_connected)
211 if (realtime - cl.last_received_message < 0.3)
213 if (cls.demoplayback)
216 DrawQ_Pic (64, 0, Draw_CachePic("gfx/net", true), 0, 0, 1, 1, 1, 1, 0);
224 void SCR_DrawPause (void)
228 if (cls.state != ca_connected)
231 if (!scr_showpause.integer) // turn off for screenshots
237 pic = Draw_CachePic ("gfx/pause", true);
238 DrawQ_Pic ((vid_conwidth.integer - pic->width)/2, (vid_conheight.integer - pic->height)/2, pic, 0, 0, 1, 1, 1, 1, 0);
246 void SCR_DrawBrand (void)
251 if (!scr_showbrand.value)
254 pic = Draw_CachePic ("gfx/brand", true);
256 switch ((int)scr_showbrand.value)
258 case 1: // bottom left
260 y = vid_conheight.integer - pic->height;
262 case 2: // bottom centre
263 x = (vid_conwidth.integer - pic->width) / 2;
264 y = vid_conheight.integer - pic->height;
266 case 3: // bottom right
267 x = vid_conwidth.integer - pic->width;
268 y = vid_conheight.integer - pic->height;
270 case 4: // centre right
271 x = vid_conwidth.integer - pic->width;
272 y = (vid_conheight.integer - pic->height) / 2;
275 x = vid_conwidth.integer - pic->width;
278 case 6: // top centre
279 x = (vid_conwidth.integer - pic->width) / 2;
286 case 8: // centre left
288 y = (vid_conheight.integer - pic->height) / 2;
294 DrawQ_Pic (x, y, pic, 0, 0, 1, 1, 1, 1, 0);
302 static void SCR_DrawDownload(void)
308 if (!cls.qw_downloadname[0])
310 dpsnprintf(temp, sizeof(temp), "Downloading %s ... %3i%%\n", cls.qw_downloadname, cls.qw_downloadpercent);
311 len = (int)strlen(temp);
312 x = (vid_conwidth.integer - len*size) / 2;
313 y = vid_conheight.integer - size;
314 DrawQ_Pic(0, y, NULL, vid_conwidth.integer, size, 0, 0, 0, 0.5, 0);
315 DrawQ_String(x, y, temp, len, size, size, 1, 1, 1, 1, 0);
318 //=============================================================================
323 SCR_SetUpToDrawConsole
326 void SCR_SetUpToDrawConsole (void)
328 // lines of console to display
330 static int framecounter = 0;
334 if (scr_menuforcewhiledisconnected.integer && key_dest == key_game && cls.state == ca_disconnected)
336 if (framecounter >= 2)
344 if (scr_conforcewhiledisconnected.integer && key_dest == key_game && cls.signon != SIGNONS)
345 key_consoleactive |= KEY_CONSOLEACTIVE_FORCED;
347 key_consoleactive &= ~KEY_CONSOLEACTIVE_FORCED;
349 // decide on the height of the console
350 if (key_consoleactive & KEY_CONSOLEACTIVE_USER)
351 conlines = vid_conheight.integer/2; // half screen
353 conlines = 0; // none visible
355 if (scr_conspeed.value)
357 if (scr_con_current > conlines)
359 scr_con_current -= scr_conspeed.value*host_realframetime;
360 if (scr_con_current < conlines)
361 scr_con_current = conlines;
364 else if (scr_con_current < conlines)
366 scr_con_current += scr_conspeed.value*host_realframetime;
367 if (scr_con_current > conlines)
368 scr_con_current = conlines;
372 scr_con_current = conlines;
380 void SCR_DrawConsole (void)
382 if (key_consoleactive & KEY_CONSOLEACTIVE_FORCED)
385 Con_DrawConsole (vid_conheight.integer);
387 else if (scr_con_current)
388 Con_DrawConsole (scr_con_current);
392 if (key_dest == key_game || key_dest == key_message)
393 Con_DrawNotify (); // only draw notify in game
399 SCR_BeginLoadingPlaque
403 void SCR_BeginLoadingPlaque (void)
405 // save console log up to this point to log_file if it was set by configs
410 SCR_UpdateLoadingScreen();
413 //=============================================================================
415 char r_speeds_string[1024];
416 int speedstringcount, r_timereport_active;
417 double r_timereport_temp = 0, r_timereport_current = 0, r_timereport_start = 0;
419 void R_TimeReport(char *desc)
425 if (r_speeds.integer < 2 || !r_timereport_active)
429 r_timereport_temp = r_timereport_current;
430 r_timereport_current = Sys_DoubleTime();
431 t = (int) ((r_timereport_current - r_timereport_temp) * 1000000.0 + 0.5);
433 dpsnprintf(tempbuf, sizeof(tempbuf), "%8i %-11s", t, desc);
434 length = (int)strlen(tempbuf);
435 if (speedstringcount + length > (vid_conwidth.integer / 8))
437 strlcat(r_speeds_string, "\n", sizeof(r_speeds_string));
438 speedstringcount = 0;
440 strlcat(r_speeds_string, tempbuf, sizeof(r_speeds_string));
441 speedstringcount += length;
444 void R_TimeReport_Frame(void)
448 if (r_speeds_string[0])
450 if (r_timereport_active)
452 r_timereport_current = r_timereport_start;
453 R_TimeReport("total");
456 if (r_speeds_string[strlen(r_speeds_string)-1] == '\n')
457 r_speeds_string[strlen(r_speeds_string)-1] = 0;
459 for (i = 0;r_speeds_string[i];i++)
460 if (r_speeds_string[i] == '\n')
462 y = vid_conheight.integer - sb_lines - lines * 8;
464 DrawQ_Pic(0, y, NULL, vid_conwidth.integer, lines * 8, 0, 0, 0, 0.5, 0);
465 while (r_speeds_string[i])
468 while (r_speeds_string[i] && r_speeds_string[i] != '\n')
471 DrawQ_String(0, y, r_speeds_string + j, i - j, 8, 8, 1, 1, 1, 1, 0);
472 if (r_speeds_string[i] == '\n')
476 r_speeds_string[0] = 0;
477 r_timereport_active = false;
479 if (r_speeds.integer && cls.signon == SIGNONS && cls.state == ca_connected)
481 speedstringcount = 0;
482 r_speeds_string[0] = 0;
483 r_timereport_active = false;
484 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]);
485 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);
486 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);
487 if (renderstats.bloom)
488 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);
490 sprintf(r_speeds_string + strlen(r_speeds_string), "rendered%6i meshes%8i triangles\n", renderstats.meshes, renderstats.meshes_elements / 3);
492 memset(&renderstats, 0, sizeof(renderstats));
494 if (r_speeds.integer >= 2)
496 r_timereport_active = true;
497 r_timereport_start = r_timereport_current = Sys_DoubleTime();
509 void SCR_SizeUp_f (void)
511 Cvar_SetValue ("viewsize",scr_viewsize.value+10);
522 void SCR_SizeDown_f (void)
524 Cvar_SetValue ("viewsize",scr_viewsize.value-10);
527 void CL_Screen_Init(void)
529 Cvar_RegisterVariable (&scr_fov);
530 Cvar_RegisterVariable (&scr_viewsize);
531 Cvar_RegisterVariable (&scr_conspeed);
532 Cvar_RegisterVariable (&scr_conalpha);
533 Cvar_RegisterVariable (&scr_conbrightness);
534 Cvar_RegisterVariable (&scr_conforcewhiledisconnected);
535 Cvar_RegisterVariable (&scr_menuforcewhiledisconnected);
536 Cvar_RegisterVariable (&scr_showram);
537 Cvar_RegisterVariable (&scr_showturtle);
538 Cvar_RegisterVariable (&scr_showpause);
539 Cvar_RegisterVariable (&scr_showbrand);
540 Cvar_RegisterVariable (&scr_centertime);
541 Cvar_RegisterVariable (&scr_printspeed);
542 Cvar_RegisterVariable (&vid_conwidth);
543 Cvar_RegisterVariable (&vid_conheight);
544 Cvar_RegisterVariable (&vid_pixelheight);
545 Cvar_RegisterVariable (&scr_screenshot_jpeg);
546 Cvar_RegisterVariable (&scr_screenshot_jpeg_quality);
547 Cvar_RegisterVariable (&scr_screenshot_gamma);
548 Cvar_RegisterVariable (&cl_capturevideo);
549 Cvar_RegisterVariable (&cl_capturevideo_sound);
550 Cvar_RegisterVariable (&cl_capturevideo_fps);
551 Cvar_RegisterVariable (&cl_capturevideo_rawrgb);
552 Cvar_RegisterVariable (&cl_capturevideo_rawyv12);
553 Cvar_RegisterVariable (&r_letterbox);
554 Cvar_RegisterVariable(&r_stereo_separation);
555 Cvar_RegisterVariable(&r_stereo_sidebyside);
556 Cvar_RegisterVariable(&r_stereo_redblue);
557 Cvar_RegisterVariable(&r_stereo_redcyan);
558 Cvar_RegisterVariable(&r_stereo_redgreen);
559 Cvar_RegisterVariable(&scr_zoomwindow);
560 Cvar_RegisterVariable(&scr_zoomwindow_viewsizex);
561 Cvar_RegisterVariable(&scr_zoomwindow_viewsizey);
562 Cvar_RegisterVariable(&scr_zoomwindow_fov);
564 Cmd_AddCommand ("sizeup",SCR_SizeUp_f, "increase view size (increases viewsize cvar)");
565 Cmd_AddCommand ("sizedown",SCR_SizeDown_f, "decrease view size (decreases viewsize cvar)");
566 Cmd_AddCommand ("screenshot",SCR_ScreenShot_f, "takes a screenshot of the next rendered frame");
567 Cmd_AddCommand ("envmap", R_Envmap_f, "render a cubemap (skybox) of the current scene");
569 scr_initialized = true;
577 void SCR_ScreenShot_f (void)
579 static int shotnumber;
580 static char oldname[MAX_QPATH];
581 char base[MAX_QPATH];
582 char filename[MAX_QPATH];
583 unsigned char *buffer1;
584 unsigned char *buffer2;
585 unsigned char *buffer3;
586 qboolean jpeg = (scr_screenshot_jpeg.integer != 0);
588 sprintf (base, "screenshots/%s", scr_screenshot_name.string);
590 if (strcmp (oldname, scr_screenshot_name.string))
592 sprintf(oldname, "%s", scr_screenshot_name.string);
596 // find a file name to save it to
597 for (;shotnumber < 1000000;shotnumber++)
598 if (!FS_SysFileExists(va("%s/%s%06d.tga", fs_gamedir, base, shotnumber)) && !FS_SysFileExists(va("%s/%s%06d.jpg", fs_gamedir, base, shotnumber)))
600 if (shotnumber >= 1000000)
602 Con_Print("SCR_ScreenShot_f: Couldn't create the image file\n");
606 sprintf(filename, "%s%06d.%s", base, shotnumber, jpeg ? "jpg" : "tga");
608 buffer1 = (unsigned char *)Mem_Alloc(tempmempool, vid.width * vid.height * 3);
609 buffer2 = (unsigned char *)Mem_Alloc(tempmempool, vid.width * vid.height * 3);
610 buffer3 = (unsigned char *)Mem_Alloc(tempmempool, vid.width * vid.height * 3 + 18);
612 if (SCR_ScreenShot (filename, buffer1, buffer2, buffer3, 0, 0, vid.width, vid.height, false, false, false, jpeg, true))
613 Con_Printf("Wrote %s\n", filename);
615 Con_Printf("unable to write %s\n", filename);
624 void SCR_CaptureVideo_BeginVideo(void)
628 unsigned char out[44];
629 if (cls.capturevideo_active)
631 // soundrate is figured out on the first SoundFrame
632 cls.capturevideo_active = true;
633 cls.capturevideo_starttime = Sys_DoubleTime();
634 cls.capturevideo_framerate = bound(1, cl_capturevideo_fps.value, 1000);
635 cls.capturevideo_soundrate = 0;
636 cls.capturevideo_frame = 0;
637 cls.capturevideo_buffer = (unsigned char *)Mem_Alloc(tempmempool, vid.width * vid.height * (3+3+3) + 18);
638 gamma = 1.0/scr_screenshot_gamma.value;
641 for (i = 0;i < 256;i++)
643 unsigned char j = (unsigned char)bound(0, 255*pow(i/255.0, gamma), 255);
644 cls.capturevideo_rgbgammatable[0][i] = j;
645 cls.capturevideo_rgbgammatable[1][i] = j;
646 cls.capturevideo_rgbgammatable[2][i] = j;
650 R = Y + 1.4075 * (Cr - 128);
651 G = Y + -0.3455 * (Cb - 128) + -0.7169 * (Cr - 128);
652 B = Y + 1.7790 * (Cb - 128);
653 Y = R * .299 + G * .587 + B * .114;
654 Cb = R * -.169 + G * -.332 + B * .500 + 128.;
655 Cr = R * .500 + G * -.419 + B * -.0813 + 128.;
657 for (i = 0;i < 256;i++)
659 g = 255*pow(i/255.0, gamma);
660 // Y weights from RGB
661 cls.capturevideo_rgbtoyuvscaletable[0][0][i] = (short)(g * 0.299);
662 cls.capturevideo_rgbtoyuvscaletable[0][1][i] = (short)(g * 0.587);
663 cls.capturevideo_rgbtoyuvscaletable[0][2][i] = (short)(g * 0.114);
664 // Cb weights from RGB
665 cls.capturevideo_rgbtoyuvscaletable[1][0][i] = (short)(g * -0.169);
666 cls.capturevideo_rgbtoyuvscaletable[1][1][i] = (short)(g * -0.332);
667 cls.capturevideo_rgbtoyuvscaletable[1][2][i] = (short)(g * 0.500);
668 // Cr weights from RGB
669 cls.capturevideo_rgbtoyuvscaletable[2][0][i] = (short)(g * 0.500);
670 cls.capturevideo_rgbtoyuvscaletable[2][1][i] = (short)(g * -0.419);
671 cls.capturevideo_rgbtoyuvscaletable[2][2][i] = (short)(g * -0.0813);
672 // range reduction of YCbCr to valid signal range
673 cls.capturevideo_yuvnormalizetable[0][i] = 16 + i * (236-16) / 256;
674 cls.capturevideo_yuvnormalizetable[1][i] = 16 + i * (240-16) / 256;
675 cls.capturevideo_yuvnormalizetable[2][i] = 16 + i * (240-16) / 256;
678 if (cl_capturevideo_rawrgb.integer)
680 cls.capturevideo_format = CAPTUREVIDEOFORMAT_RAWRGB;
681 cls.capturevideo_videofile = FS_Open ("video/dpvideo.rgb", "wb", false, true);
683 else if (cl_capturevideo_rawyv12.integer)
685 cls.capturevideo_format = CAPTUREVIDEOFORMAT_RAWYV12;
686 cls.capturevideo_videofile = FS_Open ("video/dpvideo.yv12", "wb", false, true);
688 else if (scr_screenshot_jpeg.integer)
690 cls.capturevideo_format = CAPTUREVIDEOFORMAT_JPEG;
691 cls.capturevideo_videofile = NULL;
695 cls.capturevideo_format = CAPTUREVIDEOFORMAT_TARGA;
696 cls.capturevideo_videofile = NULL;
699 if (cl_capturevideo_sound.integer)
701 cls.capturevideo_soundfile = FS_Open ("video/dpvideo.wav", "wb", false, true);
702 // wave header will be filled out when video ends
704 FS_Write (cls.capturevideo_soundfile, out, 44);
707 cls.capturevideo_soundfile = NULL;
710 void SCR_CaptureVideo_EndVideo(void)
713 unsigned char out[44];
714 if (!cls.capturevideo_active)
716 cls.capturevideo_active = false;
718 if (cls.capturevideo_videofile)
720 FS_Close(cls.capturevideo_videofile);
721 cls.capturevideo_videofile = NULL;
724 // finish the wave file
725 if (cls.capturevideo_soundfile)
727 i = (int)FS_Tell (cls.capturevideo_soundfile);
728 //"RIFF", (int) unknown (chunk size), "WAVE",
729 //"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
730 //"data", (int) unknown (chunk size)
731 memcpy (out, "RIFF****WAVEfmt \x10\x00\x00\x00\x01\x00\x02\x00********\x04\x00\x10\0data****", 44);
732 // the length of the whole RIFF chunk
735 out[5] = (n >> 8) & 0xFF;
736 out[6] = (n >> 16) & 0xFF;
737 out[7] = (n >> 24) & 0xFF;
739 n = cls.capturevideo_soundrate;
740 out[24] = (n) & 0xFF;
741 out[25] = (n >> 8) & 0xFF;
742 out[26] = (n >> 16) & 0xFF;
743 out[27] = (n >> 24) & 0xFF;
744 // bytes per second (rate * channels * bytes per channel)
745 n = cls.capturevideo_soundrate * 2 * 2;
746 out[28] = (n) & 0xFF;
747 out[29] = (n >> 8) & 0xFF;
748 out[30] = (n >> 16) & 0xFF;
749 out[31] = (n >> 24) & 0xFF;
750 // the length of the data chunk
752 out[40] = (n) & 0xFF;
753 out[41] = (n >> 8) & 0xFF;
754 out[42] = (n >> 16) & 0xFF;
755 out[43] = (n >> 24) & 0xFF;
756 FS_Seek (cls.capturevideo_soundfile, 0, SEEK_SET);
757 FS_Write (cls.capturevideo_soundfile, out, 44);
758 FS_Close (cls.capturevideo_soundfile);
759 cls.capturevideo_soundfile = NULL;
762 if (cls.capturevideo_buffer)
764 Mem_Free (cls.capturevideo_buffer);
765 cls.capturevideo_buffer = NULL;
768 cls.capturevideo_starttime = 0;
769 cls.capturevideo_framerate = 0;
770 cls.capturevideo_frame = 0;
773 qboolean SCR_CaptureVideo_VideoFrame(int newframenum)
775 int x = 0, y = 0, width = vid.width, height = vid.height;
776 unsigned char *b, *out;
778 int outoffset = (width/2)*(height/2);
779 //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);
780 // speed is critical here, so do saving as directly as possible
781 switch (cls.capturevideo_format)
783 case CAPTUREVIDEOFORMAT_RAWYV12:
784 // FIXME: width/height must be multiple of 2, enforce this?
785 qglReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, cls.capturevideo_buffer);
787 // process one line at a time, and CbCr every other line at 2 pixel intervals
788 for (y = 0;y < height;y++)
791 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++)
792 *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]]];
795 // 2x2 Cb and Cr planes
797 // low quality, no averaging
798 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++)
801 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];
803 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];
806 // high quality, averaging
807 int inpitch = width*3;
808 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++)
810 int blockr, blockg, blockb;
811 blockr = (b[0] + b[3] + b[inpitch+0] + b[inpitch+3]) >> 2;
812 blockg = (b[1] + b[4] + b[inpitch+1] + b[inpitch+4]) >> 2;
813 blockb = (b[2] + b[5] + b[inpitch+2] + b[inpitch+5]) >> 2;
815 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];
817 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];
822 for (;cls.capturevideo_frame < newframenum;cls.capturevideo_frame++)
823 if (!FS_Write (cls.capturevideo_videofile, cls.capturevideo_buffer + width*height*3, width*height+(width/2)*(height/2)*2))
826 case CAPTUREVIDEOFORMAT_RAWRGB:
827 qglReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, cls.capturevideo_buffer);
829 for (;cls.capturevideo_frame < newframenum;cls.capturevideo_frame++)
830 if (!FS_Write (cls.capturevideo_videofile, cls.capturevideo_buffer, width*height*3))
833 case CAPTUREVIDEOFORMAT_JPEG:
834 qglReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, cls.capturevideo_buffer);
836 for (;cls.capturevideo_frame < newframenum;cls.capturevideo_frame++)
838 sprintf(filename, "video/dp%06d.jpg", cls.capturevideo_frame);
839 if (!JPEG_SaveImage_preflipped (filename, width, height, cls.capturevideo_buffer))
843 case CAPTUREVIDEOFORMAT_TARGA:
844 //return Image_WriteTGARGB_preflipped (filename, width, height, cls.capturevideo_buffer, cls.capturevideo_buffer + vid.width * vid.height * 3, );
845 memset (cls.capturevideo_buffer, 0, 18);
846 cls.capturevideo_buffer[2] = 2; // uncompressed type
847 cls.capturevideo_buffer[12] = (width >> 0) & 0xFF;
848 cls.capturevideo_buffer[13] = (width >> 8) & 0xFF;
849 cls.capturevideo_buffer[14] = (height >> 0) & 0xFF;
850 cls.capturevideo_buffer[15] = (height >> 8) & 0xFF;
851 cls.capturevideo_buffer[16] = 24; // pixel size
852 qglReadPixels (x, y, width, height, GL_BGR, GL_UNSIGNED_BYTE, cls.capturevideo_buffer + 18);
854 for (;cls.capturevideo_frame < newframenum;cls.capturevideo_frame++)
856 sprintf(filename, "video/dp%06d.tga", cls.capturevideo_frame);
857 if (!FS_WriteFile (filename, cls.capturevideo_buffer, width*height*3 + 18))
866 void SCR_CaptureVideo_SoundFrame(unsigned char *bufstereo16le, size_t length, int rate)
868 if (!cls.capturevideo_soundfile)
870 cls.capturevideo_soundrate = rate;
871 if (FS_Write (cls.capturevideo_soundfile, bufstereo16le, 4 * length) < (fs_offset_t)(4 * length))
873 Cvar_SetValueQuick(&cl_capturevideo, 0);
874 Con_Printf("video sound saving failed on frame %i, out of disk space? stopping video capture.\n", cls.capturevideo_frame);
875 SCR_CaptureVideo_EndVideo();
879 void SCR_CaptureVideo(void)
882 if (cl_capturevideo.integer && r_render.integer)
884 if (!cls.capturevideo_active)
885 SCR_CaptureVideo_BeginVideo();
886 if (cls.capturevideo_framerate != cl_capturevideo_fps.value)
888 Con_Printf("You can not change the video framerate while recording a video.\n");
889 Cvar_SetValueQuick(&cl_capturevideo_fps, cls.capturevideo_framerate);
891 if (cls.capturevideo_soundfile)
893 // preserve sound sync by duplicating frames when running slow
894 newframenum = (Sys_DoubleTime() - cls.capturevideo_starttime) * cls.capturevideo_framerate;
897 newframenum = cls.capturevideo_frame + 1;
898 // if falling behind more than one second, stop
899 if (newframenum - cls.capturevideo_frame > (int)ceil(cls.capturevideo_framerate))
901 Cvar_SetValueQuick(&cl_capturevideo, 0);
902 Con_Printf("video saving failed on frame %i, your machine is too slow for this capture speed.\n", cls.capturevideo_frame);
903 SCR_CaptureVideo_EndVideo();
907 if (!SCR_CaptureVideo_VideoFrame(newframenum))
909 Cvar_SetValueQuick(&cl_capturevideo, 0);
910 Con_Printf("video saving failed on frame %i, out of disk space? stopping video capture.\n", cls.capturevideo_frame);
911 SCR_CaptureVideo_EndVideo();
914 else if (cls.capturevideo_active)
915 SCR_CaptureVideo_EndVideo();
922 Grab six views for environment mapping tests
929 qboolean flipx, flipy, flipdiagonaly;
933 {{ 0, 0, 0}, "rt", false, false, false},
934 {{ 0, 270, 0}, "ft", false, false, false},
935 {{ 0, 180, 0}, "lf", false, false, false},
936 {{ 0, 90, 0}, "bk", false, false, false},
937 {{-90, 180, 0}, "up", true, true, false},
938 {{ 90, 180, 0}, "dn", true, true, false},
940 {{ 0, 0, 0}, "px", true, true, true},
941 {{ 0, 90, 0}, "py", false, true, false},
942 {{ 0, 180, 0}, "nx", false, false, true},
943 {{ 0, 270, 0}, "ny", true, false, false},
944 {{-90, 180, 0}, "pz", false, false, true},
945 {{ 90, 180, 0}, "nz", false, false, true}
948 static void R_Envmap_f (void)
951 char filename[MAX_QPATH], basename[MAX_QPATH];
952 unsigned char *buffer1;
953 unsigned char *buffer2;
954 unsigned char *buffer3;
958 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");
962 strlcpy (basename, Cmd_Argv(1), sizeof (basename));
963 size = atoi(Cmd_Argv(2));
964 if (size != 128 && size != 256 && size != 512 && size != 1024)
966 Con_Print("envmap: size must be one of 128, 256, 512, or 1024\n");
969 if (size > vid.width || size > vid.height)
971 Con_Print("envmap: your resolution is not big enough to render that size\n");
979 r_refdef.width = size;
980 r_refdef.height = size;
982 r_refdef.frustum_x = tan(90 * M_PI / 360.0);
983 r_refdef.frustum_y = tan(90 * M_PI / 360.0);
985 buffer1 = (unsigned char *)Mem_Alloc(tempmempool, size * size * 3);
986 buffer2 = (unsigned char *)Mem_Alloc(tempmempool, size * size * 3);
987 buffer3 = (unsigned char *)Mem_Alloc(tempmempool, size * size * 3 + 18);
989 for (j = 0;j < 12;j++)
991 sprintf(filename, "env/%s%s.tga", basename, envmapinfo[j].name);
992 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);
997 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);
1007 //=============================================================================
1009 // LordHavoc: SHOWLMP stuff
1010 #define SHOWLMP_MAXLABELS 256
1011 typedef struct showlmp_s
1021 showlmp_t showlmp[SHOWLMP_MAXLABELS];
1023 void SHOWLMP_decodehide(void)
1027 lmplabel = MSG_ReadString();
1028 for (i = 0;i < SHOWLMP_MAXLABELS;i++)
1029 if (showlmp[i].isactive && strcmp(showlmp[i].label, lmplabel) == 0)
1031 showlmp[i].isactive = false;
1036 void SHOWLMP_decodeshow(void)
1039 char lmplabel[256], picname[256];
1041 strlcpy (lmplabel,MSG_ReadString(), sizeof (lmplabel));
1042 strlcpy (picname, MSG_ReadString(), sizeof (picname));
1043 if (gamemode == GAME_NEHAHRA) // LordHavoc: nasty old legacy junk
1050 x = MSG_ReadShort();
1051 y = MSG_ReadShort();
1054 for (i = 0;i < SHOWLMP_MAXLABELS;i++)
1055 if (showlmp[i].isactive)
1057 if (strcmp(showlmp[i].label, lmplabel) == 0)
1060 break; // drop out to replace it
1063 else if (k < 0) // find first empty one to replace
1066 return; // none found to replace
1067 // change existing one
1068 showlmp[k].isactive = true;
1069 strlcpy (showlmp[k].label, lmplabel, sizeof (showlmp[k].label));
1070 strlcpy (showlmp[k].pic, picname, sizeof (showlmp[k].pic));
1075 void SHOWLMP_drawall(void)
1078 for (i = 0;i < SHOWLMP_MAXLABELS;i++)
1079 if (showlmp[i].isactive)
1080 DrawQ_Pic(showlmp[i].x, showlmp[i].y, Draw_CachePic(showlmp[i].pic, true), 0, 0, 1, 1, 1, 1, 0);
1083 void SHOWLMP_clear(void)
1086 for (i = 0;i < SHOWLMP_MAXLABELS;i++)
1087 showlmp[i].isactive = false;
1091 ==============================================================================
1095 ==============================================================================
1098 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)
1100 int indices[3] = {0,1,2};
1103 if (!r_render.integer)
1106 qglReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer1);
1109 if (scr_screenshot_gamma.value != 1 && gammacorrect)
1112 double igamma = 1.0 / scr_screenshot_gamma.value;
1113 unsigned char ramp[256];
1114 for (i = 0;i < 256;i++)
1115 ramp[i] = (unsigned char) (pow(i * (1.0 / 255.0), igamma) * 255.0);
1116 for (i = 0;i < width*height*3;i++)
1117 buffer1[i] = ramp[buffer1[i]];
1120 Image_CopyMux (buffer2, buffer1, width, height, flipx, flipy, flipdiagonal, 3, 3, indices);
1123 ret = JPEG_SaveImage_preflipped (filename, width, height, buffer2);
1125 ret = Image_WriteTGARGB_preflipped (filename, width, height, buffer2, buffer3);
1130 //=============================================================================
1132 void R_ClearScreen(void)
1134 if (r_render.integer)
1138 qglClearColor(fogcolor[0],fogcolor[1],fogcolor[2],0);
1140 qglClearColor(0,0,0,0);
1142 qglClearDepth(1);CHECKGLERROR
1145 // LordHavoc: we use a stencil centered around 128 instead of 0,
1146 // to avoid clamping interfering with strange shadow volume
1148 qglClearStencil(128);CHECKGLERROR
1151 GL_Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | (gl_stencil ? GL_STENCIL_BUFFER_BIT : 0));
1152 // set dithering mode
1153 if (gl_dither.integer)
1155 qglEnable(GL_DITHER);CHECKGLERROR
1159 qglDisable(GL_DITHER);CHECKGLERROR
1164 qboolean CL_VM_UpdateView (void);
1165 void SCR_DrawConsole (void);
1166 void R_Shadow_EditLights_DrawSelectedLightProperties(void);
1170 void SCR_DrawScreen (void)
1174 if (r_timereport_active)
1175 R_TimeReport("setup");
1177 if (cls.signon == SIGNONS)
1181 size = scr_viewsize.value * (1.0 / 100.0);
1182 size = min(size, 1);
1184 if (r_stereo_sidebyside.integer)
1186 r_refdef.width = vid.width * size / 2.5;
1187 r_refdef.height = vid.height * size / 2.5 * (1 - bound(0, r_letterbox.value, 100) / 100);
1188 r_refdef.x = (vid.width - r_refdef.width * 2.5) * 0.5;
1189 r_refdef.y = (vid.height - r_refdef.height)/2;
1191 r_refdef.x += r_refdef.width * 1.5;
1195 r_refdef.width = vid.width * size;
1196 r_refdef.height = vid.height * size * (1 - bound(0, r_letterbox.value, 100) / 100);
1197 r_refdef.x = (vid.width - r_refdef.width)/2;
1198 r_refdef.y = (vid.height - r_refdef.height)/2;
1201 // LordHavoc: viewzoom (zoom in for sniper rifles, etc)
1202 // LordHavoc: this is designed to produce widescreen fov values
1203 // when the screen is wider than 4/3 width/height aspect, to do
1204 // this it simply assumes the requested fov is the vertical fov
1205 // for a 4x3 display, if the ratio is not 4x3 this makes the fov
1206 // higher/lower according to the ratio
1207 r_refdef.frustum_y = tan(scr_fov.value * cl.viewzoom * M_PI / 360.0) * (3.0/4.0);
1208 r_refdef.frustum_x = r_refdef.frustum_y * (float)r_refdef.width / (float)r_refdef.height / vid_pixelheight.value;
1210 r_refdef.frustum_x *= r_refdef.frustumscale_x;
1211 r_refdef.frustum_y *= r_refdef.frustumscale_y;
1213 if(!CL_VM_UpdateView())
1218 if (scr_zoomwindow.integer)
1220 float sizex = bound(10, scr_zoomwindow_viewsizex.value, 100) / 100.0;
1221 float sizey = bound(10, scr_zoomwindow_viewsizey.value, 100) / 100.0;
1222 r_refdef.width = vid.width * sizex;
1223 r_refdef.height = vid.height * sizey;
1224 r_refdef.x = (vid.width - r_refdef.width)/2;
1227 r_refdef.frustum_y = tan(scr_zoomwindow_fov.value * cl.viewzoom * M_PI / 360.0) * (3.0/4.0);
1228 r_refdef.frustum_x = r_refdef.frustum_y * vid_pixelheight.value * (float)r_refdef.width / (float)r_refdef.height;
1230 r_refdef.frustum_x *= r_refdef.frustumscale_x;
1231 r_refdef.frustum_y *= r_refdef.frustumscale_y;
1233 if(!CL_VM_UpdateView())
1238 if (!r_stereo_sidebyside.integer)
1240 r_refdef.width = vid.width;
1241 r_refdef.height = vid.height;
1249 //FIXME: force menu if nothing else to look at?
1250 //if (key_dest == key_game && cls.signon != SIGNONS && cls.state == ca_disconnected)
1252 if (cls.signon == SIGNONS)
1257 if (!r_letterbox.value)
1260 SCR_CheckDrawCenterString();
1264 R_Shadow_EditLights_DrawSelectedLightProperties();
1273 if (r_timereport_active)
1276 if (cls.signon == SIGNONS)
1277 R_TimeReport_Frame();
1285 if (r_timereport_active)
1286 R_TimeReport("meshfinish");
1289 void SCR_UpdateLoadingScreen (void)
1295 float texcoord2f[8];
1296 // don't do anything if not initialized yet
1299 qglViewport(0, 0, vid.width, vid.height);
1300 //qglDisable(GL_SCISSOR_TEST);
1302 qglColorMask(1,1,1,1);
1303 //qglClearColor(0,0,0,0);
1304 //qglClear(GL_COLOR_BUFFER_BIT);
1305 //qglCullFace(GL_FRONT);
1306 //qglDisable(GL_CULL_FACE);
1309 GL_SetupView_Mode_Ortho(0, 0, vid_conwidth.integer, vid_conheight.integer, -10, 100);
1311 R_Mesh_Matrix(&identitymatrix);
1312 // draw the loading plaque
1313 pic = Draw_CachePic("gfx/loading", true);
1314 x = (vid_conwidth.integer - pic->width)/2;
1315 y = (vid_conheight.integer - pic->height)/2;
1317 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1318 GL_DepthTest(false);
1319 memset(&m, 0, sizeof(m));
1320 m.pointer_vertex = vertex3f;
1321 m.pointer_texcoord[0] = texcoord2f;
1322 m.tex[0] = R_GetTexture(pic->tex);
1324 vertex3f[2] = vertex3f[5] = vertex3f[8] = vertex3f[11] = 0;
1325 vertex3f[0] = vertex3f[9] = x;
1326 vertex3f[1] = vertex3f[4] = y;
1327 vertex3f[3] = vertex3f[6] = x + pic->width;
1328 vertex3f[7] = vertex3f[10] = y + pic->height;
1329 texcoord2f[0] = 0;texcoord2f[1] = 0;
1330 texcoord2f[2] = 1;texcoord2f[3] = 0;
1331 texcoord2f[4] = 1;texcoord2f[5] = 1;
1332 texcoord2f[6] = 0;texcoord2f[7] = 1;
1333 R_Mesh_Draw(0, 4, 2, polygonelements);
1339 void CL_UpdateScreen(void)
1341 float conwidth, conheight;
1346 if (!scr_initialized || !con_initialized || vid_hidden)
1347 return; // not initialized yet
1349 // don't allow cheats in multiplayer
1350 if (!cl.islocalgame && cl.worldmodel)
1352 if (r_fullbright.integer != 0)
1353 Cvar_Set ("r_fullbright", "0");
1354 if (r_ambient.value != 0)
1355 Cvar_Set ("r_ambient", "0");
1358 conwidth = bound(320, vid_conwidth.value, 2048);
1359 conheight = bound(200, vid_conheight.value, 1536);
1360 if (vid_conwidth.value != conwidth)
1361 Cvar_SetValue("vid_conwidth", conwidth);
1362 if (vid_conheight.value != conheight)
1363 Cvar_SetValue("vid_conheight", conheight);
1366 if (scr_viewsize.value < 30)
1367 Cvar_Set ("viewsize","30");
1368 if (scr_viewsize.value > 120)
1369 Cvar_Set ("viewsize","120");
1371 // bound field of view
1372 if (scr_fov.value < 1)
1373 Cvar_Set ("fov","1");
1374 if (scr_fov.value > 170)
1375 Cvar_Set ("fov","170");
1377 // validate r_textureunits cvar
1378 if (r_textureunits.integer > gl_textureunits)
1379 Cvar_SetValueQuick(&r_textureunits, gl_textureunits);
1380 if (r_textureunits.integer < 1)
1381 Cvar_SetValueQuick(&r_textureunits, 1);
1383 // validate gl_combine cvar
1384 if (gl_combine.integer && !gl_combine_extension)
1385 Cvar_SetValueQuick(&gl_combine, 0);
1387 // intermission is always full screen
1388 if (cl.intermission)
1392 if (scr_viewsize.value >= 120)
1393 sb_lines = 0; // no status bar at all
1394 else if (scr_viewsize.value >= 110)
1395 sb_lines = 24; // no inventory
1400 r_refdef.colormask[0] = 1;
1401 r_refdef.colormask[1] = 1;
1402 r_refdef.colormask[2] = 1;
1404 if (r_timereport_active)
1405 R_TimeReport("other");
1407 SCR_SetUpToDrawConsole();
1409 if (r_timereport_active)
1410 R_TimeReport("start");
1413 qglViewport(0, 0, vid.width, vid.height);
1414 qglDisable(GL_SCISSOR_TEST);
1416 qglColorMask(1,1,1,1);
1417 qglClearColor(0,0,0,0);
1418 qglClear(GL_COLOR_BUFFER_BIT);
1421 if (r_timereport_active)
1422 R_TimeReport("clear");
1424 if (r_stereo_redblue.integer || r_stereo_redgreen.integer || r_stereo_redcyan.integer || r_stereo_sidebyside.integer)
1426 matrix4x4_t originalmatrix = r_refdef.viewentitymatrix;
1427 r_refdef.viewentitymatrix.m[0][3] = originalmatrix.m[0][3] + r_stereo_separation.value * -0.5f * r_refdef.viewentitymatrix.m[0][1];
1428 r_refdef.viewentitymatrix.m[1][3] = originalmatrix.m[1][3] + r_stereo_separation.value * -0.5f * r_refdef.viewentitymatrix.m[1][1];
1429 r_refdef.viewentitymatrix.m[2][3] = originalmatrix.m[2][3] + r_stereo_separation.value * -0.5f * r_refdef.viewentitymatrix.m[2][1];
1431 if (r_stereo_sidebyside.integer)
1434 if (r_stereo_redblue.integer || r_stereo_redgreen.integer || r_stereo_redcyan.integer)
1436 r_refdef.colormask[0] = 1;
1437 r_refdef.colormask[1] = 0;
1438 r_refdef.colormask[2] = 0;
1443 r_refdef.viewentitymatrix.m[0][3] = originalmatrix.m[0][3] + r_stereo_separation.value * 0.5f * r_refdef.viewentitymatrix.m[0][1];
1444 r_refdef.viewentitymatrix.m[1][3] = originalmatrix.m[1][3] + r_stereo_separation.value * 0.5f * r_refdef.viewentitymatrix.m[1][1];
1445 r_refdef.viewentitymatrix.m[2][3] = originalmatrix.m[2][3] + r_stereo_separation.value * 0.5f * r_refdef.viewentitymatrix.m[2][1];
1447 if (r_stereo_sidebyside.integer)
1450 if (r_stereo_redblue.integer || r_stereo_redgreen.integer || r_stereo_redcyan.integer)
1452 r_refdef.colormask[0] = 0;
1453 r_refdef.colormask[1] = r_stereo_redcyan.integer || r_stereo_redgreen.integer;
1454 r_refdef.colormask[2] = r_stereo_redcyan.integer || r_stereo_redblue.integer;
1459 r_refdef.viewentitymatrix = originalmatrix;
1467 if (r_timereport_active)
1468 R_TimeReport("finish");
1471 void CL_Screen_NewMap(void)