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
53 // 8.8 fraction of base light value
54 unsigned short d_lightstylevalue[256];
56 cvar_t r_drawentities = {0, "r_drawentities","1"};
57 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1"};
58 cvar_t r_shadow_staticworldlights = {0, "r_shadow_staticworldlights", "1"};
59 cvar_t r_speeds = {0, "r_speeds","0"};
60 cvar_t r_fullbright = {0, "r_fullbright","0"};
61 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1"};
62 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1"};
63 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1"};
64 cvar_t r_shadow_cull = {0, "r_shadow_cull", "1"};
65 cvar_t r_drawcollisionbrushes = {0, "r_drawcollisionbrushes", "0"};
67 cvar_t gl_fogenable = {0, "gl_fogenable", "0"};
68 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25"};
69 cvar_t gl_fogred = {0, "gl_fogred","0.3"};
70 cvar_t gl_foggreen = {0, "gl_foggreen","0.3"};
71 cvar_t gl_fogblue = {0, "gl_fogblue","0.3"};
72 cvar_t gl_fogstart = {0, "gl_fogstart", "0"};
73 cvar_t gl_fogend = {0, "gl_fogend","0"};
75 cvar_t r_textureunits = {0, "r_textureunits", "32"};
77 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1"};
78 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1"};
79 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1"};
80 cvar_t r_watershader = {CVAR_SAVE, "r_watershader", "1"};
83 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
86 for (i = 0;i < verts;i++)
97 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
100 for (i = 0;i < verts;i++)
114 For program optimization
117 qboolean intimerefresh = 0;
118 static void R_TimeRefresh_f (void)
121 float timestart, timedelta, oldangles[3];
124 VectorCopy(cl.viewangles, oldangles);
125 VectorClear(cl.viewangles);
127 timestart = Sys_DoubleTime();
128 for (i = 0;i < 128;i++)
130 Matrix4x4_CreateFromQuakeEntity(&r_refdef.viewentitymatrix, r_vieworigin[0], r_vieworigin[1], r_vieworigin[2], 0, i / 128.0 * 360.0, 0, 1);
133 timedelta = Sys_DoubleTime() - timestart;
135 VectorCopy(oldangles, cl.viewangles);
137 Con_Printf ("%f seconds (%f fps)\n", timedelta, 128/timedelta);
142 float fog_density, fog_red, fog_green, fog_blue;
144 qboolean oldgl_fogenable;
145 void R_UpdateFog(void)
147 if (gamemode == GAME_NEHAHRA)
149 if (gl_fogenable.integer)
151 oldgl_fogenable = true;
152 fog_density = gl_fogdensity.value;
153 fog_red = gl_fogred.value;
154 fog_green = gl_foggreen.value;
155 fog_blue = gl_fogblue.value;
157 else if (oldgl_fogenable)
159 oldgl_fogenable = false;
168 fogcolor[0] = fog_red = bound(0.0f, fog_red , 1.0f);
169 fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
170 fogcolor[2] = fog_blue = bound(0.0f, fog_blue , 1.0f);
175 fogdensity = -4000.0f / (fog_density * fog_density);
176 // fog color was already set
182 // FIXME: move this to client?
185 if (gamemode == GAME_NEHAHRA)
187 Cvar_Set("gl_fogenable", "0");
188 Cvar_Set("gl_fogdensity", "0.2");
189 Cvar_Set("gl_fogred", "0.3");
190 Cvar_Set("gl_foggreen", "0.3");
191 Cvar_Set("gl_fogblue", "0.3");
193 fog_density = fog_red = fog_green = fog_blue = 0.0f;
196 // FIXME: move this to client?
197 void FOG_registercvars(void)
199 if (gamemode == GAME_NEHAHRA)
201 Cvar_RegisterVariable (&gl_fogenable);
202 Cvar_RegisterVariable (&gl_fogdensity);
203 Cvar_RegisterVariable (&gl_fogred);
204 Cvar_RegisterVariable (&gl_foggreen);
205 Cvar_RegisterVariable (&gl_fogblue);
206 Cvar_RegisterVariable (&gl_fogstart);
207 Cvar_RegisterVariable (&gl_fogend);
211 void gl_main_start(void)
215 void gl_main_shutdown(void)
219 extern void CL_ParseEntityLump(char *entitystring);
220 void gl_main_newmap(void)
223 char *entities, entname[MAX_QPATH];
227 strcpy(entname, cl.worldmodel->name);
228 l = strlen(entname) - 4;
229 if (l >= 0 && !strcmp(entname + l, ".bsp"))
231 strcpy(entname + l, ".ent");
232 if ((entities = FS_LoadFile(entname, true)))
234 CL_ParseEntityLump(entities);
239 if (cl.worldmodel->brush.entities)
240 CL_ParseEntityLump(cl.worldmodel->brush.entities);
244 void GL_Main_Init(void)
246 Matrix4x4_CreateIdentity(&r_identitymatrix);
247 // FIXME: move this to client?
249 Cmd_AddCommand("timerefresh", R_TimeRefresh_f);
250 Cvar_RegisterVariable(&r_drawentities);
251 Cvar_RegisterVariable(&r_drawviewmodel);
252 Cvar_RegisterVariable(&r_shadow_staticworldlights);
253 Cvar_RegisterVariable(&r_speeds);
254 Cvar_RegisterVariable(&r_fullbrights);
255 Cvar_RegisterVariable(&r_wateralpha);
256 Cvar_RegisterVariable(&r_dynamic);
257 Cvar_RegisterVariable(&r_fullbright);
258 Cvar_RegisterVariable(&r_textureunits);
259 Cvar_RegisterVariable(&r_shadow_cull);
260 Cvar_RegisterVariable(&r_lerpsprites);
261 Cvar_RegisterVariable(&r_lerpmodels);
262 Cvar_RegisterVariable(&r_waterscroll);
263 Cvar_RegisterVariable(&r_watershader);
264 Cvar_RegisterVariable(&r_drawcollisionbrushes);
265 if (gamemode == GAME_NEHAHRA || gamemode == GAME_NEXUIZ)
266 Cvar_SetValue("r_fullbrights", 0);
267 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
270 static vec3_t r_farclip_origin;
271 static vec3_t r_farclip_direction;
272 static vec_t r_farclip_directiondist;
273 static vec_t r_farclip_meshfarclip;
274 static int r_farclip_directionbit0;
275 static int r_farclip_directionbit1;
276 static int r_farclip_directionbit2;
278 // enlarge farclip to accomodate box
279 static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
282 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
283 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
284 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
285 if (r_farclip_meshfarclip < d)
286 r_farclip_meshfarclip = d;
289 // return farclip value
290 static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
294 VectorCopy(origin, r_farclip_origin);
295 VectorCopy(direction, r_farclip_direction);
296 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
297 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
298 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
299 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
300 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
303 R_FarClip_Box(cl.worldmodel->normalmins, cl.worldmodel->normalmaxs);
304 for (i = 0;i < r_refdef.numentities;i++)
305 R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
307 return r_farclip_meshfarclip - r_farclip_directiondist;
310 extern void R_Textures_Init(void);
311 extern void Mod_RenderInit(void);
312 extern void GL_Draw_Init(void);
313 extern void GL_Main_Init(void);
314 extern void R_Shadow_Init(void);
315 extern void GL_Models_Init(void);
316 extern void R_Sky_Init(void);
317 extern void GL_Surf_Init(void);
318 extern void R_Crosshairs_Init(void);
319 extern void R_Light_Init(void);
320 extern void R_Particles_Init(void);
321 extern void R_Explosion_Init(void);
322 extern void ui_init(void);
323 extern void gl_backend_init(void);
324 extern void Sbar_Init(void);
325 extern void R_LightningBeams_Init(void);
327 void Render_Init(void)
346 R_LightningBeams_Init();
354 extern char *ENGINE_EXTENSIONS;
357 VID_CheckExtensions();
359 // LordHavoc: report supported extensions
360 Con_DPrintf("\nengine extensions: %s\n", ENGINE_EXTENSIONS);
363 int R_CullBox(const vec3_t mins, const vec3_t maxs)
367 for (i = 0;i < 4;i++)
374 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
378 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
382 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
386 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
390 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
394 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
398 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
402 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
410 #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))))
412 //==================================================================================
414 static void R_MarkEntities (void)
417 entity_render_t *ent;
419 ent = &cl_entities[0].render;
420 Matrix4x4_CreateIdentity(&ent->matrix);
421 Matrix4x4_CreateIdentity(&ent->inversematrix);
423 if (!r_drawentities.integer)
426 for (i = 0;i < r_refdef.numentities;i++)
428 ent = r_refdef.entities[i];
429 Mod_CheckLoaded(ent->model);
430 // some of the renderer still relies on origin...
431 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
432 // some of the renderer still relies on scale...
433 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
434 R_LerpAnimation(ent);
435 R_UpdateEntLights(ent);
436 if ((chase_active.integer || !(ent->flags & RENDER_EXTERIORMODEL))
437 && !VIS_CullBox(ent->mins, ent->maxs)
438 && (!envmap || !(ent->flags & (RENDER_VIEWMODEL | RENDER_EXTERIORMODEL))))
439 ent->visframe = r_framecount;
443 // only used if skyrendermasked, and normally returns false
444 int R_DrawBrushModelsSky (void)
447 entity_render_t *ent;
449 if (!r_drawentities.integer)
453 for (i = 0;i < r_refdef.numentities;i++)
455 ent = r_refdef.entities[i];
456 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
458 ent->model->DrawSky(ent);
471 void R_DrawViewModel (void)
473 entity_render_t *ent;
475 // FIXME: move these checks to client
476 if (!r_drawviewmodel.integer || chase_active.integer || envmap || !r_drawentities.integer || cl.items & IT_INVISIBILITY || cl.stats[STAT_HEALTH] <= 0 || !cl.viewent.render.model)
479 ent = &cl.viewent.render;
480 Mod_CheckLoaded(ent->model);
481 R_LerpAnimation(ent);
482 Matrix4x4_CreateFromQuakeEntity(&ent->matrix, ent->origin[0], ent->origin[1], ent->origin[2], -ent->angles[0], ent->angles[1], ent->angles[2], ent->scale);
483 Matrix4x4_Invert_Simple(&ent->inversematrix, &ent->matrix);
484 R_UpdateEntLights(ent);
485 ent->model->Draw(ent);
489 void R_DrawNoModel(entity_render_t *ent);
490 void R_DrawModels(void)
493 entity_render_t *ent;
495 if (!r_drawentities.integer)
498 for (i = 0;i < r_refdef.numentities;i++)
500 ent = r_refdef.entities[i];
501 if (ent->visframe == r_framecount)
503 if (ent->model && ent->model->Draw != NULL)
504 ent->model->Draw(ent);
511 #include "r_shadow.h"
513 int shadowframecount = 0;
515 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)
517 vec3_t relativelightorigin;
519 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])))
521 Matrix4x4_Transform(&ent->inversematrix, lightorigin, relativelightorigin);
522 ent->model->DrawShadowVolume (ent, relativelightorigin, lightradius);
526 void R_Shadow_DrawWorldLightShadowVolume(matrix4x4_t *matrix, worldlight_t *light);
528 void R_ShadowVolumeLighting(int visiblevolumes)
531 entity_render_t *ent;
533 float f, lightradius, cullradius;
534 vec3_t relativelightorigin, relativeeyeorigin, lightcolor, clipmins, clipmaxs;
538 rtexture_t *cubemaptexture;
539 matrix4x4_t matrix_modeltolight, 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 (R_CullBox(wl->mins, wl->maxs))
564 for (i = 0;i < wl->numclusters;i++)
565 if (CHECKPVSBIT(r_pvsbits, wl->clusterindices[i]))
567 if (i == wl->numclusters)
569 if (r_shadow_debuglight.integer >= 0 && lnum != r_shadow_debuglight.integer)
571 if (R_Shadow_ScissorForBBox(wl->mins, wl->maxs))
574 cullradius = wl->cullradius;
575 lightradius = wl->radius;
576 VectorCopy(wl->mins, clipmins);
577 VectorCopy(wl->maxs, clipmaxs);
579 f = d_lightstylevalue[wl->style] * (1.0f / 256.0f);
580 VectorScale(wl->color, f, lightcolor);
583 f = 2 + sin(realtime * M_PI * 4.0);
584 VectorScale(lightcolor, f, lightcolor);
587 if (r_shadow_worldshadows.integer && wl->drawshadows && (gl_stencil || visiblevolumes))
590 R_Shadow_Stage_ShadowVolumes();
591 ent = &cl_entities[0].render;
592 if (r_shadow_staticworldlights.integer)
593 R_Shadow_DrawStaticWorldLight_Shadow(wl, &ent->matrix);
595 R_TestAndDrawShadowVolume(ent, wl->origin, cullradius, lightradius, wl->mins, wl->maxs, clipmins, clipmaxs, true);
596 if (r_drawentities.integer)
597 for (i = 0;i < r_refdef.numentities;i++)
598 R_TestAndDrawShadowVolume(r_refdef.entities[i], wl->origin, cullradius, lightradius, wl->mins, wl->maxs, clipmins, clipmaxs, true);
603 if (r_shadow_worldshadows.integer && wl->drawshadows && gl_stencil)
604 R_Shadow_Stage_LightWithShadows();
606 R_Shadow_Stage_LightWithoutShadows();
608 ent = &cl_entities[0].render;
609 if (ent->model && ent->model->DrawLight)
611 Matrix4x4_Transform(&ent->inversematrix, wl->origin, relativelightorigin);
612 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, relativeeyeorigin);
613 Matrix4x4_Concat(&matrix_modeltolight, &wl->matrix_worldtolight, &ent->matrix);
614 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &wl->matrix_worldtoattenuationxyz, &ent->matrix);
615 Matrix4x4_Concat(&matrix_modeltoattenuationz, &wl->matrix_worldtoattenuationz, &ent->matrix);
616 if (r_shadow_staticworldlights.integer)
617 R_Shadow_DrawStaticWorldLight_Light(wl, &ent->matrix, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, &matrix_modeltolight, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
619 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltolight, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz, wl->cubemap);
621 if (r_drawentities.integer)
623 for (i = 0;i < r_refdef.numentities;i++)
625 ent = r_refdef.entities[i];
626 if (ent->visframe == r_framecount && ent->model && ent->model->DrawLight
627 && BoxesOverlap(ent->mins, ent->maxs, clipmins, clipmaxs)
628 && !(ent->effects & EF_ADDITIVE) && ent->alpha == 1)
630 Matrix4x4_Transform(&ent->inversematrix, wl->origin, relativelightorigin);
631 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, relativeeyeorigin);
632 Matrix4x4_Concat(&matrix_modeltolight, &wl->matrix_worldtolight, &ent->matrix);
633 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &wl->matrix_worldtoattenuationxyz, &ent->matrix);
634 Matrix4x4_Concat(&matrix_modeltoattenuationz, &wl->matrix_worldtoattenuationz, &ent->matrix);
635 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltolight, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz, wl->cubemap);
642 if (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer)
644 for (lnum = 0, rd = r_dlight;lnum < r_numdlights;lnum++, rd++)
646 lightradius = rd->radius;
647 clipmins[0] = rd->origin[0] - lightradius;
648 clipmins[1] = rd->origin[1] - lightradius;
649 clipmins[2] = rd->origin[2] - lightradius;
650 clipmaxs[0] = rd->origin[0] + lightradius;
651 clipmaxs[1] = rd->origin[1] + lightradius;
652 clipmaxs[2] = rd->origin[2] + lightradius;
653 if (VIS_CullBox(clipmins, clipmaxs) || R_Shadow_ScissorForBBox(clipmins, clipmaxs))
656 cullradius = RadiusFromBoundsAndOrigin(clipmins, clipmaxs, rd->origin);
657 VectorCopy(rd->color, lightcolor);
659 if (rd->cubemapnum > 0)
660 cubemaptexture = R_Shadow_Cubemap(va("cubemaps/%i", rd->cubemapnum));
662 cubemaptexture = NULL;
664 if (r_shadow_dlightshadows.integer && rd->shadow && (gl_stencil || visiblevolumes))
667 R_Shadow_Stage_ShadowVolumes();
668 ent = &cl_entities[0].render;
669 R_TestAndDrawShadowVolume(ent, rd->origin, cullradius, lightradius, clipmins, clipmaxs, clipmins, clipmaxs, false);
670 if (r_drawentities.integer)
672 for (i = 0;i < r_refdef.numentities;i++)
674 ent = r_refdef.entities[i];
676 R_TestAndDrawShadowVolume(ent, rd->origin, cullradius, lightradius, clipmins, clipmaxs, clipmins, clipmaxs, false);
683 if (r_shadow_dlightshadows.integer && gl_stencil && rd->shadow)
684 R_Shadow_Stage_LightWithShadows();
686 R_Shadow_Stage_LightWithoutShadows();
688 ent = &cl_entities[0].render;
689 if (ent->model && ent->model->DrawLight)
691 Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin);
692 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, relativeeyeorigin);
693 Matrix4x4_Concat(&matrix_modeltolight, &rd->matrix_worldtolight, &ent->matrix);
694 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &rd->matrix_worldtoattenuationxyz, &ent->matrix);
695 Matrix4x4_Concat(&matrix_modeltoattenuationz, &rd->matrix_worldtoattenuationz, &ent->matrix);
696 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltolight, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz, cubemaptexture);
698 if (r_drawentities.integer)
700 for (i = 0;i < r_refdef.numentities;i++)
702 ent = r_refdef.entities[i];
703 if (ent->visframe == r_framecount && ent->model && ent->model->DrawLight
704 && BoxesOverlap(ent->mins, ent->maxs, clipmins, clipmaxs)
705 && !(ent->effects & EF_ADDITIVE) && ent->alpha == 1)
707 Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin);
708 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, relativeeyeorigin);
709 Matrix4x4_Concat(&matrix_modeltolight, &rd->matrix_worldtolight, &ent->matrix);
710 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &rd->matrix_worldtoattenuationxyz, &ent->matrix);
711 Matrix4x4_Concat(&matrix_modeltoattenuationz, &rd->matrix_worldtoattenuationz, &ent->matrix);
712 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltolight, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz, cubemaptexture);
722 qglEnable(GL_CULL_FACE);
723 GL_Scissor(r_refdef.x, r_refdef.y, r_refdef.width, r_refdef.height);
726 R_Shadow_Stage_End();
729 static void R_SetFrustum(void)
731 // break apart the viewentity matrix into vectors for various purposes
732 Matrix4x4_ToVectors(&r_refdef.viewentitymatrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
733 VectorNegate(r_viewleft, r_viewright);
735 // LordHavoc: note to all quake engine coders, the special case for 90
736 // degrees assumed a square view (wrong), so I removed it, Quake2 has it
739 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
740 RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_refdef.fov_x / 2));
741 frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
742 PlaneClassify(&frustum[0]);
744 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
745 RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_refdef.fov_x / 2));
746 frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
747 PlaneClassify(&frustum[1]);
749 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
750 RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_refdef.fov_y / 2));
751 frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
752 PlaneClassify(&frustum[2]);
754 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
755 RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_refdef.fov_y / 2));
756 frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
757 PlaneClassify(&frustum[3]);
760 static void R_BlendView(void)
766 if (r_refdef.viewblend[3] < 0.01f)
769 R_Mesh_Matrix(&r_identitymatrix);
771 memset(&m, 0, sizeof(m));
772 R_Mesh_State_Texture(&m);
774 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
776 GL_DepthTest(false); // magic
777 GL_VertexPointer(vertex3f);
778 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
780 vertex3f[0] = r_vieworigin[0] + r_viewforward[0] * 1.5 + r_viewleft[0] * r - r_viewup[0] * r;
781 vertex3f[1] = r_vieworigin[1] + r_viewforward[1] * 1.5 + r_viewleft[1] * r - r_viewup[1] * r;
782 vertex3f[2] = r_vieworigin[2] + r_viewforward[2] * 1.5 + r_viewleft[2] * r - r_viewup[2] * r;
783 vertex3f[3] = r_vieworigin[0] + r_viewforward[0] * 1.5 + r_viewleft[0] * r + r_viewup[0] * r * 3;
784 vertex3f[4] = r_vieworigin[1] + r_viewforward[1] * 1.5 + r_viewleft[1] * r + r_viewup[1] * r * 3;
785 vertex3f[5] = r_vieworigin[2] + r_viewforward[2] * 1.5 + r_viewleft[2] * r + r_viewup[2] * r * 3;
786 vertex3f[6] = r_vieworigin[0] + r_viewforward[0] * 1.5 - r_viewleft[0] * r * 3 - r_viewup[0] * r;
787 vertex3f[7] = r_vieworigin[1] + r_viewforward[1] * 1.5 - r_viewleft[1] * r * 3 - r_viewup[1] * r;
788 vertex3f[8] = r_vieworigin[2] + r_viewforward[2] * 1.5 - r_viewleft[2] * r * 3 - r_viewup[2] * r;
789 R_Mesh_Draw(3, 1, polygonelements);
792 void R_UpdateWorld(void)
794 if (!r_refdef.entities/* || !cl.worldmodel*/)
795 return; //Host_Error ("R_RenderView: NULL worldmodel");
797 if (r_shadow_realtime_world.integer && !gl_stencil)
799 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");
800 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
803 // don't allow cheats in multiplayer
806 if (r_fullbright.integer != 0)
807 Cvar_Set ("r_fullbright", "0");
808 if (r_ambient.value != 0)
809 Cvar_Set ("r_ambient", "0");
817 void R_RenderScene(void);
824 void R_RenderView(void)
826 if (!r_refdef.entities/* || !cl.worldmodel*/)
827 return; //Host_Error ("R_RenderView: NULL worldmodel");
829 r_refdef.width = bound(0, r_refdef.width, vid.realwidth);
830 r_refdef.height = bound(0, r_refdef.height, vid.realheight);
831 r_refdef.x = bound(0, r_refdef.x, vid.realwidth - r_refdef.width);
832 r_refdef.y = bound(0, r_refdef.y, vid.realheight - r_refdef.height);
833 r_refdef.fov_x = bound(1, r_refdef.fov_x, 170);
834 r_refdef.fov_y = bound(1, r_refdef.fov_y, 170);
836 // GL is weird because it's bottom to top, r_refdef.y is top to bottom
837 qglViewport(r_refdef.x, vid.realheight - (r_refdef.y + r_refdef.height), r_refdef.width, r_refdef.height);
838 GL_Scissor(r_refdef.x, r_refdef.y, r_refdef.width, r_refdef.height);
839 GL_ScissorTest(true);
843 r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
845 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)))
846 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.fov_x, r_refdef.fov_y, 1.0f);
848 GL_SetupView_Mode_Perspective(r_refdef.fov_x, r_refdef.fov_y, 1.0f, r_farclip);
850 GL_SetupView_Orientation_FromEntity(&r_refdef.viewentitymatrix);
851 R_TimeReport("setup");
856 R_TimeReport("blendview");
858 GL_Scissor(0, 0, vid.realwidth, vid.realheight);
859 GL_ScissorTest(false);
862 extern void R_DrawLightningBeams (void);
863 void R_RenderScene(void)
865 entity_render_t *world;
867 // don't let sound skip if going slow
868 if (!intimerefresh && !r_speeds.integer)
875 if (cl.worldmodel && cl.worldmodel->brush.FatPVS)
876 cl.worldmodel->brush.FatPVS(cl.worldmodel, r_vieworigin, 2, r_pvsbits, sizeof(r_pvsbits));
877 world = &cl_entities[0].render;
878 R_WorldVisibility(world);
879 R_TimeReport("worldvis");
882 R_TimeReport("markentity");
884 qglDepthFunc(GL_LEQUAL);
885 qglPolygonOffset(0, 0);
886 qglEnable(GL_POLYGON_OFFSET_FILL);
889 R_MeshQueue_BeginScene();
891 R_Shadow_UpdateWorldLightSelection();
893 // don't let sound skip if going slow
894 if (!intimerefresh && !r_speeds.integer)
897 if (R_DrawBrushModelsSky())
898 R_TimeReport("bmodelsky");
900 // must occur early because it can draw sky
902 R_TimeReport("world");
904 // don't let sound skip if going slow
905 if (!intimerefresh && !r_speeds.integer)
909 R_TimeReport("models");
911 // don't let sound skip if going slow
912 if (!intimerefresh && !r_speeds.integer)
915 R_ShadowVolumeLighting(false);
916 R_TimeReport("rtlights");
918 // don't let sound skip if going slow
919 if (!intimerefresh && !r_speeds.integer)
922 R_DrawLightningBeams();
923 R_TimeReport("lightning");
926 R_TimeReport("particles");
929 R_TimeReport("explosions");
931 R_MeshQueue_RenderTransparent();
932 R_TimeReport("drawtrans");
935 R_TimeReport("coronas");
937 R_DrawWorldCrosshair();
938 R_TimeReport("crosshair");
940 R_MeshQueue_Render();
941 R_MeshQueue_EndScene();
943 if (r_shadow_visiblevolumes.integer)
945 R_ShadowVolumeLighting(true);
946 R_TimeReport("shadowvolume");
950 R_TimeReport("meshfinish");
952 qglPolygonOffset(0, 0);
953 qglDisable(GL_POLYGON_OFFSET_FILL);
955 // don't let sound skip if going slow
956 if (!intimerefresh && !r_speeds.integer)
961 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
964 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
966 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
969 R_Mesh_Matrix(&r_identitymatrix);
971 memset(&m, 0, sizeof(m));
972 R_Mesh_State_Texture(&m);
975 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
976 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
977 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
978 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
979 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
980 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
981 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
982 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
983 GL_ColorPointer(color);
984 R_FillColors(color, 8, cr, cg, cb, ca);
987 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
989 VectorSubtract(v, r_vieworigin, diff);
990 f2 = exp(fogdensity/DotProduct(diff, diff));
992 c[0] = c[0] * f1 + fogcolor[0] * f2;
993 c[1] = c[1] * f1 + fogcolor[1] * f2;
994 c[2] = c[2] * f1 + fogcolor[2] * f2;
1001 int nomodelelements[24] =
1013 float nomodelvertex3f[6*3] =
1023 float nomodelcolor4f[6*4] =
1025 0.0f, 0.0f, 0.5f, 1.0f,
1026 0.0f, 0.0f, 0.5f, 1.0f,
1027 0.0f, 0.5f, 0.0f, 1.0f,
1028 0.0f, 0.5f, 0.0f, 1.0f,
1029 0.5f, 0.0f, 0.0f, 1.0f,
1030 0.5f, 0.0f, 0.0f, 1.0f
1033 void R_DrawNoModelCallback(const void *calldata1, int calldata2)
1035 const entity_render_t *ent = calldata1;
1037 float f1, f2, *c, diff[3];
1040 R_Mesh_Matrix(&ent->matrix);
1042 memset(&m, 0, sizeof(m));
1043 R_Mesh_State_Texture(&m);
1045 if (ent->flags & EF_ADDITIVE)
1047 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1048 GL_DepthMask(false);
1050 else if (ent->alpha < 1)
1052 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1053 GL_DepthMask(false);
1057 GL_BlendFunc(GL_ONE, GL_ZERO);
1061 GL_VertexPointer(nomodelvertex3f);
1064 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1065 GL_ColorPointer(color4f);
1066 VectorSubtract(ent->origin, r_vieworigin, diff);
1067 f2 = exp(fogdensity/DotProduct(diff, diff));
1069 for (i = 0, c = color4f;i < 6;i++, c += 4)
1071 c[0] = (c[0] * f1 + fogcolor[0] * f2);
1072 c[1] = (c[1] * f1 + fogcolor[1] * f2);
1073 c[2] = (c[2] * f1 + fogcolor[2] * f2);
1077 else if (ent->alpha != 1)
1079 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1080 GL_ColorPointer(color4f);
1081 for (i = 0, c = color4f;i < 6;i++, c += 4)
1085 GL_ColorPointer(nomodelcolor4f);
1086 R_Mesh_Draw(6, 8, nomodelelements);
1089 void R_DrawNoModel(entity_render_t *ent)
1091 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1092 R_MeshQueue_AddTransparent(ent->origin, R_DrawNoModelCallback, ent, 0);
1094 // R_DrawNoModelCallback(ent, 0);
1097 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1099 vec3_t right1, right2, diff, normal;
1101 VectorSubtract (org2, org1, normal);
1102 VectorNormalizeFast (normal);
1104 // calculate 'right' vector for start
1105 VectorSubtract (r_vieworigin, org1, diff);
1106 VectorNormalizeFast (diff);
1107 CrossProduct (normal, diff, right1);
1109 // calculate 'right' vector for end
1110 VectorSubtract (r_vieworigin, org2, diff);
1111 VectorNormalizeFast (diff);
1112 CrossProduct (normal, diff, right2);
1114 vert[ 0] = org1[0] + width * right1[0];
1115 vert[ 1] = org1[1] + width * right1[1];
1116 vert[ 2] = org1[2] + width * right1[2];
1117 vert[ 3] = org1[0] - width * right1[0];
1118 vert[ 4] = org1[1] - width * right1[1];
1119 vert[ 5] = org1[2] - width * right1[2];
1120 vert[ 6] = org2[0] - width * right2[0];
1121 vert[ 7] = org2[1] - width * right2[1];
1122 vert[ 8] = org2[2] - width * right2[2];
1123 vert[ 9] = org2[0] + width * right2[0];
1124 vert[10] = org2[1] + width * right2[1];
1125 vert[11] = org2[2] + width * right2[2];
1128 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
1130 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)
1137 VectorSubtract(origin, r_vieworigin, diff);
1138 ca *= 1 - exp(fogdensity/DotProduct(diff,diff));
1141 R_Mesh_Matrix(&r_identitymatrix);
1142 GL_Color(cr, cg, cb, ca);
1143 GL_VertexPointer(varray_vertex3f);
1144 GL_BlendFunc(blendfunc1, blendfunc2);
1145 GL_DepthMask(false);
1146 GL_DepthTest(!depthdisable);
1148 memset(&m, 0, sizeof(m));
1149 m.tex[0] = R_GetTexture(texture);
1150 m.pointer_texcoord[0] = spritetexcoord2f;
1151 R_Mesh_State_Texture(&m);
1153 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
1154 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
1155 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
1156 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
1157 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
1158 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
1159 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
1160 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
1161 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
1162 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
1163 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
1164 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
1165 R_Mesh_Draw(4, 2, polygonelements);