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