added r_rtworld, r_rtworldshadows, r_rtdlight, r_rtdlightshadows, and r_lightmapinten...
[xonotic/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
384 int R_CullBox(const vec3_t mins, const vec3_t maxs)
385 {
386         int i;
387         mplane_t *p;
388         for (i = 0;i < 4;i++)
389         {
390                 p = frustum + i;
391                 switch(p->signbits)
392                 {
393                 default:
394                 case 0:
395                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
396                                 return true;
397                         break;
398                 case 1:
399                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
400                                 return true;
401                         break;
402                 case 2:
403                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
404                                 return true;
405                         break;
406                 case 3:
407                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
408                                 return true;
409                         break;
410                 case 4:
411                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
412                                 return true;
413                         break;
414                 case 5:
415                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
416                                 return true;
417                         break;
418                 case 6:
419                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
420                                 return true;
421                         break;
422                 case 7:
423                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
424                                 return true;
425                         break;
426                 }
427         }
428         return false;
429 }
430
431 //==================================================================================
432
433 static void R_MarkEntities (void)
434 {
435         int i;
436         entity_render_t *ent;
437
438         ent = &cl_entities[0].render;
439         Matrix4x4_CreateIdentity(&ent->matrix);
440         Matrix4x4_CreateIdentity(&ent->inversematrix);
441
442         if (!r_drawentities.integer)
443                 return;
444
445         for (i = 0;i < r_refdef.numentities;i++)
446         {
447                 ent = r_refdef.entities[i];
448                 Mod_CheckLoaded(ent->model);
449                 // some of the renderer still relies on origin...
450                 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
451                 // some of the renderer still relies on scale...
452                 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
453                 R_LerpAnimation(ent);
454                 R_UpdateEntLights(ent);
455                 if ((chase_active.integer || !(ent->flags & RENDER_EXTERIORMODEL))
456                  && !VIS_CullBox(ent->mins, ent->maxs)
457                  && (!envmap || !(ent->flags & (RENDER_VIEWMODEL | RENDER_EXTERIORMODEL))))
458                         ent->visframe = r_framecount;
459         }
460 }
461
462 // only used if skyrendermasked, and normally returns false
463 int R_DrawBrushModelsSky (void)
464 {
465         int i, sky;
466         entity_render_t *ent;
467
468         if (!r_drawentities.integer)
469                 return false;
470
471         sky = false;
472         for (i = 0;i < r_refdef.numentities;i++)
473         {
474                 ent = r_refdef.entities[i];
475                 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
476                 {
477                         ent->model->DrawSky(ent);
478                         sky = true;
479                 }
480         }
481         return sky;
482 }
483
484 void R_DrawNoModel(entity_render_t *ent);
485 void R_DrawModels(void)
486 {
487         int i;
488         entity_render_t *ent;
489
490         if (!r_drawentities.integer)
491                 return;
492
493         for (i = 0;i < r_refdef.numentities;i++)
494         {
495                 ent = r_refdef.entities[i];
496                 if (ent->visframe == r_framecount)
497                 {
498                         if (ent->model && ent->model->Draw != NULL)
499                                 ent->model->Draw(ent);
500                         else
501                                 R_DrawNoModel(ent);
502                 }
503         }
504 }
505
506 static void R_SetFrustum(void)
507 {
508         // break apart the view matrix into vectors for various purposes
509         Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
510         VectorNegate(r_viewleft, r_viewright);
511
512         // LordHavoc: note to all quake engine coders, the special case for 90
513         // degrees assumed a square view (wrong), so I removed it, Quake2 has it
514         // disabled as well.
515
516         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
517         RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_view_fov_x / 2));
518         frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
519         PlaneClassify(&frustum[0]);
520
521         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
522         RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_view_fov_x / 2));
523         frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
524         PlaneClassify(&frustum[1]);
525
526         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
527         RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_view_fov_y / 2));
528         frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
529         PlaneClassify(&frustum[2]);
530
531         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
532         RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_view_fov_y / 2));
533         frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
534         PlaneClassify(&frustum[3]);
535 }
536
537 static void R_BlendView(void)
538 {
539         rmeshstate_t m;
540         float r;
541         float vertex3f[3*3];
542
543         if (r_refdef.viewblend[3] < 0.01f)
544                 return;
545
546         R_Mesh_Matrix(&r_identitymatrix);
547
548         memset(&m, 0, sizeof(m));
549         m.pointer_vertex = vertex3f;
550         R_Mesh_State(&m);
551
552         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
553         GL_DepthMask(true);
554         GL_DepthTest(false); // magic
555         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
556         r = 64;
557         vertex3f[0] = r_vieworigin[0] + r_viewforward[0] * 1.5 + r_viewleft[0] * r - r_viewup[0] * r;
558         vertex3f[1] = r_vieworigin[1] + r_viewforward[1] * 1.5 + r_viewleft[1] * r - r_viewup[1] * r;
559         vertex3f[2] = r_vieworigin[2] + r_viewforward[2] * 1.5 + r_viewleft[2] * r - r_viewup[2] * r;
560         vertex3f[3] = r_vieworigin[0] + r_viewforward[0] * 1.5 + r_viewleft[0] * r + r_viewup[0] * r * 3;
561         vertex3f[4] = r_vieworigin[1] + r_viewforward[1] * 1.5 + r_viewleft[1] * r + r_viewup[1] * r * 3;
562         vertex3f[5] = r_vieworigin[2] + r_viewforward[2] * 1.5 + r_viewleft[2] * r + r_viewup[2] * r * 3;
563         vertex3f[6] = r_vieworigin[0] + r_viewforward[0] * 1.5 - r_viewleft[0] * r * 3 - r_viewup[0] * r;
564         vertex3f[7] = r_vieworigin[1] + r_viewforward[1] * 1.5 - r_viewleft[1] * r * 3 - r_viewup[1] * r;
565         vertex3f[8] = r_vieworigin[2] + r_viewforward[2] * 1.5 - r_viewleft[2] * r * 3 - r_viewup[2] * r;
566         R_Mesh_Draw(3, 1, polygonelements);
567 }
568
569 void R_UpdateWorld(void)
570 {
571         if (!r_refdef.entities/* || !cl.worldmodel*/)
572                 return; //Host_Error ("R_RenderView: NULL worldmodel");
573
574         /*
575         if (r_shadow_realtime_world.integer && !gl_stencil)
576         {
577                 Con_Print("Realtime world lighting requires 32bit color; turning off r_shadow_realtime_world, please type vid_bitsperpixel 32;vid_restart and try again\n");
578                 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
579         }
580         */
581
582         // don't allow cheats in multiplayer
583         if (!cl.islocalgame && cl.worldmodel)
584         {
585                 if (r_fullbright.integer != 0)
586                         Cvar_Set ("r_fullbright", "0");
587                 if (r_ambient.value != 0)
588                         Cvar_Set ("r_ambient", "0");
589         }
590
591         R_Textures_Frame();
592         R_UpdateFog();
593         R_UpdateLights();
594 }
595
596 void R_RenderScene(void);
597
598 /*
599 ================
600 R_RenderView
601 ================
602 */
603 void R_RenderView(void)
604 {
605         if (!r_refdef.entities/* || !cl.worldmodel*/)
606                 return; //Host_Error ("R_RenderView: NULL worldmodel");
607         
608         r_view_width = bound(0, r_refdef.width, vid.realwidth);
609         r_view_height = bound(0, r_refdef.height, vid.realheight);
610         r_view_depth = 1;
611         r_view_x = bound(0, r_refdef.x, vid.realwidth - r_refdef.width);
612         r_view_y = bound(0, r_refdef.y, vid.realheight - r_refdef.height);
613         r_view_z = 0;
614         r_view_fov_x = bound(1, r_refdef.fov_x, 170);
615         r_view_fov_y = bound(1, r_refdef.fov_y, 170);
616         r_view_matrix = r_refdef.viewentitymatrix;
617         GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
618         r_rtworld = r_shadow_realtime_world.integer;
619         r_rtworldshadows = r_rtworld && r_shadow_realtime_world_shadows.integer;
620         r_rtdlight = r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer;
621         r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer);
622         r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
623
624         // GL is weird because it's bottom to top, r_view_y is top to bottom
625         qglViewport(r_view_x, vid.realheight - (r_view_y + r_view_height), r_view_width, r_view_height);
626         GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
627         GL_ScissorTest(true);
628         GL_DepthMask(true);
629         R_ClearScreen();
630         R_TimeReport("setup");
631
632         qglDepthFunc(GL_LEQUAL);
633         qglPolygonOffset(0, 0);
634         qglEnable(GL_POLYGON_OFFSET_FILL);
635
636         R_RenderScene();
637
638         qglPolygonOffset(0, 0);
639         qglDisable(GL_POLYGON_OFFSET_FILL);
640
641         R_BlendView();
642         R_TimeReport("blendview");
643         
644         GL_Scissor(0, 0, vid.realwidth, vid.realheight);
645         GL_ScissorTest(false);
646 }
647
648 extern void R_DrawLightningBeams (void);
649 void R_RenderScene(void)
650 {
651         entity_render_t *world;
652         
653         // don't let sound skip if going slow
654         if (!intimerefresh && !r_speeds.integer)
655                 S_ExtraUpdate ();
656
657         r_framecount++;
658
659         R_MeshQueue_BeginScene();
660
661         GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
662
663         R_SetFrustum();
664
665         r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
666         if (gl_stencil && (r_rtworldshadows || r_rtdlightshadows))
667                 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view_fov_x, r_view_fov_y, 1.0f);
668         else
669                 GL_SetupView_Mode_Perspective(r_view_fov_x, r_view_fov_y, 1.0f, r_farclip);
670
671         GL_SetupView_Orientation_FromEntity(&r_view_matrix);
672
673         R_SkyStartFrame();
674
675         if (cl.worldmodel && cl.worldmodel->brush.FatPVS)
676                 cl.worldmodel->brush.FatPVS(cl.worldmodel, r_vieworigin, 2, r_pvsbits, sizeof(r_pvsbits));
677         world = &cl_entities[0].render;
678         R_WorldVisibility(world);
679         R_TimeReport("worldvis");
680
681         R_MarkEntities();
682         R_TimeReport("markentity");
683
684         R_Shadow_UpdateWorldLightSelection();
685
686         // don't let sound skip if going slow
687         if (!intimerefresh && !r_speeds.integer)
688                 S_ExtraUpdate ();
689
690         GL_ShowTrisColor(0.025, 0.025, 0, 1);
691         if (world->model && world->model->DrawSky)
692         {
693                 world->model->DrawSky(world);
694                 R_TimeReport("worldsky");
695         }
696
697         if (R_DrawBrushModelsSky())
698                 R_TimeReport("bmodelsky");
699
700         GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
701         if (world->model && world->model->Draw)
702         {
703                 world->model->Draw(world);
704                 R_TimeReport("world");
705         }
706
707         // don't let sound skip if going slow
708         if (!intimerefresh && !r_speeds.integer)
709                 S_ExtraUpdate ();
710
711         GL_ShowTrisColor(0, 0.015, 0, 1);
712
713         R_DrawModels();
714         R_TimeReport("models");
715
716         // don't let sound skip if going slow
717         if (!intimerefresh && !r_speeds.integer)
718                 S_ExtraUpdate ();
719
720         GL_ShowTrisColor(0, 0, 0.033, 1);
721         R_ShadowVolumeLighting(false);
722         R_TimeReport("rtlights");
723
724         // don't let sound skip if going slow
725         if (!intimerefresh && !r_speeds.integer)
726                 S_ExtraUpdate ();
727
728         GL_ShowTrisColor(0.1, 0, 0, 1);
729
730         R_DrawLightningBeams();
731         R_TimeReport("lightning");
732
733         R_DrawParticles();
734         R_TimeReport("particles");
735
736         R_DrawExplosions();
737         R_TimeReport("explosions");
738
739         R_MeshQueue_RenderTransparent();
740         R_TimeReport("drawtrans");
741
742         R_DrawCoronas();
743         R_TimeReport("coronas");
744
745         R_DrawWorldCrosshair();
746         R_TimeReport("crosshair");
747
748         R_MeshQueue_Render();
749         R_MeshQueue_EndScene();
750
751         if (r_shadow_visiblevolumes.integer && !r_showtrispass)
752         {
753                 R_ShadowVolumeLighting(true);
754                 R_TimeReport("shadowvolume");
755         }
756
757         GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
758
759         // don't let sound skip if going slow
760         if (!intimerefresh && !r_speeds.integer)
761                 S_ExtraUpdate ();
762 }
763
764 /*
765 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
766 {
767         int i;
768         float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
769         rmeshstate_t m;
770         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
771         GL_DepthMask(false);
772         GL_DepthTest(true);
773         R_Mesh_Matrix(&r_identitymatrix);
774
775         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
776         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
777         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
778         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
779         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
780         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
781         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
782         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
783         R_FillColors(color, 8, cr, cg, cb, ca);
784         if (fogenabled)
785         {
786                 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
787                 {
788                         VectorSubtract(v, r_vieworigin, diff);
789                         f2 = exp(fogdensity/DotProduct(diff, diff));
790                         f1 = 1 - f2;
791                         c[0] = c[0] * f1 + fogcolor[0] * f2;
792                         c[1] = c[1] * f1 + fogcolor[1] * f2;
793                         c[2] = c[2] * f1 + fogcolor[2] * f2;
794                 }
795         }
796         memset(&m, 0, sizeof(m));
797         m.pointer_vertex = vertex3f;
798         m.pointer_color = color;
799         R_Mesh_State(&m);
800         R_Mesh_Draw(8, 12);
801 }
802 */
803
804 int nomodelelements[24] =
805 {
806         5, 2, 0,
807         5, 1, 2,
808         5, 0, 3,
809         5, 3, 1,
810         0, 2, 4,
811         2, 1, 4,
812         3, 0, 4,
813         1, 3, 4
814 };
815
816 float nomodelvertex3f[6*3] =
817 {
818         -16,   0,   0,
819          16,   0,   0,
820           0, -16,   0,
821           0,  16,   0,
822           0,   0, -16,
823           0,   0,  16
824 };
825
826 float nomodelcolor4f[6*4] =
827 {
828         0.0f, 0.0f, 0.5f, 1.0f,
829         0.0f, 0.0f, 0.5f, 1.0f,
830         0.0f, 0.5f, 0.0f, 1.0f,
831         0.0f, 0.5f, 0.0f, 1.0f,
832         0.5f, 0.0f, 0.0f, 1.0f,
833         0.5f, 0.0f, 0.0f, 1.0f
834 };
835
836 void R_DrawNoModelCallback(const void *calldata1, int calldata2)
837 {
838         const entity_render_t *ent = calldata1;
839         int i;
840         float f1, f2, *c, diff[3];
841         float color4f[6*4];
842         rmeshstate_t m;
843         R_Mesh_Matrix(&ent->matrix);
844
845         memset(&m, 0, sizeof(m));
846         m.pointer_vertex = nomodelvertex3f;
847
848         if (ent->flags & EF_ADDITIVE)
849         {
850                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
851                 GL_DepthMask(false);
852         }
853         else if (ent->alpha < 1)
854         {
855                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
856                 GL_DepthMask(false);
857         }
858         else
859         {
860                 GL_BlendFunc(GL_ONE, GL_ZERO);
861                 GL_DepthMask(true);
862         }
863         GL_DepthTest(true);
864         if (fogenabled)
865         {
866                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
867                 m.pointer_color = color4f;
868                 VectorSubtract(ent->origin, r_vieworigin, diff);
869                 f2 = exp(fogdensity/DotProduct(diff, diff));
870                 f1 = 1 - f2;
871                 for (i = 0, c = color4f;i < 6;i++, c += 4)
872                 {
873                         c[0] = (c[0] * f1 + fogcolor[0] * f2);
874                         c[1] = (c[1] * f1 + fogcolor[1] * f2);
875                         c[2] = (c[2] * f1 + fogcolor[2] * f2);
876                         c[3] *= ent->alpha;
877                 }
878         }
879         else if (ent->alpha != 1)
880         {
881                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
882                 m.pointer_color = color4f;
883                 for (i = 0, c = color4f;i < 6;i++, c += 4)
884                         c[3] *= ent->alpha;
885         }
886         else
887                 m.pointer_color = nomodelcolor4f;
888         R_Mesh_State(&m);
889         R_Mesh_Draw(6, 8, nomodelelements);
890 }
891
892 void R_DrawNoModel(entity_render_t *ent)
893 {
894         //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
895                 R_MeshQueue_AddTransparent(ent->origin, R_DrawNoModelCallback, ent, 0);
896         //else
897         //      R_DrawNoModelCallback(ent, 0);
898 }
899
900 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
901 {
902         vec3_t right1, right2, diff, normal;
903
904         VectorSubtract (org2, org1, normal);
905         VectorNormalizeFast (normal);
906
907         // calculate 'right' vector for start
908         VectorSubtract (r_vieworigin, org1, diff);
909         VectorNormalizeFast (diff);
910         CrossProduct (normal, diff, right1);
911
912         // calculate 'right' vector for end
913         VectorSubtract (r_vieworigin, org2, diff);
914         VectorNormalizeFast (diff);
915         CrossProduct (normal, diff, right2);
916
917         vert[ 0] = org1[0] + width * right1[0];
918         vert[ 1] = org1[1] + width * right1[1];
919         vert[ 2] = org1[2] + width * right1[2];
920         vert[ 3] = org1[0] - width * right1[0];
921         vert[ 4] = org1[1] - width * right1[1];
922         vert[ 5] = org1[2] - width * right1[2];
923         vert[ 6] = org2[0] - width * right2[0];
924         vert[ 7] = org2[1] - width * right2[1];
925         vert[ 8] = org2[2] - width * right2[2];
926         vert[ 9] = org2[0] + width * right2[0];
927         vert[10] = org2[1] + width * right2[1];
928         vert[11] = org2[2] + width * right2[2];
929 }
930
931 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
932
933 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)
934 {
935         float diff[3];
936         rmeshstate_t m;
937
938         if (fogenabled)
939         {
940                 VectorSubtract(origin, r_vieworigin, diff);
941                 ca *= 1 - exp(fogdensity/DotProduct(diff,diff));
942         }
943
944         R_Mesh_Matrix(&r_identitymatrix);
945         GL_BlendFunc(blendfunc1, blendfunc2);
946         GL_DepthMask(false);
947         GL_DepthTest(!depthdisable);
948
949         varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
950         varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
951         varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
952         varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
953         varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
954         varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
955         varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
956         varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
957         varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
958         varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
959         varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
960         varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
961
962         memset(&m, 0, sizeof(m));
963         m.tex[0] = R_GetTexture(texture);
964         m.pointer_texcoord[0] = spritetexcoord2f;
965         m.pointer_vertex = varray_vertex3f;
966         R_Mesh_State(&m);
967         GL_Color(cr, cg, cb, ca);
968         R_Mesh_Draw(4, 2, polygonelements);
969 }
970