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] + cl.time * 12, wl->angles[1] + cl.time * 45, wl->angles[2], lightradius);
609 Matrix4x4_CreateFromQuakeEntity(&matrix, wl->origin[0], wl->origin[1], wl->origin[2], wl->angles[0], wl->angles[1], wl->angles[2], lightradius);
610 Matrix4x4_Invert_Simple(&matrix_worldtofilter, &matrix);
611 // calculate world to attenuationxyz/xy matrix
612 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5, 0.5, 0.5, 0, 0, 0, 0.5);
613 Matrix4x4_Concat(&matrix_worldtoattenuationxyz, &matrix, &matrix_worldtofilter);
614 // calculate world to attenuationz matrix
615 matrix.m[0][0] = 0;matrix.m[0][1] = 0;matrix.m[0][2] = 0.5;matrix.m[0][3] = 0.5;
616 matrix.m[1][0] = 0;matrix.m[1][1] = 0;matrix.m[1][2] = 0 ;matrix.m[1][3] = 0.5;
617 matrix.m[2][0] = 0;matrix.m[2][1] = 0;matrix.m[2][2] = 0 ;matrix.m[2][3] = 0.5;
618 matrix.m[3][0] = 0;matrix.m[3][1] = 0;matrix.m[3][2] = 0 ;matrix.m[3][3] = 1;
619 Matrix4x4_Concat(&matrix_worldtoattenuationz, &matrix, &matrix_worldtofilter);
621 ent = &cl_entities[0].render;
622 if (ent->model && ent->model->DrawLight)
624 Matrix4x4_Transform(&ent->inversematrix, wl->origin, relativelightorigin);
625 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, relativeeyeorigin);
626 Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
627 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
628 Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
629 if (r_shadow_staticworldlights.integer)
630 R_Shadow_DrawStaticWorldLight_Light(wl, &ent->matrix, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
632 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz, wl->cubemap);
634 if (r_drawentities.integer)
636 for (i = 0;i < r_refdef.numentities;i++)
638 ent = r_refdef.entities[i];
639 if (ent->visframe == r_framecount && ent->model && ent->model->DrawLight
640 && BoxesOverlap(ent->mins, ent->maxs, clipmins, clipmaxs)
641 && !(ent->effects & EF_ADDITIVE) && ent->alpha == 1)
643 Matrix4x4_Transform(&ent->inversematrix, wl->origin, relativelightorigin);
644 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, relativeeyeorigin);
645 Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
646 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
647 Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
648 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz, wl->cubemap);
655 if (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer)
657 for (lnum = 0, rd = r_dlight;lnum < r_numdlights;lnum++, rd++)
659 lightradius = rd->cullradius;
660 clipmins[0] = rd->origin[0] - lightradius;
661 clipmins[1] = rd->origin[1] - lightradius;
662 clipmins[2] = rd->origin[2] - lightradius;
663 clipmaxs[0] = rd->origin[0] + lightradius;
664 clipmaxs[1] = rd->origin[1] + lightradius;
665 clipmaxs[2] = rd->origin[2] + lightradius;
666 if (VIS_CullBox(clipmins, clipmaxs) || R_Shadow_ScissorForBBox(clipmins, clipmaxs))
669 cullradius = RadiusFromBoundsAndOrigin(clipmins, clipmaxs, rd->origin);
670 VectorScale(rd->light, (1.0f / 4096.0f), lightcolor);
672 if (r_shadow_dlightshadows.integer && (gl_stencil || visiblevolumes))
675 R_Shadow_Stage_ShadowVolumes();
676 ent = &cl_entities[0].render;
677 R_TestAndDrawShadowVolume(ent, rd->origin, cullradius, lightradius, clipmins, clipmaxs, clipmins, clipmaxs, false);
678 if (r_drawentities.integer)
680 for (i = 0;i < r_refdef.numentities;i++)
682 ent = r_refdef.entities[i];
684 R_TestAndDrawShadowVolume(ent, rd->origin, cullradius, lightradius, clipmins, clipmaxs, clipmins, clipmaxs, false);
691 if (r_shadow_dlightshadows.integer && gl_stencil)
692 R_Shadow_Stage_LightWithShadows();
694 R_Shadow_Stage_LightWithoutShadows();
696 // calculate world to filter matrix
697 Matrix4x4_CreateFromQuakeEntity(&matrix, rd->origin[0], rd->origin[1], rd->origin[2], 0, 0, 0, lightradius);
698 Matrix4x4_Invert_Simple(&matrix_worldtofilter, &matrix);
699 // calculate world to attenuationxyz/xy matrix
700 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5, 0.5, 0.5, 0, 0, 0, 0.5);
701 Matrix4x4_Concat(&matrix_worldtoattenuationxyz, &matrix, &matrix_worldtofilter);
702 // calculate world to attenuationz matrix
703 matrix.m[0][0] = 0;matrix.m[0][1] = 0;matrix.m[0][2] = 0.5;matrix.m[0][3] = 0.5;
704 matrix.m[1][0] = 0;matrix.m[1][1] = 0;matrix.m[1][2] = 0 ;matrix.m[1][3] = 0.5;
705 matrix.m[2][0] = 0;matrix.m[2][1] = 0;matrix.m[2][2] = 0 ;matrix.m[2][3] = 0.5;
706 matrix.m[3][0] = 0;matrix.m[3][1] = 0;matrix.m[3][2] = 0 ;matrix.m[3][3] = 1;
707 Matrix4x4_Concat(&matrix_worldtoattenuationz, &matrix, &matrix_worldtofilter);
709 ent = &cl_entities[0].render;
710 if (ent->model && ent->model->DrawLight)
712 Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin);
713 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, relativeeyeorigin);
714 Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
715 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
716 Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
717 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz, NULL);
719 if (r_drawentities.integer)
721 for (i = 0;i < r_refdef.numentities;i++)
723 ent = r_refdef.entities[i];
724 if (ent->visframe == r_framecount && ent->model && ent->model->DrawLight
725 && BoxesOverlap(ent->mins, ent->maxs, clipmins, clipmaxs)
726 && !(ent->effects & EF_ADDITIVE) && ent->alpha == 1)
728 Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin);
729 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, relativeeyeorigin);
730 Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
731 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
732 Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
733 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz, NULL);
743 qglEnable(GL_CULL_FACE);
744 qglDisable(GL_SCISSOR_TEST);
747 R_Shadow_Stage_End();
750 static void R_SetFrustum (void)
752 // LordHavoc: note to all quake engine coders, the special case for 90
753 // degrees assumed a square view (wrong), so I removed it, Quake2 has it
756 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
757 RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_refdef.fov_x / 2));
758 frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
759 PlaneClassify(&frustum[0]);
761 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
762 RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_refdef.fov_x / 2));
763 frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
764 PlaneClassify(&frustum[1]);
766 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
767 RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_refdef.fov_y / 2));
768 frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
769 PlaneClassify(&frustum[2]);
771 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
772 RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_refdef.fov_y / 2));
773 frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
774 PlaneClassify(&frustum[3]);
782 static void R_SetupFrame (void)
784 // don't allow cheats in multiplayer
787 if (r_fullbright.integer != 0)
788 Cvar_Set ("r_fullbright", "0");
789 if (r_ambient.value != 0)
790 Cvar_Set ("r_ambient", "0");
795 // break apart the viewentity matrix into vectors for various purposes
796 Matrix4x4_ToVectors(&r_refdef.viewentitymatrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
797 VectorNegate(r_viewleft, r_viewright);
799 GL_SetupView_ViewPort(r_refdef.x, r_refdef.y, r_refdef.width, r_refdef.height);
805 static void R_BlendView(void)
811 if (r_refdef.viewblend[3] < 0.01f)
814 R_Mesh_Matrix(&r_identitymatrix);
816 memset(&m, 0, sizeof(m));
817 R_Mesh_State_Texture(&m);
819 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
821 GL_DepthTest(false); // magic
822 GL_VertexPointer(vertex3f);
823 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
825 vertex3f[0] = r_vieworigin[0] + r_viewforward[0] * 1.5 + r_viewleft[0] * r - r_viewup[0] * r;
826 vertex3f[1] = r_vieworigin[1] + r_viewforward[1] * 1.5 + r_viewleft[1] * r - r_viewup[1] * r;
827 vertex3f[2] = r_vieworigin[2] + r_viewforward[2] * 1.5 + r_viewleft[2] * r - r_viewup[2] * r;
828 vertex3f[3] = r_vieworigin[0] + r_viewforward[0] * 1.5 + r_viewleft[0] * r + r_viewup[0] * r * 3;
829 vertex3f[4] = r_vieworigin[1] + r_viewforward[1] * 1.5 + r_viewleft[1] * r + r_viewup[1] * r * 3;
830 vertex3f[5] = r_vieworigin[2] + r_viewforward[2] * 1.5 + r_viewleft[2] * r + r_viewup[2] * r * 3;
831 vertex3f[6] = r_vieworigin[0] + r_viewforward[0] * 1.5 - r_viewleft[0] * r * 3 - r_viewup[0] * r;
832 vertex3f[7] = r_vieworigin[1] + r_viewforward[1] * 1.5 - r_viewleft[1] * r * 3 - r_viewup[1] * r;
833 vertex3f[8] = r_vieworigin[2] + r_viewforward[2] * 1.5 - r_viewleft[2] * r * 3 - r_viewup[2] * r;
834 R_Mesh_Draw(3, 1, polygonelements);
841 r_refdef must be set before the first call
844 extern void R_DrawLightningBeams (void);
845 void R_RenderView (void)
847 entity_render_t *world;
848 if (!r_refdef.entities/* || !cl.worldmodel*/)
849 return; //Host_Error ("R_RenderView: NULL worldmodel");
851 if (r_shadow_realtime_world.integer)
855 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");
856 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
860 world = &cl_entities[0].render;
862 // FIXME: move to client
864 R_TimeReport("mexplosion");
866 qglPolygonOffset(0, 0);
867 qglEnable(GL_POLYGON_OFFSET_FILL);
875 R_TimeReport("setup");
877 if (cl.worldmodel && cl.worldmodel->brush.FatPVS)
878 cl.worldmodel->brush.FatPVS(cl.worldmodel, r_vieworigin, 2, r_pvsbits, sizeof(r_pvsbits));
880 R_WorldVisibility(world);
881 R_TimeReport("worldvis");
883 R_FarClip_Start(r_vieworigin, r_viewforward, 768.0f);
885 r_farclip = R_FarClip_Finish() + 256.0f;
886 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)))
887 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.fov_x, r_refdef.fov_y, 1.0f);
889 GL_SetupView_Mode_Perspective(r_refdef.fov_x, r_refdef.fov_y, 1.0f, r_farclip);
890 GL_SetupView_Orientation_FromEntity(&r_refdef.viewentitymatrix);
891 R_TimeReport("markentity");
893 qglDepthFunc(GL_LEQUAL);
896 R_MeshQueue_BeginScene();
898 R_Shadow_UpdateWorldLightSelection();
900 if (R_DrawBrushModelsSky())
901 R_TimeReport("bmodelsky");
903 // must occur early because it can draw sky
905 R_TimeReport("world");
907 // don't let sound skip if going slow
908 if (!intimerefresh && !r_speeds.integer)
912 R_TimeReport("models");
914 R_ShadowVolumeLighting(false);
915 R_TimeReport("rtlights");
917 R_DrawLightningBeams();
918 R_TimeReport("lightning");
921 R_TimeReport("particles");
924 R_TimeReport("explosions");
926 R_MeshQueue_RenderTransparent();
927 R_TimeReport("drawtrans");
930 R_TimeReport("coronas");
932 R_DrawWorldCrosshair();
933 R_TimeReport("crosshair");
936 R_TimeReport("blendview");
938 R_MeshQueue_Render();
939 R_MeshQueue_EndScene();
941 if (r_shadow_visiblevolumes.integer)
943 R_ShadowVolumeLighting(true);
944 R_TimeReport("shadowvolume");
948 R_TimeReport("meshfinish");
950 qglPolygonOffset(0, 0);
951 qglDisable(GL_POLYGON_OFFSET_FILL);
955 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
958 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
960 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
963 R_Mesh_Matrix(&r_identitymatrix);
965 memset(&m, 0, sizeof(m));
966 R_Mesh_State_Texture(&m);
969 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
970 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
971 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
972 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
973 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
974 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
975 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
976 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
977 GL_ColorPointer(color);
978 R_FillColors(color, 8, cr, cg, cb, ca);
981 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
983 VectorSubtract(v, r_vieworigin, diff);
984 f2 = exp(fogdensity/DotProduct(diff, diff));
986 c[0] = c[0] * f1 + fogcolor[0] * f2;
987 c[1] = c[1] * f1 + fogcolor[1] * f2;
988 c[2] = c[2] * f1 + fogcolor[2] * f2;
995 int nomodelelements[24] =
1007 float nomodelvertex3f[6*3] =
1017 float nomodelcolor4f[6*4] =
1019 0.0f, 0.0f, 0.5f, 1.0f,
1020 0.0f, 0.0f, 0.5f, 1.0f,
1021 0.0f, 0.5f, 0.0f, 1.0f,
1022 0.0f, 0.5f, 0.0f, 1.0f,
1023 0.5f, 0.0f, 0.0f, 1.0f,
1024 0.5f, 0.0f, 0.0f, 1.0f
1027 void R_DrawNoModelCallback(const void *calldata1, int calldata2)
1029 const entity_render_t *ent = calldata1;
1031 float f1, f2, *c, diff[3];
1034 R_Mesh_Matrix(&ent->matrix);
1036 memset(&m, 0, sizeof(m));
1037 R_Mesh_State_Texture(&m);
1039 if (ent->flags & EF_ADDITIVE)
1041 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1042 GL_DepthMask(false);
1044 else if (ent->alpha < 1)
1046 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1047 GL_DepthMask(false);
1051 GL_BlendFunc(GL_ONE, GL_ZERO);
1055 GL_VertexPointer(nomodelvertex3f);
1058 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1059 GL_ColorPointer(color4f);
1060 VectorSubtract(ent->origin, r_vieworigin, diff);
1061 f2 = exp(fogdensity/DotProduct(diff, diff));
1063 for (i = 0, c = color4f;i < 6;i++, c += 4)
1065 c[0] = (c[0] * f1 + fogcolor[0] * f2);
1066 c[1] = (c[1] * f1 + fogcolor[1] * f2);
1067 c[2] = (c[2] * f1 + fogcolor[2] * f2);
1071 else if (ent->alpha != 1)
1073 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1074 GL_ColorPointer(color4f);
1075 for (i = 0, c = color4f;i < 6;i++, c += 4)
1079 GL_ColorPointer(nomodelcolor4f);
1080 R_Mesh_Draw(6, 8, nomodelelements);
1083 void R_DrawNoModel(entity_render_t *ent)
1085 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1086 R_MeshQueue_AddTransparent(ent->origin, R_DrawNoModelCallback, ent, 0);
1088 // R_DrawNoModelCallback(ent, 0);
1091 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1093 vec3_t right1, right2, diff, normal;
1095 VectorSubtract (org2, org1, normal);
1096 VectorNormalizeFast (normal);
1098 // calculate 'right' vector for start
1099 VectorSubtract (r_vieworigin, org1, diff);
1100 VectorNormalizeFast (diff);
1101 CrossProduct (normal, diff, right1);
1103 // calculate 'right' vector for end
1104 VectorSubtract (r_vieworigin, org2, diff);
1105 VectorNormalizeFast (diff);
1106 CrossProduct (normal, diff, right2);
1108 vert[ 0] = org1[0] + width * right1[0];
1109 vert[ 1] = org1[1] + width * right1[1];
1110 vert[ 2] = org1[2] + width * right1[2];
1111 vert[ 3] = org1[0] - width * right1[0];
1112 vert[ 4] = org1[1] - width * right1[1];
1113 vert[ 5] = org1[2] - width * right1[2];
1114 vert[ 6] = org2[0] - width * right2[0];
1115 vert[ 7] = org2[1] - width * right2[1];
1116 vert[ 8] = org2[2] - width * right2[2];
1117 vert[ 9] = org2[0] + width * right2[0];
1118 vert[10] = org2[1] + width * right2[1];
1119 vert[11] = org2[2] + width * right2[2];
1122 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
1124 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)
1131 VectorSubtract(origin, r_vieworigin, diff);
1132 ca *= 1 - exp(fogdensity/DotProduct(diff,diff));
1135 R_Mesh_Matrix(&r_identitymatrix);
1136 GL_Color(cr, cg, cb, ca);
1137 GL_VertexPointer(varray_vertex3f);
1138 GL_BlendFunc(blendfunc1, blendfunc2);
1139 GL_DepthMask(false);
1140 GL_DepthTest(!depthdisable);
1142 memset(&m, 0, sizeof(m));
1143 m.tex[0] = R_GetTexture(texture);
1144 m.pointer_texcoord[0] = spritetexcoord2f;
1145 R_Mesh_State_Texture(&m);
1147 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
1148 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
1149 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
1150 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
1151 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
1152 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
1153 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
1154 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
1155 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
1156 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
1157 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
1158 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
1159 R_Mesh_Draw(4, 2, polygonelements);