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_UpdateFog(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 static vec3_t r_farclip_origin;
271 static vec3_t r_farclip_direction;
272 static vec_t r_farclip_directiondist;
273 static vec_t r_farclip_meshfarclip;
274 static int r_farclip_directionbit0;
275 static int r_farclip_directionbit1;
276 static int r_farclip_directionbit2;
278 // enlarge farclip to accomodate box
279 static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
282 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
283 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
284 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
285 if (r_farclip_meshfarclip < d)
286 r_farclip_meshfarclip = d;
289 // return farclip value
290 static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
294 VectorCopy(origin, r_farclip_origin);
295 VectorCopy(direction, r_farclip_direction);
296 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
297 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
298 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
299 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
300 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
303 R_FarClip_Box(cl.worldmodel->normalmins, cl.worldmodel->normalmaxs);
304 for (i = 0;i < r_refdef.numentities;i++)
305 R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
307 return r_farclip_meshfarclip - r_farclip_directiondist;
310 extern void R_Textures_Init(void);
311 extern void Mod_RenderInit(void);
312 extern void GL_Draw_Init(void);
313 extern void GL_Main_Init(void);
314 extern void R_Shadow_Init(void);
315 extern void GL_Models_Init(void);
316 extern void R_Sky_Init(void);
317 extern void GL_Surf_Init(void);
318 extern void R_Crosshairs_Init(void);
319 extern void R_Light_Init(void);
320 extern void R_Particles_Init(void);
321 extern void R_Explosion_Init(void);
322 extern void ui_init(void);
323 extern void gl_backend_init(void);
324 extern void Sbar_Init(void);
325 extern void R_LightningBeams_Init(void);
327 void Render_Init(void)
346 R_LightningBeams_Init();
354 extern char *ENGINE_EXTENSIONS;
357 VID_CheckExtensions();
359 // LordHavoc: report supported extensions
360 Con_DPrintf("\nengine extensions: %s\n", ENGINE_EXTENSIONS);
363 int R_CullBox(const vec3_t mins, const vec3_t maxs)
367 for (i = 0;i < 4;i++)
374 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
378 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
382 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
386 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
390 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
394 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
398 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
402 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
410 #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))))
412 //==================================================================================
414 static void R_MarkEntities (void)
417 entity_render_t *ent;
419 ent = &cl_entities[0].render;
420 Matrix4x4_CreateIdentity(&ent->matrix);
421 Matrix4x4_CreateIdentity(&ent->inversematrix);
423 if (!r_drawentities.integer)
426 for (i = 0;i < r_refdef.numentities;i++)
428 ent = r_refdef.entities[i];
429 Mod_CheckLoaded(ent->model);
430 // some of the renderer still relies on origin...
431 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
432 // some of the renderer still relies on scale...
433 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
434 R_LerpAnimation(ent);
435 R_UpdateEntLights(ent);
436 if ((chase_active.integer || !(ent->flags & RENDER_EXTERIORMODEL))
437 && !VIS_CullBox(ent->mins, ent->maxs)
438 && (!envmap || !(ent->flags & (RENDER_VIEWMODEL | RENDER_EXTERIORMODEL))))
439 ent->visframe = r_framecount;
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 #include "r_shadow.h"
513 int shadowframecount = 0;
515 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)
517 vec3_t relativelightorigin;
519 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])))
521 Matrix4x4_Transform(&ent->inversematrix, lightorigin, relativelightorigin);
522 ent->model->DrawShadowVolume (ent, relativelightorigin, lightradius);
526 void R_Shadow_DrawWorldLightShadowVolume(matrix4x4_t *matrix, worldlight_t *light);
528 void R_ShadowVolumeLighting(int visiblevolumes)
531 entity_render_t *ent;
533 float f, lightradius, cullradius;
534 vec3_t relativelightorigin, relativeeyeorigin, lightcolor, clipmins, clipmaxs;
538 rtexture_t *cubemaptexture;
539 matrix4x4_t matrix_modeltolight, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz;
543 memset(&m, 0, sizeof(m));
544 R_Mesh_State_Texture(&m);
546 GL_BlendFunc(GL_ONE, GL_ONE);
548 GL_DepthTest(r_shadow_visiblevolumes.integer < 2);
549 qglDisable(GL_CULL_FACE);
550 GL_Color(0.0, 0.0125, 0.1, 1);
553 R_Shadow_Stage_Begin();
555 if (r_shadow_realtime_world.integer)
557 R_Shadow_LoadWorldLightsIfNeeded();
558 for (lnum = 0, wl = r_shadow_worldlightchain;wl;wl = wl->next, lnum++)
560 if (d_lightstylevalue[wl->style] <= 0)
562 if (VIS_CullBox(wl->mins, wl->maxs))
564 if (r_shadow_debuglight.integer >= 0 && lnum != r_shadow_debuglight.integer)
566 if (R_Shadow_ScissorForBBox(wl->mins, wl->maxs))
569 cullradius = wl->cullradius;
570 lightradius = wl->radius;
571 VectorCopy(wl->mins, clipmins);
572 VectorCopy(wl->maxs, clipmaxs);
574 f = d_lightstylevalue[wl->style] * (1.0f / 256.0f);
575 VectorScale(wl->color, f, lightcolor);
578 f = 2 + sin(realtime * M_PI * 4.0);
579 VectorScale(lightcolor, f, lightcolor);
582 if (r_shadow_worldshadows.integer && wl->drawshadows && (gl_stencil || visiblevolumes))
585 R_Shadow_Stage_ShadowVolumes();
586 ent = &cl_entities[0].render;
587 if (r_shadow_staticworldlights.integer)
588 R_Shadow_DrawStaticWorldLight_Shadow(wl, &ent->matrix);
590 R_TestAndDrawShadowVolume(ent, wl->origin, cullradius, lightradius, wl->mins, wl->maxs, clipmins, clipmaxs, true);
591 if (r_drawentities.integer)
592 for (i = 0;i < r_refdef.numentities;i++)
593 R_TestAndDrawShadowVolume(r_refdef.entities[i], wl->origin, cullradius, lightradius, wl->mins, wl->maxs, clipmins, clipmaxs, true);
598 if (r_shadow_worldshadows.integer && wl->drawshadows && gl_stencil)
599 R_Shadow_Stage_LightWithShadows();
601 R_Shadow_Stage_LightWithoutShadows();
603 ent = &cl_entities[0].render;
604 if (ent->model && ent->model->DrawLight)
606 Matrix4x4_Transform(&ent->inversematrix, wl->origin, relativelightorigin);
607 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, relativeeyeorigin);
608 Matrix4x4_Concat(&matrix_modeltolight, &wl->matrix_worldtolight, &ent->matrix);
609 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &wl->matrix_worldtoattenuationxyz, &ent->matrix);
610 Matrix4x4_Concat(&matrix_modeltoattenuationz, &wl->matrix_worldtoattenuationz, &ent->matrix);
611 if (r_shadow_staticworldlights.integer)
612 R_Shadow_DrawStaticWorldLight_Light(wl, &ent->matrix, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, &matrix_modeltolight, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
614 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltolight, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz, wl->cubemap);
616 if (r_drawentities.integer)
618 for (i = 0;i < r_refdef.numentities;i++)
620 ent = r_refdef.entities[i];
621 if (ent->visframe == r_framecount && ent->model && ent->model->DrawLight
622 && BoxesOverlap(ent->mins, ent->maxs, clipmins, clipmaxs)
623 && !(ent->effects & EF_ADDITIVE) && ent->alpha == 1)
625 Matrix4x4_Transform(&ent->inversematrix, wl->origin, relativelightorigin);
626 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, relativeeyeorigin);
627 Matrix4x4_Concat(&matrix_modeltolight, &wl->matrix_worldtolight, &ent->matrix);
628 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &wl->matrix_worldtoattenuationxyz, &ent->matrix);
629 Matrix4x4_Concat(&matrix_modeltoattenuationz, &wl->matrix_worldtoattenuationz, &ent->matrix);
630 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltolight, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz, wl->cubemap);
637 if (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer)
639 for (lnum = 0, rd = r_dlight;lnum < r_numdlights;lnum++, rd++)
641 lightradius = rd->radius;
642 clipmins[0] = rd->origin[0] - lightradius;
643 clipmins[1] = rd->origin[1] - lightradius;
644 clipmins[2] = rd->origin[2] - lightradius;
645 clipmaxs[0] = rd->origin[0] + lightradius;
646 clipmaxs[1] = rd->origin[1] + lightradius;
647 clipmaxs[2] = rd->origin[2] + lightradius;
648 if (VIS_CullBox(clipmins, clipmaxs) || R_Shadow_ScissorForBBox(clipmins, clipmaxs))
651 cullradius = RadiusFromBoundsAndOrigin(clipmins, clipmaxs, rd->origin);
652 VectorCopy(rd->color, lightcolor);
654 if (rd->cubemapnum > 0)
655 cubemaptexture = R_Shadow_Cubemap(va("cubemaps/%i", rd->cubemapnum));
657 cubemaptexture = NULL;
659 if (r_shadow_dlightshadows.integer && rd->shadow && (gl_stencil || visiblevolumes))
662 R_Shadow_Stage_ShadowVolumes();
663 ent = &cl_entities[0].render;
664 R_TestAndDrawShadowVolume(ent, rd->origin, cullradius, lightradius, clipmins, clipmaxs, clipmins, clipmaxs, false);
665 if (r_drawentities.integer)
667 for (i = 0;i < r_refdef.numentities;i++)
669 ent = r_refdef.entities[i];
671 R_TestAndDrawShadowVolume(ent, rd->origin, cullradius, lightradius, clipmins, clipmaxs, clipmins, clipmaxs, false);
678 if (r_shadow_dlightshadows.integer && gl_stencil && rd->shadow)
679 R_Shadow_Stage_LightWithShadows();
681 R_Shadow_Stage_LightWithoutShadows();
683 ent = &cl_entities[0].render;
684 if (ent->model && ent->model->DrawLight)
686 Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin);
687 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, relativeeyeorigin);
688 Matrix4x4_Concat(&matrix_modeltolight, &rd->matrix_worldtolight, &ent->matrix);
689 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &rd->matrix_worldtoattenuationxyz, &ent->matrix);
690 Matrix4x4_Concat(&matrix_modeltoattenuationz, &rd->matrix_worldtoattenuationz, &ent->matrix);
691 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltolight, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz, cubemaptexture);
693 if (r_drawentities.integer)
695 for (i = 0;i < r_refdef.numentities;i++)
697 ent = r_refdef.entities[i];
698 if (ent->visframe == r_framecount && ent->model && ent->model->DrawLight
699 && BoxesOverlap(ent->mins, ent->maxs, clipmins, clipmaxs)
700 && !(ent->effects & EF_ADDITIVE) && ent->alpha == 1)
702 Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin);
703 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, relativeeyeorigin);
704 Matrix4x4_Concat(&matrix_modeltolight, &rd->matrix_worldtolight, &ent->matrix);
705 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &rd->matrix_worldtoattenuationxyz, &ent->matrix);
706 Matrix4x4_Concat(&matrix_modeltoattenuationz, &rd->matrix_worldtoattenuationz, &ent->matrix);
707 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltolight, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz, cubemaptexture);
717 qglEnable(GL_CULL_FACE);
718 GL_Scissor(r_refdef.x, r_refdef.y, r_refdef.width, r_refdef.height);
721 R_Shadow_Stage_End();
724 static void R_SetFrustum(void)
726 // break apart the viewentity matrix into vectors for various purposes
727 Matrix4x4_ToVectors(&r_refdef.viewentitymatrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
728 VectorNegate(r_viewleft, r_viewright);
730 // LordHavoc: note to all quake engine coders, the special case for 90
731 // degrees assumed a square view (wrong), so I removed it, Quake2 has it
734 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
735 RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_refdef.fov_x / 2));
736 frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
737 PlaneClassify(&frustum[0]);
739 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
740 RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_refdef.fov_x / 2));
741 frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
742 PlaneClassify(&frustum[1]);
744 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
745 RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_refdef.fov_y / 2));
746 frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
747 PlaneClassify(&frustum[2]);
749 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
750 RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_refdef.fov_y / 2));
751 frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
752 PlaneClassify(&frustum[3]);
755 static void R_BlendView(void)
761 if (r_refdef.viewblend[3] < 0.01f)
764 R_Mesh_Matrix(&r_identitymatrix);
766 memset(&m, 0, sizeof(m));
767 R_Mesh_State_Texture(&m);
769 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
771 GL_DepthTest(false); // magic
772 GL_VertexPointer(vertex3f);
773 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
775 vertex3f[0] = r_vieworigin[0] + r_viewforward[0] * 1.5 + r_viewleft[0] * r - r_viewup[0] * r;
776 vertex3f[1] = r_vieworigin[1] + r_viewforward[1] * 1.5 + r_viewleft[1] * r - r_viewup[1] * r;
777 vertex3f[2] = r_vieworigin[2] + r_viewforward[2] * 1.5 + r_viewleft[2] * r - r_viewup[2] * r;
778 vertex3f[3] = r_vieworigin[0] + r_viewforward[0] * 1.5 + r_viewleft[0] * r + r_viewup[0] * r * 3;
779 vertex3f[4] = r_vieworigin[1] + r_viewforward[1] * 1.5 + r_viewleft[1] * r + r_viewup[1] * r * 3;
780 vertex3f[5] = r_vieworigin[2] + r_viewforward[2] * 1.5 + r_viewleft[2] * r + r_viewup[2] * r * 3;
781 vertex3f[6] = r_vieworigin[0] + r_viewforward[0] * 1.5 - r_viewleft[0] * r * 3 - r_viewup[0] * r;
782 vertex3f[7] = r_vieworigin[1] + r_viewforward[1] * 1.5 - r_viewleft[1] * r * 3 - r_viewup[1] * r;
783 vertex3f[8] = r_vieworigin[2] + r_viewforward[2] * 1.5 - r_viewleft[2] * r * 3 - r_viewup[2] * r;
784 R_Mesh_Draw(3, 1, polygonelements);
787 void R_UpdateWorld(void)
789 if (!r_refdef.entities/* || !cl.worldmodel*/)
790 return; //Host_Error ("R_RenderView: NULL worldmodel");
792 if (r_shadow_realtime_world.integer && !gl_stencil)
794 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");
795 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
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");
812 void R_RenderScene(void);
819 void R_RenderView(void)
821 if (!r_refdef.entities/* || !cl.worldmodel*/)
822 return; //Host_Error ("R_RenderView: NULL worldmodel");
824 r_refdef.width = bound(0, r_refdef.width, vid.realwidth);
825 r_refdef.height = bound(0, r_refdef.height, vid.realheight);
826 r_refdef.x = bound(0, r_refdef.x, vid.realwidth - r_refdef.width);
827 r_refdef.y = bound(0, r_refdef.y, vid.realheight - r_refdef.height);
828 r_refdef.fov_x = bound(1, r_refdef.fov_x, 170);
829 r_refdef.fov_y = bound(1, r_refdef.fov_y, 170);
831 // GL is weird because it's bottom to top, r_refdef.y is top to bottom
832 qglViewport(r_refdef.x, vid.realheight - (r_refdef.y + r_refdef.height), r_refdef.width, r_refdef.height);
833 GL_Scissor(r_refdef.x, r_refdef.y, r_refdef.width, r_refdef.height);
834 GL_ScissorTest(true);
838 r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
840 if (gl_stencil && ((r_shadow_realtime_world.integer && r_shadow_worldshadows.integer) || ((r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && r_shadow_dlightshadows.integer)))
841 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.fov_x, r_refdef.fov_y, 1.0f);
843 GL_SetupView_Mode_Perspective(r_refdef.fov_x, r_refdef.fov_y, 1.0f, r_farclip);
845 GL_SetupView_Orientation_FromEntity(&r_refdef.viewentitymatrix);
846 R_TimeReport("setup");
851 R_TimeReport("blendview");
853 GL_Scissor(0, 0, vid.realwidth, vid.realheight);
854 GL_ScissorTest(false);
857 extern void R_DrawLightningBeams (void);
858 void R_RenderScene(void)
860 entity_render_t *world;
862 // don't let sound skip if going slow
863 if (!intimerefresh && !r_speeds.integer)
870 if (cl.worldmodel && cl.worldmodel->brush.FatPVS)
871 cl.worldmodel->brush.FatPVS(cl.worldmodel, r_vieworigin, 2, r_pvsbits, sizeof(r_pvsbits));
872 world = &cl_entities[0].render;
873 R_WorldVisibility(world);
874 R_TimeReport("worldvis");
877 R_TimeReport("markentity");
879 qglDepthFunc(GL_LEQUAL);
880 qglPolygonOffset(0, 0);
881 qglEnable(GL_POLYGON_OFFSET_FILL);
884 R_MeshQueue_BeginScene();
886 R_Shadow_UpdateWorldLightSelection();
888 // don't let sound skip if going slow
889 if (!intimerefresh && !r_speeds.integer)
892 if (R_DrawBrushModelsSky())
893 R_TimeReport("bmodelsky");
895 // must occur early because it can draw sky
897 R_TimeReport("world");
899 // don't let sound skip if going slow
900 if (!intimerefresh && !r_speeds.integer)
904 R_TimeReport("models");
906 // don't let sound skip if going slow
907 if (!intimerefresh && !r_speeds.integer)
910 R_ShadowVolumeLighting(false);
911 R_TimeReport("rtlights");
913 // don't let sound skip if going slow
914 if (!intimerefresh && !r_speeds.integer)
917 R_DrawLightningBeams();
918 R_TimeReport("lightning");
921 R_TimeReport("particles");
924 R_TimeReport("explosions");
926 R_MeshQueue_RenderTransparent();
927 R_TimeReport("drawtrans");
930 R_TimeReport("coronas");
932 R_DrawWorldCrosshair();
933 R_TimeReport("crosshair");
935 R_MeshQueue_Render();
936 R_MeshQueue_EndScene();
938 if (r_shadow_visiblevolumes.integer)
940 R_ShadowVolumeLighting(true);
941 R_TimeReport("shadowvolume");
945 R_TimeReport("meshfinish");
947 qglPolygonOffset(0, 0);
948 qglDisable(GL_POLYGON_OFFSET_FILL);
950 // don't let sound skip if going slow
951 if (!intimerefresh && !r_speeds.integer)
956 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
959 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
961 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
964 R_Mesh_Matrix(&r_identitymatrix);
966 memset(&m, 0, sizeof(m));
967 R_Mesh_State_Texture(&m);
970 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
971 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
972 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
973 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
974 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
975 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
976 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
977 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
978 GL_ColorPointer(color);
979 R_FillColors(color, 8, cr, cg, cb, ca);
982 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
984 VectorSubtract(v, r_vieworigin, diff);
985 f2 = exp(fogdensity/DotProduct(diff, diff));
987 c[0] = c[0] * f1 + fogcolor[0] * f2;
988 c[1] = c[1] * f1 + fogcolor[1] * f2;
989 c[2] = c[2] * f1 + fogcolor[2] * f2;
996 int nomodelelements[24] =
1008 float nomodelvertex3f[6*3] =
1018 float nomodelcolor4f[6*4] =
1020 0.0f, 0.0f, 0.5f, 1.0f,
1021 0.0f, 0.0f, 0.5f, 1.0f,
1022 0.0f, 0.5f, 0.0f, 1.0f,
1023 0.0f, 0.5f, 0.0f, 1.0f,
1024 0.5f, 0.0f, 0.0f, 1.0f,
1025 0.5f, 0.0f, 0.0f, 1.0f
1028 void R_DrawNoModelCallback(const void *calldata1, int calldata2)
1030 const entity_render_t *ent = calldata1;
1032 float f1, f2, *c, diff[3];
1035 R_Mesh_Matrix(&ent->matrix);
1037 memset(&m, 0, sizeof(m));
1038 R_Mesh_State_Texture(&m);
1040 if (ent->flags & EF_ADDITIVE)
1042 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1043 GL_DepthMask(false);
1045 else if (ent->alpha < 1)
1047 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1048 GL_DepthMask(false);
1052 GL_BlendFunc(GL_ONE, GL_ZERO);
1056 GL_VertexPointer(nomodelvertex3f);
1059 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1060 GL_ColorPointer(color4f);
1061 VectorSubtract(ent->origin, r_vieworigin, diff);
1062 f2 = exp(fogdensity/DotProduct(diff, diff));
1064 for (i = 0, c = color4f;i < 6;i++, c += 4)
1066 c[0] = (c[0] * f1 + fogcolor[0] * f2);
1067 c[1] = (c[1] * f1 + fogcolor[1] * f2);
1068 c[2] = (c[2] * f1 + fogcolor[2] * f2);
1072 else if (ent->alpha != 1)
1074 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1075 GL_ColorPointer(color4f);
1076 for (i = 0, c = color4f;i < 6;i++, c += 4)
1080 GL_ColorPointer(nomodelcolor4f);
1081 R_Mesh_Draw(6, 8, nomodelelements);
1084 void R_DrawNoModel(entity_render_t *ent)
1086 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1087 R_MeshQueue_AddTransparent(ent->origin, R_DrawNoModelCallback, ent, 0);
1089 // R_DrawNoModelCallback(ent, 0);
1092 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1094 vec3_t right1, right2, diff, normal;
1096 VectorSubtract (org2, org1, normal);
1097 VectorNormalizeFast (normal);
1099 // calculate 'right' vector for start
1100 VectorSubtract (r_vieworigin, org1, diff);
1101 VectorNormalizeFast (diff);
1102 CrossProduct (normal, diff, right1);
1104 // calculate 'right' vector for end
1105 VectorSubtract (r_vieworigin, org2, diff);
1106 VectorNormalizeFast (diff);
1107 CrossProduct (normal, diff, right2);
1109 vert[ 0] = org1[0] + width * right1[0];
1110 vert[ 1] = org1[1] + width * right1[1];
1111 vert[ 2] = org1[2] + width * right1[2];
1112 vert[ 3] = org1[0] - width * right1[0];
1113 vert[ 4] = org1[1] - width * right1[1];
1114 vert[ 5] = org1[2] - width * right1[2];
1115 vert[ 6] = org2[0] - width * right2[0];
1116 vert[ 7] = org2[1] - width * right2[1];
1117 vert[ 8] = org2[2] - width * right2[2];
1118 vert[ 9] = org2[0] + width * right2[0];
1119 vert[10] = org2[1] + width * right2[1];
1120 vert[11] = org2[2] + width * right2[2];
1123 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
1125 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)
1132 VectorSubtract(origin, r_vieworigin, diff);
1133 ca *= 1 - exp(fogdensity/DotProduct(diff,diff));
1136 R_Mesh_Matrix(&r_identitymatrix);
1137 GL_Color(cr, cg, cb, ca);
1138 GL_VertexPointer(varray_vertex3f);
1139 GL_BlendFunc(blendfunc1, blendfunc2);
1140 GL_DepthMask(false);
1141 GL_DepthTest(!depthdisable);
1143 memset(&m, 0, sizeof(m));
1144 m.tex[0] = R_GetTexture(texture);
1145 m.pointer_texcoord[0] = spritetexcoord2f;
1146 R_Mesh_State_Texture(&m);
1148 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
1149 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
1150 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
1151 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
1152 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
1153 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
1154 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
1155 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
1156 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
1157 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
1158 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
1159 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
1160 R_Mesh_Draw(4, 2, polygonelements);