2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 // used for dlight push checking and other things
27 // used for visibility checking
28 qbyte r_pvsbits[(MAX_MAP_LEAFS+7)>>3];
32 matrix4x4_t r_identitymatrix;
34 int c_alias_polys, c_light_polys, c_faces, c_nodes, c_leafs, c_models, c_bmodels, c_sprites, c_particles, c_dlights;
36 // true during envmap command capture
52 // 8.8 fraction of base light value
53 unsigned short d_lightstylevalue[256];
55 cvar_t r_drawentities = {0, "r_drawentities","1"};
56 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1"};
57 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0"};
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"};
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 start, stop, time;
124 start = Sys_DoubleTime ();
125 for (i = 0;i < 128;i++)
127 r_refdef.viewangles[0] = 0;
128 r_refdef.viewangles[1] = i/128.0*360.0;
129 r_refdef.viewangles[2] = 0;
133 stop = Sys_DoubleTime ();
136 Con_Printf ("%f seconds (%f fps)\n", time, 128/time);
141 float fog_density, fog_red, fog_green, fog_blue;
143 qboolean oldgl_fogenable;
144 void R_SetupFog(void)
146 if (gamemode == GAME_NEHAHRA)
148 if (gl_fogenable.integer)
150 oldgl_fogenable = true;
151 fog_density = gl_fogdensity.value;
152 fog_red = gl_fogred.value;
153 fog_green = gl_foggreen.value;
154 fog_blue = gl_fogblue.value;
156 else if (oldgl_fogenable)
158 oldgl_fogenable = false;
167 fogcolor[0] = fog_red = bound(0.0f, fog_red , 1.0f);
168 fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
169 fogcolor[2] = fog_blue = bound(0.0f, fog_blue , 1.0f);
174 fogdensity = -4000.0f / (fog_density * fog_density);
175 // fog color was already set
181 // FIXME: move this to client?
184 if (gamemode == GAME_NEHAHRA)
186 Cvar_Set("gl_fogenable", "0");
187 Cvar_Set("gl_fogdensity", "0.2");
188 Cvar_Set("gl_fogred", "0.3");
189 Cvar_Set("gl_foggreen", "0.3");
190 Cvar_Set("gl_fogblue", "0.3");
192 fog_density = fog_red = fog_green = fog_blue = 0.0f;
195 // FIXME: move this to client?
196 void FOG_registercvars(void)
198 if (gamemode == GAME_NEHAHRA)
200 Cvar_RegisterVariable (&gl_fogenable);
201 Cvar_RegisterVariable (&gl_fogdensity);
202 Cvar_RegisterVariable (&gl_fogred);
203 Cvar_RegisterVariable (&gl_foggreen);
204 Cvar_RegisterVariable (&gl_fogblue);
205 Cvar_RegisterVariable (&gl_fogstart);
206 Cvar_RegisterVariable (&gl_fogend);
210 void gl_main_start(void)
214 void gl_main_shutdown(void)
218 extern void CL_ParseEntityLump(char *entitystring);
219 void gl_main_newmap(void)
222 char *entities, entname[MAX_QPATH];
226 strcpy(entname, cl.worldmodel->name);
227 l = strlen(entname) - 4;
228 if (l >= 0 && !strcmp(entname + l, ".bsp"))
230 strcpy(entname + l, ".ent");
231 if ((entities = FS_LoadFile(entname, true)))
233 CL_ParseEntityLump(entities);
238 if (cl.worldmodel->brush.entities)
239 CL_ParseEntityLump(cl.worldmodel->brush.entities);
243 void GL_Main_Init(void)
245 Matrix4x4_CreateIdentity(&r_identitymatrix);
246 // FIXME: move this to client?
248 Cmd_AddCommand("timerefresh", R_TimeRefresh_f);
249 Cvar_RegisterVariable(&r_drawentities);
250 Cvar_RegisterVariable(&r_drawviewmodel);
251 Cvar_RegisterVariable(&r_shadows);
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_drawcollisionbrushes);
264 if (gamemode == GAME_NEHAHRA || gamemode == GAME_NEXUIZ)
265 Cvar_SetValue("r_fullbrights", 0);
266 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
269 vec3_t r_farclip_origin;
270 vec3_t r_farclip_direction;
271 vec_t r_farclip_directiondist;
272 vec_t r_farclip_meshfarclip;
273 int r_farclip_directionbit0;
274 int r_farclip_directionbit1;
275 int r_farclip_directionbit2;
277 // start a farclip measuring session
278 void R_FarClip_Start(vec3_t origin, vec3_t direction, vec_t startfarclip)
280 VectorCopy(origin, r_farclip_origin);
281 VectorCopy(direction, r_farclip_direction);
282 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
283 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
284 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
285 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
286 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
289 // enlarge farclip to accomodate box
290 void R_FarClip_Box(vec3_t mins, vec3_t maxs)
293 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
294 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
295 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
296 if (r_farclip_meshfarclip < d)
297 r_farclip_meshfarclip = d;
300 // return farclip value
301 float R_FarClip_Finish(void)
303 return r_farclip_meshfarclip - r_farclip_directiondist;
306 extern void R_Textures_Init(void);
307 extern void Mod_RenderInit(void);
308 extern void GL_Draw_Init(void);
309 extern void GL_Main_Init(void);
310 extern void R_Shadow_Init(void);
311 extern void GL_Models_Init(void);
312 extern void R_Sky_Init(void);
313 extern void GL_Surf_Init(void);
314 extern void R_Crosshairs_Init(void);
315 extern void R_Light_Init(void);
316 extern void R_Particles_Init(void);
317 extern void R_Explosion_Init(void);
318 extern void ui_init(void);
319 extern void gl_backend_init(void);
320 extern void Sbar_Init(void);
321 extern void R_LightningBeams_Init(void);
323 void Render_Init(void)
341 R_LightningBeams_Init();
349 extern char *ENGINE_EXTENSIONS;
352 VID_CheckExtensions();
354 // LordHavoc: report supported extensions
355 Con_DPrintf("\nengine extensions: %s\n", ENGINE_EXTENSIONS);
358 int R_CullBox(const vec3_t mins, const vec3_t maxs)
362 for (i = 0;i < 4;i++)
369 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
373 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
377 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
381 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
385 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
389 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
393 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
397 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
405 #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))))
407 //==================================================================================
409 static void R_MarkEntities (void)
412 entity_render_t *ent;
414 ent = &cl_entities[0].render;
415 Matrix4x4_CreateIdentity(&ent->matrix);
416 Matrix4x4_CreateIdentity(&ent->inversematrix);
419 R_FarClip_Box(cl.worldmodel->normalmins, cl.worldmodel->normalmaxs);
421 if (!r_drawentities.integer)
424 for (i = 0;i < r_refdef.numentities;i++)
426 ent = r_refdef.entities[i];
427 Mod_CheckLoaded(ent->model);
428 // some of the renderer still relies on origin...
429 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
430 // some of the renderer still relies on scale...
431 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
432 R_LerpAnimation(ent);
433 R_UpdateEntLights(ent);
434 if ((chase_active.integer || !(ent->flags & RENDER_EXTERIORMODEL))
435 && !VIS_CullBox(ent->mins, ent->maxs))
437 ent->visframe = r_framecount;
438 R_FarClip_Box(ent->mins, ent->maxs);
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 void R_DrawFakeShadows(void)
514 entity_render_t *ent;
516 ent = &cl_entities[0].render;
517 if (ent->model && ent->model->DrawFakeShadow)
518 ent->model->DrawFakeShadow(ent);
520 if (!r_drawentities.integer)
522 for (i = 0;i < r_refdef.numentities;i++)
524 ent = r_refdef.entities[i];
525 if ((ent->flags & RENDER_SHADOW) && ent->model && ent->model->DrawFakeShadow)
526 ent->model->DrawFakeShadow(ent);
530 #include "r_shadow.h"
532 int shadowframecount = 0;
534 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)
536 vec3_t relativelightorigin;
538 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])))
540 Matrix4x4_Transform(&ent->inversematrix, lightorigin, relativelightorigin);
541 ent->model->DrawShadowVolume (ent, relativelightorigin, lightradius);
545 void R_Shadow_DrawWorldLightShadowVolume(matrix4x4_t *matrix, worldlight_t *light);
547 extern void R_Model_Brush_DrawLightForSurfaceList(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, msurface_t **surflist, int numsurfaces, const matrix4x4_t *matrix_modeltofilter, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz);
548 void R_ShadowVolumeLighting(int visiblevolumes)
551 entity_render_t *ent;
553 float f, lightradius, cullradius;
554 vec3_t relativelightorigin, relativeeyeorigin, lightcolor, clipmins, clipmaxs;
559 matrix4x4_t matrix_worldtofilter, matrix_worldtoattenuationxyz, matrix_worldtoattenuationz;
560 matrix4x4_t matrix_modeltofilter, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz;
564 memset(&m, 0, sizeof(m));
565 R_Mesh_State_Texture(&m);
567 GL_BlendFunc(GL_ONE, GL_ONE);
569 GL_DepthTest(r_shadow_visiblevolumes.integer < 2);
570 qglDisable(GL_CULL_FACE);
571 GL_Color(0.0 * r_colorscale, 0.0125 * r_colorscale, 0.1 * r_colorscale, 1);
574 R_Shadow_Stage_Begin();
576 if (r_shadow_realtime_world.integer)
578 R_Shadow_LoadWorldLightsIfNeeded();
579 for (lnum = 0, wl = r_shadow_worldlightchain;wl;wl = wl->next, lnum++)
581 if (d_lightstylevalue[wl->style] <= 0)
583 if (VIS_CullBox(wl->mins, wl->maxs))
585 if (r_shadow_debuglight.integer >= 0 && lnum != r_shadow_debuglight.integer)
587 if (R_Shadow_ScissorForBBox(wl->mins, wl->maxs))
590 cullradius = wl->cullradius;
591 lightradius = wl->lightradius;
592 VectorCopy(wl->mins, clipmins);
593 VectorCopy(wl->maxs, clipmaxs);
595 f = d_lightstylevalue[wl->style] * (1.0f / 256.0f);
596 VectorScale(wl->light, f, lightcolor);
599 f = 2 + sin(realtime * M_PI * 4.0);
600 VectorScale(lightcolor, f, lightcolor);
603 if (wl->castshadows && (gl_stencil || visiblevolumes))
606 R_Shadow_Stage_ShadowVolumes();
607 ent = &cl_entities[0].render;
608 if (wl->shadowvolume && r_shadow_staticworldlights.integer)
609 R_Shadow_DrawWorldLightShadowVolume(&ent->matrix, wl);
611 R_TestAndDrawShadowVolume(ent, wl->origin, cullradius, lightradius, wl->mins, wl->maxs, clipmins, clipmaxs, true);
612 if (r_drawentities.integer)
613 for (i = 0;i < r_refdef.numentities;i++)
614 R_TestAndDrawShadowVolume(r_refdef.entities[i], wl->origin, cullradius, lightradius, wl->mins, wl->maxs, clipmins, clipmaxs, true);
619 if (wl->castshadows && gl_stencil)
620 R_Shadow_Stage_LightWithShadows();
622 R_Shadow_Stage_LightWithoutShadows();
624 // calculate world to filter matrix
625 Matrix4x4_CreateFromQuakeEntity(&matrix, wl->origin[0], wl->origin[1], wl->origin[2], wl->angles[0], wl->angles[1], wl->angles[2], lightradius);
626 Matrix4x4_Invert_Simple(&matrix_worldtofilter, &matrix);
627 // calculate world to attenuationxyz/xy matrix
628 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5, 0.5, 0.5, 0, 0, 0, 0.5);
629 Matrix4x4_Concat(&matrix_worldtoattenuationxyz, &matrix, &matrix_worldtofilter);
630 // calculate world to attenuationz matrix
631 matrix.m[0][0] = 0;matrix.m[0][1] = 0;matrix.m[0][2] = 0.5;matrix.m[0][3] = 0.5;
632 matrix.m[1][0] = 0;matrix.m[1][1] = 0;matrix.m[1][2] = 0 ;matrix.m[1][3] = 0.5;
633 matrix.m[2][0] = 0;matrix.m[2][1] = 0;matrix.m[2][2] = 0 ;matrix.m[2][3] = 0.5;
634 matrix.m[3][0] = 0;matrix.m[3][1] = 0;matrix.m[3][2] = 0 ;matrix.m[3][3] = 1;
635 Matrix4x4_Concat(&matrix_worldtoattenuationz, &matrix, &matrix_worldtofilter);
637 ent = &cl_entities[0].render;
638 if (ent->model && ent->model->DrawLight)
640 Matrix4x4_Transform(&ent->inversematrix, wl->origin, relativelightorigin);
641 Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin);
642 Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
643 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
644 Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
646 R_Model_Brush_DrawLightForSurfaceList(ent, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, wl->surfaces, wl->numsurfaces, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
648 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
650 if (r_drawentities.integer)
652 for (i = 0;i < r_refdef.numentities;i++)
654 ent = r_refdef.entities[i];
655 if (ent->visframe == r_framecount && ent->model && ent->model->DrawLight
656 && BoxesOverlap(ent->mins, ent->maxs, clipmins, clipmaxs)
657 && !(ent->effects & EF_ADDITIVE) && ent->alpha == 1)
659 Matrix4x4_Transform(&ent->inversematrix, wl->origin, relativelightorigin);
660 Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin);
661 Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
662 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
663 Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
664 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
671 if (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer)
673 for (lnum = 0, rd = r_dlight;lnum < r_numdlights;lnum++, rd++)
675 lightradius = rd->cullradius;
676 clipmins[0] = rd->origin[0] - lightradius;
677 clipmins[1] = rd->origin[1] - lightradius;
678 clipmins[2] = rd->origin[2] - lightradius;
679 clipmaxs[0] = rd->origin[0] + lightradius;
680 clipmaxs[1] = rd->origin[1] + lightradius;
681 clipmaxs[2] = rd->origin[2] + lightradius;
682 if (VIS_CullBox(clipmins, clipmaxs) || R_Shadow_ScissorForBBox(clipmins, clipmaxs))
685 cullradius = RadiusFromBoundsAndOrigin(clipmins, clipmaxs, rd->origin);
686 VectorScale(rd->light, (1.0f / 4096.0f), lightcolor);
688 if (gl_stencil || visiblevolumes)
691 R_Shadow_Stage_ShadowVolumes();
692 ent = &cl_entities[0].render;
693 R_TestAndDrawShadowVolume(ent, rd->origin, cullradius, lightradius, clipmins, clipmaxs, clipmins, clipmaxs, false);
694 if (r_drawentities.integer)
696 for (i = 0;i < r_refdef.numentities;i++)
698 ent = r_refdef.entities[i];
700 R_TestAndDrawShadowVolume(ent, rd->origin, cullradius, lightradius, clipmins, clipmaxs, clipmins, clipmaxs, false);
708 R_Shadow_Stage_LightWithShadows();
710 R_Shadow_Stage_LightWithoutShadows();
712 // calculate world to filter matrix
713 Matrix4x4_CreateFromQuakeEntity(&matrix, rd->origin[0], rd->origin[1], rd->origin[2], 0, 0, 0, lightradius);
714 Matrix4x4_Invert_Simple(&matrix_worldtofilter, &matrix);
715 // calculate world to attenuationxyz/xy matrix
716 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5, 0.5, 0.5, 0, 0, 0, 0.5);
717 Matrix4x4_Concat(&matrix_worldtoattenuationxyz, &matrix, &matrix_worldtofilter);
718 // calculate world to attenuationz matrix
719 matrix.m[0][0] = 0;matrix.m[0][1] = 0;matrix.m[0][2] = 0.5;matrix.m[0][3] = 0.5;
720 matrix.m[1][0] = 0;matrix.m[1][1] = 0;matrix.m[1][2] = 0 ;matrix.m[1][3] = 0.5;
721 matrix.m[2][0] = 0;matrix.m[2][1] = 0;matrix.m[2][2] = 0 ;matrix.m[2][3] = 0.5;
722 matrix.m[3][0] = 0;matrix.m[3][1] = 0;matrix.m[3][2] = 0 ;matrix.m[3][3] = 1;
723 Matrix4x4_Concat(&matrix_worldtoattenuationz, &matrix, &matrix_worldtofilter);
725 ent = &cl_entities[0].render;
726 if (ent->model && ent->model->DrawLight)
728 Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin);
729 Matrix4x4_Transform(&ent->inversematrix, r_origin, 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);
735 if (r_drawentities.integer)
737 for (i = 0;i < r_refdef.numentities;i++)
739 ent = r_refdef.entities[i];
740 if (ent->visframe == r_framecount && ent->model && ent->model->DrawLight
741 && BoxesOverlap(ent->mins, ent->maxs, clipmins, clipmaxs)
742 && !(ent->effects & EF_ADDITIVE) && ent->alpha == 1)
744 Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin);
745 Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin);
746 Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
747 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
748 Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
749 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
758 qglEnable(GL_CULL_FACE);
760 R_Shadow_Stage_End();
761 qglDisable(GL_SCISSOR_TEST);
764 static void R_SetFrustum (void)
766 // LordHavoc: note to all quake engine coders, the special case for 90
767 // degrees assumed a square view (wrong), so I removed it, Quake2 has it
770 // rotate VPN right by FOV_X/2 degrees
771 RotatePointAroundVector( frustum[0].normal, vup, vpn, -(90-r_refdef.fov_x / 2 ) );
772 frustum[0].dist = DotProduct (r_origin, frustum[0].normal);
773 PlaneClassify(&frustum[0]);
775 // rotate VPN left by FOV_X/2 degrees
776 RotatePointAroundVector( frustum[1].normal, vup, vpn, 90-r_refdef.fov_x / 2 );
777 frustum[1].dist = DotProduct (r_origin, frustum[1].normal);
778 PlaneClassify(&frustum[1]);
780 // rotate VPN up by FOV_X/2 degrees
781 RotatePointAroundVector( frustum[2].normal, vright, vpn, 90-r_refdef.fov_y / 2 );
782 frustum[2].dist = DotProduct (r_origin, frustum[2].normal);
783 PlaneClassify(&frustum[2]);
785 // rotate VPN down by FOV_X/2 degrees
786 RotatePointAroundVector( frustum[3].normal, vright, vpn, -( 90 - r_refdef.fov_y / 2 ) );
787 frustum[3].dist = DotProduct (r_origin, frustum[3].normal);
788 PlaneClassify(&frustum[3]);
796 static void R_SetupFrame (void)
798 // don't allow cheats in multiplayer
801 if (r_fullbright.integer != 0)
802 Cvar_Set ("r_fullbright", "0");
803 if (r_ambient.value != 0)
804 Cvar_Set ("r_ambient", "0");
809 // build the transformation matrix for the given view angles
810 VectorCopy (r_refdef.vieworg, r_origin);
812 AngleVectors (r_refdef.viewangles, vpn, vright, vup);
818 static void R_BlendView(void)
824 if (r_refdef.viewblend[3] < 0.01f)
827 R_Mesh_Matrix(&r_identitymatrix);
829 memset(&m, 0, sizeof(m));
830 R_Mesh_State_Texture(&m);
832 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
834 GL_DepthTest(false); // magic
835 GL_VertexPointer(vertex3f);
836 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
838 vertex3f[0] = r_origin[0] + vpn[0] * 1.5 - vright[0] * r - vup[0] * r;
839 vertex3f[1] = r_origin[1] + vpn[1] * 1.5 - vright[1] * r - vup[1] * r;
840 vertex3f[2] = r_origin[2] + vpn[2] * 1.5 - vright[2] * r - vup[2] * r;
841 vertex3f[3] = r_origin[0] + vpn[0] * 1.5 - vright[0] * r + vup[0] * r * 3;
842 vertex3f[4] = r_origin[1] + vpn[1] * 1.5 - vright[1] * r + vup[1] * r * 3;
843 vertex3f[5] = r_origin[2] + vpn[2] * 1.5 - vright[2] * r + vup[2] * r * 3;
844 vertex3f[6] = r_origin[0] + vpn[0] * 1.5 + vright[0] * r * 3 - vup[0] * r;
845 vertex3f[7] = r_origin[1] + vpn[1] * 1.5 + vright[1] * r * 3 - vup[1] * r;
846 vertex3f[8] = r_origin[2] + vpn[2] * 1.5 + vright[2] * r * 3 - vup[2] * r;
847 R_Mesh_Draw(3, 1, polygonelements);
854 r_refdef must be set before the first call
857 extern void R_DrawLightningBeams (void);
858 void R_RenderView (void)
860 entity_render_t *world;
861 if (!r_refdef.entities/* || !cl.worldmodel*/)
862 return; //Host_Error ("R_RenderView: NULL worldmodel");
864 if (r_shadow_realtime_world.integer)
868 Con_Printf("Stencil not enabled, turning off r_shadow_realtime_world, please type vid_stencil 1;vid_bitsperpixel 32;vid_restart and try again\n");
869 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
873 world = &cl_entities[0].render;
875 // FIXME: move to client
877 R_TimeReport("mexplosion");
885 R_TimeReport("setup");
887 if (cl.worldmodel && cl.worldmodel->brush.FatPVS)
888 cl.worldmodel->brush.FatPVS(cl.worldmodel, r_origin, 2, r_pvsbits, sizeof(r_pvsbits));
890 R_WorldVisibility(world);
891 R_TimeReport("worldvis");
893 R_FarClip_Start(r_origin, vpn, 768.0f);
895 r_farclip = R_FarClip_Finish() + 256.0f;
896 R_TimeReport("markentity");
898 GL_SetupView_ViewPort(r_refdef.x, r_refdef.y, r_refdef.width, r_refdef.height);
899 if (r_shadow_realtime_world.integer || gl_stencil)
900 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.fov_x, r_refdef.fov_y, 1.0f);
902 GL_SetupView_Mode_Perspective(r_refdef.fov_x, r_refdef.fov_y, 1.0f, r_farclip);
903 GL_SetupView_Orientation_FromEntity (r_refdef.vieworg, r_refdef.viewangles);
904 qglDepthFunc(GL_LEQUAL);
907 R_MeshQueue_BeginScene();
909 R_Shadow_UpdateWorldLightSelection();
911 if (R_DrawBrushModelsSky())
912 R_TimeReport("bmodelsky");
914 // must occur early because it can draw sky
916 R_TimeReport("world");
918 // don't let sound skip if going slow
919 if (!intimerefresh && !r_speeds.integer)
923 R_TimeReport("models");
925 if (r_shadows.integer == 1 && !r_shadow_realtime_world.integer)
928 R_TimeReport("fakeshadow");
931 if (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer)
933 R_ShadowVolumeLighting(false);
934 R_TimeReport("dynlight");
937 R_DrawLightningBeams();
938 R_TimeReport("lightning");
941 R_TimeReport("particles");
944 R_TimeReport("explosions");
946 R_MeshQueue_RenderTransparent();
947 R_TimeReport("drawtrans");
950 R_TimeReport("coronas");
952 R_DrawWorldCrosshair();
953 R_TimeReport("crosshair");
956 R_TimeReport("blendview");
958 R_MeshQueue_Render();
959 R_MeshQueue_EndScene();
961 if (r_shadow_visiblevolumes.integer)
963 R_ShadowVolumeLighting(true);
964 R_TimeReport("shadowvolume");
968 R_TimeReport("meshfinish");
972 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
975 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
977 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
980 R_Mesh_Matrix(&r_identitymatrix);
982 memset(&m, 0, sizeof(m));
983 R_Mesh_State_Texture(&m);
986 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
987 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
988 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
989 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
990 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
991 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
992 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
993 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
994 GL_ColorPointer(color);
995 R_FillColors(color, 8, cr * r_colorscale, cg * r_colorscale, cb * r_colorscale, ca);
998 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1000 VectorSubtract(v, r_origin, diff);
1001 f2 = exp(fogdensity/DotProduct(diff, diff));
1004 c[0] = c[0] * f1 + fogcolor[0] * f2;
1005 c[1] = c[1] * f1 + fogcolor[1] * f2;
1006 c[2] = c[2] * f1 + fogcolor[2] * f2;
1013 int nomodelelements[24] =
1025 float nomodelvertex3f[6*3] =
1035 float nomodelcolor4f[6*4] =
1037 0.0f, 0.0f, 0.5f, 1.0f,
1038 0.0f, 0.0f, 0.5f, 1.0f,
1039 0.0f, 0.5f, 0.0f, 1.0f,
1040 0.0f, 0.5f, 0.0f, 1.0f,
1041 0.5f, 0.0f, 0.0f, 1.0f,
1042 0.5f, 0.0f, 0.0f, 1.0f
1045 void R_DrawNoModelCallback(const void *calldata1, int calldata2)
1047 const entity_render_t *ent = calldata1;
1049 float f1, f2, *c, diff[3];
1052 R_Mesh_Matrix(&ent->matrix);
1054 memset(&m, 0, sizeof(m));
1055 R_Mesh_State_Texture(&m);
1057 if (ent->flags & EF_ADDITIVE)
1059 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1060 GL_DepthMask(false);
1062 else if (ent->alpha < 1)
1064 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1065 GL_DepthMask(false);
1069 GL_BlendFunc(GL_ONE, GL_ZERO);
1073 GL_VertexPointer(nomodelvertex3f);
1076 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1077 GL_ColorPointer(color4f);
1078 VectorSubtract(ent->origin, r_origin, diff);
1079 f2 = exp(fogdensity/DotProduct(diff, diff));
1081 for (i = 0, c = color4f;i < 6;i++, c += 4)
1083 c[0] = (c[0] * f1 + fogcolor[0] * f2) * r_colorscale;
1084 c[1] = (c[1] * f1 + fogcolor[1] * f2) * r_colorscale;
1085 c[2] = (c[2] * f1 + fogcolor[2] * f2) * r_colorscale;
1089 else if (r_colorscale != 1 || ent->alpha != 1)
1091 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1092 GL_ColorPointer(color4f);
1093 for (i = 0, c = color4f;i < 6;i++, c += 4)
1095 c[0] *= r_colorscale;
1096 c[1] *= r_colorscale;
1097 c[2] *= r_colorscale;
1102 GL_ColorPointer(nomodelcolor4f);
1103 R_Mesh_Draw(6, 8, nomodelelements);
1106 void R_DrawNoModel(entity_render_t *ent)
1108 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1109 R_MeshQueue_AddTransparent(ent->origin, R_DrawNoModelCallback, ent, 0);
1111 // R_DrawNoModelCallback(ent, 0);
1114 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1116 vec3_t right1, right2, diff, normal;
1118 VectorSubtract (org2, org1, normal);
1119 VectorNormalizeFast (normal);
1121 // calculate 'right' vector for start
1122 VectorSubtract (r_origin, org1, diff);
1123 VectorNormalizeFast (diff);
1124 CrossProduct (normal, diff, right1);
1126 // calculate 'right' vector for end
1127 VectorSubtract (r_origin, org2, diff);
1128 VectorNormalizeFast (diff);
1129 CrossProduct (normal, diff, right2);
1131 vert[ 0] = org1[0] + width * right1[0];
1132 vert[ 1] = org1[1] + width * right1[1];
1133 vert[ 2] = org1[2] + width * right1[2];
1134 vert[ 3] = org1[0] - width * right1[0];
1135 vert[ 4] = org1[1] - width * right1[1];
1136 vert[ 5] = org1[2] - width * right1[2];
1137 vert[ 6] = org2[0] - width * right2[0];
1138 vert[ 7] = org2[1] - width * right2[1];
1139 vert[ 8] = org2[2] - width * right2[2];
1140 vert[ 9] = org2[0] + width * right2[0];
1141 vert[10] = org2[1] + width * right2[1];
1142 vert[11] = org2[2] + width * right2[2];
1145 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
1147 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)
1154 VectorSubtract(origin, r_origin, diff);
1155 ca *= 1 - exp(fogdensity/DotProduct(diff,diff));
1158 R_Mesh_Matrix(&r_identitymatrix);
1159 GL_Color(cr * r_colorscale, cg * r_colorscale, cb * r_colorscale, ca);
1160 GL_VertexPointer(varray_vertex3f);
1161 GL_BlendFunc(blendfunc1, blendfunc2);
1162 GL_DepthMask(false);
1163 GL_DepthTest(!depthdisable);
1165 memset(&m, 0, sizeof(m));
1166 m.tex[0] = R_GetTexture(texture);
1167 m.pointer_texcoord[0] = spritetexcoord2f;
1168 R_Mesh_State_Texture(&m);
1170 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
1171 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
1172 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
1173 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
1174 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
1175 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
1176 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
1177 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
1178 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
1179 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
1180 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
1181 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
1182 R_Mesh_Draw(4, 2, polygonelements);