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_SetupFog(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 vec3_t r_farclip_origin;
271 vec3_t r_farclip_direction;
272 vec_t r_farclip_directiondist;
273 vec_t r_farclip_meshfarclip;
274 int r_farclip_directionbit0;
275 int r_farclip_directionbit1;
276 int r_farclip_directionbit2;
278 // start a farclip measuring session
279 void R_FarClip_Start(vec3_t origin, vec3_t direction, vec_t startfarclip)
281 VectorCopy(origin, r_farclip_origin);
282 VectorCopy(direction, r_farclip_direction);
283 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
284 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
285 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
286 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
287 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
290 // enlarge farclip to accomodate box
291 void R_FarClip_Box(vec3_t mins, vec3_t maxs)
294 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
295 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
296 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
297 if (r_farclip_meshfarclip < d)
298 r_farclip_meshfarclip = d;
301 // return farclip value
302 float R_FarClip_Finish(void)
304 return r_farclip_meshfarclip - r_farclip_directiondist;
307 extern void R_Textures_Init(void);
308 extern void Mod_RenderInit(void);
309 extern void GL_Draw_Init(void);
310 extern void GL_Main_Init(void);
311 extern void R_Shadow_Init(void);
312 extern void GL_Models_Init(void);
313 extern void R_Sky_Init(void);
314 extern void GL_Surf_Init(void);
315 extern void R_Crosshairs_Init(void);
316 extern void R_Light_Init(void);
317 extern void R_Particles_Init(void);
318 extern void R_Explosion_Init(void);
319 extern void ui_init(void);
320 extern void gl_backend_init(void);
321 extern void Sbar_Init(void);
322 extern void R_LightningBeams_Init(void);
324 void Render_Init(void)
343 R_LightningBeams_Init();
351 extern char *ENGINE_EXTENSIONS;
354 VID_CheckExtensions();
356 // LordHavoc: report supported extensions
357 Con_DPrintf("\nengine extensions: %s\n", ENGINE_EXTENSIONS);
360 int R_CullBox(const vec3_t mins, const vec3_t maxs)
364 for (i = 0;i < 4;i++)
371 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
375 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
379 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
383 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
387 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
391 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
395 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
399 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
407 #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))))
409 //==================================================================================
411 static void R_MarkEntities (void)
414 entity_render_t *ent;
416 ent = &cl_entities[0].render;
417 Matrix4x4_CreateIdentity(&ent->matrix);
418 Matrix4x4_CreateIdentity(&ent->inversematrix);
421 R_FarClip_Box(cl.worldmodel->normalmins, cl.worldmodel->normalmaxs);
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))))
440 ent->visframe = r_framecount;
441 R_FarClip_Box(ent->mins, ent->maxs);
446 // only used if skyrendermasked, and normally returns false
447 int R_DrawBrushModelsSky (void)
450 entity_render_t *ent;
452 if (!r_drawentities.integer)
456 for (i = 0;i < r_refdef.numentities;i++)
458 ent = r_refdef.entities[i];
459 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
461 ent->model->DrawSky(ent);
474 void R_DrawViewModel (void)
476 entity_render_t *ent;
478 // FIXME: move these checks to client
479 if (!r_drawviewmodel.integer || chase_active.integer || envmap || !r_drawentities.integer || cl.items & IT_INVISIBILITY || cl.stats[STAT_HEALTH] <= 0 || !cl.viewent.render.model)
482 ent = &cl.viewent.render;
483 Mod_CheckLoaded(ent->model);
484 R_LerpAnimation(ent);
485 Matrix4x4_CreateFromQuakeEntity(&ent->matrix, ent->origin[0], ent->origin[1], ent->origin[2], -ent->angles[0], ent->angles[1], ent->angles[2], ent->scale);
486 Matrix4x4_Invert_Simple(&ent->inversematrix, &ent->matrix);
487 R_UpdateEntLights(ent);
488 ent->model->Draw(ent);
492 void R_DrawNoModel(entity_render_t *ent);
493 void R_DrawModels(void)
496 entity_render_t *ent;
498 if (!r_drawentities.integer)
501 for (i = 0;i < r_refdef.numentities;i++)
503 ent = r_refdef.entities[i];
504 if (ent->visframe == r_framecount)
506 if (ent->model && ent->model->Draw != NULL)
507 ent->model->Draw(ent);
514 #include "r_shadow.h"
516 int shadowframecount = 0;
518 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)
520 vec3_t relativelightorigin;
522 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])))
524 Matrix4x4_Transform(&ent->inversematrix, lightorigin, relativelightorigin);
525 ent->model->DrawShadowVolume (ent, relativelightorigin, lightradius);
529 void R_Shadow_DrawWorldLightShadowVolume(matrix4x4_t *matrix, worldlight_t *light);
531 void R_ShadowVolumeLighting(int visiblevolumes)
534 entity_render_t *ent;
536 float f, lightradius, cullradius;
537 vec3_t relativelightorigin, relativeeyeorigin, lightcolor, clipmins, clipmaxs;
542 matrix4x4_t matrix_worldtofilter, matrix_worldtoattenuationxyz, matrix_worldtoattenuationz;
543 matrix4x4_t matrix_modeltofilter, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz;
547 memset(&m, 0, sizeof(m));
548 R_Mesh_State_Texture(&m);
550 GL_BlendFunc(GL_ONE, GL_ONE);
552 GL_DepthTest(r_shadow_visiblevolumes.integer < 2);
553 qglDisable(GL_CULL_FACE);
554 GL_Color(0.0, 0.0125, 0.1, 1);
557 R_Shadow_Stage_Begin();
559 if (r_shadow_realtime_world.integer)
561 R_Shadow_LoadWorldLightsIfNeeded();
562 for (lnum = 0, wl = r_shadow_worldlightchain;wl;wl = wl->next, lnum++)
564 if (d_lightstylevalue[wl->style] <= 0)
566 if (VIS_CullBox(wl->mins, wl->maxs))
568 if (r_shadow_debuglight.integer >= 0 && lnum != r_shadow_debuglight.integer)
570 if (R_Shadow_ScissorForBBox(wl->mins, wl->maxs))
573 cullradius = wl->cullradius;
574 lightradius = wl->lightradius;
575 VectorCopy(wl->mins, clipmins);
576 VectorCopy(wl->maxs, clipmaxs);
578 f = d_lightstylevalue[wl->style] * (1.0f / 256.0f);
579 VectorScale(wl->light, f, lightcolor);
582 f = 2 + sin(realtime * M_PI * 4.0);
583 VectorScale(lightcolor, f, lightcolor);
586 if (r_shadow_worldshadows.integer && wl->castshadows && (gl_stencil || visiblevolumes))
589 R_Shadow_Stage_ShadowVolumes();
590 ent = &cl_entities[0].render;
591 if (r_shadow_staticworldlights.integer)
592 R_Shadow_DrawStaticWorldLight_Shadow(wl, &ent->matrix);
594 R_TestAndDrawShadowVolume(ent, wl->origin, cullradius, lightradius, wl->mins, wl->maxs, clipmins, clipmaxs, true);
595 if (r_drawentities.integer)
596 for (i = 0;i < r_refdef.numentities;i++)
597 R_TestAndDrawShadowVolume(r_refdef.entities[i], wl->origin, cullradius, lightradius, wl->mins, wl->maxs, clipmins, clipmaxs, true);
602 if (r_shadow_worldshadows.integer && wl->castshadows && gl_stencil)
603 R_Shadow_Stage_LightWithShadows();
605 R_Shadow_Stage_LightWithoutShadows();
607 // calculate world to filter matrix
608 Matrix4x4_CreateFromQuakeEntity(&matrix, wl->origin[0], wl->origin[1], wl->origin[2], wl->angles[0], wl->angles[1], wl->angles[2], lightradius);
609 Matrix4x4_Invert_Simple(&matrix_worldtofilter, &matrix);
610 // calculate world to attenuationxyz/xy matrix
611 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5, 0.5, 0.5, 0, 0, 0, 0.5);
612 Matrix4x4_Concat(&matrix_worldtoattenuationxyz, &matrix, &matrix_worldtofilter);
613 // calculate world to attenuationz matrix
614 matrix.m[0][0] = 0;matrix.m[0][1] = 0;matrix.m[0][2] = 0.5;matrix.m[0][3] = 0.5;
615 matrix.m[1][0] = 0;matrix.m[1][1] = 0;matrix.m[1][2] = 0 ;matrix.m[1][3] = 0.5;
616 matrix.m[2][0] = 0;matrix.m[2][1] = 0;matrix.m[2][2] = 0 ;matrix.m[2][3] = 0.5;
617 matrix.m[3][0] = 0;matrix.m[3][1] = 0;matrix.m[3][2] = 0 ;matrix.m[3][3] = 1;
618 Matrix4x4_Concat(&matrix_worldtoattenuationz, &matrix, &matrix_worldtofilter);
620 ent = &cl_entities[0].render;
621 if (ent->model && ent->model->DrawLight)
623 Matrix4x4_Transform(&ent->inversematrix, wl->origin, relativelightorigin);
624 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, relativeeyeorigin);
625 Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
626 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
627 Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
628 if (r_shadow_staticworldlights.integer)
629 R_Shadow_DrawStaticWorldLight_Light(wl, &ent->matrix, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
631 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
633 if (r_drawentities.integer)
635 for (i = 0;i < r_refdef.numentities;i++)
637 ent = r_refdef.entities[i];
638 if (ent->visframe == r_framecount && ent->model && ent->model->DrawLight
639 && BoxesOverlap(ent->mins, ent->maxs, clipmins, clipmaxs)
640 && !(ent->effects & EF_ADDITIVE) && ent->alpha == 1)
642 Matrix4x4_Transform(&ent->inversematrix, wl->origin, relativelightorigin);
643 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, relativeeyeorigin);
644 Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
645 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
646 Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
647 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
654 if (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer)
656 for (lnum = 0, rd = r_dlight;lnum < r_numdlights;lnum++, rd++)
658 lightradius = rd->cullradius;
659 clipmins[0] = rd->origin[0] - lightradius;
660 clipmins[1] = rd->origin[1] - lightradius;
661 clipmins[2] = rd->origin[2] - lightradius;
662 clipmaxs[0] = rd->origin[0] + lightradius;
663 clipmaxs[1] = rd->origin[1] + lightradius;
664 clipmaxs[2] = rd->origin[2] + lightradius;
665 if (VIS_CullBox(clipmins, clipmaxs) || R_Shadow_ScissorForBBox(clipmins, clipmaxs))
668 cullradius = RadiusFromBoundsAndOrigin(clipmins, clipmaxs, rd->origin);
669 VectorScale(rd->light, (1.0f / 4096.0f), lightcolor);
671 if (r_shadow_dlightshadows.integer && (gl_stencil || visiblevolumes))
674 R_Shadow_Stage_ShadowVolumes();
675 ent = &cl_entities[0].render;
676 R_TestAndDrawShadowVolume(ent, rd->origin, cullradius, lightradius, clipmins, clipmaxs, clipmins, clipmaxs, false);
677 if (r_drawentities.integer)
679 for (i = 0;i < r_refdef.numentities;i++)
681 ent = r_refdef.entities[i];
683 R_TestAndDrawShadowVolume(ent, rd->origin, cullradius, lightradius, clipmins, clipmaxs, clipmins, clipmaxs, false);
690 if (r_shadow_dlightshadows.integer && gl_stencil)
691 R_Shadow_Stage_LightWithShadows();
693 R_Shadow_Stage_LightWithoutShadows();
695 // calculate world to filter matrix
696 Matrix4x4_CreateFromQuakeEntity(&matrix, rd->origin[0], rd->origin[1], rd->origin[2], 0, 0, 0, lightradius);
697 Matrix4x4_Invert_Simple(&matrix_worldtofilter, &matrix);
698 // calculate world to attenuationxyz/xy matrix
699 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5, 0.5, 0.5, 0, 0, 0, 0.5);
700 Matrix4x4_Concat(&matrix_worldtoattenuationxyz, &matrix, &matrix_worldtofilter);
701 // calculate world to attenuationz matrix
702 matrix.m[0][0] = 0;matrix.m[0][1] = 0;matrix.m[0][2] = 0.5;matrix.m[0][3] = 0.5;
703 matrix.m[1][0] = 0;matrix.m[1][1] = 0;matrix.m[1][2] = 0 ;matrix.m[1][3] = 0.5;
704 matrix.m[2][0] = 0;matrix.m[2][1] = 0;matrix.m[2][2] = 0 ;matrix.m[2][3] = 0.5;
705 matrix.m[3][0] = 0;matrix.m[3][1] = 0;matrix.m[3][2] = 0 ;matrix.m[3][3] = 1;
706 Matrix4x4_Concat(&matrix_worldtoattenuationz, &matrix, &matrix_worldtofilter);
708 ent = &cl_entities[0].render;
709 if (ent->model && ent->model->DrawLight)
711 Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin);
712 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, relativeeyeorigin);
713 Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
714 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
715 Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
716 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
718 if (r_drawentities.integer)
720 for (i = 0;i < r_refdef.numentities;i++)
722 ent = r_refdef.entities[i];
723 if (ent->visframe == r_framecount && ent->model && ent->model->DrawLight
724 && BoxesOverlap(ent->mins, ent->maxs, clipmins, clipmaxs)
725 && !(ent->effects & EF_ADDITIVE) && ent->alpha == 1)
727 Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin);
728 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, relativeeyeorigin);
729 Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
730 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
731 Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
732 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
742 qglEnable(GL_CULL_FACE);
743 qglDisable(GL_SCISSOR_TEST);
746 R_Shadow_Stage_End();
749 static void R_SetFrustum (void)
751 // LordHavoc: note to all quake engine coders, the special case for 90
752 // degrees assumed a square view (wrong), so I removed it, Quake2 has it
755 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
756 RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_refdef.fov_x / 2));
757 frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
758 PlaneClassify(&frustum[0]);
760 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
761 RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_refdef.fov_x / 2));
762 frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
763 PlaneClassify(&frustum[1]);
765 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
766 RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_refdef.fov_y / 2));
767 frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
768 PlaneClassify(&frustum[2]);
770 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
771 RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_refdef.fov_y / 2));
772 frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
773 PlaneClassify(&frustum[3]);
781 static void R_SetupFrame (void)
783 // don't allow cheats in multiplayer
786 if (r_fullbright.integer != 0)
787 Cvar_Set ("r_fullbright", "0");
788 if (r_ambient.value != 0)
789 Cvar_Set ("r_ambient", "0");
794 // break apart the viewentity matrix into vectors for various purposes
795 Matrix4x4_ToVectors(&r_refdef.viewentitymatrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
796 VectorNegate(r_viewleft, r_viewright);
798 GL_SetupView_ViewPort(r_refdef.x, r_refdef.y, r_refdef.width, r_refdef.height);
804 static void R_BlendView(void)
810 if (r_refdef.viewblend[3] < 0.01f)
813 R_Mesh_Matrix(&r_identitymatrix);
815 memset(&m, 0, sizeof(m));
816 R_Mesh_State_Texture(&m);
818 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
820 GL_DepthTest(false); // magic
821 GL_VertexPointer(vertex3f);
822 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
824 vertex3f[0] = r_vieworigin[0] + r_viewforward[0] * 1.5 + r_viewleft[0] * r - r_viewup[0] * r;
825 vertex3f[1] = r_vieworigin[1] + r_viewforward[1] * 1.5 + r_viewleft[1] * r - r_viewup[1] * r;
826 vertex3f[2] = r_vieworigin[2] + r_viewforward[2] * 1.5 + r_viewleft[2] * r - r_viewup[2] * r;
827 vertex3f[3] = r_vieworigin[0] + r_viewforward[0] * 1.5 + r_viewleft[0] * r + r_viewup[0] * r * 3;
828 vertex3f[4] = r_vieworigin[1] + r_viewforward[1] * 1.5 + r_viewleft[1] * r + r_viewup[1] * r * 3;
829 vertex3f[5] = r_vieworigin[2] + r_viewforward[2] * 1.5 + r_viewleft[2] * r + r_viewup[2] * r * 3;
830 vertex3f[6] = r_vieworigin[0] + r_viewforward[0] * 1.5 - r_viewleft[0] * r * 3 - r_viewup[0] * r;
831 vertex3f[7] = r_vieworigin[1] + r_viewforward[1] * 1.5 - r_viewleft[1] * r * 3 - r_viewup[1] * r;
832 vertex3f[8] = r_vieworigin[2] + r_viewforward[2] * 1.5 - r_viewleft[2] * r * 3 - r_viewup[2] * r;
833 R_Mesh_Draw(3, 1, polygonelements);
840 r_refdef must be set before the first call
843 extern void R_DrawLightningBeams (void);
844 void R_RenderView (void)
846 entity_render_t *world;
847 if (!r_refdef.entities/* || !cl.worldmodel*/)
848 return; //Host_Error ("R_RenderView: NULL worldmodel");
850 if (r_shadow_realtime_world.integer)
854 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");
855 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
859 world = &cl_entities[0].render;
861 // FIXME: move to client
863 R_TimeReport("mexplosion");
865 qglPolygonOffset(0, 0);
866 qglEnable(GL_POLYGON_OFFSET_FILL);
874 R_TimeReport("setup");
876 if (cl.worldmodel && cl.worldmodel->brush.FatPVS)
877 cl.worldmodel->brush.FatPVS(cl.worldmodel, r_vieworigin, 2, r_pvsbits, sizeof(r_pvsbits));
879 R_WorldVisibility(world);
880 R_TimeReport("worldvis");
882 R_FarClip_Start(r_vieworigin, r_viewforward, 768.0f);
884 r_farclip = R_FarClip_Finish() + 256.0f;
885 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)))
886 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.fov_x, r_refdef.fov_y, 1.0f);
888 GL_SetupView_Mode_Perspective(r_refdef.fov_x, r_refdef.fov_y, 1.0f, r_farclip);
889 GL_SetupView_Orientation_FromEntity(&r_refdef.viewentitymatrix);
890 R_TimeReport("markentity");
892 qglDepthFunc(GL_LEQUAL);
895 R_MeshQueue_BeginScene();
897 R_Shadow_UpdateWorldLightSelection();
899 if (R_DrawBrushModelsSky())
900 R_TimeReport("bmodelsky");
902 // must occur early because it can draw sky
904 R_TimeReport("world");
906 // don't let sound skip if going slow
907 if (!intimerefresh && !r_speeds.integer)
911 R_TimeReport("models");
913 R_ShadowVolumeLighting(false);
914 R_TimeReport("rtlights");
916 R_DrawLightningBeams();
917 R_TimeReport("lightning");
920 R_TimeReport("particles");
923 R_TimeReport("explosions");
925 R_MeshQueue_RenderTransparent();
926 R_TimeReport("drawtrans");
929 R_TimeReport("coronas");
931 R_DrawWorldCrosshair();
932 R_TimeReport("crosshair");
935 R_TimeReport("blendview");
937 R_MeshQueue_Render();
938 R_MeshQueue_EndScene();
940 if (r_shadow_visiblevolumes.integer)
942 R_ShadowVolumeLighting(true);
943 R_TimeReport("shadowvolume");
947 R_TimeReport("meshfinish");
949 qglPolygonOffset(0, 0);
950 qglDisable(GL_POLYGON_OFFSET_FILL);
954 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
957 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
959 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
962 R_Mesh_Matrix(&r_identitymatrix);
964 memset(&m, 0, sizeof(m));
965 R_Mesh_State_Texture(&m);
968 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
969 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
970 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
971 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
972 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
973 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
974 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
975 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
976 GL_ColorPointer(color);
977 R_FillColors(color, 8, cr, cg, cb, ca);
980 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
982 VectorSubtract(v, r_vieworigin, diff);
983 f2 = exp(fogdensity/DotProduct(diff, diff));
985 c[0] = c[0] * f1 + fogcolor[0] * f2;
986 c[1] = c[1] * f1 + fogcolor[1] * f2;
987 c[2] = c[2] * f1 + fogcolor[2] * f2;
994 int nomodelelements[24] =
1006 float nomodelvertex3f[6*3] =
1016 float nomodelcolor4f[6*4] =
1018 0.0f, 0.0f, 0.5f, 1.0f,
1019 0.0f, 0.0f, 0.5f, 1.0f,
1020 0.0f, 0.5f, 0.0f, 1.0f,
1021 0.0f, 0.5f, 0.0f, 1.0f,
1022 0.5f, 0.0f, 0.0f, 1.0f,
1023 0.5f, 0.0f, 0.0f, 1.0f
1026 void R_DrawNoModelCallback(const void *calldata1, int calldata2)
1028 const entity_render_t *ent = calldata1;
1030 float f1, f2, *c, diff[3];
1033 R_Mesh_Matrix(&ent->matrix);
1035 memset(&m, 0, sizeof(m));
1036 R_Mesh_State_Texture(&m);
1038 if (ent->flags & EF_ADDITIVE)
1040 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1041 GL_DepthMask(false);
1043 else if (ent->alpha < 1)
1045 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1046 GL_DepthMask(false);
1050 GL_BlendFunc(GL_ONE, GL_ZERO);
1054 GL_VertexPointer(nomodelvertex3f);
1057 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1058 GL_ColorPointer(color4f);
1059 VectorSubtract(ent->origin, r_vieworigin, diff);
1060 f2 = exp(fogdensity/DotProduct(diff, diff));
1062 for (i = 0, c = color4f;i < 6;i++, c += 4)
1064 c[0] = (c[0] * f1 + fogcolor[0] * f2);
1065 c[1] = (c[1] * f1 + fogcolor[1] * f2);
1066 c[2] = (c[2] * f1 + fogcolor[2] * f2);
1070 else if (ent->alpha != 1)
1072 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1073 GL_ColorPointer(color4f);
1074 for (i = 0, c = color4f;i < 6;i++, c += 4)
1078 GL_ColorPointer(nomodelcolor4f);
1079 R_Mesh_Draw(6, 8, nomodelelements);
1082 void R_DrawNoModel(entity_render_t *ent)
1084 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1085 R_MeshQueue_AddTransparent(ent->origin, R_DrawNoModelCallback, ent, 0);
1087 // R_DrawNoModelCallback(ent, 0);
1090 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1092 vec3_t right1, right2, diff, normal;
1094 VectorSubtract (org2, org1, normal);
1095 VectorNormalizeFast (normal);
1097 // calculate 'right' vector for start
1098 VectorSubtract (r_vieworigin, org1, diff);
1099 VectorNormalizeFast (diff);
1100 CrossProduct (normal, diff, right1);
1102 // calculate 'right' vector for end
1103 VectorSubtract (r_vieworigin, org2, diff);
1104 VectorNormalizeFast (diff);
1105 CrossProduct (normal, diff, right2);
1107 vert[ 0] = org1[0] + width * right1[0];
1108 vert[ 1] = org1[1] + width * right1[1];
1109 vert[ 2] = org1[2] + width * right1[2];
1110 vert[ 3] = org1[0] - width * right1[0];
1111 vert[ 4] = org1[1] - width * right1[1];
1112 vert[ 5] = org1[2] - width * right1[2];
1113 vert[ 6] = org2[0] - width * right2[0];
1114 vert[ 7] = org2[1] - width * right2[1];
1115 vert[ 8] = org2[2] - width * right2[2];
1116 vert[ 9] = org2[0] + width * right2[0];
1117 vert[10] = org2[1] + width * right2[1];
1118 vert[11] = org2[2] + width * right2[2];
1121 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
1123 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)
1130 VectorSubtract(origin, r_vieworigin, diff);
1131 ca *= 1 - exp(fogdensity/DotProduct(diff,diff));
1134 R_Mesh_Matrix(&r_identitymatrix);
1135 GL_Color(cr, cg, cb, ca);
1136 GL_VertexPointer(varray_vertex3f);
1137 GL_BlendFunc(blendfunc1, blendfunc2);
1138 GL_DepthMask(false);
1139 GL_DepthTest(!depthdisable);
1141 memset(&m, 0, sizeof(m));
1142 m.tex[0] = R_GetTexture(texture);
1143 m.pointer_texcoord[0] = spritetexcoord2f;
1144 R_Mesh_State_Texture(&m);
1146 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
1147 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
1148 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
1149 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
1150 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
1151 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
1152 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
1153 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
1154 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
1155 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
1156 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
1157 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
1158 R_Mesh_Draw(4, 2, polygonelements);