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