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)
342 R_LightningBeams_Init();
350 extern char *ENGINE_EXTENSIONS;
353 VID_CheckExtensions();
355 // LordHavoc: report supported extensions
356 Con_DPrintf("\nengine extensions: %s\n", ENGINE_EXTENSIONS);
359 int R_CullBox(const vec3_t mins, const vec3_t maxs)
363 for (i = 0;i < 4;i++)
370 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
374 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
378 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
382 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
386 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
390 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
394 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
398 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
406 #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))))
408 //==================================================================================
410 static void R_MarkEntities (void)
413 entity_render_t *ent;
415 ent = &cl_entities[0].render;
416 Matrix4x4_CreateIdentity(&ent->matrix);
417 Matrix4x4_CreateIdentity(&ent->inversematrix);
420 R_FarClip_Box(cl.worldmodel->normalmins, cl.worldmodel->normalmaxs);
422 if (!r_drawentities.integer)
425 for (i = 0;i < r_refdef.numentities;i++)
427 ent = r_refdef.entities[i];
428 Mod_CheckLoaded(ent->model);
429 // some of the renderer still relies on origin...
430 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
431 // some of the renderer still relies on scale...
432 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
433 R_LerpAnimation(ent);
434 R_UpdateEntLights(ent);
435 if ((chase_active.integer || !(ent->flags & RENDER_EXTERIORMODEL))
436 && !VIS_CullBox(ent->mins, ent->maxs)
437 && (!envmap || !(ent->flags & (RENDER_VIEWMODEL | RENDER_EXTERIORMODEL))))
439 ent->visframe = r_framecount;
440 R_FarClip_Box(ent->mins, ent->maxs);
445 // only used if skyrendermasked, and normally returns false
446 int R_DrawBrushModelsSky (void)
449 entity_render_t *ent;
451 if (!r_drawentities.integer)
455 for (i = 0;i < r_refdef.numentities;i++)
457 ent = r_refdef.entities[i];
458 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
460 ent->model->DrawSky(ent);
473 void R_DrawViewModel (void)
475 entity_render_t *ent;
477 // FIXME: move these checks to client
478 if (!r_drawviewmodel.integer || chase_active.integer || envmap || !r_drawentities.integer || cl.items & IT_INVISIBILITY || cl.stats[STAT_HEALTH] <= 0 || !cl.viewent.render.model)
481 ent = &cl.viewent.render;
482 Mod_CheckLoaded(ent->model);
483 R_LerpAnimation(ent);
484 Matrix4x4_CreateFromQuakeEntity(&ent->matrix, ent->origin[0], ent->origin[1], ent->origin[2], -ent->angles[0], ent->angles[1], ent->angles[2], ent->scale);
485 Matrix4x4_Invert_Simple(&ent->inversematrix, &ent->matrix);
486 R_UpdateEntLights(ent);
487 ent->model->Draw(ent);
491 void R_DrawNoModel(entity_render_t *ent);
492 void R_DrawModels(void)
495 entity_render_t *ent;
497 if (!r_drawentities.integer)
500 for (i = 0;i < r_refdef.numentities;i++)
502 ent = r_refdef.entities[i];
503 if (ent->visframe == r_framecount)
505 if (ent->model && ent->model->Draw != NULL)
506 ent->model->Draw(ent);
513 #include "r_shadow.h"
515 int shadowframecount = 0;
517 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)
519 vec3_t relativelightorigin;
521 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])))
523 Matrix4x4_Transform(&ent->inversematrix, lightorigin, relativelightorigin);
524 ent->model->DrawShadowVolume (ent, relativelightorigin, lightradius);
528 void R_Shadow_DrawWorldLightShadowVolume(matrix4x4_t *matrix, worldlight_t *light);
530 void R_ShadowVolumeLighting(int visiblevolumes)
533 entity_render_t *ent;
535 float f, lightradius, cullradius;
536 vec3_t relativelightorigin, relativeeyeorigin, lightcolor, clipmins, clipmaxs;
541 matrix4x4_t matrix_worldtofilter, matrix_worldtoattenuationxyz, matrix_worldtoattenuationz;
542 matrix4x4_t matrix_modeltofilter, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz;
546 memset(&m, 0, sizeof(m));
547 R_Mesh_State_Texture(&m);
549 GL_BlendFunc(GL_ONE, GL_ONE);
551 GL_DepthTest(r_shadow_visiblevolumes.integer < 2);
552 qglDisable(GL_CULL_FACE);
553 GL_Color(0.0, 0.0125, 0.1, 1);
556 R_Shadow_Stage_Begin();
558 if (r_shadow_realtime_world.integer)
560 R_Shadow_LoadWorldLightsIfNeeded();
561 for (lnum = 0, wl = r_shadow_worldlightchain;wl;wl = wl->next, lnum++)
563 if (d_lightstylevalue[wl->style] <= 0)
565 if (VIS_CullBox(wl->mins, wl->maxs))
567 if (r_shadow_debuglight.integer >= 0 && lnum != r_shadow_debuglight.integer)
569 if (R_Shadow_ScissorForBBox(wl->mins, wl->maxs))
572 cullradius = wl->cullradius;
573 lightradius = wl->lightradius;
574 VectorCopy(wl->mins, clipmins);
575 VectorCopy(wl->maxs, clipmaxs);
577 f = d_lightstylevalue[wl->style] * (1.0f / 256.0f);
578 VectorScale(wl->light, f, lightcolor);
581 f = 2 + sin(realtime * M_PI * 4.0);
582 VectorScale(lightcolor, f, lightcolor);
585 if (wl->castshadows && (gl_stencil || visiblevolumes))
588 R_Shadow_Stage_ShadowVolumes();
589 ent = &cl_entities[0].render;
590 if (r_shadow_staticworldlights.integer)
591 R_Shadow_DrawStaticWorldLight_Shadow(wl, &ent->matrix);
593 R_TestAndDrawShadowVolume(ent, wl->origin, cullradius, lightradius, wl->mins, wl->maxs, clipmins, clipmaxs, true);
594 if (r_drawentities.integer)
595 for (i = 0;i < r_refdef.numentities;i++)
596 R_TestAndDrawShadowVolume(r_refdef.entities[i], wl->origin, cullradius, lightradius, wl->mins, wl->maxs, clipmins, clipmaxs, true);
601 if (wl->castshadows && gl_stencil)
602 R_Shadow_Stage_LightWithShadows();
604 R_Shadow_Stage_LightWithoutShadows();
606 // calculate world to filter matrix
607 Matrix4x4_CreateFromQuakeEntity(&matrix, wl->origin[0], wl->origin[1], wl->origin[2], wl->angles[0], wl->angles[1], wl->angles[2], lightradius);
608 Matrix4x4_Invert_Simple(&matrix_worldtofilter, &matrix);
609 // calculate world to attenuationxyz/xy matrix
610 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5, 0.5, 0.5, 0, 0, 0, 0.5);
611 Matrix4x4_Concat(&matrix_worldtoattenuationxyz, &matrix, &matrix_worldtofilter);
612 // calculate world to attenuationz matrix
613 matrix.m[0][0] = 0;matrix.m[0][1] = 0;matrix.m[0][2] = 0.5;matrix.m[0][3] = 0.5;
614 matrix.m[1][0] = 0;matrix.m[1][1] = 0;matrix.m[1][2] = 0 ;matrix.m[1][3] = 0.5;
615 matrix.m[2][0] = 0;matrix.m[2][1] = 0;matrix.m[2][2] = 0 ;matrix.m[2][3] = 0.5;
616 matrix.m[3][0] = 0;matrix.m[3][1] = 0;matrix.m[3][2] = 0 ;matrix.m[3][3] = 1;
617 Matrix4x4_Concat(&matrix_worldtoattenuationz, &matrix, &matrix_worldtofilter);
619 ent = &cl_entities[0].render;
620 if (ent->model && ent->model->DrawLight)
622 Matrix4x4_Transform(&ent->inversematrix, wl->origin, relativelightorigin);
623 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, relativeeyeorigin);
624 Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
625 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
626 Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
627 if (r_shadow_staticworldlights.integer)
628 R_Shadow_DrawStaticWorldLight_Light(wl, &ent->matrix, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
630 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
632 if (r_drawentities.integer)
634 for (i = 0;i < r_refdef.numentities;i++)
636 ent = r_refdef.entities[i];
637 if (ent->visframe == r_framecount && ent->model && ent->model->DrawLight
638 && BoxesOverlap(ent->mins, ent->maxs, clipmins, clipmaxs)
639 && !(ent->effects & EF_ADDITIVE) && ent->alpha == 1)
641 Matrix4x4_Transform(&ent->inversematrix, wl->origin, relativelightorigin);
642 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, relativeeyeorigin);
643 Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
644 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
645 Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
646 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
653 if (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer)
655 for (lnum = 0, rd = r_dlight;lnum < r_numdlights;lnum++, rd++)
657 lightradius = rd->cullradius;
658 clipmins[0] = rd->origin[0] - lightradius;
659 clipmins[1] = rd->origin[1] - lightradius;
660 clipmins[2] = rd->origin[2] - lightradius;
661 clipmaxs[0] = rd->origin[0] + lightradius;
662 clipmaxs[1] = rd->origin[1] + lightradius;
663 clipmaxs[2] = rd->origin[2] + lightradius;
664 if (VIS_CullBox(clipmins, clipmaxs) || R_Shadow_ScissorForBBox(clipmins, clipmaxs))
667 cullradius = RadiusFromBoundsAndOrigin(clipmins, clipmaxs, rd->origin);
668 VectorScale(rd->light, (1.0f / 4096.0f), lightcolor);
670 if (r_shadow_shadows.integer && (gl_stencil || visiblevolumes))
673 R_Shadow_Stage_ShadowVolumes();
674 ent = &cl_entities[0].render;
675 R_TestAndDrawShadowVolume(ent, rd->origin, cullradius, lightradius, clipmins, clipmaxs, clipmins, clipmaxs, false);
676 if (r_drawentities.integer)
678 for (i = 0;i < r_refdef.numentities;i++)
680 ent = r_refdef.entities[i];
682 R_TestAndDrawShadowVolume(ent, rd->origin, cullradius, lightradius, clipmins, clipmaxs, clipmins, clipmaxs, false);
689 if (r_shadow_shadows.integer && gl_stencil)
690 R_Shadow_Stage_LightWithShadows();
692 R_Shadow_Stage_LightWithoutShadows();
694 // calculate world to filter matrix
695 Matrix4x4_CreateFromQuakeEntity(&matrix, rd->origin[0], rd->origin[1], rd->origin[2], 0, 0, 0, lightradius);
696 Matrix4x4_Invert_Simple(&matrix_worldtofilter, &matrix);
697 // calculate world to attenuationxyz/xy matrix
698 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5, 0.5, 0.5, 0, 0, 0, 0.5);
699 Matrix4x4_Concat(&matrix_worldtoattenuationxyz, &matrix, &matrix_worldtofilter);
700 // calculate world to attenuationz matrix
701 matrix.m[0][0] = 0;matrix.m[0][1] = 0;matrix.m[0][2] = 0.5;matrix.m[0][3] = 0.5;
702 matrix.m[1][0] = 0;matrix.m[1][1] = 0;matrix.m[1][2] = 0 ;matrix.m[1][3] = 0.5;
703 matrix.m[2][0] = 0;matrix.m[2][1] = 0;matrix.m[2][2] = 0 ;matrix.m[2][3] = 0.5;
704 matrix.m[3][0] = 0;matrix.m[3][1] = 0;matrix.m[3][2] = 0 ;matrix.m[3][3] = 1;
705 Matrix4x4_Concat(&matrix_worldtoattenuationz, &matrix, &matrix_worldtofilter);
707 ent = &cl_entities[0].render;
708 if (ent->model && ent->model->DrawLight)
710 Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin);
711 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, relativeeyeorigin);
712 Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
713 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
714 Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
715 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
717 if (r_drawentities.integer)
719 for (i = 0;i < r_refdef.numentities;i++)
721 ent = r_refdef.entities[i];
722 if (ent->visframe == r_framecount && ent->model && ent->model->DrawLight
723 && BoxesOverlap(ent->mins, ent->maxs, clipmins, clipmaxs)
724 && !(ent->effects & EF_ADDITIVE) && ent->alpha == 1)
726 Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin);
727 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, relativeeyeorigin);
728 Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
729 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
730 Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
731 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
740 qglEnable(GL_CULL_FACE);
742 R_Shadow_Stage_End();
743 qglDisable(GL_SCISSOR_TEST);
746 static void R_SetFrustum (void)
748 // LordHavoc: note to all quake engine coders, the special case for 90
749 // degrees assumed a square view (wrong), so I removed it, Quake2 has it
752 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
753 RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_refdef.fov_x / 2));
754 frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
755 PlaneClassify(&frustum[0]);
757 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
758 RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_refdef.fov_x / 2));
759 frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
760 PlaneClassify(&frustum[1]);
762 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
763 RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_refdef.fov_y / 2));
764 frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
765 PlaneClassify(&frustum[2]);
767 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
768 RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_refdef.fov_y / 2));
769 frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
770 PlaneClassify(&frustum[3]);
778 static void R_SetupFrame (void)
780 // don't allow cheats in multiplayer
783 if (r_fullbright.integer != 0)
784 Cvar_Set ("r_fullbright", "0");
785 if (r_ambient.value != 0)
786 Cvar_Set ("r_ambient", "0");
791 // break apart the viewentity matrix into vectors for various purposes
792 Matrix4x4_ToVectors(&r_refdef.viewentitymatrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
793 VectorNegate(r_viewleft, r_viewright);
795 GL_SetupView_ViewPort(r_refdef.x, r_refdef.y, r_refdef.width, r_refdef.height);
796 if ((r_shadow_realtime_world.integer || r_shadow_shadows.integer) && gl_stencil)
797 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.fov_x, r_refdef.fov_y, 1.0f);
799 GL_SetupView_Mode_Perspective(r_refdef.fov_x, r_refdef.fov_y, 1.0f, r_farclip);
800 GL_SetupView_Orientation_FromEntity(&r_refdef.viewentitymatrix);
806 static void R_BlendView(void)
812 if (r_refdef.viewblend[3] < 0.01f)
815 R_Mesh_Matrix(&r_identitymatrix);
817 memset(&m, 0, sizeof(m));
818 R_Mesh_State_Texture(&m);
820 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
822 GL_DepthTest(false); // magic
823 GL_VertexPointer(vertex3f);
824 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
826 vertex3f[0] = r_vieworigin[0] + r_viewforward[0] * 1.5 + r_viewleft[0] * r - r_viewup[0] * r;
827 vertex3f[1] = r_vieworigin[1] + r_viewforward[1] * 1.5 + r_viewleft[1] * r - r_viewup[1] * r;
828 vertex3f[2] = r_vieworigin[2] + r_viewforward[2] * 1.5 + r_viewleft[2] * r - r_viewup[2] * r;
829 vertex3f[3] = r_vieworigin[0] + r_viewforward[0] * 1.5 + r_viewleft[0] * r + r_viewup[0] * r * 3;
830 vertex3f[4] = r_vieworigin[1] + r_viewforward[1] * 1.5 + r_viewleft[1] * r + r_viewup[1] * r * 3;
831 vertex3f[5] = r_vieworigin[2] + r_viewforward[2] * 1.5 + r_viewleft[2] * r + r_viewup[2] * r * 3;
832 vertex3f[6] = r_vieworigin[0] + r_viewforward[0] * 1.5 - r_viewleft[0] * r * 3 - r_viewup[0] * r;
833 vertex3f[7] = r_vieworigin[1] + r_viewforward[1] * 1.5 - r_viewleft[1] * r * 3 - r_viewup[1] * r;
834 vertex3f[8] = r_vieworigin[2] + r_viewforward[2] * 1.5 - r_viewleft[2] * r * 3 - r_viewup[2] * r;
835 R_Mesh_Draw(3, 1, polygonelements);
842 r_refdef must be set before the first call
845 extern void R_DrawLightningBeams (void);
846 void R_RenderView (void)
848 entity_render_t *world;
849 if (!r_refdef.entities/* || !cl.worldmodel*/)
850 return; //Host_Error ("R_RenderView: NULL worldmodel");
852 if (r_shadow_realtime_world.integer)
856 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");
857 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
861 world = &cl_entities[0].render;
863 // FIXME: move to client
865 R_TimeReport("mexplosion");
873 R_TimeReport("setup");
875 if (cl.worldmodel && cl.worldmodel->brush.FatPVS)
876 cl.worldmodel->brush.FatPVS(cl.worldmodel, r_vieworigin, 2, r_pvsbits, sizeof(r_pvsbits));
878 R_WorldVisibility(world);
879 R_TimeReport("worldvis");
881 R_FarClip_Start(r_vieworigin, r_viewforward, 768.0f);
883 r_farclip = R_FarClip_Finish() + 256.0f;
884 R_TimeReport("markentity");
886 qglDepthFunc(GL_LEQUAL);
889 R_MeshQueue_BeginScene();
891 R_Shadow_UpdateWorldLightSelection();
893 if (R_DrawBrushModelsSky())
894 R_TimeReport("bmodelsky");
896 // must occur early because it can draw sky
898 R_TimeReport("world");
900 // don't let sound skip if going slow
901 if (!intimerefresh && !r_speeds.integer)
905 R_TimeReport("models");
907 if (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer)
909 R_ShadowVolumeLighting(false);
910 R_TimeReport("dynlight");
913 R_DrawLightningBeams();
914 R_TimeReport("lightning");
917 R_TimeReport("particles");
920 R_TimeReport("explosions");
922 R_MeshQueue_RenderTransparent();
923 R_TimeReport("drawtrans");
926 R_TimeReport("coronas");
928 R_DrawWorldCrosshair();
929 R_TimeReport("crosshair");
932 R_TimeReport("blendview");
934 R_MeshQueue_Render();
935 R_MeshQueue_EndScene();
937 if (r_shadow_visiblevolumes.integer)
939 R_ShadowVolumeLighting(true);
940 R_TimeReport("shadowvolume");
944 R_TimeReport("meshfinish");
948 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
951 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
953 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
956 R_Mesh_Matrix(&r_identitymatrix);
958 memset(&m, 0, sizeof(m));
959 R_Mesh_State_Texture(&m);
962 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
963 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
964 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
965 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
966 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
967 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
968 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
969 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
970 GL_ColorPointer(color);
971 R_FillColors(color, 8, cr, cg, cb, ca);
974 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
976 VectorSubtract(v, r_vieworigin, diff);
977 f2 = exp(fogdensity/DotProduct(diff, diff));
979 c[0] = c[0] * f1 + fogcolor[0] * f2;
980 c[1] = c[1] * f1 + fogcolor[1] * f2;
981 c[2] = c[2] * f1 + fogcolor[2] * f2;
988 int nomodelelements[24] =
1000 float nomodelvertex3f[6*3] =
1010 float nomodelcolor4f[6*4] =
1012 0.0f, 0.0f, 0.5f, 1.0f,
1013 0.0f, 0.0f, 0.5f, 1.0f,
1014 0.0f, 0.5f, 0.0f, 1.0f,
1015 0.0f, 0.5f, 0.0f, 1.0f,
1016 0.5f, 0.0f, 0.0f, 1.0f,
1017 0.5f, 0.0f, 0.0f, 1.0f
1020 void R_DrawNoModelCallback(const void *calldata1, int calldata2)
1022 const entity_render_t *ent = calldata1;
1024 float f1, f2, *c, diff[3];
1027 R_Mesh_Matrix(&ent->matrix);
1029 memset(&m, 0, sizeof(m));
1030 R_Mesh_State_Texture(&m);
1032 if (ent->flags & EF_ADDITIVE)
1034 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1035 GL_DepthMask(false);
1037 else if (ent->alpha < 1)
1039 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1040 GL_DepthMask(false);
1044 GL_BlendFunc(GL_ONE, GL_ZERO);
1048 GL_VertexPointer(nomodelvertex3f);
1051 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1052 GL_ColorPointer(color4f);
1053 VectorSubtract(ent->origin, r_vieworigin, diff);
1054 f2 = exp(fogdensity/DotProduct(diff, diff));
1056 for (i = 0, c = color4f;i < 6;i++, c += 4)
1058 c[0] = (c[0] * f1 + fogcolor[0] * f2);
1059 c[1] = (c[1] * f1 + fogcolor[1] * f2);
1060 c[2] = (c[2] * f1 + fogcolor[2] * f2);
1064 else if (ent->alpha != 1)
1066 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1067 GL_ColorPointer(color4f);
1068 for (i = 0, c = color4f;i < 6;i++, c += 4)
1072 GL_ColorPointer(nomodelcolor4f);
1073 R_Mesh_Draw(6, 8, nomodelelements);
1076 void R_DrawNoModel(entity_render_t *ent)
1078 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1079 R_MeshQueue_AddTransparent(ent->origin, R_DrawNoModelCallback, ent, 0);
1081 // R_DrawNoModelCallback(ent, 0);
1084 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1086 vec3_t right1, right2, diff, normal;
1088 VectorSubtract (org2, org1, normal);
1089 VectorNormalizeFast (normal);
1091 // calculate 'right' vector for start
1092 VectorSubtract (r_vieworigin, org1, diff);
1093 VectorNormalizeFast (diff);
1094 CrossProduct (normal, diff, right1);
1096 // calculate 'right' vector for end
1097 VectorSubtract (r_vieworigin, org2, diff);
1098 VectorNormalizeFast (diff);
1099 CrossProduct (normal, diff, right2);
1101 vert[ 0] = org1[0] + width * right1[0];
1102 vert[ 1] = org1[1] + width * right1[1];
1103 vert[ 2] = org1[2] + width * right1[2];
1104 vert[ 3] = org1[0] - width * right1[0];
1105 vert[ 4] = org1[1] - width * right1[1];
1106 vert[ 5] = org1[2] - width * right1[2];
1107 vert[ 6] = org2[0] - width * right2[0];
1108 vert[ 7] = org2[1] - width * right2[1];
1109 vert[ 8] = org2[2] - width * right2[2];
1110 vert[ 9] = org2[0] + width * right2[0];
1111 vert[10] = org2[1] + width * right2[1];
1112 vert[11] = org2[2] + width * right2[2];
1115 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
1117 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)
1124 VectorSubtract(origin, r_vieworigin, diff);
1125 ca *= 1 - exp(fogdensity/DotProduct(diff,diff));
1128 R_Mesh_Matrix(&r_identitymatrix);
1129 GL_Color(cr, cg, cb, ca);
1130 GL_VertexPointer(varray_vertex3f);
1131 GL_BlendFunc(blendfunc1, blendfunc2);
1132 GL_DepthMask(false);
1133 GL_DepthTest(!depthdisable);
1135 memset(&m, 0, sizeof(m));
1136 m.tex[0] = R_GetTexture(texture);
1137 m.pointer_texcoord[0] = spritetexcoord2f;
1138 R_Mesh_State_Texture(&m);
1140 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
1141 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
1142 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
1143 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
1144 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
1145 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
1146 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
1147 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
1148 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
1149 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
1150 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
1151 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
1152 R_Mesh_Draw(4, 2, polygonelements);