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_shadow_staticworldlights = {0, "r_shadow_staticworldlights", "1"};
58 cvar_t r_speeds = {0, "r_speeds","0"};
59 cvar_t r_fullbright = {0, "r_fullbright","0"};
60 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1"};
61 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1"};
62 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1"};
63 cvar_t r_shadow_cull = {0, "r_shadow_cull", "1"};
64 cvar_t r_drawcollisionbrushes = {0, "r_drawcollisionbrushes", "0"};
66 cvar_t gl_fogenable = {0, "gl_fogenable", "0"};
67 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25"};
68 cvar_t gl_fogred = {0, "gl_fogred","0.3"};
69 cvar_t gl_foggreen = {0, "gl_foggreen","0.3"};
70 cvar_t gl_fogblue = {0, "gl_fogblue","0.3"};
71 cvar_t gl_fogstart = {0, "gl_fogstart", "0"};
72 cvar_t gl_fogend = {0, "gl_fogend","0"};
74 cvar_t r_textureunits = {0, "r_textureunits", "32"};
76 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1"};
77 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1"};
78 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1"};
79 cvar_t r_watershader = {CVAR_SAVE, "r_watershader", "1"};
82 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
85 for (i = 0;i < verts;i++)
96 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
99 for (i = 0;i < verts;i++)
113 For program optimization
116 qboolean intimerefresh = 0;
117 static void R_TimeRefresh_f (void)
120 float start, stop, time;
123 start = Sys_DoubleTime ();
124 for (i = 0;i < 128;i++)
126 r_refdef.viewangles[0] = 0;
127 r_refdef.viewangles[1] = i/128.0*360.0;
128 r_refdef.viewangles[2] = 0;
132 stop = Sys_DoubleTime ();
135 Con_Printf ("%f seconds (%f fps)\n", time, 128/time);
140 float fog_density, fog_red, fog_green, fog_blue;
142 qboolean oldgl_fogenable;
143 void R_SetupFog(void)
145 if (gamemode == GAME_NEHAHRA)
147 if (gl_fogenable.integer)
149 oldgl_fogenable = true;
150 fog_density = gl_fogdensity.value;
151 fog_red = gl_fogred.value;
152 fog_green = gl_foggreen.value;
153 fog_blue = gl_fogblue.value;
155 else if (oldgl_fogenable)
157 oldgl_fogenable = false;
166 fogcolor[0] = fog_red = bound(0.0f, fog_red , 1.0f);
167 fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
168 fogcolor[2] = fog_blue = bound(0.0f, fog_blue , 1.0f);
173 fogdensity = -4000.0f / (fog_density * fog_density);
174 // fog color was already set
180 // FIXME: move this to client?
183 if (gamemode == GAME_NEHAHRA)
185 Cvar_Set("gl_fogenable", "0");
186 Cvar_Set("gl_fogdensity", "0.2");
187 Cvar_Set("gl_fogred", "0.3");
188 Cvar_Set("gl_foggreen", "0.3");
189 Cvar_Set("gl_fogblue", "0.3");
191 fog_density = fog_red = fog_green = fog_blue = 0.0f;
194 // FIXME: move this to client?
195 void FOG_registercvars(void)
197 if (gamemode == GAME_NEHAHRA)
199 Cvar_RegisterVariable (&gl_fogenable);
200 Cvar_RegisterVariable (&gl_fogdensity);
201 Cvar_RegisterVariable (&gl_fogred);
202 Cvar_RegisterVariable (&gl_foggreen);
203 Cvar_RegisterVariable (&gl_fogblue);
204 Cvar_RegisterVariable (&gl_fogstart);
205 Cvar_RegisterVariable (&gl_fogend);
209 void gl_main_start(void)
213 void gl_main_shutdown(void)
217 extern void CL_ParseEntityLump(char *entitystring);
218 void gl_main_newmap(void)
221 char *entities, entname[MAX_QPATH];
225 strcpy(entname, cl.worldmodel->name);
226 l = strlen(entname) - 4;
227 if (l >= 0 && !strcmp(entname + l, ".bsp"))
229 strcpy(entname + l, ".ent");
230 if ((entities = FS_LoadFile(entname, true)))
232 CL_ParseEntityLump(entities);
237 if (cl.worldmodel->brush.entities)
238 CL_ParseEntityLump(cl.worldmodel->brush.entities);
242 void GL_Main_Init(void)
244 Matrix4x4_CreateIdentity(&r_identitymatrix);
245 // FIXME: move this to client?
247 Cmd_AddCommand("timerefresh", R_TimeRefresh_f);
248 Cvar_RegisterVariable(&r_drawentities);
249 Cvar_RegisterVariable(&r_drawviewmodel);
250 Cvar_RegisterVariable(&r_shadow_staticworldlights);
251 Cvar_RegisterVariable(&r_speeds);
252 Cvar_RegisterVariable(&r_fullbrights);
253 Cvar_RegisterVariable(&r_wateralpha);
254 Cvar_RegisterVariable(&r_dynamic);
255 Cvar_RegisterVariable(&r_fullbright);
256 Cvar_RegisterVariable(&r_textureunits);
257 Cvar_RegisterVariable(&r_shadow_cull);
258 Cvar_RegisterVariable(&r_lerpsprites);
259 Cvar_RegisterVariable(&r_lerpmodels);
260 Cvar_RegisterVariable(&r_waterscroll);
261 Cvar_RegisterVariable(&r_watershader);
262 Cvar_RegisterVariable(&r_drawcollisionbrushes);
263 if (gamemode == GAME_NEHAHRA || gamemode == GAME_NEXUIZ)
264 Cvar_SetValue("r_fullbrights", 0);
265 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
268 vec3_t r_farclip_origin;
269 vec3_t r_farclip_direction;
270 vec_t r_farclip_directiondist;
271 vec_t r_farclip_meshfarclip;
272 int r_farclip_directionbit0;
273 int r_farclip_directionbit1;
274 int r_farclip_directionbit2;
276 // start a farclip measuring session
277 void R_FarClip_Start(vec3_t origin, vec3_t direction, vec_t startfarclip)
279 VectorCopy(origin, r_farclip_origin);
280 VectorCopy(direction, r_farclip_direction);
281 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
282 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
283 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
284 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
285 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
288 // enlarge farclip to accomodate box
289 void R_FarClip_Box(vec3_t mins, vec3_t maxs)
292 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
293 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
294 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
295 if (r_farclip_meshfarclip < d)
296 r_farclip_meshfarclip = d;
299 // return farclip value
300 float R_FarClip_Finish(void)
302 return r_farclip_meshfarclip - r_farclip_directiondist;
305 extern void R_Textures_Init(void);
306 extern void Mod_RenderInit(void);
307 extern void GL_Draw_Init(void);
308 extern void GL_Main_Init(void);
309 extern void R_Shadow_Init(void);
310 extern void GL_Models_Init(void);
311 extern void R_Sky_Init(void);
312 extern void GL_Surf_Init(void);
313 extern void R_Crosshairs_Init(void);
314 extern void R_Light_Init(void);
315 extern void R_Particles_Init(void);
316 extern void R_Explosion_Init(void);
317 extern void ui_init(void);
318 extern void gl_backend_init(void);
319 extern void Sbar_Init(void);
320 extern void R_LightningBeams_Init(void);
322 void Render_Init(void)
340 R_LightningBeams_Init();
348 extern char *ENGINE_EXTENSIONS;
351 VID_CheckExtensions();
353 // LordHavoc: report supported extensions
354 Con_DPrintf("\nengine extensions: %s\n", ENGINE_EXTENSIONS);
357 int R_CullBox(const vec3_t mins, const vec3_t maxs)
361 for (i = 0;i < 4;i++)
368 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
372 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
376 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
380 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
384 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
388 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
392 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
396 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
404 #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))))
406 //==================================================================================
408 static void R_MarkEntities (void)
411 entity_render_t *ent;
413 ent = &cl_entities[0].render;
414 Matrix4x4_CreateIdentity(&ent->matrix);
415 Matrix4x4_CreateIdentity(&ent->inversematrix);
418 R_FarClip_Box(cl.worldmodel->normalmins, cl.worldmodel->normalmaxs);
420 if (!r_drawentities.integer)
423 for (i = 0;i < r_refdef.numentities;i++)
425 ent = r_refdef.entities[i];
426 Mod_CheckLoaded(ent->model);
427 // some of the renderer still relies on origin...
428 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
429 // some of the renderer still relies on scale...
430 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
431 R_LerpAnimation(ent);
432 R_UpdateEntLights(ent);
433 if ((chase_active.integer || !(ent->flags & RENDER_EXTERIORMODEL))
434 && !VIS_CullBox(ent->mins, ent->maxs))
436 ent->visframe = r_framecount;
437 R_FarClip_Box(ent->mins, ent->maxs);
442 // only used if skyrendermasked, and normally returns false
443 int R_DrawBrushModelsSky (void)
446 entity_render_t *ent;
448 if (!r_drawentities.integer)
452 for (i = 0;i < r_refdef.numentities;i++)
454 ent = r_refdef.entities[i];
455 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
457 ent->model->DrawSky(ent);
470 void R_DrawViewModel (void)
472 entity_render_t *ent;
474 // FIXME: move these checks to client
475 if (!r_drawviewmodel.integer || chase_active.integer || envmap || !r_drawentities.integer || cl.items & IT_INVISIBILITY || cl.stats[STAT_HEALTH] <= 0 || !cl.viewent.render.model)
478 ent = &cl.viewent.render;
479 Mod_CheckLoaded(ent->model);
480 R_LerpAnimation(ent);
481 Matrix4x4_CreateFromQuakeEntity(&ent->matrix, ent->origin[0], ent->origin[1], ent->origin[2], -ent->angles[0], ent->angles[1], ent->angles[2], ent->scale);
482 Matrix4x4_Invert_Simple(&ent->inversematrix, &ent->matrix);
483 R_UpdateEntLights(ent);
484 ent->model->Draw(ent);
488 void R_DrawNoModel(entity_render_t *ent);
489 void R_DrawModels(void)
492 entity_render_t *ent;
494 if (!r_drawentities.integer)
497 for (i = 0;i < r_refdef.numentities;i++)
499 ent = r_refdef.entities[i];
500 if (ent->visframe == r_framecount)
502 if (ent->model && ent->model->Draw != NULL)
503 ent->model->Draw(ent);
510 #include "r_shadow.h"
512 int shadowframecount = 0;
514 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)
516 vec3_t relativelightorigin;
518 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])))
520 Matrix4x4_Transform(&ent->inversematrix, lightorigin, relativelightorigin);
521 ent->model->DrawShadowVolume (ent, relativelightorigin, lightradius);
525 void R_Shadow_DrawWorldLightShadowVolume(matrix4x4_t *matrix, worldlight_t *light);
527 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);
528 void R_ShadowVolumeLighting(int visiblevolumes)
531 entity_render_t *ent;
533 float f, lightradius, cullradius;
534 vec3_t relativelightorigin, relativeeyeorigin, lightcolor, clipmins, clipmaxs;
539 matrix4x4_t matrix_worldtofilter, matrix_worldtoattenuationxyz, matrix_worldtoattenuationz;
540 matrix4x4_t matrix_modeltofilter, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz;
544 memset(&m, 0, sizeof(m));
545 R_Mesh_State_Texture(&m);
547 GL_BlendFunc(GL_ONE, GL_ONE);
549 GL_DepthTest(r_shadow_visiblevolumes.integer < 2);
550 qglDisable(GL_CULL_FACE);
551 GL_Color(0.0, 0.0125, 0.1, 1);
554 R_Shadow_Stage_Begin();
556 if (r_shadow_realtime_world.integer)
558 R_Shadow_LoadWorldLightsIfNeeded();
559 for (lnum = 0, wl = r_shadow_worldlightchain;wl;wl = wl->next, lnum++)
561 if (d_lightstylevalue[wl->style] <= 0)
563 if (VIS_CullBox(wl->mins, wl->maxs))
565 if (r_shadow_debuglight.integer >= 0 && lnum != r_shadow_debuglight.integer)
567 if (R_Shadow_ScissorForBBox(wl->mins, wl->maxs))
570 cullradius = wl->cullradius;
571 lightradius = wl->lightradius;
572 VectorCopy(wl->mins, clipmins);
573 VectorCopy(wl->maxs, clipmaxs);
575 f = d_lightstylevalue[wl->style] * (1.0f / 256.0f);
576 VectorScale(wl->light, f, lightcolor);
579 f = 2 + sin(realtime * M_PI * 4.0);
580 VectorScale(lightcolor, f, lightcolor);
583 if (wl->castshadows && (gl_stencil || visiblevolumes))
586 R_Shadow_Stage_ShadowVolumes();
587 ent = &cl_entities[0].render;
588 if (wl->shadowvolume && r_shadow_staticworldlights.integer)
589 R_Shadow_DrawWorldLightShadowVolume(&ent->matrix, wl);
591 R_TestAndDrawShadowVolume(ent, wl->origin, cullradius, lightradius, wl->mins, wl->maxs, clipmins, clipmaxs, true);
592 if (r_drawentities.integer)
593 for (i = 0;i < r_refdef.numentities;i++)
594 R_TestAndDrawShadowVolume(r_refdef.entities[i], wl->origin, cullradius, lightradius, wl->mins, wl->maxs, clipmins, clipmaxs, true);
599 if (wl->castshadows && gl_stencil)
600 R_Shadow_Stage_LightWithShadows();
602 R_Shadow_Stage_LightWithoutShadows();
604 // calculate world to filter matrix
605 Matrix4x4_CreateFromQuakeEntity(&matrix, wl->origin[0], wl->origin[1], wl->origin[2], wl->angles[0], wl->angles[1], wl->angles[2], lightradius);
606 Matrix4x4_Invert_Simple(&matrix_worldtofilter, &matrix);
607 // calculate world to attenuationxyz/xy matrix
608 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5, 0.5, 0.5, 0, 0, 0, 0.5);
609 Matrix4x4_Concat(&matrix_worldtoattenuationxyz, &matrix, &matrix_worldtofilter);
610 // calculate world to attenuationz matrix
611 matrix.m[0][0] = 0;matrix.m[0][1] = 0;matrix.m[0][2] = 0.5;matrix.m[0][3] = 0.5;
612 matrix.m[1][0] = 0;matrix.m[1][1] = 0;matrix.m[1][2] = 0 ;matrix.m[1][3] = 0.5;
613 matrix.m[2][0] = 0;matrix.m[2][1] = 0;matrix.m[2][2] = 0 ;matrix.m[2][3] = 0.5;
614 matrix.m[3][0] = 0;matrix.m[3][1] = 0;matrix.m[3][2] = 0 ;matrix.m[3][3] = 1;
615 Matrix4x4_Concat(&matrix_worldtoattenuationz, &matrix, &matrix_worldtofilter);
617 ent = &cl_entities[0].render;
618 if (ent->model && ent->model->DrawLight)
620 Matrix4x4_Transform(&ent->inversematrix, wl->origin, relativelightorigin);
621 Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin);
622 Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
623 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
624 Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
626 R_Model_Brush_DrawLightForSurfaceList(ent, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, wl->surfaces, wl->numsurfaces, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
628 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
630 if (r_drawentities.integer)
632 for (i = 0;i < r_refdef.numentities;i++)
634 ent = r_refdef.entities[i];
635 if (ent->visframe == r_framecount && ent->model && ent->model->DrawLight
636 && BoxesOverlap(ent->mins, ent->maxs, clipmins, clipmaxs)
637 && !(ent->effects & EF_ADDITIVE) && ent->alpha == 1)
639 Matrix4x4_Transform(&ent->inversematrix, wl->origin, relativelightorigin);
640 Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin);
641 Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
642 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
643 Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
644 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
651 if (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer)
653 for (lnum = 0, rd = r_dlight;lnum < r_numdlights;lnum++, rd++)
655 lightradius = rd->cullradius;
656 clipmins[0] = rd->origin[0] - lightradius;
657 clipmins[1] = rd->origin[1] - lightradius;
658 clipmins[2] = rd->origin[2] - lightradius;
659 clipmaxs[0] = rd->origin[0] + lightradius;
660 clipmaxs[1] = rd->origin[1] + lightradius;
661 clipmaxs[2] = rd->origin[2] + lightradius;
662 if (VIS_CullBox(clipmins, clipmaxs) || R_Shadow_ScissorForBBox(clipmins, clipmaxs))
665 cullradius = RadiusFromBoundsAndOrigin(clipmins, clipmaxs, rd->origin);
666 VectorScale(rd->light, (1.0f / 4096.0f), lightcolor);
668 if (r_shadow_shadows.integer && (gl_stencil || visiblevolumes))
671 R_Shadow_Stage_ShadowVolumes();
672 ent = &cl_entities[0].render;
673 R_TestAndDrawShadowVolume(ent, rd->origin, cullradius, lightradius, clipmins, clipmaxs, clipmins, clipmaxs, false);
674 if (r_drawentities.integer)
676 for (i = 0;i < r_refdef.numentities;i++)
678 ent = r_refdef.entities[i];
680 R_TestAndDrawShadowVolume(ent, rd->origin, cullradius, lightradius, clipmins, clipmaxs, clipmins, clipmaxs, false);
687 if (r_shadow_shadows.integer && gl_stencil)
688 R_Shadow_Stage_LightWithShadows();
690 R_Shadow_Stage_LightWithoutShadows();
692 // calculate world to filter matrix
693 Matrix4x4_CreateFromQuakeEntity(&matrix, rd->origin[0], rd->origin[1], rd->origin[2], 0, 0, 0, lightradius);
694 Matrix4x4_Invert_Simple(&matrix_worldtofilter, &matrix);
695 // calculate world to attenuationxyz/xy matrix
696 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5, 0.5, 0.5, 0, 0, 0, 0.5);
697 Matrix4x4_Concat(&matrix_worldtoattenuationxyz, &matrix, &matrix_worldtofilter);
698 // calculate world to attenuationz matrix
699 matrix.m[0][0] = 0;matrix.m[0][1] = 0;matrix.m[0][2] = 0.5;matrix.m[0][3] = 0.5;
700 matrix.m[1][0] = 0;matrix.m[1][1] = 0;matrix.m[1][2] = 0 ;matrix.m[1][3] = 0.5;
701 matrix.m[2][0] = 0;matrix.m[2][1] = 0;matrix.m[2][2] = 0 ;matrix.m[2][3] = 0.5;
702 matrix.m[3][0] = 0;matrix.m[3][1] = 0;matrix.m[3][2] = 0 ;matrix.m[3][3] = 1;
703 Matrix4x4_Concat(&matrix_worldtoattenuationz, &matrix, &matrix_worldtofilter);
705 ent = &cl_entities[0].render;
706 if (ent->model && ent->model->DrawLight)
708 Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin);
709 Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin);
710 Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
711 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
712 Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
713 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
715 if (r_drawentities.integer)
717 for (i = 0;i < r_refdef.numentities;i++)
719 ent = r_refdef.entities[i];
720 if (ent->visframe == r_framecount && ent->model && ent->model->DrawLight
721 && BoxesOverlap(ent->mins, ent->maxs, clipmins, clipmaxs)
722 && !(ent->effects & EF_ADDITIVE) && ent->alpha == 1)
724 Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin);
725 Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin);
726 Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
727 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
728 Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
729 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
738 qglEnable(GL_CULL_FACE);
740 R_Shadow_Stage_End();
741 qglDisable(GL_SCISSOR_TEST);
744 static void R_SetFrustum (void)
746 // LordHavoc: note to all quake engine coders, the special case for 90
747 // degrees assumed a square view (wrong), so I removed it, Quake2 has it
750 // rotate VPN right by FOV_X/2 degrees
751 RotatePointAroundVector( frustum[0].normal, vup, vpn, -(90-r_refdef.fov_x / 2 ) );
752 frustum[0].dist = DotProduct (r_origin, frustum[0].normal);
753 PlaneClassify(&frustum[0]);
755 // rotate VPN left by FOV_X/2 degrees
756 RotatePointAroundVector( frustum[1].normal, vup, vpn, 90-r_refdef.fov_x / 2 );
757 frustum[1].dist = DotProduct (r_origin, frustum[1].normal);
758 PlaneClassify(&frustum[1]);
760 // rotate VPN up by FOV_X/2 degrees
761 RotatePointAroundVector( frustum[2].normal, vright, vpn, 90-r_refdef.fov_y / 2 );
762 frustum[2].dist = DotProduct (r_origin, frustum[2].normal);
763 PlaneClassify(&frustum[2]);
765 // rotate VPN down by FOV_X/2 degrees
766 RotatePointAroundVector( frustum[3].normal, vright, vpn, -( 90 - r_refdef.fov_y / 2 ) );
767 frustum[3].dist = DotProduct (r_origin, frustum[3].normal);
768 PlaneClassify(&frustum[3]);
776 static void R_SetupFrame (void)
778 // don't allow cheats in multiplayer
781 if (r_fullbright.integer != 0)
782 Cvar_Set ("r_fullbright", "0");
783 if (r_ambient.value != 0)
784 Cvar_Set ("r_ambient", "0");
789 // build the transformation matrix for the given view angles
790 VectorCopy (r_refdef.vieworg, r_origin);
792 AngleVectors (r_refdef.viewangles, vpn, vright, vup);
798 static void R_BlendView(void)
804 if (r_refdef.viewblend[3] < 0.01f)
807 R_Mesh_Matrix(&r_identitymatrix);
809 memset(&m, 0, sizeof(m));
810 R_Mesh_State_Texture(&m);
812 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
814 GL_DepthTest(false); // magic
815 GL_VertexPointer(vertex3f);
816 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
818 vertex3f[0] = r_origin[0] + vpn[0] * 1.5 - vright[0] * r - vup[0] * r;
819 vertex3f[1] = r_origin[1] + vpn[1] * 1.5 - vright[1] * r - vup[1] * r;
820 vertex3f[2] = r_origin[2] + vpn[2] * 1.5 - vright[2] * r - vup[2] * r;
821 vertex3f[3] = r_origin[0] + vpn[0] * 1.5 - vright[0] * r + vup[0] * r * 3;
822 vertex3f[4] = r_origin[1] + vpn[1] * 1.5 - vright[1] * r + vup[1] * r * 3;
823 vertex3f[5] = r_origin[2] + vpn[2] * 1.5 - vright[2] * r + vup[2] * r * 3;
824 vertex3f[6] = r_origin[0] + vpn[0] * 1.5 + vright[0] * r * 3 - vup[0] * r;
825 vertex3f[7] = r_origin[1] + vpn[1] * 1.5 + vright[1] * r * 3 - vup[1] * r;
826 vertex3f[8] = r_origin[2] + vpn[2] * 1.5 + vright[2] * r * 3 - vup[2] * r;
827 R_Mesh_Draw(3, 1, polygonelements);
834 r_refdef must be set before the first call
837 extern void R_DrawLightningBeams (void);
838 void R_RenderView (void)
840 entity_render_t *world;
841 if (!r_refdef.entities/* || !cl.worldmodel*/)
842 return; //Host_Error ("R_RenderView: NULL worldmodel");
844 if (r_shadow_realtime_world.integer)
848 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");
849 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
853 world = &cl_entities[0].render;
855 // FIXME: move to client
857 R_TimeReport("mexplosion");
865 R_TimeReport("setup");
867 if (cl.worldmodel && cl.worldmodel->brush.FatPVS)
868 cl.worldmodel->brush.FatPVS(cl.worldmodel, r_origin, 2, r_pvsbits, sizeof(r_pvsbits));
870 R_WorldVisibility(world);
871 R_TimeReport("worldvis");
873 R_FarClip_Start(r_origin, vpn, 768.0f);
875 r_farclip = R_FarClip_Finish() + 256.0f;
876 R_TimeReport("markentity");
878 GL_SetupView_ViewPort(r_refdef.x, r_refdef.y, r_refdef.width, r_refdef.height);
879 if ((r_shadow_realtime_world.integer || r_shadow_shadows.integer) && gl_stencil)
880 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.fov_x, r_refdef.fov_y, 1.0f);
882 GL_SetupView_Mode_Perspective(r_refdef.fov_x, r_refdef.fov_y, 1.0f, r_farclip);
883 GL_SetupView_Orientation_FromEntity (r_refdef.vieworg, r_refdef.viewangles);
884 qglDepthFunc(GL_LEQUAL);
887 R_MeshQueue_BeginScene();
889 R_Shadow_UpdateWorldLightSelection();
891 if (R_DrawBrushModelsSky())
892 R_TimeReport("bmodelsky");
894 // must occur early because it can draw sky
896 R_TimeReport("world");
898 // don't let sound skip if going slow
899 if (!intimerefresh && !r_speeds.integer)
903 R_TimeReport("models");
905 if (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer)
907 R_ShadowVolumeLighting(false);
908 R_TimeReport("dynlight");
911 R_DrawLightningBeams();
912 R_TimeReport("lightning");
915 R_TimeReport("particles");
918 R_TimeReport("explosions");
920 R_MeshQueue_RenderTransparent();
921 R_TimeReport("drawtrans");
924 R_TimeReport("coronas");
926 R_DrawWorldCrosshair();
927 R_TimeReport("crosshair");
930 R_TimeReport("blendview");
932 R_MeshQueue_Render();
933 R_MeshQueue_EndScene();
935 if (r_shadow_visiblevolumes.integer)
937 R_ShadowVolumeLighting(true);
938 R_TimeReport("shadowvolume");
942 R_TimeReport("meshfinish");
946 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
949 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
951 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
954 R_Mesh_Matrix(&r_identitymatrix);
956 memset(&m, 0, sizeof(m));
957 R_Mesh_State_Texture(&m);
960 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
961 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
962 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
963 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
964 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
965 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
966 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
967 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
968 GL_ColorPointer(color);
969 R_FillColors(color, 8, cr, cg, cb, ca);
972 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
974 VectorSubtract(v, r_origin, diff);
975 f2 = exp(fogdensity/DotProduct(diff, diff));
977 c[0] = c[0] * f1 + fogcolor[0] * f2;
978 c[1] = c[1] * f1 + fogcolor[1] * f2;
979 c[2] = c[2] * f1 + fogcolor[2] * f2;
986 int nomodelelements[24] =
998 float nomodelvertex3f[6*3] =
1008 float nomodelcolor4f[6*4] =
1010 0.0f, 0.0f, 0.5f, 1.0f,
1011 0.0f, 0.0f, 0.5f, 1.0f,
1012 0.0f, 0.5f, 0.0f, 1.0f,
1013 0.0f, 0.5f, 0.0f, 1.0f,
1014 0.5f, 0.0f, 0.0f, 1.0f,
1015 0.5f, 0.0f, 0.0f, 1.0f
1018 void R_DrawNoModelCallback(const void *calldata1, int calldata2)
1020 const entity_render_t *ent = calldata1;
1022 float f1, f2, *c, diff[3];
1025 R_Mesh_Matrix(&ent->matrix);
1027 memset(&m, 0, sizeof(m));
1028 R_Mesh_State_Texture(&m);
1030 if (ent->flags & EF_ADDITIVE)
1032 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1033 GL_DepthMask(false);
1035 else if (ent->alpha < 1)
1037 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1038 GL_DepthMask(false);
1042 GL_BlendFunc(GL_ONE, GL_ZERO);
1046 GL_VertexPointer(nomodelvertex3f);
1049 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1050 GL_ColorPointer(color4f);
1051 VectorSubtract(ent->origin, r_origin, diff);
1052 f2 = exp(fogdensity/DotProduct(diff, diff));
1054 for (i = 0, c = color4f;i < 6;i++, c += 4)
1056 c[0] = (c[0] * f1 + fogcolor[0] * f2);
1057 c[1] = (c[1] * f1 + fogcolor[1] * f2);
1058 c[2] = (c[2] * f1 + fogcolor[2] * f2);
1062 else if (ent->alpha != 1)
1064 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1065 GL_ColorPointer(color4f);
1066 for (i = 0, c = color4f;i < 6;i++, c += 4)
1070 GL_ColorPointer(nomodelcolor4f);
1071 R_Mesh_Draw(6, 8, nomodelelements);
1074 void R_DrawNoModel(entity_render_t *ent)
1076 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1077 R_MeshQueue_AddTransparent(ent->origin, R_DrawNoModelCallback, ent, 0);
1079 // R_DrawNoModelCallback(ent, 0);
1082 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1084 vec3_t right1, right2, diff, normal;
1086 VectorSubtract (org2, org1, normal);
1087 VectorNormalizeFast (normal);
1089 // calculate 'right' vector for start
1090 VectorSubtract (r_origin, org1, diff);
1091 VectorNormalizeFast (diff);
1092 CrossProduct (normal, diff, right1);
1094 // calculate 'right' vector for end
1095 VectorSubtract (r_origin, org2, diff);
1096 VectorNormalizeFast (diff);
1097 CrossProduct (normal, diff, right2);
1099 vert[ 0] = org1[0] + width * right1[0];
1100 vert[ 1] = org1[1] + width * right1[1];
1101 vert[ 2] = org1[2] + width * right1[2];
1102 vert[ 3] = org1[0] - width * right1[0];
1103 vert[ 4] = org1[1] - width * right1[1];
1104 vert[ 5] = org1[2] - width * right1[2];
1105 vert[ 6] = org2[0] - width * right2[0];
1106 vert[ 7] = org2[1] - width * right2[1];
1107 vert[ 8] = org2[2] - width * right2[2];
1108 vert[ 9] = org2[0] + width * right2[0];
1109 vert[10] = org2[1] + width * right2[1];
1110 vert[11] = org2[2] + width * right2[2];
1113 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
1115 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)
1122 VectorSubtract(origin, r_origin, diff);
1123 ca *= 1 - exp(fogdensity/DotProduct(diff,diff));
1126 R_Mesh_Matrix(&r_identitymatrix);
1127 GL_Color(cr, cg, cb, ca);
1128 GL_VertexPointer(varray_vertex3f);
1129 GL_BlendFunc(blendfunc1, blendfunc2);
1130 GL_DepthMask(false);
1131 GL_DepthTest(!depthdisable);
1133 memset(&m, 0, sizeof(m));
1134 m.tex[0] = R_GetTexture(texture);
1135 m.pointer_texcoord[0] = spritetexcoord2f;
1136 R_Mesh_State_Texture(&m);
1138 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
1139 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
1140 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
1141 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
1142 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
1143 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
1144 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
1145 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
1146 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
1147 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
1148 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
1149 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
1150 R_Mesh_Draw(4, 2, polygonelements);