2 Copyright (C) 1996-1997 Id Software, Inc.
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.
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.
13 See the GNU General Public License for more details.
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.
24 // used for dlight push checking and other things
27 // used for visibility checking
28 qbyte r_pvsbits[(MAX_MAP_LEAFS+7)>>3];
32 matrix4x4_t r_identitymatrix;
34 int c_alias_polys, c_light_polys, c_faces, c_nodes, c_leafs, c_models, c_bmodels, c_sprites, c_particles, c_dlights;
36 // true during envmap command capture
52 // 8.8 fraction of base light value
53 unsigned short d_lightstylevalue[256];
55 cvar_t r_drawentities = {0, "r_drawentities","1"};
56 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1"};
57 cvar_t r_shadow_staticworldlights = {0, "r_shadow_staticworldlights", "1"};
58 cvar_t r_speeds = {0, "r_speeds","0"};
59 cvar_t r_fullbright = {0, "r_fullbright","0"};
60 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1"};
61 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1"};
62 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1"};
63 cvar_t r_shadow_cull = {0, "r_shadow_cull", "1"};
64 cvar_t r_drawcollisionbrushes = {0, "r_drawcollisionbrushes", "0"};
66 cvar_t gl_fogenable = {0, "gl_fogenable", "0"};
67 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25"};
68 cvar_t gl_fogred = {0, "gl_fogred","0.3"};
69 cvar_t gl_foggreen = {0, "gl_foggreen","0.3"};
70 cvar_t gl_fogblue = {0, "gl_fogblue","0.3"};
71 cvar_t gl_fogstart = {0, "gl_fogstart", "0"};
72 cvar_t gl_fogend = {0, "gl_fogend","0"};
74 cvar_t r_textureunits = {0, "r_textureunits", "32"};
76 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1"};
77 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1"};
78 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1"};
79 cvar_t r_watershader = {CVAR_SAVE, "r_watershader", "1"};
82 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
85 for (i = 0;i < verts;i++)
96 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
99 for (i = 0;i < verts;i++)
113 For program optimization
116 qboolean intimerefresh = 0;
117 static void R_TimeRefresh_f (void)
120 float start, stop, time;
123 start = Sys_DoubleTime ();
124 for (i = 0;i < 128;i++)
126 r_refdef.viewangles[0] = 0;
127 r_refdef.viewangles[1] = i/128.0*360.0;
128 r_refdef.viewangles[2] = 0;
132 stop = Sys_DoubleTime ();
135 Con_Printf ("%f seconds (%f fps)\n", time, 128/time);
140 float fog_density, fog_red, fog_green, fog_blue;
142 qboolean oldgl_fogenable;
143 void R_SetupFog(void)
145 if (gamemode == GAME_NEHAHRA)
147 if (gl_fogenable.integer)
149 oldgl_fogenable = true;
150 fog_density = gl_fogdensity.value;
151 fog_red = gl_fogred.value;
152 fog_green = gl_foggreen.value;
153 fog_blue = gl_fogblue.value;
155 else if (oldgl_fogenable)
157 oldgl_fogenable = false;
166 fogcolor[0] = fog_red = bound(0.0f, fog_red , 1.0f);
167 fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
168 fogcolor[2] = fog_blue = bound(0.0f, fog_blue , 1.0f);
173 fogdensity = -4000.0f / (fog_density * fog_density);
174 // fog color was already set
180 // FIXME: move this to client?
183 if (gamemode == GAME_NEHAHRA)
185 Cvar_Set("gl_fogenable", "0");
186 Cvar_Set("gl_fogdensity", "0.2");
187 Cvar_Set("gl_fogred", "0.3");
188 Cvar_Set("gl_foggreen", "0.3");
189 Cvar_Set("gl_fogblue", "0.3");
191 fog_density = fog_red = fog_green = fog_blue = 0.0f;
194 // FIXME: move this to client?
195 void FOG_registercvars(void)
197 if (gamemode == GAME_NEHAHRA)
199 Cvar_RegisterVariable (&gl_fogenable);
200 Cvar_RegisterVariable (&gl_fogdensity);
201 Cvar_RegisterVariable (&gl_fogred);
202 Cvar_RegisterVariable (&gl_foggreen);
203 Cvar_RegisterVariable (&gl_fogblue);
204 Cvar_RegisterVariable (&gl_fogstart);
205 Cvar_RegisterVariable (&gl_fogend);
209 void gl_main_start(void)
213 void gl_main_shutdown(void)
217 extern void CL_ParseEntityLump(char *entitystring);
218 void gl_main_newmap(void)
221 char *entities, entname[MAX_QPATH];
225 strcpy(entname, cl.worldmodel->name);
226 l = strlen(entname) - 4;
227 if (l >= 0 && !strcmp(entname + l, ".bsp"))
229 strcpy(entname + l, ".ent");
230 if ((entities = FS_LoadFile(entname, true)))
232 CL_ParseEntityLump(entities);
237 if (cl.worldmodel->brush.entities)
238 CL_ParseEntityLump(cl.worldmodel->brush.entities);
242 void GL_Main_Init(void)
244 Matrix4x4_CreateIdentity(&r_identitymatrix);
245 // FIXME: move this to client?
247 Cmd_AddCommand("timerefresh", R_TimeRefresh_f);
248 Cvar_RegisterVariable(&r_drawentities);
249 Cvar_RegisterVariable(&r_drawviewmodel);
250 Cvar_RegisterVariable(&r_shadow_staticworldlights);
251 Cvar_RegisterVariable(&r_speeds);
252 Cvar_RegisterVariable(&r_fullbrights);
253 Cvar_RegisterVariable(&r_wateralpha);
254 Cvar_RegisterVariable(&r_dynamic);
255 Cvar_RegisterVariable(&r_fullbright);
256 Cvar_RegisterVariable(&r_textureunits);
257 Cvar_RegisterVariable(&r_shadow_cull);
258 Cvar_RegisterVariable(&r_lerpsprites);
259 Cvar_RegisterVariable(&r_lerpmodels);
260 Cvar_RegisterVariable(&r_waterscroll);
261 Cvar_RegisterVariable(&r_watershader);
262 Cvar_RegisterVariable(&r_drawcollisionbrushes);
263 if (gamemode == GAME_NEHAHRA || gamemode == GAME_NEXUIZ)
264 Cvar_SetValue("r_fullbrights", 0);
265 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
268 vec3_t r_farclip_origin;
269 vec3_t r_farclip_direction;
270 vec_t r_farclip_directiondist;
271 vec_t r_farclip_meshfarclip;
272 int r_farclip_directionbit0;
273 int r_farclip_directionbit1;
274 int r_farclip_directionbit2;
276 // start a farclip measuring session
277 void R_FarClip_Start(vec3_t origin, vec3_t direction, vec_t startfarclip)
279 VectorCopy(origin, r_farclip_origin);
280 VectorCopy(direction, r_farclip_direction);
281 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
282 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
283 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
284 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
285 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
288 // enlarge farclip to accomodate box
289 void R_FarClip_Box(vec3_t mins, vec3_t maxs)
292 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
293 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
294 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
295 if (r_farclip_meshfarclip < d)
296 r_farclip_meshfarclip = d;
299 // return farclip value
300 float R_FarClip_Finish(void)
302 return r_farclip_meshfarclip - r_farclip_directiondist;
305 extern void R_Textures_Init(void);
306 extern void Mod_RenderInit(void);
307 extern void GL_Draw_Init(void);
308 extern void GL_Main_Init(void);
309 extern void R_Shadow_Init(void);
310 extern void GL_Models_Init(void);
311 extern void R_Sky_Init(void);
312 extern void GL_Surf_Init(void);
313 extern void R_Crosshairs_Init(void);
314 extern void R_Light_Init(void);
315 extern void R_Particles_Init(void);
316 extern void R_Explosion_Init(void);
317 extern void ui_init(void);
318 extern void gl_backend_init(void);
319 extern void Sbar_Init(void);
320 extern void R_LightningBeams_Init(void);
322 void Render_Init(void)
340 R_LightningBeams_Init();
348 extern char *ENGINE_EXTENSIONS;
351 VID_CheckExtensions();
353 // LordHavoc: report supported extensions
354 Con_DPrintf("\nengine extensions: %s\n", ENGINE_EXTENSIONS);
357 int R_CullBox(const vec3_t mins, const vec3_t maxs)
361 for (i = 0;i < 4;i++)
368 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
372 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
376 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
380 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
384 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
388 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
392 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
396 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
404 #define VIS_CullBox(mins,maxs) (R_CullBox((mins), (maxs)) || (cl.worldmodel && cl.worldmodel->brush.BoxTouchingPVS && !cl.worldmodel->brush.BoxTouchingPVS(cl.worldmodel, r_pvsbits, (mins), (maxs))))
406 //==================================================================================
408 static void R_MarkEntities (void)
411 entity_render_t *ent;
413 ent = &cl_entities[0].render;
414 Matrix4x4_CreateIdentity(&ent->matrix);
415 Matrix4x4_CreateIdentity(&ent->inversematrix);
418 R_FarClip_Box(cl.worldmodel->normalmins, cl.worldmodel->normalmaxs);
420 if (!r_drawentities.integer)
423 for (i = 0;i < r_refdef.numentities;i++)
425 ent = r_refdef.entities[i];
426 Mod_CheckLoaded(ent->model);
427 // some of the renderer still relies on origin...
428 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
429 // some of the renderer still relies on scale...
430 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
431 R_LerpAnimation(ent);
432 R_UpdateEntLights(ent);
433 if ((chase_active.integer || !(ent->flags & RENDER_EXTERIORMODEL))
434 && !VIS_CullBox(ent->mins, ent->maxs))
436 ent->visframe = r_framecount;
437 R_FarClip_Box(ent->mins, ent->maxs);
442 // only used if skyrendermasked, and normally returns false
443 int R_DrawBrushModelsSky (void)
446 entity_render_t *ent;
448 if (!r_drawentities.integer)
452 for (i = 0;i < r_refdef.numentities;i++)
454 ent = r_refdef.entities[i];
455 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
457 ent->model->DrawSky(ent);
470 void R_DrawViewModel (void)
472 entity_render_t *ent;
474 // FIXME: move these checks to client
475 if (!r_drawviewmodel.integer || chase_active.integer || envmap || !r_drawentities.integer || cl.items & IT_INVISIBILITY || cl.stats[STAT_HEALTH] <= 0 || !cl.viewent.render.model)
478 ent = &cl.viewent.render;
479 Mod_CheckLoaded(ent->model);
480 R_LerpAnimation(ent);
481 Matrix4x4_CreateFromQuakeEntity(&ent->matrix, ent->origin[0], ent->origin[1], ent->origin[2], -ent->angles[0], ent->angles[1], ent->angles[2], ent->scale);
482 Matrix4x4_Invert_Simple(&ent->inversematrix, &ent->matrix);
483 R_UpdateEntLights(ent);
484 ent->model->Draw(ent);
488 void R_DrawNoModel(entity_render_t *ent);
489 void R_DrawModels(void)
492 entity_render_t *ent;
494 if (!r_drawentities.integer)
497 for (i = 0;i < r_refdef.numentities;i++)
499 ent = r_refdef.entities[i];
500 if (ent->visframe == r_framecount)
502 if (ent->model && ent->model->Draw != NULL)
503 ent->model->Draw(ent);
510 #include "r_shadow.h"
512 int shadowframecount = 0;
514 void R_TestAndDrawShadowVolume(entity_render_t *ent, vec3_t lightorigin, float cullradius, float lightradius, vec3_t lightmins, vec3_t lightmaxs, vec3_t clipmins, vec3_t clipmaxs, int lightmarked)
516 vec3_t relativelightorigin;
518 if ((ent->flags & RENDER_SHADOW) && ent->model && ent->model->DrawShadowVolume && !(r_shadow_cull.integer && (ent->maxs[0] < lightmins[0] || ent->mins[0] > lightmaxs[0] || ent->maxs[1] < lightmins[1] || ent->mins[1] > lightmaxs[1] || ent->maxs[2] < lightmins[2] || ent->mins[2] > lightmaxs[2])))
520 Matrix4x4_Transform(&ent->inversematrix, lightorigin, relativelightorigin);
521 ent->model->DrawShadowVolume (ent, relativelightorigin, lightradius);
525 void R_Shadow_DrawWorldLightShadowVolume(matrix4x4_t *matrix, worldlight_t *light);
527 void R_ShadowVolumeLighting(int visiblevolumes)
530 entity_render_t *ent;
532 float f, lightradius, cullradius;
533 vec3_t relativelightorigin, relativeeyeorigin, lightcolor, clipmins, clipmaxs;
538 matrix4x4_t matrix_worldtofilter, matrix_worldtoattenuationxyz, matrix_worldtoattenuationz;
539 matrix4x4_t matrix_modeltofilter, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz;
543 memset(&m, 0, sizeof(m));
544 R_Mesh_State_Texture(&m);
546 GL_BlendFunc(GL_ONE, GL_ONE);
548 GL_DepthTest(r_shadow_visiblevolumes.integer < 2);
549 qglDisable(GL_CULL_FACE);
550 GL_Color(0.0, 0.0125, 0.1, 1);
553 R_Shadow_Stage_Begin();
555 if (r_shadow_realtime_world.integer)
557 R_Shadow_LoadWorldLightsIfNeeded();
558 for (lnum = 0, wl = r_shadow_worldlightchain;wl;wl = wl->next, lnum++)
560 if (d_lightstylevalue[wl->style] <= 0)
562 if (VIS_CullBox(wl->mins, wl->maxs))
564 if (r_shadow_debuglight.integer >= 0 && lnum != r_shadow_debuglight.integer)
566 if (R_Shadow_ScissorForBBox(wl->mins, wl->maxs))
569 cullradius = wl->cullradius;
570 lightradius = wl->lightradius;
571 VectorCopy(wl->mins, clipmins);
572 VectorCopy(wl->maxs, clipmaxs);
574 f = d_lightstylevalue[wl->style] * (1.0f / 256.0f);
575 VectorScale(wl->light, f, lightcolor);
578 f = 2 + sin(realtime * M_PI * 4.0);
579 VectorScale(lightcolor, f, lightcolor);
582 if (wl->castshadows && (gl_stencil || visiblevolumes))
585 R_Shadow_Stage_ShadowVolumes();
586 ent = &cl_entities[0].render;
587 if (r_shadow_staticworldlights.integer)
588 R_Shadow_DrawStaticWorldLight_Shadow(wl, &ent->matrix);
590 R_TestAndDrawShadowVolume(ent, wl->origin, cullradius, lightradius, wl->mins, wl->maxs, clipmins, clipmaxs, true);
591 if (r_drawentities.integer)
592 for (i = 0;i < r_refdef.numentities;i++)
593 R_TestAndDrawShadowVolume(r_refdef.entities[i], wl->origin, cullradius, lightradius, wl->mins, wl->maxs, clipmins, clipmaxs, true);
598 if (wl->castshadows && gl_stencil)
599 R_Shadow_Stage_LightWithShadows();
601 R_Shadow_Stage_LightWithoutShadows();
603 // calculate world to filter matrix
604 Matrix4x4_CreateFromQuakeEntity(&matrix, wl->origin[0], wl->origin[1], wl->origin[2], wl->angles[0], wl->angles[1], wl->angles[2], lightradius);
605 Matrix4x4_Invert_Simple(&matrix_worldtofilter, &matrix);
606 // calculate world to attenuationxyz/xy matrix
607 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5, 0.5, 0.5, 0, 0, 0, 0.5);
608 Matrix4x4_Concat(&matrix_worldtoattenuationxyz, &matrix, &matrix_worldtofilter);
609 // calculate world to attenuationz matrix
610 matrix.m[0][0] = 0;matrix.m[0][1] = 0;matrix.m[0][2] = 0.5;matrix.m[0][3] = 0.5;
611 matrix.m[1][0] = 0;matrix.m[1][1] = 0;matrix.m[1][2] = 0 ;matrix.m[1][3] = 0.5;
612 matrix.m[2][0] = 0;matrix.m[2][1] = 0;matrix.m[2][2] = 0 ;matrix.m[2][3] = 0.5;
613 matrix.m[3][0] = 0;matrix.m[3][1] = 0;matrix.m[3][2] = 0 ;matrix.m[3][3] = 1;
614 Matrix4x4_Concat(&matrix_worldtoattenuationz, &matrix, &matrix_worldtofilter);
616 ent = &cl_entities[0].render;
617 if (ent->model && ent->model->DrawLight)
619 Matrix4x4_Transform(&ent->inversematrix, wl->origin, relativelightorigin);
620 Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin);
621 Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
622 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
623 Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
624 if (r_shadow_staticworldlights.integer)
625 R_Shadow_DrawStaticWorldLight_Light(wl, &ent->matrix, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
627 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
629 if (r_drawentities.integer)
631 for (i = 0;i < r_refdef.numentities;i++)
633 ent = r_refdef.entities[i];
634 if (ent->visframe == r_framecount && ent->model && ent->model->DrawLight
635 && BoxesOverlap(ent->mins, ent->maxs, clipmins, clipmaxs)
636 && !(ent->effects & EF_ADDITIVE) && ent->alpha == 1)
638 Matrix4x4_Transform(&ent->inversematrix, wl->origin, relativelightorigin);
639 Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin);
640 Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
641 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
642 Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
643 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
650 if (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer)
652 for (lnum = 0, rd = r_dlight;lnum < r_numdlights;lnum++, rd++)
654 lightradius = rd->cullradius;
655 clipmins[0] = rd->origin[0] - lightradius;
656 clipmins[1] = rd->origin[1] - lightradius;
657 clipmins[2] = rd->origin[2] - lightradius;
658 clipmaxs[0] = rd->origin[0] + lightradius;
659 clipmaxs[1] = rd->origin[1] + lightradius;
660 clipmaxs[2] = rd->origin[2] + lightradius;
661 if (VIS_CullBox(clipmins, clipmaxs) || R_Shadow_ScissorForBBox(clipmins, clipmaxs))
664 cullradius = RadiusFromBoundsAndOrigin(clipmins, clipmaxs, rd->origin);
665 VectorScale(rd->light, (1.0f / 4096.0f), lightcolor);
667 if (r_shadow_shadows.integer && (gl_stencil || visiblevolumes))
670 R_Shadow_Stage_ShadowVolumes();
671 ent = &cl_entities[0].render;
672 R_TestAndDrawShadowVolume(ent, rd->origin, cullradius, lightradius, clipmins, clipmaxs, clipmins, clipmaxs, false);
673 if (r_drawentities.integer)
675 for (i = 0;i < r_refdef.numentities;i++)
677 ent = r_refdef.entities[i];
679 R_TestAndDrawShadowVolume(ent, rd->origin, cullradius, lightradius, clipmins, clipmaxs, clipmins, clipmaxs, false);
686 if (r_shadow_shadows.integer && gl_stencil)
687 R_Shadow_Stage_LightWithShadows();
689 R_Shadow_Stage_LightWithoutShadows();
691 // calculate world to filter matrix
692 Matrix4x4_CreateFromQuakeEntity(&matrix, rd->origin[0], rd->origin[1], rd->origin[2], 0, 0, 0, lightradius);
693 Matrix4x4_Invert_Simple(&matrix_worldtofilter, &matrix);
694 // calculate world to attenuationxyz/xy matrix
695 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5, 0.5, 0.5, 0, 0, 0, 0.5);
696 Matrix4x4_Concat(&matrix_worldtoattenuationxyz, &matrix, &matrix_worldtofilter);
697 // calculate world to attenuationz matrix
698 matrix.m[0][0] = 0;matrix.m[0][1] = 0;matrix.m[0][2] = 0.5;matrix.m[0][3] = 0.5;
699 matrix.m[1][0] = 0;matrix.m[1][1] = 0;matrix.m[1][2] = 0 ;matrix.m[1][3] = 0.5;
700 matrix.m[2][0] = 0;matrix.m[2][1] = 0;matrix.m[2][2] = 0 ;matrix.m[2][3] = 0.5;
701 matrix.m[3][0] = 0;matrix.m[3][1] = 0;matrix.m[3][2] = 0 ;matrix.m[3][3] = 1;
702 Matrix4x4_Concat(&matrix_worldtoattenuationz, &matrix, &matrix_worldtofilter);
704 ent = &cl_entities[0].render;
705 if (ent->model && ent->model->DrawLight)
707 Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin);
708 Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin);
709 Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
710 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
711 Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
712 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
714 if (r_drawentities.integer)
716 for (i = 0;i < r_refdef.numentities;i++)
718 ent = r_refdef.entities[i];
719 if (ent->visframe == r_framecount && ent->model && ent->model->DrawLight
720 && BoxesOverlap(ent->mins, ent->maxs, clipmins, clipmaxs)
721 && !(ent->effects & EF_ADDITIVE) && ent->alpha == 1)
723 Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin);
724 Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin);
725 Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
726 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
727 Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
728 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
737 qglEnable(GL_CULL_FACE);
739 R_Shadow_Stage_End();
740 qglDisable(GL_SCISSOR_TEST);
743 static void R_SetFrustum (void)
745 // LordHavoc: note to all quake engine coders, the special case for 90
746 // degrees assumed a square view (wrong), so I removed it, Quake2 has it
749 // rotate VPN right by FOV_X/2 degrees
750 RotatePointAroundVector( frustum[0].normal, vup, vpn, -(90-r_refdef.fov_x / 2 ) );
751 frustum[0].dist = DotProduct (r_origin, frustum[0].normal);
752 PlaneClassify(&frustum[0]);
754 // rotate VPN left by FOV_X/2 degrees
755 RotatePointAroundVector( frustum[1].normal, vup, vpn, 90-r_refdef.fov_x / 2 );
756 frustum[1].dist = DotProduct (r_origin, frustum[1].normal);
757 PlaneClassify(&frustum[1]);
759 // rotate VPN up by FOV_X/2 degrees
760 RotatePointAroundVector( frustum[2].normal, vright, vpn, 90-r_refdef.fov_y / 2 );
761 frustum[2].dist = DotProduct (r_origin, frustum[2].normal);
762 PlaneClassify(&frustum[2]);
764 // rotate VPN down by FOV_X/2 degrees
765 RotatePointAroundVector( frustum[3].normal, vright, vpn, -( 90 - r_refdef.fov_y / 2 ) );
766 frustum[3].dist = DotProduct (r_origin, frustum[3].normal);
767 PlaneClassify(&frustum[3]);
775 static void R_SetupFrame (void)
777 // don't allow cheats in multiplayer
780 if (r_fullbright.integer != 0)
781 Cvar_Set ("r_fullbright", "0");
782 if (r_ambient.value != 0)
783 Cvar_Set ("r_ambient", "0");
788 // build the transformation matrix for the given view angles
789 VectorCopy (r_refdef.vieworg, r_origin);
791 AngleVectors (r_refdef.viewangles, vpn, vright, vup);
797 static void R_BlendView(void)
803 if (r_refdef.viewblend[3] < 0.01f)
806 R_Mesh_Matrix(&r_identitymatrix);
808 memset(&m, 0, sizeof(m));
809 R_Mesh_State_Texture(&m);
811 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
813 GL_DepthTest(false); // magic
814 GL_VertexPointer(vertex3f);
815 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
817 vertex3f[0] = r_origin[0] + vpn[0] * 1.5 - vright[0] * r - vup[0] * r;
818 vertex3f[1] = r_origin[1] + vpn[1] * 1.5 - vright[1] * r - vup[1] * r;
819 vertex3f[2] = r_origin[2] + vpn[2] * 1.5 - vright[2] * r - vup[2] * r;
820 vertex3f[3] = r_origin[0] + vpn[0] * 1.5 - vright[0] * r + vup[0] * r * 3;
821 vertex3f[4] = r_origin[1] + vpn[1] * 1.5 - vright[1] * r + vup[1] * r * 3;
822 vertex3f[5] = r_origin[2] + vpn[2] * 1.5 - vright[2] * r + vup[2] * r * 3;
823 vertex3f[6] = r_origin[0] + vpn[0] * 1.5 + vright[0] * r * 3 - vup[0] * r;
824 vertex3f[7] = r_origin[1] + vpn[1] * 1.5 + vright[1] * r * 3 - vup[1] * r;
825 vertex3f[8] = r_origin[2] + vpn[2] * 1.5 + vright[2] * r * 3 - vup[2] * r;
826 R_Mesh_Draw(3, 1, polygonelements);
833 r_refdef must be set before the first call
836 extern void R_DrawLightningBeams (void);
837 void R_RenderView (void)
839 entity_render_t *world;
840 if (!r_refdef.entities/* || !cl.worldmodel*/)
841 return; //Host_Error ("R_RenderView: NULL worldmodel");
843 if (r_shadow_realtime_world.integer)
847 Con_Printf("Realtime world lighting requires 32bit color turning off r_shadow_realtime_world, please type vid_bitsperpixel 32;vid_restart and try again\n");
848 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
852 world = &cl_entities[0].render;
854 // FIXME: move to client
856 R_TimeReport("mexplosion");
864 R_TimeReport("setup");
866 if (cl.worldmodel && cl.worldmodel->brush.FatPVS)
867 cl.worldmodel->brush.FatPVS(cl.worldmodel, r_origin, 2, r_pvsbits, sizeof(r_pvsbits));
869 R_WorldVisibility(world);
870 R_TimeReport("worldvis");
872 R_FarClip_Start(r_origin, vpn, 768.0f);
874 r_farclip = R_FarClip_Finish() + 256.0f;
875 R_TimeReport("markentity");
877 GL_SetupView_ViewPort(r_refdef.x, r_refdef.y, r_refdef.width, r_refdef.height);
878 if ((r_shadow_realtime_world.integer || r_shadow_shadows.integer) && gl_stencil)
879 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.fov_x, r_refdef.fov_y, 1.0f);
881 GL_SetupView_Mode_Perspective(r_refdef.fov_x, r_refdef.fov_y, 1.0f, r_farclip);
882 GL_SetupView_Orientation_FromEntity (r_refdef.vieworg, r_refdef.viewangles);
883 qglDepthFunc(GL_LEQUAL);
886 R_MeshQueue_BeginScene();
888 R_Shadow_UpdateWorldLightSelection();
890 if (R_DrawBrushModelsSky())
891 R_TimeReport("bmodelsky");
893 // must occur early because it can draw sky
895 R_TimeReport("world");
897 // don't let sound skip if going slow
898 if (!intimerefresh && !r_speeds.integer)
902 R_TimeReport("models");
904 if (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer)
906 R_ShadowVolumeLighting(false);
907 R_TimeReport("dynlight");
910 R_DrawLightningBeams();
911 R_TimeReport("lightning");
914 R_TimeReport("particles");
917 R_TimeReport("explosions");
919 R_MeshQueue_RenderTransparent();
920 R_TimeReport("drawtrans");
923 R_TimeReport("coronas");
925 R_DrawWorldCrosshair();
926 R_TimeReport("crosshair");
929 R_TimeReport("blendview");
931 R_MeshQueue_Render();
932 R_MeshQueue_EndScene();
934 if (r_shadow_visiblevolumes.integer)
936 R_ShadowVolumeLighting(true);
937 R_TimeReport("shadowvolume");
941 R_TimeReport("meshfinish");
945 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
948 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
950 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
953 R_Mesh_Matrix(&r_identitymatrix);
955 memset(&m, 0, sizeof(m));
956 R_Mesh_State_Texture(&m);
959 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
960 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
961 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
962 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
963 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
964 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
965 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
966 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
967 GL_ColorPointer(color);
968 R_FillColors(color, 8, cr, cg, cb, ca);
971 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
973 VectorSubtract(v, r_origin, diff);
974 f2 = exp(fogdensity/DotProduct(diff, diff));
976 c[0] = c[0] * f1 + fogcolor[0] * f2;
977 c[1] = c[1] * f1 + fogcolor[1] * f2;
978 c[2] = c[2] * f1 + fogcolor[2] * f2;
985 int nomodelelements[24] =
997 float nomodelvertex3f[6*3] =
1007 float nomodelcolor4f[6*4] =
1009 0.0f, 0.0f, 0.5f, 1.0f,
1010 0.0f, 0.0f, 0.5f, 1.0f,
1011 0.0f, 0.5f, 0.0f, 1.0f,
1012 0.0f, 0.5f, 0.0f, 1.0f,
1013 0.5f, 0.0f, 0.0f, 1.0f,
1014 0.5f, 0.0f, 0.0f, 1.0f
1017 void R_DrawNoModelCallback(const void *calldata1, int calldata2)
1019 const entity_render_t *ent = calldata1;
1021 float f1, f2, *c, diff[3];
1024 R_Mesh_Matrix(&ent->matrix);
1026 memset(&m, 0, sizeof(m));
1027 R_Mesh_State_Texture(&m);
1029 if (ent->flags & EF_ADDITIVE)
1031 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1032 GL_DepthMask(false);
1034 else if (ent->alpha < 1)
1036 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1037 GL_DepthMask(false);
1041 GL_BlendFunc(GL_ONE, GL_ZERO);
1045 GL_VertexPointer(nomodelvertex3f);
1048 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1049 GL_ColorPointer(color4f);
1050 VectorSubtract(ent->origin, r_origin, diff);
1051 f2 = exp(fogdensity/DotProduct(diff, diff));
1053 for (i = 0, c = color4f;i < 6;i++, c += 4)
1055 c[0] = (c[0] * f1 + fogcolor[0] * f2);
1056 c[1] = (c[1] * f1 + fogcolor[1] * f2);
1057 c[2] = (c[2] * f1 + fogcolor[2] * f2);
1061 else if (ent->alpha != 1)
1063 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1064 GL_ColorPointer(color4f);
1065 for (i = 0, c = color4f;i < 6;i++, c += 4)
1069 GL_ColorPointer(nomodelcolor4f);
1070 R_Mesh_Draw(6, 8, nomodelelements);
1073 void R_DrawNoModel(entity_render_t *ent)
1075 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1076 R_MeshQueue_AddTransparent(ent->origin, R_DrawNoModelCallback, ent, 0);
1078 // R_DrawNoModelCallback(ent, 0);
1081 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1083 vec3_t right1, right2, diff, normal;
1085 VectorSubtract (org2, org1, normal);
1086 VectorNormalizeFast (normal);
1088 // calculate 'right' vector for start
1089 VectorSubtract (r_origin, org1, diff);
1090 VectorNormalizeFast (diff);
1091 CrossProduct (normal, diff, right1);
1093 // calculate 'right' vector for end
1094 VectorSubtract (r_origin, org2, diff);
1095 VectorNormalizeFast (diff);
1096 CrossProduct (normal, diff, right2);
1098 vert[ 0] = org1[0] + width * right1[0];
1099 vert[ 1] = org1[1] + width * right1[1];
1100 vert[ 2] = org1[2] + width * right1[2];
1101 vert[ 3] = org1[0] - width * right1[0];
1102 vert[ 4] = org1[1] - width * right1[1];
1103 vert[ 5] = org1[2] - width * right1[2];
1104 vert[ 6] = org2[0] - width * right2[0];
1105 vert[ 7] = org2[1] - width * right2[1];
1106 vert[ 8] = org2[2] - width * right2[2];
1107 vert[ 9] = org2[0] + width * right2[0];
1108 vert[10] = org2[1] + width * right2[1];
1109 vert[11] = org2[2] + width * right2[2];
1112 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
1114 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)
1121 VectorSubtract(origin, r_origin, diff);
1122 ca *= 1 - exp(fogdensity/DotProduct(diff,diff));
1125 R_Mesh_Matrix(&r_identitymatrix);
1126 GL_Color(cr, cg, cb, ca);
1127 GL_VertexPointer(varray_vertex3f);
1128 GL_BlendFunc(blendfunc1, blendfunc2);
1129 GL_DepthMask(false);
1130 GL_DepthTest(!depthdisable);
1132 memset(&m, 0, sizeof(m));
1133 m.tex[0] = R_GetTexture(texture);
1134 m.pointer_texcoord[0] = spritetexcoord2f;
1135 R_Mesh_State_Texture(&m);
1137 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
1138 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
1139 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
1140 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
1141 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
1142 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
1143 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
1144 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
1145 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
1146 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
1147 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
1148 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
1149 R_Mesh_Draw(4, 2, polygonelements);