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_conforcewhiledisconnected = {0, "scr_conforcewhiledisconnected", "1", "forces fullscreen console while disconnected"};
13 cvar_t scr_menuforcewhiledisconnected = {0, "scr_menuforcewhiledisconnected", "0", "forces menu while disconnected"};
14 cvar_t scr_centertime = {0, "scr_centertime","2", "how long centerprint messages show"};
15 cvar_t scr_showram = {CVAR_SAVE, "showram","1", "show ram icon if low on surface cache memory (not used)"};
16 cvar_t scr_showturtle = {CVAR_SAVE, "showturtle","0", "show turtle icon when framerate is too low (not used)"};
17 cvar_t scr_showpause = {CVAR_SAVE, "showpause","1", "show pause icon when game is paused"};
18 cvar_t scr_showbrand = {0, "showbrand","0", "shows gfx/brand.tga in a corner of the screen (different values select different positions, including centered)"};
19 cvar_t scr_printspeed = {0, "scr_printspeed","8", "speed of intermission printing (episode end texts)"};
20 cvar_t vid_conwidth = {CVAR_SAVE, "vid_conwidth", "640", "virtual width of 2D graphics system"};
21 cvar_t vid_conheight = {CVAR_SAVE, "vid_conheight", "480", "virtual height of 2D graphics system"};
22 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)"};
23 cvar_t scr_screenshot_jpeg = {CVAR_SAVE, "scr_screenshot_jpeg","1", "save jpeg instead of targa"};
24 cvar_t scr_screenshot_jpeg_quality = {CVAR_SAVE, "scr_screenshot_jpeg_quality","0.9", "image quality of saved jpeg"};
25 cvar_t scr_screenshot_gamma = {CVAR_SAVE, "scr_screenshot_gamma","2.2", "gamma correction on saved screenshots and videos, 1.0 saves unmodified images"};
26 // scr_screenshot_name is defined in fs.c
27 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)"};
28 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)"};
29 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)"};
30 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)"};
31 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)"};
32 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)"};
33 cvar_t r_stereo_separation = {0, "r_stereo_separation", "4", "separation of eyes in the world (try negative values too)"};
34 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)"};
35 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)"};
36 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"};
37 cvar_t r_stereo_redgreen = {0, "r_stereo_redgreen", "0", "red/green anaglyph stereo glasses (for those who don't mind yellow)"};
38 cvar_t scr_zoomwindow = {CVAR_SAVE, "scr_zoomwindow", "0", "displays a zoomed in overlay window"};
39 cvar_t scr_zoomwindow_viewsizex = {CVAR_SAVE, "scr_zoomwindow_viewsizex", "20", "horizontal viewsize of zoom window"};
40 cvar_t scr_zoomwindow_viewsizey = {CVAR_SAVE, "scr_zoomwindow_viewsizey", "20", "vertical viewsize of zoom window"};
41 cvar_t scr_zoomwindow_fov = {CVAR_SAVE, "scr_zoomwindow_fov", "20", "fov of zoom window"};
44 int jpeg_supported = false;
46 qboolean scr_initialized; // ready to draw
48 float scr_con_current;
50 extern int con_vislines;
52 void DrawCrosshair(int num);
53 static void SCR_ScreenShot_f (void);
54 static void R_Envmap_f (void);
57 void R_ClearScreen(void);
60 ===============================================================================
64 ===============================================================================
67 char scr_centerstring[MAX_INPUTLINE];
68 float scr_centertime_start; // for slow victory printing
69 float scr_centertime_off;
78 Called for important messages that should stay in the center of the screen
82 void SCR_CenterPrint(char *str)
84 strlcpy (scr_centerstring, str, sizeof (scr_centerstring));
85 scr_centertime_off = scr_centertime.value;
86 scr_centertime_start = cl.time;
88 // count the number of lines for centering
99 void SCR_DrawCenterString (void)
107 // the finale prints the characters one at a time
109 remaining = (int)(scr_printspeed.value * (cl.time - scr_centertime_start));
113 scr_erase_center = 0;
114 start = scr_centerstring;
119 if (scr_center_lines <= 4)
120 y = (int)(vid_conheight.integer*0.35);
127 // scan the width of the line
128 for (l=0 ; l<vid_conwidth.integer/8 ; l++)
129 if (start[l] == '\n' || !start[l])
131 x = (vid_conwidth.integer - l*8)/2;
136 DrawQ_ColoredString(x, y, start, l, 8, 8, 1, 1, 1, 1, 0, &color);
144 while (*start && *start != '\n')
149 start++; // skip the \n
153 void SCR_CheckDrawCenterString (void)
155 if (scr_center_lines > scr_erase_lines)
156 scr_erase_lines = scr_center_lines;
158 scr_centertime_off -= cl.realframetime;
160 // don't draw if this is a normal stats-screen intermission,
161 // only if it is not an intermission, or a finale intermission
162 if (cl.intermission == 1)
164 if (scr_centertime_off <= 0 && !cl.intermission)
166 if (key_dest != key_game)
169 SCR_DrawCenterString ();
177 void SCR_DrawTurtle (void)
181 if (cls.state != ca_connected)
184 if (!scr_showturtle.integer)
187 if (cl.realframetime < 0.1)
197 DrawQ_Pic (0, 0, Draw_CachePic("gfx/turtle", true), 0, 0, 1, 1, 1, 1, 0);
205 void SCR_DrawNet (void)
207 if (cls.state != ca_connected)
209 if (realtime - cl.last_received_message < 0.3)
211 if (cls.demoplayback)
214 DrawQ_Pic (64, 0, Draw_CachePic("gfx/net", true), 0, 0, 1, 1, 1, 1, 0);
222 void SCR_DrawPause (void)
226 if (cls.state != ca_connected)
229 if (!scr_showpause.integer) // turn off for screenshots
235 pic = Draw_CachePic ("gfx/pause", true);
236 DrawQ_Pic ((vid_conwidth.integer - pic->width)/2, (vid_conheight.integer - pic->height)/2, pic, 0, 0, 1, 1, 1, 1, 0);
244 void SCR_DrawBrand (void)
249 if (!scr_showbrand.value)
252 pic = Draw_CachePic ("gfx/brand", true);
254 switch ((int)scr_showbrand.value)
256 case 1: // bottom left
258 y = vid_conheight.integer - pic->height;
260 case 2: // bottom centre
261 x = (vid_conwidth.integer - pic->width) / 2;
262 y = vid_conheight.integer - pic->height;
264 case 3: // bottom right
265 x = vid_conwidth.integer - pic->width;
266 y = vid_conheight.integer - pic->height;
268 case 4: // centre right
269 x = vid_conwidth.integer - pic->width;
270 y = (vid_conheight.integer - pic->height) / 2;
273 x = vid_conwidth.integer - pic->width;
276 case 6: // top centre
277 x = (vid_conwidth.integer - pic->width) / 2;
284 case 8: // centre left
286 y = (vid_conheight.integer - pic->height) / 2;
292 DrawQ_Pic (x, y, pic, 0, 0, 1, 1, 1, 1, 0);
300 static void SCR_DrawDownload(void)
306 if (!cls.qw_downloadname[0])
308 dpsnprintf(temp, sizeof(temp), "Downloading %s ... %3i%%\n", cls.qw_downloadname, cls.qw_downloadpercent);
309 len = (int)strlen(temp);
310 x = (vid_conwidth.integer - len*size) / 2;
311 y = vid_conheight.integer - size;
312 DrawQ_Pic(0, y, NULL, vid_conwidth.integer, size, 0, 0, 0, 0.5, 0);
313 DrawQ_String(x, y, temp, len, size, size, 1, 1, 1, 1, 0);
316 //=============================================================================
321 SCR_SetUpToDrawConsole
324 void SCR_SetUpToDrawConsole (void)
326 // lines of console to display
328 static int framecounter = 0;
332 if (scr_menuforcewhiledisconnected.integer && key_dest == key_game && cls.state == ca_disconnected)
334 if (framecounter >= 2)
342 if (scr_conforcewhiledisconnected.integer && key_dest == key_game && cls.signon != SIGNONS)
343 key_consoleactive |= KEY_CONSOLEACTIVE_FORCED;
345 key_consoleactive &= ~KEY_CONSOLEACTIVE_FORCED;
347 // decide on the height of the console
348 if (key_consoleactive & KEY_CONSOLEACTIVE_USER)
349 conlines = vid_conheight.integer/2; // half screen
351 conlines = 0; // none visible
353 scr_con_current = conlines;
361 void SCR_DrawConsole (void)
363 if (key_consoleactive & KEY_CONSOLEACTIVE_FORCED)
366 Con_DrawConsole (vid_conheight.integer);
368 else if (scr_con_current)
369 Con_DrawConsole ((int)scr_con_current);
373 if (key_dest == key_game || key_dest == key_message)
374 Con_DrawNotify (); // only draw notify in game
380 SCR_BeginLoadingPlaque
384 void SCR_BeginLoadingPlaque (void)
386 // save console log up to this point to log_file if it was set by configs
391 SCR_UpdateLoadingScreen();
394 //=============================================================================
396 char r_speeds_string[1024];
397 int speedstringcount, r_timereport_active;
398 double r_timereport_temp = 0, r_timereport_current = 0, r_timereport_start = 0;
400 void R_TimeReport(char *desc)
406 if (r_speeds.integer < 2 || !r_timereport_active)
410 r_timereport_temp = r_timereport_current;
411 r_timereport_current = Sys_DoubleTime();
412 t = (int) ((r_timereport_current - r_timereport_temp) * 1000000.0 + 0.5);
414 dpsnprintf(tempbuf, sizeof(tempbuf), "%8i %-11s", t, desc);
415 length = (int)strlen(tempbuf);
416 if (speedstringcount + length > (vid_conwidth.integer / 8))
418 strlcat(r_speeds_string, "\n", sizeof(r_speeds_string));
419 speedstringcount = 0;
421 strlcat(r_speeds_string, tempbuf, sizeof(r_speeds_string));
422 speedstringcount += length;
425 void R_TimeReport_Frame(void)
429 if (r_speeds_string[0])
431 if (r_timereport_active)
433 r_timereport_current = r_timereport_start;
434 R_TimeReport("total");
437 if (r_speeds_string[strlen(r_speeds_string)-1] == '\n')
438 r_speeds_string[strlen(r_speeds_string)-1] = 0;
440 for (i = 0;r_speeds_string[i];i++)
441 if (r_speeds_string[i] == '\n')
443 y = vid_conheight.integer - sb_lines - lines * 8;
445 DrawQ_Pic(0, y, NULL, vid_conwidth.integer, lines * 8, 0, 0, 0, 0.5, 0);
446 while (r_speeds_string[i])
449 while (r_speeds_string[i] && r_speeds_string[i] != '\n')
452 DrawQ_String(0, y, r_speeds_string + j, i - j, 8, 8, 1, 1, 1, 1, 0);
453 if (r_speeds_string[i] == '\n')
457 r_speeds_string[0] = 0;
458 r_timereport_active = false;
460 if (r_speeds.integer && cls.signon == SIGNONS && cls.state == ca_connected)
462 speedstringcount = 0;
463 r_speeds_string[0] = 0;
464 r_timereport_active = false;
465 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]);
466 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);
467 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);
468 if (renderstats.bloom)
469 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);
471 sprintf(r_speeds_string + strlen(r_speeds_string), "rendered%6i meshes%8i triangles\n", renderstats.meshes, renderstats.meshes_elements / 3);
473 memset(&renderstats, 0, sizeof(renderstats));
475 if (r_speeds.integer >= 2)
477 r_timereport_active = true;
478 r_timereport_start = r_timereport_current = Sys_DoubleTime();
490 void SCR_SizeUp_f (void)
492 Cvar_SetValue ("viewsize",scr_viewsize.value+10);
503 void SCR_SizeDown_f (void)
505 Cvar_SetValue ("viewsize",scr_viewsize.value-10);
508 void CL_Screen_Init(void)
510 Cvar_RegisterVariable (&scr_fov);
511 Cvar_RegisterVariable (&scr_viewsize);
512 Cvar_RegisterVariable (&scr_conalpha);
513 Cvar_RegisterVariable (&scr_conforcewhiledisconnected);
514 Cvar_RegisterVariable (&scr_menuforcewhiledisconnected);
515 Cvar_RegisterVariable (&scr_showram);
516 Cvar_RegisterVariable (&scr_showturtle);
517 Cvar_RegisterVariable (&scr_showpause);
518 Cvar_RegisterVariable (&scr_showbrand);
519 Cvar_RegisterVariable (&scr_centertime);
520 Cvar_RegisterVariable (&scr_printspeed);
521 Cvar_RegisterVariable (&vid_conwidth);
522 Cvar_RegisterVariable (&vid_conheight);
523 Cvar_RegisterVariable (&vid_pixelheight);
524 Cvar_RegisterVariable (&scr_screenshot_jpeg);
525 Cvar_RegisterVariable (&scr_screenshot_jpeg_quality);
526 Cvar_RegisterVariable (&scr_screenshot_gamma);
527 Cvar_RegisterVariable (&cl_capturevideo);
528 Cvar_RegisterVariable (&cl_capturevideo_sound);
529 Cvar_RegisterVariable (&cl_capturevideo_fps);
530 Cvar_RegisterVariable (&cl_capturevideo_rawrgb);
531 Cvar_RegisterVariable (&cl_capturevideo_rawyv12);
532 Cvar_RegisterVariable (&r_letterbox);
533 Cvar_RegisterVariable(&r_stereo_separation);
534 Cvar_RegisterVariable(&r_stereo_sidebyside);
535 Cvar_RegisterVariable(&r_stereo_redblue);
536 Cvar_RegisterVariable(&r_stereo_redcyan);
537 Cvar_RegisterVariable(&r_stereo_redgreen);
538 Cvar_RegisterVariable(&scr_zoomwindow);
539 Cvar_RegisterVariable(&scr_zoomwindow_viewsizex);
540 Cvar_RegisterVariable(&scr_zoomwindow_viewsizey);
541 Cvar_RegisterVariable(&scr_zoomwindow_fov);
543 Cmd_AddCommand ("sizeup",SCR_SizeUp_f, "increase view size (increases viewsize cvar)");
544 Cmd_AddCommand ("sizedown",SCR_SizeDown_f, "decrease view size (decreases viewsize cvar)");
545 Cmd_AddCommand ("screenshot",SCR_ScreenShot_f, "takes a screenshot of the next rendered frame");
546 Cmd_AddCommand ("envmap", R_Envmap_f, "render a cubemap (skybox) of the current scene");
548 scr_initialized = true;
556 void SCR_ScreenShot_f (void)
558 static int shotnumber;
559 static char oldname[MAX_QPATH];
560 char base[MAX_QPATH];
561 char filename[MAX_QPATH];
562 unsigned char *buffer1;
563 unsigned char *buffer2;
564 unsigned char *buffer3;
565 qboolean jpeg = (scr_screenshot_jpeg.integer != 0);
567 sprintf (base, "screenshots/%s", scr_screenshot_name.string);
569 if (strcmp (oldname, scr_screenshot_name.string))
571 sprintf(oldname, "%s", scr_screenshot_name.string);
575 // find a file name to save it to
576 for (;shotnumber < 1000000;shotnumber++)
577 if (!FS_SysFileExists(va("%s/%s%06d.tga", fs_gamedir, base, shotnumber)) && !FS_SysFileExists(va("%s/%s%06d.jpg", fs_gamedir, base, shotnumber)))
579 if (shotnumber >= 1000000)
581 Con_Print("SCR_ScreenShot_f: Couldn't create the image file\n");
585 sprintf(filename, "%s%06d.%s", base, shotnumber, jpeg ? "jpg" : "tga");
587 buffer1 = (unsigned char *)Mem_Alloc(tempmempool, vid.width * vid.height * 3);
588 buffer2 = (unsigned char *)Mem_Alloc(tempmempool, vid.width * vid.height * 3);
589 buffer3 = (unsigned char *)Mem_Alloc(tempmempool, vid.width * vid.height * 3 + 18);
591 if (SCR_ScreenShot (filename, buffer1, buffer2, buffer3, 0, 0, vid.width, vid.height, false, false, false, jpeg, true))
592 Con_Printf("Wrote %s\n", filename);
594 Con_Printf("unable to write %s\n", filename);
603 void SCR_CaptureVideo_BeginVideo(void)
607 unsigned char out[44];
608 if (cls.capturevideo_active)
610 // soundrate is figured out on the first SoundFrame
611 cls.capturevideo_active = true;
612 cls.capturevideo_starttime = Sys_DoubleTime();
613 cls.capturevideo_framerate = bound(1, cl_capturevideo_fps.value, 1000);
614 cls.capturevideo_soundrate = 0;
615 cls.capturevideo_frame = 0;
616 cls.capturevideo_buffer = (unsigned char *)Mem_Alloc(tempmempool, vid.width * vid.height * (3+3+3) + 18);
617 gamma = 1.0/scr_screenshot_gamma.value;
620 for (i = 0;i < 256;i++)
622 unsigned char j = (unsigned char)bound(0, 255*pow(i/255.0, gamma), 255);
623 cls.capturevideo_rgbgammatable[0][i] = j;
624 cls.capturevideo_rgbgammatable[1][i] = j;
625 cls.capturevideo_rgbgammatable[2][i] = j;
629 R = Y + 1.4075 * (Cr - 128);
630 G = Y + -0.3455 * (Cb - 128) + -0.7169 * (Cr - 128);
631 B = Y + 1.7790 * (Cb - 128);
632 Y = R * .299 + G * .587 + B * .114;
633 Cb = R * -.169 + G * -.332 + B * .500 + 128.;
634 Cr = R * .500 + G * -.419 + B * -.0813 + 128.;
636 for (i = 0;i < 256;i++)
638 g = 255*pow(i/255.0, gamma);
639 // Y weights from RGB
640 cls.capturevideo_rgbtoyuvscaletable[0][0][i] = (short)(g * 0.299);
641 cls.capturevideo_rgbtoyuvscaletable[0][1][i] = (short)(g * 0.587);
642 cls.capturevideo_rgbtoyuvscaletable[0][2][i] = (short)(g * 0.114);
643 // Cb weights from RGB
644 cls.capturevideo_rgbtoyuvscaletable[1][0][i] = (short)(g * -0.169);
645 cls.capturevideo_rgbtoyuvscaletable[1][1][i] = (short)(g * -0.332);
646 cls.capturevideo_rgbtoyuvscaletable[1][2][i] = (short)(g * 0.500);
647 // Cr weights from RGB
648 cls.capturevideo_rgbtoyuvscaletable[2][0][i] = (short)(g * 0.500);
649 cls.capturevideo_rgbtoyuvscaletable[2][1][i] = (short)(g * -0.419);
650 cls.capturevideo_rgbtoyuvscaletable[2][2][i] = (short)(g * -0.0813);
651 // range reduction of YCbCr to valid signal range
652 cls.capturevideo_yuvnormalizetable[0][i] = 16 + i * (236-16) / 256;
653 cls.capturevideo_yuvnormalizetable[1][i] = 16 + i * (240-16) / 256;
654 cls.capturevideo_yuvnormalizetable[2][i] = 16 + i * (240-16) / 256;
657 if (cl_capturevideo_rawrgb.integer)
659 cls.capturevideo_format = CAPTUREVIDEOFORMAT_RAWRGB;
660 cls.capturevideo_videofile = FS_Open ("video/dpvideo.rgb", "wb", false, true);
662 else if (cl_capturevideo_rawyv12.integer)
664 cls.capturevideo_format = CAPTUREVIDEOFORMAT_RAWYV12;
665 cls.capturevideo_videofile = FS_Open ("video/dpvideo.yv12", "wb", false, true);
667 else if (scr_screenshot_jpeg.integer)
669 cls.capturevideo_format = CAPTUREVIDEOFORMAT_JPEG;
670 cls.capturevideo_videofile = NULL;
674 cls.capturevideo_format = CAPTUREVIDEOFORMAT_TARGA;
675 cls.capturevideo_videofile = NULL;
678 if (cl_capturevideo_sound.integer)
680 cls.capturevideo_soundfile = FS_Open ("video/dpvideo.wav", "wb", false, true);
681 // wave header will be filled out when video ends
683 FS_Write (cls.capturevideo_soundfile, out, 44);
686 cls.capturevideo_soundfile = NULL;
689 void SCR_CaptureVideo_EndVideo(void)
692 unsigned char out[44];
693 if (!cls.capturevideo_active)
695 cls.capturevideo_active = false;
697 if (cls.capturevideo_videofile)
699 FS_Close(cls.capturevideo_videofile);
700 cls.capturevideo_videofile = NULL;
703 // finish the wave file
704 if (cls.capturevideo_soundfile)
706 i = (int)FS_Tell (cls.capturevideo_soundfile);
707 //"RIFF", (int) unknown (chunk size), "WAVE",
708 //"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
709 //"data", (int) unknown (chunk size)
710 memcpy (out, "RIFF****WAVEfmt \x10\x00\x00\x00\x01\x00\x02\x00********\x04\x00\x10\0data****", 44);
711 // the length of the whole RIFF chunk
714 out[5] = (n >> 8) & 0xFF;
715 out[6] = (n >> 16) & 0xFF;
716 out[7] = (n >> 24) & 0xFF;
718 n = cls.capturevideo_soundrate;
719 out[24] = (n) & 0xFF;
720 out[25] = (n >> 8) & 0xFF;
721 out[26] = (n >> 16) & 0xFF;
722 out[27] = (n >> 24) & 0xFF;
723 // bytes per second (rate * channels * bytes per channel)
724 n = cls.capturevideo_soundrate * 2 * 2;
725 out[28] = (n) & 0xFF;
726 out[29] = (n >> 8) & 0xFF;
727 out[30] = (n >> 16) & 0xFF;
728 out[31] = (n >> 24) & 0xFF;
729 // the length of the data chunk
731 out[40] = (n) & 0xFF;
732 out[41] = (n >> 8) & 0xFF;
733 out[42] = (n >> 16) & 0xFF;
734 out[43] = (n >> 24) & 0xFF;
735 FS_Seek (cls.capturevideo_soundfile, 0, SEEK_SET);
736 FS_Write (cls.capturevideo_soundfile, out, 44);
737 FS_Close (cls.capturevideo_soundfile);
738 cls.capturevideo_soundfile = NULL;
741 if (cls.capturevideo_buffer)
743 Mem_Free (cls.capturevideo_buffer);
744 cls.capturevideo_buffer = NULL;
747 cls.capturevideo_starttime = 0;
748 cls.capturevideo_framerate = 0;
749 cls.capturevideo_frame = 0;
752 qboolean SCR_CaptureVideo_VideoFrame(int newframenum)
754 int x = 0, y = 0, width = vid.width, height = vid.height;
755 unsigned char *b, *out;
757 int outoffset = (width/2)*(height/2);
758 //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);
759 // speed is critical here, so do saving as directly as possible
760 switch (cls.capturevideo_format)
762 case CAPTUREVIDEOFORMAT_RAWYV12:
763 // FIXME: width/height must be multiple of 2, enforce this?
764 qglReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, cls.capturevideo_buffer);
766 // process one line at a time, and CbCr every other line at 2 pixel intervals
767 for (y = 0;y < height;y++)
770 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++)
771 *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]]];
774 // 2x2 Cb and Cr planes
776 // low quality, no averaging
777 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++)
780 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];
782 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];
785 // high quality, averaging
786 int inpitch = width*3;
787 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++)
789 int blockr, blockg, blockb;
790 blockr = (b[0] + b[3] + b[inpitch+0] + b[inpitch+3]) >> 2;
791 blockg = (b[1] + b[4] + b[inpitch+1] + b[inpitch+4]) >> 2;
792 blockb = (b[2] + b[5] + b[inpitch+2] + b[inpitch+5]) >> 2;
794 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];
796 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];
801 for (;cls.capturevideo_frame < newframenum;cls.capturevideo_frame++)
802 if (!FS_Write (cls.capturevideo_videofile, cls.capturevideo_buffer + width*height*3, width*height+(width/2)*(height/2)*2))
805 case CAPTUREVIDEOFORMAT_RAWRGB:
806 qglReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, cls.capturevideo_buffer);
808 for (;cls.capturevideo_frame < newframenum;cls.capturevideo_frame++)
809 if (!FS_Write (cls.capturevideo_videofile, cls.capturevideo_buffer, width*height*3))
812 case CAPTUREVIDEOFORMAT_JPEG:
813 qglReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, cls.capturevideo_buffer);
815 for (;cls.capturevideo_frame < newframenum;cls.capturevideo_frame++)
817 sprintf(filename, "video/dp%06d.jpg", cls.capturevideo_frame);
818 if (!JPEG_SaveImage_preflipped (filename, width, height, cls.capturevideo_buffer))
822 case CAPTUREVIDEOFORMAT_TARGA:
823 //return Image_WriteTGARGB_preflipped (filename, width, height, cls.capturevideo_buffer, cls.capturevideo_buffer + vid.width * vid.height * 3, );
824 memset (cls.capturevideo_buffer, 0, 18);
825 cls.capturevideo_buffer[2] = 2; // uncompressed type
826 cls.capturevideo_buffer[12] = (width >> 0) & 0xFF;
827 cls.capturevideo_buffer[13] = (width >> 8) & 0xFF;
828 cls.capturevideo_buffer[14] = (height >> 0) & 0xFF;
829 cls.capturevideo_buffer[15] = (height >> 8) & 0xFF;
830 cls.capturevideo_buffer[16] = 24; // pixel size
831 qglReadPixels (x, y, width, height, GL_BGR, GL_UNSIGNED_BYTE, cls.capturevideo_buffer + 18);
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)
1085 qglReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer1);
1088 if (scr_screenshot_gamma.value != 1 && gammacorrect)
1091 double igamma = 1.0 / scr_screenshot_gamma.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)
1117 qglClearColor(fogcolor[0],fogcolor[1],fogcolor[2],0);
1119 qglClearColor(0,0,0,0);
1121 qglClearDepth(1);CHECKGLERROR
1124 // LordHavoc: we use a stencil centered around 128 instead of 0,
1125 // to avoid clamping interfering with strange shadow volume
1127 qglClearStencil(128);CHECKGLERROR
1130 GL_Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | (gl_stencil ? GL_STENCIL_BUFFER_BIT : 0));
1131 // set dithering mode
1132 if (gl_dither.integer)
1134 qglEnable(GL_DITHER);CHECKGLERROR
1138 qglDisable(GL_DITHER);CHECKGLERROR
1143 qboolean CL_VM_UpdateView (void);
1144 void SCR_DrawConsole (void);
1145 void R_Shadow_EditLights_DrawSelectedLightProperties(void);
1149 void SCR_DrawScreen (void)
1153 if (r_timereport_active)
1154 R_TimeReport("setup");
1156 if (cls.signon == SIGNONS)
1160 size = scr_viewsize.value * (1.0 / 100.0);
1161 size = min(size, 1);
1163 if (r_stereo_sidebyside.integer)
1165 r_refdef.width = (int)(vid.width * size / 2.5);
1166 r_refdef.height = (int)(vid.height * size / 2.5 * (1 - bound(0, r_letterbox.value, 100) / 100));
1167 r_refdef.x = (int)((vid.width - r_refdef.width * 2.5) * 0.5);
1168 r_refdef.y = (int)((vid.height - r_refdef.height)/2);
1170 r_refdef.x += (int)(r_refdef.width * 1.5);
1174 r_refdef.width = (int)(vid.width * size);
1175 r_refdef.height = (int)(vid.height * size * (1 - bound(0, r_letterbox.value, 100) / 100));
1176 r_refdef.x = (int)((vid.width - r_refdef.width)/2);
1177 r_refdef.y = (int)((vid.height - r_refdef.height)/2);
1180 // LordHavoc: viewzoom (zoom in for sniper rifles, etc)
1181 // LordHavoc: this is designed to produce widescreen fov values
1182 // when the screen is wider than 4/3 width/height aspect, to do
1183 // this it simply assumes the requested fov is the vertical fov
1184 // for a 4x3 display, if the ratio is not 4x3 this makes the fov
1185 // higher/lower according to the ratio
1186 r_refdef.frustum_y = tan(scr_fov.value * cl.viewzoom * M_PI / 360.0) * (3.0/4.0);
1187 r_refdef.frustum_x = r_refdef.frustum_y * (float)r_refdef.width / (float)r_refdef.height / vid_pixelheight.value;
1189 r_refdef.frustum_x *= r_refdef.frustumscale_x;
1190 r_refdef.frustum_y *= r_refdef.frustumscale_y;
1192 if(!CL_VM_UpdateView())
1197 if (scr_zoomwindow.integer)
1199 float sizex = bound(10, scr_zoomwindow_viewsizex.value, 100) / 100.0;
1200 float sizey = bound(10, scr_zoomwindow_viewsizey.value, 100) / 100.0;
1201 r_refdef.width = (int)(vid.width * sizex);
1202 r_refdef.height = (int)(vid.height * sizey);
1203 r_refdef.x = (int)((vid.width - r_refdef.width)/2);
1206 r_refdef.frustum_y = tan(scr_zoomwindow_fov.value * cl.viewzoom * M_PI / 360.0) * (3.0/4.0);
1207 r_refdef.frustum_x = r_refdef.frustum_y * vid_pixelheight.value * (float)r_refdef.width / (float)r_refdef.height;
1209 r_refdef.frustum_x *= r_refdef.frustumscale_x;
1210 r_refdef.frustum_y *= r_refdef.frustumscale_y;
1212 if(!CL_VM_UpdateView())
1217 if (!r_stereo_sidebyside.integer)
1219 r_refdef.width = vid.width;
1220 r_refdef.height = vid.height;
1228 //FIXME: force menu if nothing else to look at?
1229 //if (key_dest == key_game && cls.signon != SIGNONS && cls.state == ca_disconnected)
1231 if (cls.signon == SIGNONS)
1236 if (!r_letterbox.value)
1239 SCR_CheckDrawCenterString();
1243 R_Shadow_EditLights_DrawSelectedLightProperties();
1252 if (r_timereport_active)
1255 if (cls.signon == SIGNONS)
1256 R_TimeReport_Frame();
1264 if (r_timereport_active)
1265 R_TimeReport("meshfinish");
1268 void SCR_UpdateLoadingScreen (void)
1273 float texcoord2f[8];
1274 // don't do anything if not initialized yet
1277 qglViewport(0, 0, vid.width, vid.height);
1278 //qglDisable(GL_SCISSOR_TEST);
1280 qglColorMask(1,1,1,1);
1281 //qglClearColor(0,0,0,0);
1282 //qglClear(GL_COLOR_BUFFER_BIT);
1283 //qglCullFace(GL_FRONT);
1284 //qglDisable(GL_CULL_FACE);
1287 GL_SetupView_Mode_Ortho(0, 0, vid_conwidth.integer, vid_conheight.integer, -10, 100);
1289 R_Mesh_Matrix(&identitymatrix);
1290 // draw the loading plaque
1291 pic = Draw_CachePic("gfx/loading", true);
1292 x = (vid_conwidth.integer - pic->width)/2;
1293 y = (vid_conheight.integer - pic->height)/2;
1295 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1296 GL_DepthTest(false);
1297 R_Mesh_VertexPointer(vertex3f);
1298 R_Mesh_ColorPointer(NULL);
1299 R_Mesh_ResetTextureState();
1300 R_Mesh_TexBind(0, R_GetTexture(pic->tex));
1301 R_Mesh_TexCoordPointer(0, 2, texcoord2f);
1302 vertex3f[2] = vertex3f[5] = vertex3f[8] = vertex3f[11] = 0;
1303 vertex3f[0] = vertex3f[9] = x;
1304 vertex3f[1] = vertex3f[4] = y;
1305 vertex3f[3] = vertex3f[6] = x + pic->width;
1306 vertex3f[7] = vertex3f[10] = y + pic->height;
1307 texcoord2f[0] = 0;texcoord2f[1] = 0;
1308 texcoord2f[2] = 1;texcoord2f[3] = 0;
1309 texcoord2f[4] = 1;texcoord2f[5] = 1;
1310 texcoord2f[6] = 0;texcoord2f[7] = 1;
1311 R_Mesh_Draw(0, 4, 2, polygonelements);
1317 void CL_UpdateScreen(void)
1319 float conwidth, conheight;
1324 if (!scr_initialized || !con_initialized || vid_hidden)
1325 return; // not initialized yet
1327 // don't allow cheats in multiplayer
1328 if (!cl.islocalgame && cl.worldmodel)
1330 if (r_fullbright.integer != 0)
1331 Cvar_Set ("r_fullbright", "0");
1332 if (r_ambient.value != 0)
1333 Cvar_Set ("r_ambient", "0");
1336 conwidth = bound(320, vid_conwidth.value, 2048);
1337 conheight = bound(200, vid_conheight.value, 1536);
1338 if (vid_conwidth.value != conwidth)
1339 Cvar_SetValue("vid_conwidth", conwidth);
1340 if (vid_conheight.value != conheight)
1341 Cvar_SetValue("vid_conheight", conheight);
1344 if (scr_viewsize.value < 30)
1345 Cvar_Set ("viewsize","30");
1346 if (scr_viewsize.value > 120)
1347 Cvar_Set ("viewsize","120");
1349 // bound field of view
1350 if (scr_fov.value < 1)
1351 Cvar_Set ("fov","1");
1352 if (scr_fov.value > 170)
1353 Cvar_Set ("fov","170");
1355 // validate r_textureunits cvar
1356 if (r_textureunits.integer > gl_textureunits)
1357 Cvar_SetValueQuick(&r_textureunits, gl_textureunits);
1358 if (r_textureunits.integer < 1)
1359 Cvar_SetValueQuick(&r_textureunits, 1);
1361 // validate gl_combine cvar
1362 if (gl_combine.integer && !gl_combine_extension)
1363 Cvar_SetValueQuick(&gl_combine, 0);
1365 // intermission is always full screen
1366 if (cl.intermission)
1370 if (scr_viewsize.value >= 120)
1371 sb_lines = 0; // no status bar at all
1372 else if (scr_viewsize.value >= 110)
1373 sb_lines = 24; // no inventory
1378 r_refdef.colormask[0] = 1;
1379 r_refdef.colormask[1] = 1;
1380 r_refdef.colormask[2] = 1;
1382 if (r_timereport_active)
1383 R_TimeReport("other");
1385 SCR_SetUpToDrawConsole();
1387 if (r_timereport_active)
1388 R_TimeReport("start");
1391 qglViewport(0, 0, vid.width, vid.height);
1392 qglDisable(GL_SCISSOR_TEST);
1394 qglColorMask(1,1,1,1);
1395 qglClearColor(0,0,0,0);
1396 qglClear(GL_COLOR_BUFFER_BIT);
1399 if (r_timereport_active)
1400 R_TimeReport("clear");
1402 if (r_stereo_redblue.integer || r_stereo_redgreen.integer || r_stereo_redcyan.integer || r_stereo_sidebyside.integer)
1404 matrix4x4_t originalmatrix = r_refdef.viewentitymatrix;
1405 r_refdef.viewentitymatrix.m[0][3] = originalmatrix.m[0][3] + r_stereo_separation.value * -0.5f * r_refdef.viewentitymatrix.m[0][1];
1406 r_refdef.viewentitymatrix.m[1][3] = originalmatrix.m[1][3] + r_stereo_separation.value * -0.5f * r_refdef.viewentitymatrix.m[1][1];
1407 r_refdef.viewentitymatrix.m[2][3] = originalmatrix.m[2][3] + r_stereo_separation.value * -0.5f * r_refdef.viewentitymatrix.m[2][1];
1409 if (r_stereo_sidebyside.integer)
1412 if (r_stereo_redblue.integer || r_stereo_redgreen.integer || r_stereo_redcyan.integer)
1414 r_refdef.colormask[0] = 1;
1415 r_refdef.colormask[1] = 0;
1416 r_refdef.colormask[2] = 0;
1421 r_refdef.viewentitymatrix.m[0][3] = originalmatrix.m[0][3] + r_stereo_separation.value * 0.5f * r_refdef.viewentitymatrix.m[0][1];
1422 r_refdef.viewentitymatrix.m[1][3] = originalmatrix.m[1][3] + r_stereo_separation.value * 0.5f * r_refdef.viewentitymatrix.m[1][1];
1423 r_refdef.viewentitymatrix.m[2][3] = originalmatrix.m[2][3] + r_stereo_separation.value * 0.5f * r_refdef.viewentitymatrix.m[2][1];
1425 if (r_stereo_sidebyside.integer)
1428 if (r_stereo_redblue.integer || r_stereo_redgreen.integer || r_stereo_redcyan.integer)
1430 r_refdef.colormask[0] = 0;
1431 r_refdef.colormask[1] = r_stereo_redcyan.integer || r_stereo_redgreen.integer;
1432 r_refdef.colormask[2] = r_stereo_redcyan.integer || r_stereo_redblue.integer;
1437 r_refdef.viewentitymatrix = originalmatrix;
1445 if (r_timereport_active)
1446 R_TimeReport("finish");
1449 void CL_Screen_NewMap(void)