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", "0.2", "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_gamma = {CVAR_SAVE, "scr_screenshot_gamma","2.2", "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_gamma 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 r_timereport_temp = r_timereport_current;
412 r_timereport_current = Sys_DoubleTime();
413 t = (int) ((r_timereport_current - r_timereport_temp) * 1000000.0 + 0.5);
415 dpsnprintf(tempbuf, sizeof(tempbuf), "%8i %-11s", t, desc);
416 length = (int)strlen(tempbuf);
417 if (speedstringcount + length > (vid_conwidth.integer / 8))
419 strlcat(r_speeds_string, "\n", sizeof(r_speeds_string));
420 speedstringcount = 0;
422 strlcat(r_speeds_string, tempbuf, sizeof(r_speeds_string));
423 speedstringcount += length;
426 void R_TimeReport_Frame(void)
430 if (r_speeds_string[0])
432 if (r_timereport_active)
434 r_timereport_current = r_timereport_start;
435 R_TimeReport("total");
438 if (r_speeds_string[strlen(r_speeds_string)-1] == '\n')
439 r_speeds_string[strlen(r_speeds_string)-1] = 0;
441 for (i = 0;r_speeds_string[i];i++)
442 if (r_speeds_string[i] == '\n')
444 y = vid_conheight.integer - sb_lines - lines * 8;
446 DrawQ_Pic(0, y, NULL, vid_conwidth.integer, lines * 8, 0, 0, 0, 0.5, 0);
447 while (r_speeds_string[i])
450 while (r_speeds_string[i] && r_speeds_string[i] != '\n')
453 DrawQ_String(0, y, r_speeds_string + j, i - j, 8, 8, 1, 1, 1, 1, 0);
454 if (r_speeds_string[i] == '\n')
458 r_speeds_string[0] = 0;
459 r_timereport_active = false;
461 if (r_speeds.integer && cls.signon == SIGNONS && cls.state == ca_connected)
463 speedstringcount = 0;
464 r_speeds_string[0] = 0;
465 r_timereport_active = false;
466 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]);
467 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);
468 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);
469 if (renderstats.bloom)
470 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);
472 sprintf(r_speeds_string + strlen(r_speeds_string), "rendered%6i meshes%8i triangles\n", renderstats.meshes, renderstats.meshes_elements / 3);
474 memset(&renderstats, 0, sizeof(renderstats));
476 if (r_speeds.integer >= 2)
478 r_timereport_active = true;
479 r_timereport_start = r_timereport_current = Sys_DoubleTime();
491 void SCR_SizeUp_f (void)
493 Cvar_SetValue ("viewsize",scr_viewsize.value+10);
504 void SCR_SizeDown_f (void)
506 Cvar_SetValue ("viewsize",scr_viewsize.value-10);
509 void CL_Screen_Init(void)
511 Cvar_RegisterVariable (&scr_fov);
512 Cvar_RegisterVariable (&scr_viewsize);
513 Cvar_RegisterVariable (&scr_conalpha);
514 Cvar_RegisterVariable (&scr_conbrightness);
515 Cvar_RegisterVariable (&scr_conforcewhiledisconnected);
516 Cvar_RegisterVariable (&scr_menuforcewhiledisconnected);
517 Cvar_RegisterVariable (&scr_showram);
518 Cvar_RegisterVariable (&scr_showturtle);
519 Cvar_RegisterVariable (&scr_showpause);
520 Cvar_RegisterVariable (&scr_showbrand);
521 Cvar_RegisterVariable (&scr_centertime);
522 Cvar_RegisterVariable (&scr_printspeed);
523 Cvar_RegisterVariable (&vid_conwidth);
524 Cvar_RegisterVariable (&vid_conheight);
525 Cvar_RegisterVariable (&vid_pixelheight);
526 Cvar_RegisterVariable (&scr_screenshot_jpeg);
527 Cvar_RegisterVariable (&scr_screenshot_jpeg_quality);
528 Cvar_RegisterVariable (&scr_screenshot_gamma);
529 Cvar_RegisterVariable (&cl_capturevideo);
530 Cvar_RegisterVariable (&cl_capturevideo_sound);
531 Cvar_RegisterVariable (&cl_capturevideo_fps);
532 Cvar_RegisterVariable (&cl_capturevideo_rawrgb);
533 Cvar_RegisterVariable (&cl_capturevideo_rawyv12);
534 Cvar_RegisterVariable (&r_letterbox);
535 Cvar_RegisterVariable(&r_stereo_separation);
536 Cvar_RegisterVariable(&r_stereo_sidebyside);
537 Cvar_RegisterVariable(&r_stereo_redblue);
538 Cvar_RegisterVariable(&r_stereo_redcyan);
539 Cvar_RegisterVariable(&r_stereo_redgreen);
540 Cvar_RegisterVariable(&scr_zoomwindow);
541 Cvar_RegisterVariable(&scr_zoomwindow_viewsizex);
542 Cvar_RegisterVariable(&scr_zoomwindow_viewsizey);
543 Cvar_RegisterVariable(&scr_zoomwindow_fov);
545 Cmd_AddCommand ("sizeup",SCR_SizeUp_f, "increase view size (increases viewsize cvar)");
546 Cmd_AddCommand ("sizedown",SCR_SizeDown_f, "decrease view size (decreases viewsize cvar)");
547 Cmd_AddCommand ("screenshot",SCR_ScreenShot_f, "takes a screenshot of the next rendered frame");
548 Cmd_AddCommand ("envmap", R_Envmap_f, "render a cubemap (skybox) of the current scene");
550 scr_initialized = true;
558 void SCR_ScreenShot_f (void)
560 static int shotnumber;
561 static char oldname[MAX_QPATH];
562 char base[MAX_QPATH];
563 char filename[MAX_QPATH];
564 unsigned char *buffer1;
565 unsigned char *buffer2;
566 unsigned char *buffer3;
567 qboolean jpeg = (scr_screenshot_jpeg.integer != 0);
569 sprintf (base, "screenshots/%s", scr_screenshot_name.string);
571 if (strcmp (oldname, scr_screenshot_name.string))
573 sprintf(oldname, "%s", scr_screenshot_name.string);
577 // find a file name to save it to
578 for (;shotnumber < 1000000;shotnumber++)
579 if (!FS_SysFileExists(va("%s/%s%06d.tga", fs_gamedir, base, shotnumber)) && !FS_SysFileExists(va("%s/%s%06d.jpg", fs_gamedir, base, shotnumber)))
581 if (shotnumber >= 1000000)
583 Con_Print("SCR_ScreenShot_f: Couldn't create the image file\n");
587 sprintf(filename, "%s%06d.%s", base, shotnumber, jpeg ? "jpg" : "tga");
589 buffer1 = (unsigned char *)Mem_Alloc(tempmempool, vid.width * vid.height * 3);
590 buffer2 = (unsigned char *)Mem_Alloc(tempmempool, vid.width * vid.height * 3);
591 buffer3 = (unsigned char *)Mem_Alloc(tempmempool, vid.width * vid.height * 3 + 18);
593 if (SCR_ScreenShot (filename, buffer1, buffer2, buffer3, 0, 0, vid.width, vid.height, false, false, false, jpeg, true))
594 Con_Printf("Wrote %s\n", filename);
596 Con_Printf("unable to write %s\n", filename);
605 void SCR_CaptureVideo_BeginVideo(void)
609 unsigned char out[44];
610 if (cls.capturevideo_active)
612 // soundrate is figured out on the first SoundFrame
613 cls.capturevideo_active = true;
614 cls.capturevideo_starttime = Sys_DoubleTime();
615 cls.capturevideo_framerate = bound(1, cl_capturevideo_fps.value, 1000);
616 cls.capturevideo_soundrate = 0;
617 cls.capturevideo_frame = 0;
618 cls.capturevideo_buffer = (unsigned char *)Mem_Alloc(tempmempool, vid.width * vid.height * (3+3+3) + 18);
619 gamma = 1.0/scr_screenshot_gamma.value;
622 for (i = 0;i < 256;i++)
624 unsigned char j = (unsigned char)bound(0, 255*pow(i/255.0, gamma), 255);
625 cls.capturevideo_rgbgammatable[0][i] = j;
626 cls.capturevideo_rgbgammatable[1][i] = j;
627 cls.capturevideo_rgbgammatable[2][i] = j;
631 R = Y + 1.4075 * (Cr - 128);
632 G = Y + -0.3455 * (Cb - 128) + -0.7169 * (Cr - 128);
633 B = Y + 1.7790 * (Cb - 128);
634 Y = R * .299 + G * .587 + B * .114;
635 Cb = R * -.169 + G * -.332 + B * .500 + 128.;
636 Cr = R * .500 + G * -.419 + B * -.0813 + 128.;
638 for (i = 0;i < 256;i++)
640 g = 255*pow(i/255.0, gamma);
641 // Y weights from RGB
642 cls.capturevideo_rgbtoyuvscaletable[0][0][i] = (short)(g * 0.299);
643 cls.capturevideo_rgbtoyuvscaletable[0][1][i] = (short)(g * 0.587);
644 cls.capturevideo_rgbtoyuvscaletable[0][2][i] = (short)(g * 0.114);
645 // Cb weights from RGB
646 cls.capturevideo_rgbtoyuvscaletable[1][0][i] = (short)(g * -0.169);
647 cls.capturevideo_rgbtoyuvscaletable[1][1][i] = (short)(g * -0.332);
648 cls.capturevideo_rgbtoyuvscaletable[1][2][i] = (short)(g * 0.500);
649 // Cr weights from RGB
650 cls.capturevideo_rgbtoyuvscaletable[2][0][i] = (short)(g * 0.500);
651 cls.capturevideo_rgbtoyuvscaletable[2][1][i] = (short)(g * -0.419);
652 cls.capturevideo_rgbtoyuvscaletable[2][2][i] = (short)(g * -0.0813);
653 // range reduction of YCbCr to valid signal range
654 cls.capturevideo_yuvnormalizetable[0][i] = 16 + i * (236-16) / 256;
655 cls.capturevideo_yuvnormalizetable[1][i] = 16 + i * (240-16) / 256;
656 cls.capturevideo_yuvnormalizetable[2][i] = 16 + i * (240-16) / 256;
659 if (cl_capturevideo_rawrgb.integer)
661 cls.capturevideo_format = CAPTUREVIDEOFORMAT_RAWRGB;
662 cls.capturevideo_videofile = FS_Open ("video/dpvideo.rgb", "wb", false, true);
664 else if (cl_capturevideo_rawyv12.integer)
666 cls.capturevideo_format = CAPTUREVIDEOFORMAT_RAWYV12;
667 cls.capturevideo_videofile = FS_Open ("video/dpvideo.yv12", "wb", false, true);
669 else if (scr_screenshot_jpeg.integer)
671 cls.capturevideo_format = CAPTUREVIDEOFORMAT_JPEG;
672 cls.capturevideo_videofile = NULL;
676 cls.capturevideo_format = CAPTUREVIDEOFORMAT_TARGA;
677 cls.capturevideo_videofile = NULL;
680 if (cl_capturevideo_sound.integer)
682 cls.capturevideo_soundfile = FS_Open ("video/dpvideo.wav", "wb", false, true);
683 // wave header will be filled out when video ends
685 FS_Write (cls.capturevideo_soundfile, out, 44);
688 cls.capturevideo_soundfile = NULL;
691 void SCR_CaptureVideo_EndVideo(void)
694 unsigned char out[44];
695 if (!cls.capturevideo_active)
697 cls.capturevideo_active = false;
699 if (cls.capturevideo_videofile)
701 FS_Close(cls.capturevideo_videofile);
702 cls.capturevideo_videofile = NULL;
705 // finish the wave file
706 if (cls.capturevideo_soundfile)
708 i = (int)FS_Tell (cls.capturevideo_soundfile);
709 //"RIFF", (int) unknown (chunk size), "WAVE",
710 //"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
711 //"data", (int) unknown (chunk size)
712 memcpy (out, "RIFF****WAVEfmt \x10\x00\x00\x00\x01\x00\x02\x00********\x04\x00\x10\0data****", 44);
713 // the length of the whole RIFF chunk
716 out[5] = (n >> 8) & 0xFF;
717 out[6] = (n >> 16) & 0xFF;
718 out[7] = (n >> 24) & 0xFF;
720 n = cls.capturevideo_soundrate;
721 out[24] = (n) & 0xFF;
722 out[25] = (n >> 8) & 0xFF;
723 out[26] = (n >> 16) & 0xFF;
724 out[27] = (n >> 24) & 0xFF;
725 // bytes per second (rate * channels * bytes per channel)
726 n = cls.capturevideo_soundrate * 2 * 2;
727 out[28] = (n) & 0xFF;
728 out[29] = (n >> 8) & 0xFF;
729 out[30] = (n >> 16) & 0xFF;
730 out[31] = (n >> 24) & 0xFF;
731 // the length of the data chunk
733 out[40] = (n) & 0xFF;
734 out[41] = (n >> 8) & 0xFF;
735 out[42] = (n >> 16) & 0xFF;
736 out[43] = (n >> 24) & 0xFF;
737 FS_Seek (cls.capturevideo_soundfile, 0, SEEK_SET);
738 FS_Write (cls.capturevideo_soundfile, out, 44);
739 FS_Close (cls.capturevideo_soundfile);
740 cls.capturevideo_soundfile = NULL;
743 if (cls.capturevideo_buffer)
745 Mem_Free (cls.capturevideo_buffer);
746 cls.capturevideo_buffer = NULL;
749 cls.capturevideo_starttime = 0;
750 cls.capturevideo_framerate = 0;
751 cls.capturevideo_frame = 0;
754 qboolean SCR_CaptureVideo_VideoFrame(int newframenum)
756 int x = 0, y = 0, width = vid.width, height = vid.height;
757 unsigned char *b, *out;
759 int outoffset = (width/2)*(height/2);
760 //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);
761 // speed is critical here, so do saving as directly as possible
762 switch (cls.capturevideo_format)
764 case CAPTUREVIDEOFORMAT_RAWYV12:
765 // FIXME: width/height must be multiple of 2, enforce this?
766 qglReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, cls.capturevideo_buffer);
768 // process one line at a time, and CbCr every other line at 2 pixel intervals
769 for (y = 0;y < height;y++)
772 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++)
773 *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]]];
776 // 2x2 Cb and Cr planes
778 // low quality, no averaging
779 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++)
782 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];
784 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];
787 // high quality, averaging
788 int inpitch = width*3;
789 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++)
791 int blockr, blockg, blockb;
792 blockr = (b[0] + b[3] + b[inpitch+0] + b[inpitch+3]) >> 2;
793 blockg = (b[1] + b[4] + b[inpitch+1] + b[inpitch+4]) >> 2;
794 blockb = (b[2] + b[5] + b[inpitch+2] + b[inpitch+5]) >> 2;
796 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];
798 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];
803 for (;cls.capturevideo_frame < newframenum;cls.capturevideo_frame++)
804 if (!FS_Write (cls.capturevideo_videofile, cls.capturevideo_buffer + width*height*3, width*height+(width/2)*(height/2)*2))
807 case CAPTUREVIDEOFORMAT_RAWRGB:
808 qglReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, cls.capturevideo_buffer);
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);
817 for (;cls.capturevideo_frame < newframenum;cls.capturevideo_frame++)
819 sprintf(filename, "video/dp%06d.jpg", cls.capturevideo_frame);
820 if (!JPEG_SaveImage_preflipped (filename, width, height, cls.capturevideo_buffer))
824 case CAPTUREVIDEOFORMAT_TARGA:
825 //return Image_WriteTGARGB_preflipped (filename, width, height, cls.capturevideo_buffer, cls.capturevideo_buffer + vid.width * vid.height * 3, );
826 memset (cls.capturevideo_buffer, 0, 18);
827 cls.capturevideo_buffer[2] = 2; // uncompressed type
828 cls.capturevideo_buffer[12] = (width >> 0) & 0xFF;
829 cls.capturevideo_buffer[13] = (width >> 8) & 0xFF;
830 cls.capturevideo_buffer[14] = (height >> 0) & 0xFF;
831 cls.capturevideo_buffer[15] = (height >> 8) & 0xFF;
832 cls.capturevideo_buffer[16] = 24; // pixel size
833 qglReadPixels (x, y, width, height, GL_BGR, GL_UNSIGNED_BYTE, cls.capturevideo_buffer + 18);
835 for (;cls.capturevideo_frame < newframenum;cls.capturevideo_frame++)
837 sprintf(filename, "video/dp%06d.tga", cls.capturevideo_frame);
838 if (!FS_WriteFile (filename, cls.capturevideo_buffer, width*height*3 + 18))
847 void SCR_CaptureVideo_SoundFrame(unsigned char *bufstereo16le, size_t length, int rate)
849 if (!cls.capturevideo_soundfile)
851 cls.capturevideo_soundrate = rate;
852 if (FS_Write (cls.capturevideo_soundfile, bufstereo16le, 4 * length) < (fs_offset_t)(4 * length))
854 Cvar_SetValueQuick(&cl_capturevideo, 0);
855 Con_Printf("video sound saving failed on frame %i, out of disk space? stopping video capture.\n", cls.capturevideo_frame);
856 SCR_CaptureVideo_EndVideo();
860 void SCR_CaptureVideo(void)
863 if (cl_capturevideo.integer && r_render.integer)
865 if (!cls.capturevideo_active)
866 SCR_CaptureVideo_BeginVideo();
867 if (cls.capturevideo_framerate != cl_capturevideo_fps.value)
869 Con_Printf("You can not change the video framerate while recording a video.\n");
870 Cvar_SetValueQuick(&cl_capturevideo_fps, cls.capturevideo_framerate);
872 if (cls.capturevideo_soundfile)
874 // preserve sound sync by duplicating frames when running slow
875 newframenum = (int)((Sys_DoubleTime() - cls.capturevideo_starttime) * cls.capturevideo_framerate);
878 newframenum = cls.capturevideo_frame + 1;
879 // if falling behind more than one second, stop
880 if (newframenum - cls.capturevideo_frame > (int)ceil(cls.capturevideo_framerate))
882 Cvar_SetValueQuick(&cl_capturevideo, 0);
883 Con_Printf("video saving failed on frame %i, your machine is too slow for this capture speed.\n", cls.capturevideo_frame);
884 SCR_CaptureVideo_EndVideo();
888 if (!SCR_CaptureVideo_VideoFrame(newframenum))
890 Cvar_SetValueQuick(&cl_capturevideo, 0);
891 Con_Printf("video saving failed on frame %i, out of disk space? stopping video capture.\n", cls.capturevideo_frame);
892 SCR_CaptureVideo_EndVideo();
895 else if (cls.capturevideo_active)
896 SCR_CaptureVideo_EndVideo();
903 Grab six views for environment mapping tests
910 qboolean flipx, flipy, flipdiagonaly;
914 {{ 0, 0, 0}, "rt", false, false, false},
915 {{ 0, 270, 0}, "ft", false, false, false},
916 {{ 0, 180, 0}, "lf", false, false, false},
917 {{ 0, 90, 0}, "bk", false, false, false},
918 {{-90, 180, 0}, "up", true, true, false},
919 {{ 90, 180, 0}, "dn", true, true, false},
921 {{ 0, 0, 0}, "px", true, true, true},
922 {{ 0, 90, 0}, "py", false, true, false},
923 {{ 0, 180, 0}, "nx", false, false, true},
924 {{ 0, 270, 0}, "ny", true, false, false},
925 {{-90, 180, 0}, "pz", false, false, true},
926 {{ 90, 180, 0}, "nz", false, false, true}
929 static void R_Envmap_f (void)
932 char filename[MAX_QPATH], basename[MAX_QPATH];
933 unsigned char *buffer1;
934 unsigned char *buffer2;
935 unsigned char *buffer3;
939 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");
943 strlcpy (basename, Cmd_Argv(1), sizeof (basename));
944 size = atoi(Cmd_Argv(2));
945 if (size != 128 && size != 256 && size != 512 && size != 1024)
947 Con_Print("envmap: size must be one of 128, 256, 512, or 1024\n");
950 if (size > vid.width || size > vid.height)
952 Con_Print("envmap: your resolution is not big enough to render that size\n");
960 r_refdef.width = size;
961 r_refdef.height = size;
963 r_refdef.frustum_x = tan(90 * M_PI / 360.0);
964 r_refdef.frustum_y = tan(90 * M_PI / 360.0);
966 buffer1 = (unsigned char *)Mem_Alloc(tempmempool, size * size * 3);
967 buffer2 = (unsigned char *)Mem_Alloc(tempmempool, size * size * 3);
968 buffer3 = (unsigned char *)Mem_Alloc(tempmempool, size * size * 3 + 18);
970 for (j = 0;j < 12;j++)
972 sprintf(filename, "env/%s%s.tga", basename, envmapinfo[j].name);
973 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);
978 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);
988 //=============================================================================
990 // LordHavoc: SHOWLMP stuff
991 #define SHOWLMP_MAXLABELS 256
992 typedef struct showlmp_s
1002 showlmp_t showlmp[SHOWLMP_MAXLABELS];
1004 void SHOWLMP_decodehide(void)
1008 lmplabel = MSG_ReadString();
1009 for (i = 0;i < SHOWLMP_MAXLABELS;i++)
1010 if (showlmp[i].isactive && strcmp(showlmp[i].label, lmplabel) == 0)
1012 showlmp[i].isactive = false;
1017 void SHOWLMP_decodeshow(void)
1020 char lmplabel[256], picname[256];
1022 strlcpy (lmplabel,MSG_ReadString(), sizeof (lmplabel));
1023 strlcpy (picname, MSG_ReadString(), sizeof (picname));
1024 if (gamemode == GAME_NEHAHRA) // LordHavoc: nasty old legacy junk
1031 x = MSG_ReadShort();
1032 y = MSG_ReadShort();
1035 for (i = 0;i < SHOWLMP_MAXLABELS;i++)
1036 if (showlmp[i].isactive)
1038 if (strcmp(showlmp[i].label, lmplabel) == 0)
1041 break; // drop out to replace it
1044 else if (k < 0) // find first empty one to replace
1047 return; // none found to replace
1048 // change existing one
1049 showlmp[k].isactive = true;
1050 strlcpy (showlmp[k].label, lmplabel, sizeof (showlmp[k].label));
1051 strlcpy (showlmp[k].pic, picname, sizeof (showlmp[k].pic));
1056 void SHOWLMP_drawall(void)
1059 for (i = 0;i < SHOWLMP_MAXLABELS;i++)
1060 if (showlmp[i].isactive)
1061 DrawQ_Pic(showlmp[i].x, showlmp[i].y, Draw_CachePic(showlmp[i].pic, true), 0, 0, 1, 1, 1, 1, 0);
1064 void SHOWLMP_clear(void)
1067 for (i = 0;i < SHOWLMP_MAXLABELS;i++)
1068 showlmp[i].isactive = false;
1072 ==============================================================================
1076 ==============================================================================
1079 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)
1081 int indices[3] = {0,1,2};
1084 if (!r_render.integer)
1087 qglReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer1);
1090 if (scr_screenshot_gamma.value != 1 && gammacorrect)
1093 double igamma = 1.0 / scr_screenshot_gamma.value;
1094 unsigned char ramp[256];
1095 for (i = 0;i < 256;i++)
1096 ramp[i] = (unsigned char) (pow(i * (1.0 / 255.0), igamma) * 255.0);
1097 for (i = 0;i < width*height*3;i++)
1098 buffer1[i] = ramp[buffer1[i]];
1101 Image_CopyMux (buffer2, buffer1, width, height, flipx, flipy, flipdiagonal, 3, 3, indices);
1104 ret = JPEG_SaveImage_preflipped (filename, width, height, buffer2);
1106 ret = Image_WriteTGARGB_preflipped (filename, width, height, buffer2, buffer3);
1111 //=============================================================================
1113 void R_ClearScreen(void)
1115 if (r_render.integer)
1119 qglClearColor(fogcolor[0],fogcolor[1],fogcolor[2],0);
1121 qglClearColor(0,0,0,0);
1123 qglClearDepth(1);CHECKGLERROR
1126 // LordHavoc: we use a stencil centered around 128 instead of 0,
1127 // to avoid clamping interfering with strange shadow volume
1129 qglClearStencil(128);CHECKGLERROR
1132 GL_Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | (gl_stencil ? GL_STENCIL_BUFFER_BIT : 0));
1133 // set dithering mode
1134 if (gl_dither.integer)
1136 qglEnable(GL_DITHER);CHECKGLERROR
1140 qglDisable(GL_DITHER);CHECKGLERROR
1145 qboolean CL_VM_UpdateView (void);
1146 void SCR_DrawConsole (void);
1147 void R_Shadow_EditLights_DrawSelectedLightProperties(void);
1151 void SCR_DrawScreen (void)
1155 if (r_timereport_active)
1156 R_TimeReport("setup");
1158 if (cls.signon == SIGNONS)
1162 size = scr_viewsize.value * (1.0 / 100.0);
1163 size = min(size, 1);
1165 if (r_stereo_sidebyside.integer)
1167 r_refdef.width = (int)(vid.width * size / 2.5);
1168 r_refdef.height = (int)(vid.height * size / 2.5 * (1 - bound(0, r_letterbox.value, 100) / 100));
1169 r_refdef.x = (int)((vid.width - r_refdef.width * 2.5) * 0.5);
1170 r_refdef.y = (int)((vid.height - r_refdef.height)/2);
1172 r_refdef.x += (int)(r_refdef.width * 1.5);
1176 r_refdef.width = (int)(vid.width * size);
1177 r_refdef.height = (int)(vid.height * size * (1 - bound(0, r_letterbox.value, 100) / 100));
1178 r_refdef.x = (int)((vid.width - r_refdef.width)/2);
1179 r_refdef.y = (int)((vid.height - r_refdef.height)/2);
1182 // LordHavoc: viewzoom (zoom in for sniper rifles, etc)
1183 // LordHavoc: this is designed to produce widescreen fov values
1184 // when the screen is wider than 4/3 width/height aspect, to do
1185 // this it simply assumes the requested fov is the vertical fov
1186 // for a 4x3 display, if the ratio is not 4x3 this makes the fov
1187 // higher/lower according to the ratio
1188 r_refdef.frustum_y = tan(scr_fov.value * cl.viewzoom * M_PI / 360.0) * (3.0/4.0);
1189 r_refdef.frustum_x = r_refdef.frustum_y * (float)r_refdef.width / (float)r_refdef.height / vid_pixelheight.value;
1191 r_refdef.frustum_x *= r_refdef.frustumscale_x;
1192 r_refdef.frustum_y *= r_refdef.frustumscale_y;
1194 if(!CL_VM_UpdateView())
1199 if (scr_zoomwindow.integer)
1201 float sizex = bound(10, scr_zoomwindow_viewsizex.value, 100) / 100.0;
1202 float sizey = bound(10, scr_zoomwindow_viewsizey.value, 100) / 100.0;
1203 r_refdef.width = (int)(vid.width * sizex);
1204 r_refdef.height = (int)(vid.height * sizey);
1205 r_refdef.x = (int)((vid.width - r_refdef.width)/2);
1208 r_refdef.frustum_y = tan(scr_zoomwindow_fov.value * cl.viewzoom * M_PI / 360.0) * (3.0/4.0);
1209 r_refdef.frustum_x = r_refdef.frustum_y * vid_pixelheight.value * (float)r_refdef.width / (float)r_refdef.height;
1211 r_refdef.frustum_x *= r_refdef.frustumscale_x;
1212 r_refdef.frustum_y *= r_refdef.frustumscale_y;
1214 if(!CL_VM_UpdateView())
1219 if (!r_stereo_sidebyside.integer)
1221 r_refdef.width = vid.width;
1222 r_refdef.height = vid.height;
1230 //FIXME: force menu if nothing else to look at?
1231 //if (key_dest == key_game && cls.signon != SIGNONS && cls.state == ca_disconnected)
1233 if (cls.signon == SIGNONS)
1238 if (!r_letterbox.value)
1241 SCR_CheckDrawCenterString();
1245 R_Shadow_EditLights_DrawSelectedLightProperties();
1254 if (r_timereport_active)
1257 if (cls.signon == SIGNONS)
1258 R_TimeReport_Frame();
1266 if (r_timereport_active)
1267 R_TimeReport("meshfinish");
1270 void SCR_UpdateLoadingScreen (void)
1275 float texcoord2f[8];
1276 // don't do anything if not initialized yet
1279 qglViewport(0, 0, vid.width, vid.height);
1280 //qglDisable(GL_SCISSOR_TEST);
1282 qglColorMask(1,1,1,1);
1283 //qglClearColor(0,0,0,0);
1284 //qglClear(GL_COLOR_BUFFER_BIT);
1285 //qglCullFace(GL_FRONT);
1286 //qglDisable(GL_CULL_FACE);
1289 GL_SetupView_Mode_Ortho(0, 0, vid_conwidth.integer, vid_conheight.integer, -10, 100);
1291 R_Mesh_Matrix(&identitymatrix);
1292 // draw the loading plaque
1293 pic = Draw_CachePic("gfx/loading", true);
1294 x = (vid_conwidth.integer - pic->width)/2;
1295 y = (vid_conheight.integer - pic->height)/2;
1297 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1298 GL_DepthTest(false);
1299 R_Mesh_VertexPointer(vertex3f);
1300 R_Mesh_ColorPointer(NULL);
1301 R_Mesh_ResetTextureState();
1302 R_Mesh_TexBind(0, R_GetTexture(pic->tex));
1303 R_Mesh_TexCoordPointer(0, 2, texcoord2f);
1304 vertex3f[2] = vertex3f[5] = vertex3f[8] = vertex3f[11] = 0;
1305 vertex3f[0] = vertex3f[9] = x;
1306 vertex3f[1] = vertex3f[4] = y;
1307 vertex3f[3] = vertex3f[6] = x + pic->width;
1308 vertex3f[7] = vertex3f[10] = y + pic->height;
1309 texcoord2f[0] = 0;texcoord2f[1] = 0;
1310 texcoord2f[2] = 1;texcoord2f[3] = 0;
1311 texcoord2f[4] = 1;texcoord2f[5] = 1;
1312 texcoord2f[6] = 0;texcoord2f[7] = 1;
1313 R_Mesh_Draw(0, 4, 2, polygonelements);
1319 void CL_UpdateScreen(void)
1321 float conwidth, conheight;
1326 if (!scr_initialized || !con_initialized || vid_hidden)
1327 return; // not initialized yet
1329 // don't allow cheats in multiplayer
1330 if (!cl.islocalgame && cl.worldmodel)
1332 if (r_fullbright.integer != 0)
1333 Cvar_Set ("r_fullbright", "0");
1334 if (r_ambient.value != 0)
1335 Cvar_Set ("r_ambient", "0");
1338 conwidth = bound(320, vid_conwidth.value, 2048);
1339 conheight = bound(200, vid_conheight.value, 1536);
1340 if (vid_conwidth.value != conwidth)
1341 Cvar_SetValue("vid_conwidth", conwidth);
1342 if (vid_conheight.value != conheight)
1343 Cvar_SetValue("vid_conheight", conheight);
1346 if (scr_viewsize.value < 30)
1347 Cvar_Set ("viewsize","30");
1348 if (scr_viewsize.value > 120)
1349 Cvar_Set ("viewsize","120");
1351 // bound field of view
1352 if (scr_fov.value < 1)
1353 Cvar_Set ("fov","1");
1354 if (scr_fov.value > 170)
1355 Cvar_Set ("fov","170");
1357 // validate r_textureunits cvar
1358 if (r_textureunits.integer > gl_textureunits)
1359 Cvar_SetValueQuick(&r_textureunits, gl_textureunits);
1360 if (r_textureunits.integer < 1)
1361 Cvar_SetValueQuick(&r_textureunits, 1);
1363 // validate gl_combine cvar
1364 if (gl_combine.integer && !gl_combine_extension)
1365 Cvar_SetValueQuick(&gl_combine, 0);
1367 // intermission is always full screen
1368 if (cl.intermission)
1372 if (scr_viewsize.value >= 120)
1373 sb_lines = 0; // no status bar at all
1374 else if (scr_viewsize.value >= 110)
1375 sb_lines = 24; // no inventory
1380 r_refdef.colormask[0] = 1;
1381 r_refdef.colormask[1] = 1;
1382 r_refdef.colormask[2] = 1;
1384 if (r_timereport_active)
1385 R_TimeReport("other");
1387 SCR_SetUpToDrawConsole();
1389 if (r_timereport_active)
1390 R_TimeReport("start");
1393 qglViewport(0, 0, vid.width, vid.height);
1394 qglDisable(GL_SCISSOR_TEST);
1396 qglColorMask(1,1,1,1);
1397 qglClearColor(0,0,0,0);
1398 qglClear(GL_COLOR_BUFFER_BIT);
1401 if (r_timereport_active)
1402 R_TimeReport("clear");
1404 if (r_stereo_redblue.integer || r_stereo_redgreen.integer || r_stereo_redcyan.integer || r_stereo_sidebyside.integer)
1406 matrix4x4_t originalmatrix = r_refdef.viewentitymatrix;
1407 r_refdef.viewentitymatrix.m[0][3] = originalmatrix.m[0][3] + r_stereo_separation.value * -0.5f * r_refdef.viewentitymatrix.m[0][1];
1408 r_refdef.viewentitymatrix.m[1][3] = originalmatrix.m[1][3] + r_stereo_separation.value * -0.5f * r_refdef.viewentitymatrix.m[1][1];
1409 r_refdef.viewentitymatrix.m[2][3] = originalmatrix.m[2][3] + r_stereo_separation.value * -0.5f * r_refdef.viewentitymatrix.m[2][1];
1411 if (r_stereo_sidebyside.integer)
1414 if (r_stereo_redblue.integer || r_stereo_redgreen.integer || r_stereo_redcyan.integer)
1416 r_refdef.colormask[0] = 1;
1417 r_refdef.colormask[1] = 0;
1418 r_refdef.colormask[2] = 0;
1423 r_refdef.viewentitymatrix.m[0][3] = originalmatrix.m[0][3] + r_stereo_separation.value * 0.5f * r_refdef.viewentitymatrix.m[0][1];
1424 r_refdef.viewentitymatrix.m[1][3] = originalmatrix.m[1][3] + r_stereo_separation.value * 0.5f * r_refdef.viewentitymatrix.m[1][1];
1425 r_refdef.viewentitymatrix.m[2][3] = originalmatrix.m[2][3] + r_stereo_separation.value * 0.5f * r_refdef.viewentitymatrix.m[2][1];
1427 if (r_stereo_sidebyside.integer)
1430 if (r_stereo_redblue.integer || r_stereo_redgreen.integer || r_stereo_redcyan.integer)
1432 r_refdef.colormask[0] = 0;
1433 r_refdef.colormask[1] = r_stereo_redcyan.integer || r_stereo_redgreen.integer;
1434 r_refdef.colormask[2] = r_stereo_redcyan.integer || r_stereo_redblue.integer;
1439 r_refdef.viewentitymatrix = originalmatrix;
1447 if (r_timereport_active)
1448 R_TimeReport("finish");
1451 void CL_Screen_NewMap(void)