now clears screen at startup to prevent garbage from being seen around loading plaque...
[divverent/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "r_shadow.h"
24
25 // used for dlight push checking and other things
26 int r_framecount;
27
28 // used for visibility checking
29 qbyte r_pvsbits[(MAX_MAP_LEAFS+7)>>3];
30
31 mplane_t frustum[4];
32
33 matrix4x4_t r_identitymatrix;
34
35 int c_alias_polys, c_light_polys, c_faces, c_nodes, c_leafs, c_models, c_bmodels, c_sprites, c_particles, c_dlights;
36
37 // true during envmap command capture
38 qboolean envmap;
39
40 // maximum visible distance (recalculated from world box each frame)
41 float r_farclip;
42 // brightness of world lightmaps and related lighting
43 // (often reduced when world rtlights are enabled)
44 float r_lightmapintensity;
45 // whether to draw world lights realtime, dlights realtime, and their shadows
46 qboolean r_rtworld;
47 qboolean r_rtworldshadows;
48 qboolean r_rtdlight;
49 qboolean r_rtdlightshadows;
50
51
52 // forces all rendering to draw triangle outlines
53 int r_showtrispass;
54
55 // view origin
56 vec3_t r_vieworigin;
57 vec3_t r_viewforward;
58 vec3_t r_viewleft;
59 vec3_t r_viewright;
60 vec3_t r_viewup;
61 int r_view_x;
62 int r_view_y;
63 int r_view_z;
64 int r_view_width;
65 int r_view_height;
66 int r_view_depth;
67 float r_view_fov_x;
68 float r_view_fov_y;
69 matrix4x4_t r_view_matrix;
70
71 //
72 // screen size info
73 //
74 refdef_t r_refdef;
75
76 // 8.8 fraction of base light value
77 unsigned short d_lightstylevalue[256];
78
79 cvar_t r_showtris = {0, "r_showtris", "0"};
80 cvar_t r_drawentities = {0, "r_drawentities","1"};
81 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1"};
82 cvar_t r_speeds = {0, "r_speeds","0"};
83 cvar_t r_fullbright = {0, "r_fullbright","0"};
84 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1"};
85 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1"};
86 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1"};
87 cvar_t r_drawcollisionbrushes = {0, "r_drawcollisionbrushes", "0"};
88
89 cvar_t gl_fogenable = {0, "gl_fogenable", "0"};
90 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25"};
91 cvar_t gl_fogred = {0, "gl_fogred","0.3"};
92 cvar_t gl_foggreen = {0, "gl_foggreen","0.3"};
93 cvar_t gl_fogblue = {0, "gl_fogblue","0.3"};
94 cvar_t gl_fogstart = {0, "gl_fogstart", "0"};
95 cvar_t gl_fogend = {0, "gl_fogend","0"};
96
97 cvar_t r_textureunits = {0, "r_textureunits", "32"};
98
99 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1"};
100 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1"};
101 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1"};
102 cvar_t r_watershader = {CVAR_SAVE, "r_watershader", "1"};
103
104
105 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
106 {
107         int i;
108         for (i = 0;i < verts;i++)
109         {
110                 out[0] = in[0] * r;
111                 out[1] = in[1] * g;
112                 out[2] = in[2] * b;
113                 out[3] = in[3];
114                 in += 4;
115                 out += 4;
116         }
117 }
118
119 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
120 {
121         int i;
122         for (i = 0;i < verts;i++)
123         {
124                 out[0] = r;
125                 out[1] = g;
126                 out[2] = b;
127                 out[3] = a;
128                 out += 4;
129         }
130 }
131
132 /*
133 ====================
134 R_TimeRefresh_f
135
136 For program optimization
137 ====================
138 */
139 qboolean intimerefresh = 0;
140 static void R_TimeRefresh_f (void)
141 {
142         int i;
143         float timestart, timedelta, oldangles[3];
144
145         intimerefresh = 1;
146         VectorCopy(cl.viewangles, oldangles);
147         VectorClear(cl.viewangles);
148
149         timestart = Sys_DoubleTime();
150         for (i = 0;i < 128;i++)
151         {
152                 Matrix4x4_CreateFromQuakeEntity(&r_refdef.viewentitymatrix, r_vieworigin[0], r_vieworigin[1], r_vieworigin[2], 0, i / 128.0 * 360.0, 0, 1);
153                 CL_UpdateScreen();
154         }
155         timedelta = Sys_DoubleTime() - timestart;
156
157         VectorCopy(oldangles, cl.viewangles);
158         intimerefresh = 0;
159         Con_Printf("%f seconds (%f fps)\n", timedelta, 128/timedelta);
160 }
161
162 vec3_t fogcolor;
163 vec_t fogdensity;
164 float fog_density, fog_red, fog_green, fog_blue;
165 qboolean fogenabled;
166 qboolean oldgl_fogenable;
167 void R_UpdateFog(void)
168 {
169         if (gamemode == GAME_NEHAHRA)
170         {
171                 if (gl_fogenable.integer)
172                 {
173                         oldgl_fogenable = true;
174                         fog_density = gl_fogdensity.value;
175                         fog_red = gl_fogred.value;
176                         fog_green = gl_foggreen.value;
177                         fog_blue = gl_fogblue.value;
178                 }
179                 else if (oldgl_fogenable)
180                 {
181                         oldgl_fogenable = false;
182                         fog_density = 0;
183                         fog_red = 0;
184                         fog_green = 0;
185                         fog_blue = 0;
186                 }
187         }
188         if (fog_density)
189         {
190                 fogcolor[0] = fog_red   = bound(0.0f, fog_red  , 1.0f);
191                 fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
192                 fogcolor[2] = fog_blue  = bound(0.0f, fog_blue , 1.0f);
193         }
194         if (fog_density)
195         {
196                 fogenabled = true;
197                 fogdensity = -4000.0f / (fog_density * fog_density);
198                 // fog color was already set
199         }
200         else
201                 fogenabled = false;
202 }
203
204 // FIXME: move this to client?
205 void FOG_clear(void)
206 {
207         if (gamemode == GAME_NEHAHRA)
208         {
209                 Cvar_Set("gl_fogenable", "0");
210                 Cvar_Set("gl_fogdensity", "0.2");
211                 Cvar_Set("gl_fogred", "0.3");
212                 Cvar_Set("gl_foggreen", "0.3");
213                 Cvar_Set("gl_fogblue", "0.3");
214         }
215         fog_density = fog_red = fog_green = fog_blue = 0.0f;
216 }
217
218 // FIXME: move this to client?
219 void FOG_registercvars(void)
220 {
221         if (gamemode == GAME_NEHAHRA)
222         {
223                 Cvar_RegisterVariable (&gl_fogenable);
224                 Cvar_RegisterVariable (&gl_fogdensity);
225                 Cvar_RegisterVariable (&gl_fogred);
226                 Cvar_RegisterVariable (&gl_foggreen);
227                 Cvar_RegisterVariable (&gl_fogblue);
228                 Cvar_RegisterVariable (&gl_fogstart);
229                 Cvar_RegisterVariable (&gl_fogend);
230         }
231 }
232
233 void gl_main_start(void)
234 {
235 }
236
237 void gl_main_shutdown(void)
238 {
239 }
240
241 extern void CL_ParseEntityLump(char *entitystring);
242 void gl_main_newmap(void)
243 {
244         int l;
245         char *entities, entname[MAX_QPATH];
246         r_framecount = 1;
247         if (cl.worldmodel)
248         {
249                 strcpy(entname, cl.worldmodel->name);
250                 l = strlen(entname) - 4;
251                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
252                 {
253                         strcpy(entname + l, ".ent");
254                         if ((entities = FS_LoadFile(entname, tempmempool, true)))
255                         {
256                                 CL_ParseEntityLump(entities);
257                                 Mem_Free(entities);
258                                 return;
259                         }
260                 }
261                 if (cl.worldmodel->brush.entities)
262                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
263         }
264 }
265
266 void GL_Main_Init(void)
267 {
268         Matrix4x4_CreateIdentity(&r_identitymatrix);
269 // FIXME: move this to client?
270         FOG_registercvars();
271         Cmd_AddCommand("timerefresh", R_TimeRefresh_f);
272         Cvar_RegisterVariable(&r_showtris);
273         Cvar_RegisterVariable(&r_drawentities);
274         Cvar_RegisterVariable(&r_drawviewmodel);
275         Cvar_RegisterVariable(&r_speeds);
276         Cvar_RegisterVariable(&r_fullbrights);
277         Cvar_RegisterVariable(&r_wateralpha);
278         Cvar_RegisterVariable(&r_dynamic);
279         Cvar_RegisterVariable(&r_fullbright);
280         Cvar_RegisterVariable(&r_textureunits);
281         Cvar_RegisterVariable(&r_lerpsprites);
282         Cvar_RegisterVariable(&r_lerpmodels);
283         Cvar_RegisterVariable(&r_waterscroll);
284         Cvar_RegisterVariable(&r_watershader);
285         Cvar_RegisterVariable(&r_drawcollisionbrushes);
286         if (gamemode == GAME_NEHAHRA || gamemode == GAME_NEXUIZ || gamemode == GAME_TENEBRAE)
287                 Cvar_SetValue("r_fullbrights", 0);
288         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
289 }
290
291 static vec3_t r_farclip_origin;
292 static vec3_t r_farclip_direction;
293 static vec_t r_farclip_directiondist;
294 static vec_t r_farclip_meshfarclip;
295 static int r_farclip_directionbit0;
296 static int r_farclip_directionbit1;
297 static int r_farclip_directionbit2;
298
299 // enlarge farclip to accomodate box
300 static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
301 {
302         float d;
303         d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
304           + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
305           + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
306         if (r_farclip_meshfarclip < d)
307                 r_farclip_meshfarclip = d;
308 }
309
310 // return farclip value
311 static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
312 {
313         int i;
314
315         VectorCopy(origin, r_farclip_origin);
316         VectorCopy(direction, r_farclip_direction);
317         r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
318         r_farclip_directionbit0 = r_farclip_direction[0] < 0;
319         r_farclip_directionbit1 = r_farclip_direction[1] < 0;
320         r_farclip_directionbit2 = r_farclip_direction[2] < 0;
321         r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
322
323         if (cl.worldmodel)
324                 R_FarClip_Box(cl.worldmodel->normalmins, cl.worldmodel->normalmaxs);
325         for (i = 0;i < r_refdef.numentities;i++)
326                 R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
327         
328         return r_farclip_meshfarclip - r_farclip_directiondist;
329 }
330
331 extern void R_Textures_Init(void);
332 extern void Mod_RenderInit(void);
333 extern void GL_Draw_Init(void);
334 extern void GL_Main_Init(void);
335 extern void R_Shadow_Init(void);
336 extern void GL_Models_Init(void);
337 extern void R_Sky_Init(void);
338 extern void GL_Surf_Init(void);
339 extern void R_Crosshairs_Init(void);
340 extern void R_Light_Init(void);
341 extern void R_Particles_Init(void);
342 extern void R_Explosion_Init(void);
343 extern void ui_init(void);
344 extern void gl_backend_init(void);
345 extern void Sbar_Init(void);
346 extern void R_LightningBeams_Init(void);
347
348 void Render_Init(void)
349 {
350         R_Textures_Init();
351         Mod_RenderInit();
352         gl_backend_init();
353         R_MeshQueue_Init();
354         GL_Draw_Init();
355         GL_Main_Init();
356         R_Shadow_Init();
357         GL_Models_Init();
358         R_Sky_Init();
359         GL_Surf_Init();
360         R_Crosshairs_Init();
361         R_Light_Init();
362         R_Particles_Init();
363         R_Explosion_Init();
364         //ui_init();
365         UI_Init();
366         Sbar_Init();
367         R_LightningBeams_Init();
368 }
369
370 /*
371 ===============
372 GL_Init
373 ===============
374 */
375 extern char *ENGINE_EXTENSIONS;
376 void GL_Init (void)
377 {
378         VID_CheckExtensions();
379
380         // LordHavoc: report supported extensions
381         Con_DPrintf("\nengine extensions: %s\n", ENGINE_EXTENSIONS);
382
383         // clear to black (loading plaque will be seen over this)
384         qglClearColor(0,0,0,1);
385         qglClear(GL_COLOR_BUFFER_BIT);
386 }
387
388 int R_CullBox(const vec3_t mins, const vec3_t maxs)
389 {
390         int i;
391         mplane_t *p;
392         for (i = 0;i < 4;i++)
393         {
394                 p = frustum + i;
395                 switch(p->signbits)
396                 {
397                 default:
398                 case 0:
399                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
400                                 return true;
401                         break;
402                 case 1:
403                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
404                                 return true;
405                         break;
406                 case 2:
407                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
408                                 return true;
409                         break;
410                 case 3:
411                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
412                                 return true;
413                         break;
414                 case 4:
415                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
416                                 return true;
417                         break;
418                 case 5:
419                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
420                                 return true;
421                         break;
422                 case 6:
423                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
424                                 return true;
425                         break;
426                 case 7:
427                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
428                                 return true;
429                         break;
430                 }
431         }
432         return false;
433 }
434
435 //==================================================================================
436
437 static void R_MarkEntities (void)
438 {
439         int i;
440         entity_render_t *ent;
441
442         ent = &cl_entities[0].render;
443         Matrix4x4_CreateIdentity(&ent->matrix);
444         Matrix4x4_CreateIdentity(&ent->inversematrix);
445
446         if (!r_drawentities.integer)
447                 return;
448
449         for (i = 0;i < r_refdef.numentities;i++)
450         {
451                 ent = r_refdef.entities[i];
452                 Mod_CheckLoaded(ent->model);
453                 // some of the renderer still relies on origin...
454                 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
455                 // some of the renderer still relies on scale...
456                 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
457                 R_UpdateEntLights(ent);
458                 if ((chase_active.integer || !(ent->flags & RENDER_EXTERIORMODEL))
459                  && (!VIS_CullBox(ent->mins, ent->maxs) || (ent->effects & EF_NODEPTHTEST))
460                  && (!envmap || !(ent->flags & (RENDER_VIEWMODEL | RENDER_EXTERIORMODEL))))
461                         ent->visframe = r_framecount;
462         }
463 }
464
465 // only used if skyrendermasked, and normally returns false
466 int R_DrawBrushModelsSky (void)
467 {
468         int i, sky;
469         entity_render_t *ent;
470
471         if (!r_drawentities.integer)
472                 return false;
473
474         sky = false;
475         for (i = 0;i < r_refdef.numentities;i++)
476         {
477                 ent = r_refdef.entities[i];
478                 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
479                 {
480                         ent->model->DrawSky(ent);
481                         sky = true;
482                 }
483         }
484         return sky;
485 }
486
487 void R_DrawNoModel(entity_render_t *ent);
488 void R_DrawModels(void)
489 {
490         int i;
491         entity_render_t *ent;
492
493         if (!r_drawentities.integer)
494                 return;
495
496         for (i = 0;i < r_refdef.numentities;i++)
497         {
498                 ent = r_refdef.entities[i];
499                 if (ent->visframe == r_framecount)
500                 {
501                         if (ent->model && ent->model->Draw != NULL)
502                                 ent->model->Draw(ent);
503                         else
504                                 R_DrawNoModel(ent);
505                 }
506         }
507 }
508
509 static void R_SetFrustum(void)
510 {
511         // break apart the view matrix into vectors for various purposes
512         Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
513         VectorNegate(r_viewleft, r_viewright);
514
515         // LordHavoc: note to all quake engine coders, the special case for 90
516         // degrees assumed a square view (wrong), so I removed it, Quake2 has it
517         // disabled as well.
518
519         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
520         RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_view_fov_x / 2));
521         frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
522         PlaneClassify(&frustum[0]);
523
524         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
525         RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_view_fov_x / 2));
526         frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
527         PlaneClassify(&frustum[1]);
528
529         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
530         RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_view_fov_y / 2));
531         frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
532         PlaneClassify(&frustum[2]);
533
534         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
535         RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_view_fov_y / 2));
536         frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
537         PlaneClassify(&frustum[3]);
538 }
539
540 static void R_BlendView(void)
541 {
542         rmeshstate_t m;
543         float r;
544         float vertex3f[3*3];
545
546         if (r_refdef.viewblend[3] < 0.01f)
547                 return;
548
549         R_Mesh_Matrix(&r_identitymatrix);
550
551         memset(&m, 0, sizeof(m));
552         m.pointer_vertex = vertex3f;
553         R_Mesh_State(&m);
554
555         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
556         GL_DepthMask(true);
557         GL_DepthTest(false); // magic
558         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
559         r = 64;
560         vertex3f[0] = r_vieworigin[0] + r_viewforward[0] * 1.5 + r_viewleft[0] * r - r_viewup[0] * r;
561         vertex3f[1] = r_vieworigin[1] + r_viewforward[1] * 1.5 + r_viewleft[1] * r - r_viewup[1] * r;
562         vertex3f[2] = r_vieworigin[2] + r_viewforward[2] * 1.5 + r_viewleft[2] * r - r_viewup[2] * r;
563         vertex3f[3] = r_vieworigin[0] + r_viewforward[0] * 1.5 + r_viewleft[0] * r + r_viewup[0] * r * 3;
564         vertex3f[4] = r_vieworigin[1] + r_viewforward[1] * 1.5 + r_viewleft[1] * r + r_viewup[1] * r * 3;
565         vertex3f[5] = r_vieworigin[2] + r_viewforward[2] * 1.5 + r_viewleft[2] * r + r_viewup[2] * r * 3;
566         vertex3f[6] = r_vieworigin[0] + r_viewforward[0] * 1.5 - r_viewleft[0] * r * 3 - r_viewup[0] * r;
567         vertex3f[7] = r_vieworigin[1] + r_viewforward[1] * 1.5 - r_viewleft[1] * r * 3 - r_viewup[1] * r;
568         vertex3f[8] = r_vieworigin[2] + r_viewforward[2] * 1.5 - r_viewleft[2] * r * 3 - r_viewup[2] * r;
569         R_Mesh_Draw(3, 1, polygonelements);
570 }
571
572 void R_RenderScene(void);
573
574 /*
575 ================
576 R_RenderView
577 ================
578 */
579 void R_RenderView(void)
580 {
581         if (!r_refdef.entities/* || !cl.worldmodel*/)
582                 return; //Host_Error ("R_RenderView: NULL worldmodel");
583
584         r_view_width = bound(0, r_refdef.width, vid.realwidth);
585         r_view_height = bound(0, r_refdef.height, vid.realheight);
586         r_view_depth = 1;
587         r_view_x = bound(0, r_refdef.x, vid.realwidth - r_refdef.width);
588         r_view_y = bound(0, r_refdef.y, vid.realheight - r_refdef.height);
589         r_view_z = 0;
590         r_view_fov_x = bound(1, r_refdef.fov_x, 170);
591         r_view_fov_y = bound(1, r_refdef.fov_y, 170);
592         r_view_matrix = r_refdef.viewentitymatrix;
593         GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
594         r_rtworld = r_shadow_realtime_world.integer;
595         r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
596         r_rtdlight = r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer;
597         r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
598         r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
599
600         // GL is weird because it's bottom to top, r_view_y is top to bottom
601         qglViewport(r_view_x, vid.realheight - (r_view_y + r_view_height), r_view_width, r_view_height);
602         GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
603         GL_ScissorTest(true);
604         GL_DepthMask(true);
605         R_ClearScreen();
606         R_Textures_Frame();
607         R_UpdateFog();
608         R_UpdateLights();
609         R_TimeReport("setup");
610
611         qglDepthFunc(GL_LEQUAL);
612         qglPolygonOffset(0, 0);
613         qglEnable(GL_POLYGON_OFFSET_FILL);
614
615         R_RenderScene();
616
617         qglPolygonOffset(0, 0);
618         qglDisable(GL_POLYGON_OFFSET_FILL);
619
620         R_BlendView();
621         R_TimeReport("blendview");
622         
623         GL_Scissor(0, 0, vid.realwidth, vid.realheight);
624         GL_ScissorTest(false);
625 }
626
627 extern void R_DrawLightningBeams (void);
628 void R_RenderScene(void)
629 {
630         entity_render_t *world;
631         
632         // don't let sound skip if going slow
633         if (!intimerefresh && !r_speeds.integer)
634                 S_ExtraUpdate ();
635
636         r_framecount++;
637
638         R_MeshQueue_BeginScene();
639
640         GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
641
642         R_SetFrustum();
643
644         r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
645         if (r_rtworldshadows || r_rtdlightshadows)
646                 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view_fov_x, r_view_fov_y, 1.0f);
647         else
648                 GL_SetupView_Mode_Perspective(r_view_fov_x, r_view_fov_y, 1.0f, r_farclip);
649
650         GL_SetupView_Orientation_FromEntity(&r_view_matrix);
651
652         R_SkyStartFrame();
653
654         if (cl.worldmodel && cl.worldmodel->brush.FatPVS)
655                 cl.worldmodel->brush.FatPVS(cl.worldmodel, r_vieworigin, 2, r_pvsbits, sizeof(r_pvsbits));
656         world = &cl_entities[0].render;
657         R_WorldVisibility(world);
658         R_TimeReport("worldvis");
659
660         R_MarkEntities();
661         R_TimeReport("markentity");
662
663         R_Shadow_UpdateWorldLightSelection();
664
665         // don't let sound skip if going slow
666         if (!intimerefresh && !r_speeds.integer)
667                 S_ExtraUpdate ();
668
669         GL_ShowTrisColor(0.025, 0.025, 0, 1);
670         if (world->model && world->model->DrawSky)
671         {
672                 world->model->DrawSky(world);
673                 R_TimeReport("worldsky");
674         }
675
676         if (R_DrawBrushModelsSky())
677                 R_TimeReport("bmodelsky");
678
679         GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
680         if (world->model && world->model->Draw)
681         {
682                 world->model->Draw(world);
683                 R_TimeReport("world");
684         }
685
686         // don't let sound skip if going slow
687         if (!intimerefresh && !r_speeds.integer)
688                 S_ExtraUpdate ();
689
690         GL_ShowTrisColor(0, 0.015, 0, 1);
691
692         R_DrawModels();
693         R_TimeReport("models");
694
695         // don't let sound skip if going slow
696         if (!intimerefresh && !r_speeds.integer)
697                 S_ExtraUpdate ();
698
699         GL_ShowTrisColor(0, 0, 0.033, 1);
700         R_ShadowVolumeLighting(false);
701         R_TimeReport("rtlights");
702
703         // don't let sound skip if going slow
704         if (!intimerefresh && !r_speeds.integer)
705                 S_ExtraUpdate ();
706
707         GL_ShowTrisColor(0.1, 0, 0, 1);
708
709         R_DrawLightningBeams();
710         R_TimeReport("lightning");
711
712         R_DrawParticles();
713         R_TimeReport("particles");
714
715         R_DrawExplosions();
716         R_TimeReport("explosions");
717
718         R_MeshQueue_RenderTransparent();
719         R_TimeReport("drawtrans");
720
721         R_DrawCoronas();
722         R_TimeReport("coronas");
723
724         R_DrawWorldCrosshair();
725         R_TimeReport("crosshair");
726
727         R_MeshQueue_Render();
728         R_MeshQueue_EndScene();
729
730         if (r_shadow_visiblevolumes.integer && !r_showtrispass)
731         {
732                 R_ShadowVolumeLighting(true);
733                 R_TimeReport("shadowvolume");
734         }
735
736         GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
737
738         // don't let sound skip if going slow
739         if (!intimerefresh && !r_speeds.integer)
740                 S_ExtraUpdate ();
741 }
742
743 /*
744 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
745 {
746         int i;
747         float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
748         rmeshstate_t m;
749         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
750         GL_DepthMask(false);
751         GL_DepthTest(true);
752         R_Mesh_Matrix(&r_identitymatrix);
753
754         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
755         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
756         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
757         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
758         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
759         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
760         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
761         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
762         R_FillColors(color, 8, cr, cg, cb, ca);
763         if (fogenabled)
764         {
765                 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
766                 {
767                         VectorSubtract(v, r_vieworigin, diff);
768                         f2 = exp(fogdensity/DotProduct(diff, diff));
769                         f1 = 1 - f2;
770                         c[0] = c[0] * f1 + fogcolor[0] * f2;
771                         c[1] = c[1] * f1 + fogcolor[1] * f2;
772                         c[2] = c[2] * f1 + fogcolor[2] * f2;
773                 }
774         }
775         memset(&m, 0, sizeof(m));
776         m.pointer_vertex = vertex3f;
777         m.pointer_color = color;
778         R_Mesh_State(&m);
779         R_Mesh_Draw(8, 12);
780 }
781 */
782
783 int nomodelelements[24] =
784 {
785         5, 2, 0,
786         5, 1, 2,
787         5, 0, 3,
788         5, 3, 1,
789         0, 2, 4,
790         2, 1, 4,
791         3, 0, 4,
792         1, 3, 4
793 };
794
795 float nomodelvertex3f[6*3] =
796 {
797         -16,   0,   0,
798          16,   0,   0,
799           0, -16,   0,
800           0,  16,   0,
801           0,   0, -16,
802           0,   0,  16
803 };
804
805 float nomodelcolor4f[6*4] =
806 {
807         0.0f, 0.0f, 0.5f, 1.0f,
808         0.0f, 0.0f, 0.5f, 1.0f,
809         0.0f, 0.5f, 0.0f, 1.0f,
810         0.0f, 0.5f, 0.0f, 1.0f,
811         0.5f, 0.0f, 0.0f, 1.0f,
812         0.5f, 0.0f, 0.0f, 1.0f
813 };
814
815 void R_DrawNoModelCallback(const void *calldata1, int calldata2)
816 {
817         const entity_render_t *ent = calldata1;
818         int i;
819         float f1, f2, *c, diff[3];
820         float color4f[6*4];
821         rmeshstate_t m;
822         R_Mesh_Matrix(&ent->matrix);
823
824         memset(&m, 0, sizeof(m));
825         m.pointer_vertex = nomodelvertex3f;
826
827         if (ent->flags & EF_ADDITIVE)
828         {
829                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
830                 GL_DepthMask(false);
831         }
832         else if (ent->alpha < 1)
833         {
834                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
835                 GL_DepthMask(false);
836         }
837         else
838         {
839                 GL_BlendFunc(GL_ONE, GL_ZERO);
840                 GL_DepthMask(true);
841         }
842         GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
843         if (fogenabled)
844         {
845                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
846                 m.pointer_color = color4f;
847                 VectorSubtract(ent->origin, r_vieworigin, diff);
848                 f2 = exp(fogdensity/DotProduct(diff, diff));
849                 f1 = 1 - f2;
850                 for (i = 0, c = color4f;i < 6;i++, c += 4)
851                 {
852                         c[0] = (c[0] * f1 + fogcolor[0] * f2);
853                         c[1] = (c[1] * f1 + fogcolor[1] * f2);
854                         c[2] = (c[2] * f1 + fogcolor[2] * f2);
855                         c[3] *= ent->alpha;
856                 }
857         }
858         else if (ent->alpha != 1)
859         {
860                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
861                 m.pointer_color = color4f;
862                 for (i = 0, c = color4f;i < 6;i++, c += 4)
863                         c[3] *= ent->alpha;
864         }
865         else
866                 m.pointer_color = nomodelcolor4f;
867         R_Mesh_State(&m);
868         R_Mesh_Draw(6, 8, nomodelelements);
869 }
870
871 void R_DrawNoModel(entity_render_t *ent)
872 {
873         //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
874                 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModelCallback, ent, 0);
875         //else
876         //      R_DrawNoModelCallback(ent, 0);
877 }
878
879 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
880 {
881         vec3_t right1, right2, diff, normal;
882
883         VectorSubtract (org2, org1, normal);
884         VectorNormalizeFast (normal);
885
886         // calculate 'right' vector for start
887         VectorSubtract (r_vieworigin, org1, diff);
888         VectorNormalizeFast (diff);
889         CrossProduct (normal, diff, right1);
890
891         // calculate 'right' vector for end
892         VectorSubtract (r_vieworigin, org2, diff);
893         VectorNormalizeFast (diff);
894         CrossProduct (normal, diff, right2);
895
896         vert[ 0] = org1[0] + width * right1[0];
897         vert[ 1] = org1[1] + width * right1[1];
898         vert[ 2] = org1[2] + width * right1[2];
899         vert[ 3] = org1[0] - width * right1[0];
900         vert[ 4] = org1[1] - width * right1[1];
901         vert[ 5] = org1[2] - width * right1[2];
902         vert[ 6] = org2[0] - width * right2[0];
903         vert[ 7] = org2[1] - width * right2[1];
904         vert[ 8] = org2[2] - width * right2[2];
905         vert[ 9] = org2[0] + width * right2[0];
906         vert[10] = org2[1] + width * right2[1];
907         vert[11] = org2[2] + width * right2[2];
908 }
909
910 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
911
912 void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, int depthdisable, const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2, float cr, float cg, float cb, float ca)
913 {
914         float diff[3];
915         rmeshstate_t m;
916
917         if (fogenabled)
918         {
919                 VectorSubtract(origin, r_vieworigin, diff);
920                 ca *= 1 - exp(fogdensity/DotProduct(diff,diff));
921         }
922
923         R_Mesh_Matrix(&r_identitymatrix);
924         GL_BlendFunc(blendfunc1, blendfunc2);
925         GL_DepthMask(false);
926         GL_DepthTest(!depthdisable);
927
928         varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
929         varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
930         varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
931         varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
932         varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
933         varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
934         varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
935         varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
936         varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
937         varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
938         varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
939         varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
940
941         memset(&m, 0, sizeof(m));
942         m.tex[0] = R_GetTexture(texture);
943         m.pointer_texcoord[0] = spritetexcoord2f;
944         m.pointer_vertex = varray_vertex3f;
945         R_Mesh_State(&m);
946         GL_Color(cr, cg, cb, ca);
947         R_Mesh_Draw(4, 2, polygonelements);
948 }
949