2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 // used for dlight push checking and other things
27 // used for visibility checking
28 qbyte r_pvsbits[(MAX_MAP_LEAFS+7)>>3];
32 matrix4x4_t r_identitymatrix;
34 int c_alias_polys, c_light_polys, c_faces, c_nodes, c_leafs, c_models, c_bmodels, c_sprites, c_particles, c_dlights;
36 // true during envmap command capture
53 // 8.8 fraction of base light value
54 unsigned short d_lightstylevalue[256];
56 cvar_t r_drawentities = {0, "r_drawentities","1"};
57 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1"};
58 cvar_t r_shadow_staticworldlights = {0, "r_shadow_staticworldlights", "1"};
59 cvar_t r_speeds = {0, "r_speeds","0"};
60 cvar_t r_fullbright = {0, "r_fullbright","0"};
61 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1"};
62 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1"};
63 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1"};
64 cvar_t r_shadow_cull = {0, "r_shadow_cull", "1"};
65 cvar_t r_drawcollisionbrushes = {0, "r_drawcollisionbrushes", "0"};
67 cvar_t gl_fogenable = {0, "gl_fogenable", "0"};
68 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25"};
69 cvar_t gl_fogred = {0, "gl_fogred","0.3"};
70 cvar_t gl_foggreen = {0, "gl_foggreen","0.3"};
71 cvar_t gl_fogblue = {0, "gl_fogblue","0.3"};
72 cvar_t gl_fogstart = {0, "gl_fogstart", "0"};
73 cvar_t gl_fogend = {0, "gl_fogend","0"};
75 cvar_t r_textureunits = {0, "r_textureunits", "32"};
77 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1"};
78 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1"};
79 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1"};
80 cvar_t r_watershader = {CVAR_SAVE, "r_watershader", "1"};
83 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
86 for (i = 0;i < verts;i++)
97 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
100 for (i = 0;i < verts;i++)
114 For program optimization
117 qboolean intimerefresh = 0;
118 static void R_TimeRefresh_f (void)
121 float timestart, timedelta, oldangles[3];
124 VectorCopy(cl.viewangles, oldangles);
125 VectorClear(cl.viewangles);
127 timestart = Sys_DoubleTime();
128 for (i = 0;i < 128;i++)
130 Matrix4x4_CreateFromQuakeEntity(&r_refdef.viewentitymatrix, r_vieworigin[0], r_vieworigin[1], r_vieworigin[2], 0, i / 128.0 * 360.0, 0, 1);
133 timedelta = Sys_DoubleTime() - timestart;
135 VectorCopy(oldangles, cl.viewangles);
137 Con_Printf ("%f seconds (%f fps)\n", timedelta, 128/timedelta);
142 float fog_density, fog_red, fog_green, fog_blue;
144 qboolean oldgl_fogenable;
145 void R_SetupFog(void)
147 if (gamemode == GAME_NEHAHRA)
149 if (gl_fogenable.integer)
151 oldgl_fogenable = true;
152 fog_density = gl_fogdensity.value;
153 fog_red = gl_fogred.value;
154 fog_green = gl_foggreen.value;
155 fog_blue = gl_fogblue.value;
157 else if (oldgl_fogenable)
159 oldgl_fogenable = false;
168 fogcolor[0] = fog_red = bound(0.0f, fog_red , 1.0f);
169 fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
170 fogcolor[2] = fog_blue = bound(0.0f, fog_blue , 1.0f);
175 fogdensity = -4000.0f / (fog_density * fog_density);
176 // fog color was already set
182 // FIXME: move this to client?
185 if (gamemode == GAME_NEHAHRA)
187 Cvar_Set("gl_fogenable", "0");
188 Cvar_Set("gl_fogdensity", "0.2");
189 Cvar_Set("gl_fogred", "0.3");
190 Cvar_Set("gl_foggreen", "0.3");
191 Cvar_Set("gl_fogblue", "0.3");
193 fog_density = fog_red = fog_green = fog_blue = 0.0f;
196 // FIXME: move this to client?
197 void FOG_registercvars(void)
199 if (gamemode == GAME_NEHAHRA)
201 Cvar_RegisterVariable (&gl_fogenable);
202 Cvar_RegisterVariable (&gl_fogdensity);
203 Cvar_RegisterVariable (&gl_fogred);
204 Cvar_RegisterVariable (&gl_foggreen);
205 Cvar_RegisterVariable (&gl_fogblue);
206 Cvar_RegisterVariable (&gl_fogstart);
207 Cvar_RegisterVariable (&gl_fogend);
211 void gl_main_start(void)
215 void gl_main_shutdown(void)
219 extern void CL_ParseEntityLump(char *entitystring);
220 void gl_main_newmap(void)
223 char *entities, entname[MAX_QPATH];
227 strcpy(entname, cl.worldmodel->name);
228 l = strlen(entname) - 4;
229 if (l >= 0 && !strcmp(entname + l, ".bsp"))
231 strcpy(entname + l, ".ent");
232 if ((entities = FS_LoadFile(entname, true)))
234 CL_ParseEntityLump(entities);
239 if (cl.worldmodel->brush.entities)
240 CL_ParseEntityLump(cl.worldmodel->brush.entities);
244 void GL_Main_Init(void)
246 Matrix4x4_CreateIdentity(&r_identitymatrix);
247 // FIXME: move this to client?
249 Cmd_AddCommand("timerefresh", R_TimeRefresh_f);
250 Cvar_RegisterVariable(&r_drawentities);
251 Cvar_RegisterVariable(&r_drawviewmodel);
252 Cvar_RegisterVariable(&r_shadow_staticworldlights);
253 Cvar_RegisterVariable(&r_speeds);
254 Cvar_RegisterVariable(&r_fullbrights);
255 Cvar_RegisterVariable(&r_wateralpha);
256 Cvar_RegisterVariable(&r_dynamic);
257 Cvar_RegisterVariable(&r_fullbright);
258 Cvar_RegisterVariable(&r_textureunits);
259 Cvar_RegisterVariable(&r_shadow_cull);
260 Cvar_RegisterVariable(&r_lerpsprites);
261 Cvar_RegisterVariable(&r_lerpmodels);
262 Cvar_RegisterVariable(&r_waterscroll);
263 Cvar_RegisterVariable(&r_watershader);
264 Cvar_RegisterVariable(&r_drawcollisionbrushes);
265 if (gamemode == GAME_NEHAHRA || gamemode == GAME_NEXUIZ)
266 Cvar_SetValue("r_fullbrights", 0);
267 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
270 vec3_t r_farclip_origin;
271 vec3_t r_farclip_direction;
272 vec_t r_farclip_directiondist;
273 vec_t r_farclip_meshfarclip;
274 int r_farclip_directionbit0;
275 int r_farclip_directionbit1;
276 int r_farclip_directionbit2;
278 // start a farclip measuring session
279 void R_FarClip_Start(vec3_t origin, vec3_t direction, vec_t startfarclip)
281 VectorCopy(origin, r_farclip_origin);
282 VectorCopy(direction, r_farclip_direction);
283 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
284 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
285 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
286 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
287 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
290 // enlarge farclip to accomodate box
291 void R_FarClip_Box(vec3_t mins, vec3_t maxs)
294 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
295 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
296 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
297 if (r_farclip_meshfarclip < d)
298 r_farclip_meshfarclip = d;
301 // return farclip value
302 float R_FarClip_Finish(void)
304 return r_farclip_meshfarclip - r_farclip_directiondist;
307 extern void R_Textures_Init(void);
308 extern void Mod_RenderInit(void);
309 extern void GL_Draw_Init(void);
310 extern void GL_Main_Init(void);
311 extern void R_Shadow_Init(void);
312 extern void GL_Models_Init(void);
313 extern void R_Sky_Init(void);
314 extern void GL_Surf_Init(void);
315 extern void R_Crosshairs_Init(void);
316 extern void R_Light_Init(void);
317 extern void R_Particles_Init(void);
318 extern void R_Explosion_Init(void);
319 extern void ui_init(void);
320 extern void gl_backend_init(void);
321 extern void Sbar_Init(void);
322 extern void R_LightningBeams_Init(void);
324 void Render_Init(void)
343 R_LightningBeams_Init();
351 extern char *ENGINE_EXTENSIONS;
354 VID_CheckExtensions();
356 // LordHavoc: report supported extensions
357 Con_DPrintf("\nengine extensions: %s\n", ENGINE_EXTENSIONS);
360 int R_CullBox(const vec3_t mins, const vec3_t maxs)
364 for (i = 0;i < 4;i++)
371 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
375 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
379 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
383 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
387 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
391 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
395 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
399 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
407 #define VIS_CullBox(mins,maxs) (R_CullBox((mins), (maxs)) || (cl.worldmodel && cl.worldmodel->brush.BoxTouchingPVS && !cl.worldmodel->brush.BoxTouchingPVS(cl.worldmodel, r_pvsbits, (mins), (maxs))))
409 //==================================================================================
411 static void R_MarkEntities (void)
414 entity_render_t *ent;
416 ent = &cl_entities[0].render;
417 Matrix4x4_CreateIdentity(&ent->matrix);
418 Matrix4x4_CreateIdentity(&ent->inversematrix);
421 R_FarClip_Box(cl.worldmodel->normalmins, cl.worldmodel->normalmaxs);
423 if (!r_drawentities.integer)
426 for (i = 0;i < r_refdef.numentities;i++)
428 ent = r_refdef.entities[i];
429 Mod_CheckLoaded(ent->model);
430 // some of the renderer still relies on origin...
431 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
432 // some of the renderer still relies on scale...
433 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
434 R_LerpAnimation(ent);
435 R_UpdateEntLights(ent);
436 if ((chase_active.integer || !(ent->flags & RENDER_EXTERIORMODEL))
437 && !VIS_CullBox(ent->mins, ent->maxs)
438 && (!envmap || !(ent->flags & (RENDER_VIEWMODEL | RENDER_EXTERIORMODEL))))
440 ent->visframe = r_framecount;
441 R_FarClip_Box(ent->mins, ent->maxs);
446 // only used if skyrendermasked, and normally returns false
447 int R_DrawBrushModelsSky (void)
450 entity_render_t *ent;
452 if (!r_drawentities.integer)
456 for (i = 0;i < r_refdef.numentities;i++)
458 ent = r_refdef.entities[i];
459 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
461 ent->model->DrawSky(ent);
474 void R_DrawViewModel (void)
476 entity_render_t *ent;
478 // FIXME: move these checks to client
479 if (!r_drawviewmodel.integer || chase_active.integer || envmap || !r_drawentities.integer || cl.items & IT_INVISIBILITY || cl.stats[STAT_HEALTH] <= 0 || !cl.viewent.render.model)
482 ent = &cl.viewent.render;
483 Mod_CheckLoaded(ent->model);
484 R_LerpAnimation(ent);
485 Matrix4x4_CreateFromQuakeEntity(&ent->matrix, ent->origin[0], ent->origin[1], ent->origin[2], -ent->angles[0], ent->angles[1], ent->angles[2], ent->scale);
486 Matrix4x4_Invert_Simple(&ent->inversematrix, &ent->matrix);
487 R_UpdateEntLights(ent);
488 ent->model->Draw(ent);
492 void R_DrawNoModel(entity_render_t *ent);
493 void R_DrawModels(void)
496 entity_render_t *ent;
498 if (!r_drawentities.integer)
501 for (i = 0;i < r_refdef.numentities;i++)
503 ent = r_refdef.entities[i];
504 if (ent->visframe == r_framecount)
506 if (ent->model && ent->model->Draw != NULL)
507 ent->model->Draw(ent);
514 #include "r_shadow.h"
516 int shadowframecount = 0;
518 void R_TestAndDrawShadowVolume(entity_render_t *ent, vec3_t lightorigin, float cullradius, float lightradius, vec3_t lightmins, vec3_t lightmaxs, vec3_t clipmins, vec3_t clipmaxs, int lightmarked)
520 vec3_t relativelightorigin;
522 if ((ent->flags & RENDER_SHADOW) && ent->model && ent->model->DrawShadowVolume && !(r_shadow_cull.integer && (ent->maxs[0] < lightmins[0] || ent->mins[0] > lightmaxs[0] || ent->maxs[1] < lightmins[1] || ent->mins[1] > lightmaxs[1] || ent->maxs[2] < lightmins[2] || ent->mins[2] > lightmaxs[2])))
524 Matrix4x4_Transform(&ent->inversematrix, lightorigin, relativelightorigin);
525 ent->model->DrawShadowVolume (ent, relativelightorigin, lightradius);
529 void R_Shadow_DrawWorldLightShadowVolume(matrix4x4_t *matrix, worldlight_t *light);
531 void R_ShadowVolumeLighting(int visiblevolumes)
534 entity_render_t *ent;
536 float f, lightradius, cullradius;
537 vec3_t relativelightorigin, relativeeyeorigin, lightcolor, clipmins, clipmaxs;
541 rtexture_t *cubemaptexture;
542 matrix4x4_t matrix_modeltolight, 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->radius;
574 VectorCopy(wl->mins, clipmins);
575 VectorCopy(wl->maxs, clipmaxs);
577 f = d_lightstylevalue[wl->style] * (1.0f / 256.0f);
578 VectorScale(wl->color, f, lightcolor);
581 f = 2 + sin(realtime * M_PI * 4.0);
582 VectorScale(lightcolor, f, lightcolor);
585 if (r_shadow_worldshadows.integer && wl->drawshadows && (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 (r_shadow_worldshadows.integer && wl->drawshadows && gl_stencil)
602 R_Shadow_Stage_LightWithShadows();
604 R_Shadow_Stage_LightWithoutShadows();
606 ent = &cl_entities[0].render;
607 if (ent->model && ent->model->DrawLight)
609 Matrix4x4_Transform(&ent->inversematrix, wl->origin, relativelightorigin);
610 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, relativeeyeorigin);
611 Matrix4x4_Concat(&matrix_modeltolight, &wl->matrix_worldtolight, &ent->matrix);
612 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &wl->matrix_worldtoattenuationxyz, &ent->matrix);
613 Matrix4x4_Concat(&matrix_modeltoattenuationz, &wl->matrix_worldtoattenuationz, &ent->matrix);
614 if (r_shadow_staticworldlights.integer)
615 R_Shadow_DrawStaticWorldLight_Light(wl, &ent->matrix, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, &matrix_modeltolight, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
617 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltolight, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz, wl->cubemap);
619 if (r_drawentities.integer)
621 for (i = 0;i < r_refdef.numentities;i++)
623 ent = r_refdef.entities[i];
624 if (ent->visframe == r_framecount && ent->model && ent->model->DrawLight
625 && BoxesOverlap(ent->mins, ent->maxs, clipmins, clipmaxs)
626 && !(ent->effects & EF_ADDITIVE) && ent->alpha == 1)
628 Matrix4x4_Transform(&ent->inversematrix, wl->origin, relativelightorigin);
629 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, relativeeyeorigin);
630 Matrix4x4_Concat(&matrix_modeltolight, &wl->matrix_worldtolight, &ent->matrix);
631 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &wl->matrix_worldtoattenuationxyz, &ent->matrix);
632 Matrix4x4_Concat(&matrix_modeltoattenuationz, &wl->matrix_worldtoattenuationz, &ent->matrix);
633 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltolight, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz, wl->cubemap);
640 if (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer)
642 for (lnum = 0, rd = r_dlight;lnum < r_numdlights;lnum++, rd++)
644 lightradius = rd->radius;
645 clipmins[0] = rd->origin[0] - lightradius;
646 clipmins[1] = rd->origin[1] - lightradius;
647 clipmins[2] = rd->origin[2] - lightradius;
648 clipmaxs[0] = rd->origin[0] + lightradius;
649 clipmaxs[1] = rd->origin[1] + lightradius;
650 clipmaxs[2] = rd->origin[2] + lightradius;
651 if (VIS_CullBox(clipmins, clipmaxs) || R_Shadow_ScissorForBBox(clipmins, clipmaxs))
654 cullradius = RadiusFromBoundsAndOrigin(clipmins, clipmaxs, rd->origin);
655 VectorCopy(rd->color, lightcolor);
657 if (rd->cubemapnum > 0)
658 cubemaptexture = R_Shadow_Cubemap(va("cubemaps/%i", rd->cubemapnum));
660 cubemaptexture = NULL;
662 if (r_shadow_dlightshadows.integer && rd->shadow && (gl_stencil || visiblevolumes))
665 R_Shadow_Stage_ShadowVolumes();
666 ent = &cl_entities[0].render;
667 R_TestAndDrawShadowVolume(ent, rd->origin, cullradius, lightradius, clipmins, clipmaxs, clipmins, clipmaxs, false);
668 if (r_drawentities.integer)
670 for (i = 0;i < r_refdef.numentities;i++)
672 ent = r_refdef.entities[i];
674 R_TestAndDrawShadowVolume(ent, rd->origin, cullradius, lightradius, clipmins, clipmaxs, clipmins, clipmaxs, false);
681 if (r_shadow_dlightshadows.integer && gl_stencil && rd->shadow)
682 R_Shadow_Stage_LightWithShadows();
684 R_Shadow_Stage_LightWithoutShadows();
686 ent = &cl_entities[0].render;
687 if (ent->model && ent->model->DrawLight)
689 Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin);
690 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, relativeeyeorigin);
691 Matrix4x4_Concat(&matrix_modeltolight, &rd->matrix_worldtolight, &ent->matrix);
692 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &rd->matrix_worldtoattenuationxyz, &ent->matrix);
693 Matrix4x4_Concat(&matrix_modeltoattenuationz, &rd->matrix_worldtoattenuationz, &ent->matrix);
694 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltolight, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz, cubemaptexture);
696 if (r_drawentities.integer)
698 for (i = 0;i < r_refdef.numentities;i++)
700 ent = r_refdef.entities[i];
701 if (ent->visframe == r_framecount && ent->model && ent->model->DrawLight
702 && BoxesOverlap(ent->mins, ent->maxs, clipmins, clipmaxs)
703 && !(ent->effects & EF_ADDITIVE) && ent->alpha == 1)
705 Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin);
706 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, relativeeyeorigin);
707 Matrix4x4_Concat(&matrix_modeltolight, &rd->matrix_worldtolight, &ent->matrix);
708 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &rd->matrix_worldtoattenuationxyz, &ent->matrix);
709 Matrix4x4_Concat(&matrix_modeltoattenuationz, &rd->matrix_worldtoattenuationz, &ent->matrix);
710 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltolight, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz, cubemaptexture);
720 qglEnable(GL_CULL_FACE);
721 qglDisable(GL_SCISSOR_TEST);
724 R_Shadow_Stage_End();
727 static void R_SetFrustum (void)
729 // LordHavoc: note to all quake engine coders, the special case for 90
730 // degrees assumed a square view (wrong), so I removed it, Quake2 has it
733 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
734 RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_refdef.fov_x / 2));
735 frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
736 PlaneClassify(&frustum[0]);
738 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
739 RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_refdef.fov_x / 2));
740 frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
741 PlaneClassify(&frustum[1]);
743 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
744 RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_refdef.fov_y / 2));
745 frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
746 PlaneClassify(&frustum[2]);
748 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
749 RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_refdef.fov_y / 2));
750 frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
751 PlaneClassify(&frustum[3]);
759 static void R_SetupFrame (void)
761 // don't allow cheats in multiplayer
764 if (r_fullbright.integer != 0)
765 Cvar_Set ("r_fullbright", "0");
766 if (r_ambient.value != 0)
767 Cvar_Set ("r_ambient", "0");
772 // break apart the viewentity matrix into vectors for various purposes
773 Matrix4x4_ToVectors(&r_refdef.viewentitymatrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
774 VectorNegate(r_viewleft, r_viewright);
776 GL_SetupView_ViewPort(r_refdef.x, r_refdef.y, r_refdef.width, r_refdef.height);
782 static void R_BlendView(void)
788 if (r_refdef.viewblend[3] < 0.01f)
791 R_Mesh_Matrix(&r_identitymatrix);
793 memset(&m, 0, sizeof(m));
794 R_Mesh_State_Texture(&m);
796 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
798 GL_DepthTest(false); // magic
799 GL_VertexPointer(vertex3f);
800 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
802 vertex3f[0] = r_vieworigin[0] + r_viewforward[0] * 1.5 + r_viewleft[0] * r - r_viewup[0] * r;
803 vertex3f[1] = r_vieworigin[1] + r_viewforward[1] * 1.5 + r_viewleft[1] * r - r_viewup[1] * r;
804 vertex3f[2] = r_vieworigin[2] + r_viewforward[2] * 1.5 + r_viewleft[2] * r - r_viewup[2] * r;
805 vertex3f[3] = r_vieworigin[0] + r_viewforward[0] * 1.5 + r_viewleft[0] * r + r_viewup[0] * r * 3;
806 vertex3f[4] = r_vieworigin[1] + r_viewforward[1] * 1.5 + r_viewleft[1] * r + r_viewup[1] * r * 3;
807 vertex3f[5] = r_vieworigin[2] + r_viewforward[2] * 1.5 + r_viewleft[2] * r + r_viewup[2] * r * 3;
808 vertex3f[6] = r_vieworigin[0] + r_viewforward[0] * 1.5 - r_viewleft[0] * r * 3 - r_viewup[0] * r;
809 vertex3f[7] = r_vieworigin[1] + r_viewforward[1] * 1.5 - r_viewleft[1] * r * 3 - r_viewup[1] * r;
810 vertex3f[8] = r_vieworigin[2] + r_viewforward[2] * 1.5 - r_viewleft[2] * r * 3 - r_viewup[2] * r;
811 R_Mesh_Draw(3, 1, polygonelements);
818 r_refdef must be set before the first call
821 extern void R_DrawLightningBeams (void);
822 void R_RenderView (void)
824 entity_render_t *world;
825 if (!r_refdef.entities/* || !cl.worldmodel*/)
826 return; //Host_Error ("R_RenderView: NULL worldmodel");
828 if (r_shadow_realtime_world.integer)
832 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");
833 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
837 world = &cl_entities[0].render;
839 // FIXME: move to client
841 R_TimeReport("mexplosion");
843 qglPolygonOffset(0, 0);
844 qglEnable(GL_POLYGON_OFFSET_FILL);
852 R_TimeReport("setup");
854 if (cl.worldmodel && cl.worldmodel->brush.FatPVS)
855 cl.worldmodel->brush.FatPVS(cl.worldmodel, r_vieworigin, 2, r_pvsbits, sizeof(r_pvsbits));
857 R_WorldVisibility(world);
858 R_TimeReport("worldvis");
860 R_FarClip_Start(r_vieworigin, r_viewforward, 768.0f);
862 r_farclip = R_FarClip_Finish() + 256.0f;
863 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)))
864 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.fov_x, r_refdef.fov_y, 1.0f);
866 GL_SetupView_Mode_Perspective(r_refdef.fov_x, r_refdef.fov_y, 1.0f, r_farclip);
867 GL_SetupView_Orientation_FromEntity(&r_refdef.viewentitymatrix);
868 R_TimeReport("markentity");
870 qglDepthFunc(GL_LEQUAL);
873 R_MeshQueue_BeginScene();
875 R_Shadow_UpdateWorldLightSelection();
877 if (R_DrawBrushModelsSky())
878 R_TimeReport("bmodelsky");
880 // must occur early because it can draw sky
882 R_TimeReport("world");
884 // don't let sound skip if going slow
885 if (!intimerefresh && !r_speeds.integer)
889 R_TimeReport("models");
891 R_ShadowVolumeLighting(false);
892 R_TimeReport("rtlights");
894 R_DrawLightningBeams();
895 R_TimeReport("lightning");
898 R_TimeReport("particles");
901 R_TimeReport("explosions");
903 R_MeshQueue_RenderTransparent();
904 R_TimeReport("drawtrans");
907 R_TimeReport("coronas");
909 R_DrawWorldCrosshair();
910 R_TimeReport("crosshair");
913 R_TimeReport("blendview");
915 R_MeshQueue_Render();
916 R_MeshQueue_EndScene();
918 if (r_shadow_visiblevolumes.integer)
920 R_ShadowVolumeLighting(true);
921 R_TimeReport("shadowvolume");
925 R_TimeReport("meshfinish");
927 qglPolygonOffset(0, 0);
928 qglDisable(GL_POLYGON_OFFSET_FILL);
932 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
935 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
937 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
940 R_Mesh_Matrix(&r_identitymatrix);
942 memset(&m, 0, sizeof(m));
943 R_Mesh_State_Texture(&m);
946 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
947 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
948 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
949 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
950 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
951 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
952 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
953 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
954 GL_ColorPointer(color);
955 R_FillColors(color, 8, cr, cg, cb, ca);
958 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
960 VectorSubtract(v, r_vieworigin, diff);
961 f2 = exp(fogdensity/DotProduct(diff, diff));
963 c[0] = c[0] * f1 + fogcolor[0] * f2;
964 c[1] = c[1] * f1 + fogcolor[1] * f2;
965 c[2] = c[2] * f1 + fogcolor[2] * f2;
972 int nomodelelements[24] =
984 float nomodelvertex3f[6*3] =
994 float nomodelcolor4f[6*4] =
996 0.0f, 0.0f, 0.5f, 1.0f,
997 0.0f, 0.0f, 0.5f, 1.0f,
998 0.0f, 0.5f, 0.0f, 1.0f,
999 0.0f, 0.5f, 0.0f, 1.0f,
1000 0.5f, 0.0f, 0.0f, 1.0f,
1001 0.5f, 0.0f, 0.0f, 1.0f
1004 void R_DrawNoModelCallback(const void *calldata1, int calldata2)
1006 const entity_render_t *ent = calldata1;
1008 float f1, f2, *c, diff[3];
1011 R_Mesh_Matrix(&ent->matrix);
1013 memset(&m, 0, sizeof(m));
1014 R_Mesh_State_Texture(&m);
1016 if (ent->flags & EF_ADDITIVE)
1018 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1019 GL_DepthMask(false);
1021 else if (ent->alpha < 1)
1023 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1024 GL_DepthMask(false);
1028 GL_BlendFunc(GL_ONE, GL_ZERO);
1032 GL_VertexPointer(nomodelvertex3f);
1035 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1036 GL_ColorPointer(color4f);
1037 VectorSubtract(ent->origin, r_vieworigin, diff);
1038 f2 = exp(fogdensity/DotProduct(diff, diff));
1040 for (i = 0, c = color4f;i < 6;i++, c += 4)
1042 c[0] = (c[0] * f1 + fogcolor[0] * f2);
1043 c[1] = (c[1] * f1 + fogcolor[1] * f2);
1044 c[2] = (c[2] * f1 + fogcolor[2] * f2);
1048 else if (ent->alpha != 1)
1050 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1051 GL_ColorPointer(color4f);
1052 for (i = 0, c = color4f;i < 6;i++, c += 4)
1056 GL_ColorPointer(nomodelcolor4f);
1057 R_Mesh_Draw(6, 8, nomodelelements);
1060 void R_DrawNoModel(entity_render_t *ent)
1062 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1063 R_MeshQueue_AddTransparent(ent->origin, R_DrawNoModelCallback, ent, 0);
1065 // R_DrawNoModelCallback(ent, 0);
1068 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1070 vec3_t right1, right2, diff, normal;
1072 VectorSubtract (org2, org1, normal);
1073 VectorNormalizeFast (normal);
1075 // calculate 'right' vector for start
1076 VectorSubtract (r_vieworigin, org1, diff);
1077 VectorNormalizeFast (diff);
1078 CrossProduct (normal, diff, right1);
1080 // calculate 'right' vector for end
1081 VectorSubtract (r_vieworigin, org2, diff);
1082 VectorNormalizeFast (diff);
1083 CrossProduct (normal, diff, right2);
1085 vert[ 0] = org1[0] + width * right1[0];
1086 vert[ 1] = org1[1] + width * right1[1];
1087 vert[ 2] = org1[2] + width * right1[2];
1088 vert[ 3] = org1[0] - width * right1[0];
1089 vert[ 4] = org1[1] - width * right1[1];
1090 vert[ 5] = org1[2] - width * right1[2];
1091 vert[ 6] = org2[0] - width * right2[0];
1092 vert[ 7] = org2[1] - width * right2[1];
1093 vert[ 8] = org2[2] - width * right2[2];
1094 vert[ 9] = org2[0] + width * right2[0];
1095 vert[10] = org2[1] + width * right2[1];
1096 vert[11] = org2[2] + width * right2[2];
1099 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
1101 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)
1108 VectorSubtract(origin, r_vieworigin, diff);
1109 ca *= 1 - exp(fogdensity/DotProduct(diff,diff));
1112 R_Mesh_Matrix(&r_identitymatrix);
1113 GL_Color(cr, cg, cb, ca);
1114 GL_VertexPointer(varray_vertex3f);
1115 GL_BlendFunc(blendfunc1, blendfunc2);
1116 GL_DepthMask(false);
1117 GL_DepthTest(!depthdisable);
1119 memset(&m, 0, sizeof(m));
1120 m.tex[0] = R_GetTexture(texture);
1121 m.pointer_texcoord[0] = spritetexcoord2f;
1122 R_Mesh_State_Texture(&m);
1124 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
1125 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
1126 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
1127 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
1128 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
1129 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
1130 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
1131 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
1132 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
1133 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
1134 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
1135 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
1136 R_Mesh_Draw(4, 2, polygonelements);