2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 // used for dlight push checking and other things
27 // used for visibility checking
28 qbyte r_pvsbits[(MAX_MAP_LEAFS+7)>>3];
32 matrix4x4_t r_identitymatrix;
34 int c_alias_polys, c_light_polys, c_faces, c_nodes, c_leafs, c_models, c_bmodels, c_sprites, c_particles, c_dlights;
36 // true during envmap command capture
52 // 8.8 fraction of base light value
53 unsigned short d_lightstylevalue[256];
55 cvar_t r_drawentities = {0, "r_drawentities","1"};
56 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1"};
57 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0"};
58 cvar_t r_shadow_staticworldlights = {0, "r_shadow_staticworldlights", "1"};
59 cvar_t r_speeds = {0, "r_speeds","0"};
60 cvar_t r_fullbright = {0, "r_fullbright","0"};
61 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1"};
62 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1"};
63 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1"};
64 cvar_t r_shadow_cull = {0, "r_shadow_cull", "1"};
65 cvar_t r_drawcollisionbrushes = {0, "r_drawcollisionbrushes", "0"};
67 cvar_t gl_fogenable = {0, "gl_fogenable", "0"};
68 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25"};
69 cvar_t gl_fogred = {0, "gl_fogred","0.3"};
70 cvar_t gl_foggreen = {0, "gl_foggreen","0.3"};
71 cvar_t gl_fogblue = {0, "gl_fogblue","0.3"};
72 cvar_t gl_fogstart = {0, "gl_fogstart", "0"};
73 cvar_t gl_fogend = {0, "gl_fogend","0"};
75 cvar_t r_textureunits = {0, "r_textureunits", "32"};
77 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1"};
78 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1"};
79 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1"};
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 start, stop, time;
124 start = Sys_DoubleTime ();
125 for (i = 0;i < 128;i++)
127 r_refdef.viewangles[0] = 0;
128 r_refdef.viewangles[1] = i/128.0*360.0;
129 r_refdef.viewangles[2] = 0;
133 stop = Sys_DoubleTime ();
136 Con_Printf ("%f seconds (%f fps)\n", time, 128/time);
141 float fog_density, fog_red, fog_green, fog_blue;
143 qboolean oldgl_fogenable;
144 void R_SetupFog(void)
146 if (gamemode == GAME_NEHAHRA)
148 if (gl_fogenable.integer)
150 oldgl_fogenable = true;
151 fog_density = gl_fogdensity.value;
152 fog_red = gl_fogred.value;
153 fog_green = gl_foggreen.value;
154 fog_blue = gl_fogblue.value;
156 else if (oldgl_fogenable)
158 oldgl_fogenable = false;
167 fogcolor[0] = fog_red = bound(0.0f, fog_red , 1.0f);
168 fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
169 fogcolor[2] = fog_blue = bound(0.0f, fog_blue , 1.0f);
174 fogdensity = -4000.0f / (fog_density * fog_density);
175 // fog color was already set
181 // FIXME: move this to client?
184 if (gamemode == GAME_NEHAHRA)
186 Cvar_Set("gl_fogenable", "0");
187 Cvar_Set("gl_fogdensity", "0.2");
188 Cvar_Set("gl_fogred", "0.3");
189 Cvar_Set("gl_foggreen", "0.3");
190 Cvar_Set("gl_fogblue", "0.3");
192 fog_density = fog_red = fog_green = fog_blue = 0.0f;
195 // FIXME: move this to client?
196 void FOG_registercvars(void)
198 if (gamemode == GAME_NEHAHRA)
200 Cvar_RegisterVariable (&gl_fogenable);
201 Cvar_RegisterVariable (&gl_fogdensity);
202 Cvar_RegisterVariable (&gl_fogred);
203 Cvar_RegisterVariable (&gl_foggreen);
204 Cvar_RegisterVariable (&gl_fogblue);
205 Cvar_RegisterVariable (&gl_fogstart);
206 Cvar_RegisterVariable (&gl_fogend);
210 void gl_main_start(void)
214 void gl_main_shutdown(void)
218 extern void CL_ParseEntityLump(char *entitystring);
219 void gl_main_newmap(void)
222 char *entities, entname[MAX_QPATH];
226 strcpy(entname, cl.worldmodel->name);
227 l = strlen(entname) - 4;
228 if (l >= 0 && !strcmp(entname + l, ".bsp"))
230 strcpy(entname + l, ".ent");
231 if ((entities = FS_LoadFile(entname, true)))
233 CL_ParseEntityLump(entities);
238 if (cl.worldmodel->brush.entities)
239 CL_ParseEntityLump(cl.worldmodel->brush.entities);
243 void GL_Main_Init(void)
245 Matrix4x4_CreateIdentity(&r_identitymatrix);
246 // FIXME: move this to client?
248 Cmd_AddCommand("timerefresh", R_TimeRefresh_f);
249 Cvar_RegisterVariable(&r_drawentities);
250 Cvar_RegisterVariable(&r_drawviewmodel);
251 Cvar_RegisterVariable(&r_shadows);
252 Cvar_RegisterVariable(&r_shadow_staticworldlights);
253 Cvar_RegisterVariable(&r_speeds);
254 Cvar_RegisterVariable(&r_fullbrights);
255 Cvar_RegisterVariable(&r_wateralpha);
256 Cvar_RegisterVariable(&r_dynamic);
257 Cvar_RegisterVariable(&r_fullbright);
258 Cvar_RegisterVariable(&r_textureunits);
259 Cvar_RegisterVariable(&r_shadow_cull);
260 Cvar_RegisterVariable(&r_lerpsprites);
261 Cvar_RegisterVariable(&r_lerpmodels);
262 Cvar_RegisterVariable(&r_waterscroll);
263 Cvar_RegisterVariable(&r_watershader);
264 Cvar_RegisterVariable(&r_drawcollisionbrushes);
265 if (gamemode == GAME_NEHAHRA || gamemode == GAME_NEXUIZ)
266 Cvar_SetValue("r_fullbrights", 0);
267 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
270 vec3_t r_farclip_origin;
271 vec3_t r_farclip_direction;
272 vec_t r_farclip_directiondist;
273 vec_t r_farclip_meshfarclip;
274 int r_farclip_directionbit0;
275 int r_farclip_directionbit1;
276 int r_farclip_directionbit2;
278 // start a farclip measuring session
279 void R_FarClip_Start(vec3_t origin, vec3_t direction, vec_t startfarclip)
281 VectorCopy(origin, r_farclip_origin);
282 VectorCopy(direction, r_farclip_direction);
283 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
284 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
285 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
286 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
287 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
290 // enlarge farclip to accomodate box
291 void R_FarClip_Box(vec3_t mins, vec3_t maxs)
294 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
295 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
296 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
297 if (r_farclip_meshfarclip < d)
298 r_farclip_meshfarclip = d;
301 // return farclip value
302 float R_FarClip_Finish(void)
304 return r_farclip_meshfarclip - r_farclip_directiondist;
307 extern void R_Textures_Init(void);
308 extern void Mod_RenderInit(void);
309 extern void GL_Draw_Init(void);
310 extern void GL_Main_Init(void);
311 extern void R_Shadow_Init(void);
312 extern void GL_Models_Init(void);
313 extern void R_Sky_Init(void);
314 extern void GL_Surf_Init(void);
315 extern void R_Crosshairs_Init(void);
316 extern void R_Light_Init(void);
317 extern void R_Particles_Init(void);
318 extern void R_Explosion_Init(void);
319 extern void ui_init(void);
320 extern void gl_backend_init(void);
321 extern void Sbar_Init(void);
322 extern void R_LightningBeams_Init(void);
324 void Render_Init(void)
342 R_LightningBeams_Init();
350 extern char *ENGINE_EXTENSIONS;
353 VID_CheckExtensions();
355 // LordHavoc: report supported extensions
356 Con_DPrintf("\nengine extensions: %s\n", ENGINE_EXTENSIONS);
359 int R_CullBox(const vec3_t mins, const vec3_t maxs)
363 for (i = 0;i < 4;i++)
370 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
374 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
378 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
382 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
386 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
390 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
394 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
398 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
406 #define VIS_CullBox(mins,maxs) (R_CullBox((mins), (maxs)) || (cl.worldmodel && cl.worldmodel->brush.BoxTouchingPVS && !cl.worldmodel->brush.BoxTouchingPVS(cl.worldmodel, r_pvsbits, (mins), (maxs))))
408 //==================================================================================
410 static void R_MarkEntities (void)
413 entity_render_t *ent;
415 ent = &cl_entities[0].render;
416 Matrix4x4_CreateIdentity(&ent->matrix);
417 Matrix4x4_CreateIdentity(&ent->inversematrix);
420 R_FarClip_Box(cl.worldmodel->normalmins, cl.worldmodel->normalmaxs);
422 if (!r_drawentities.integer)
425 for (i = 0;i < r_refdef.numentities;i++)
427 ent = r_refdef.entities[i];
428 Mod_CheckLoaded(ent->model);
429 // some of the renderer still relies on origin...
430 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
431 // some of the renderer still relies on scale...
432 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
433 R_LerpAnimation(ent);
434 R_UpdateEntLights(ent);
435 if ((chase_active.integer || !(ent->flags & RENDER_EXTERIORMODEL))
436 && !VIS_CullBox(ent->mins, ent->maxs))
438 ent->visframe = r_framecount;
439 R_FarClip_Box(ent->mins, ent->maxs);
444 // only used if skyrendermasked, and normally returns false
445 int R_DrawBrushModelsSky (void)
448 entity_render_t *ent;
450 if (!r_drawentities.integer)
454 for (i = 0;i < r_refdef.numentities;i++)
456 ent = r_refdef.entities[i];
457 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
459 ent->model->DrawSky(ent);
472 void R_DrawViewModel (void)
474 entity_render_t *ent;
476 // FIXME: move these checks to client
477 if (!r_drawviewmodel.integer || chase_active.integer || envmap || !r_drawentities.integer || cl.items & IT_INVISIBILITY || cl.stats[STAT_HEALTH] <= 0 || !cl.viewent.render.model)
480 ent = &cl.viewent.render;
481 Mod_CheckLoaded(ent->model);
482 R_LerpAnimation(ent);
483 Matrix4x4_CreateFromQuakeEntity(&ent->matrix, ent->origin[0], ent->origin[1], ent->origin[2], -ent->angles[0], ent->angles[1], ent->angles[2], ent->scale);
484 Matrix4x4_Invert_Simple(&ent->inversematrix, &ent->matrix);
485 R_UpdateEntLights(ent);
486 ent->model->Draw(ent);
490 void R_DrawNoModel(entity_render_t *ent);
491 void R_DrawModels(void)
494 entity_render_t *ent;
496 if (!r_drawentities.integer)
499 for (i = 0;i < r_refdef.numentities;i++)
501 ent = r_refdef.entities[i];
502 if (ent->visframe == r_framecount)
504 if (ent->model && ent->model->Draw != NULL)
505 ent->model->Draw(ent);
512 void R_DrawFakeShadows(void)
515 entity_render_t *ent;
517 ent = &cl_entities[0].render;
518 if (ent->model && ent->model->DrawFakeShadow)
519 ent->model->DrawFakeShadow(ent);
521 if (!r_drawentities.integer)
523 for (i = 0;i < r_refdef.numentities;i++)
525 ent = r_refdef.entities[i];
526 if ((ent->flags & RENDER_SHADOW) && ent->model && ent->model->DrawFakeShadow)
527 ent->model->DrawFakeShadow(ent);
531 #include "r_shadow.h"
533 int shadowframecount = 0;
535 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)
537 vec3_t relativelightorigin;
539 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])))
541 Matrix4x4_Transform(&ent->inversematrix, lightorigin, relativelightorigin);
542 ent->model->DrawShadowVolume (ent, relativelightorigin, lightradius);
546 void R_Shadow_DrawWorldLightShadowVolume(matrix4x4_t *matrix, worldlight_t *light);
548 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);
549 void R_ShadowVolumeLighting(int visiblevolumes)
552 entity_render_t *ent;
554 float f, lightradius, cullradius;
555 vec3_t relativelightorigin, relativeeyeorigin, lightcolor, clipmins, clipmaxs;
560 matrix4x4_t matrix_worldtofilter, matrix_worldtoattenuationxyz, matrix_worldtoattenuationz;
561 matrix4x4_t matrix_modeltofilter, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz;
565 memset(&m, 0, sizeof(m));
566 R_Mesh_State_Texture(&m);
568 GL_BlendFunc(GL_ONE, GL_ONE);
570 GL_DepthTest(r_shadow_visiblevolumes.integer < 2);
571 qglDisable(GL_CULL_FACE);
572 GL_Color(0.0, 0.0125, 0.1, 1);
575 R_Shadow_Stage_Begin();
577 if (r_shadow_realtime_world.integer)
579 R_Shadow_LoadWorldLightsIfNeeded();
580 for (lnum = 0, wl = r_shadow_worldlightchain;wl;wl = wl->next, lnum++)
582 if (d_lightstylevalue[wl->style] <= 0)
584 if (VIS_CullBox(wl->mins, wl->maxs))
586 if (r_shadow_debuglight.integer >= 0 && lnum != r_shadow_debuglight.integer)
588 if (R_Shadow_ScissorForBBox(wl->mins, wl->maxs))
591 cullradius = wl->cullradius;
592 lightradius = wl->lightradius;
593 VectorCopy(wl->mins, clipmins);
594 VectorCopy(wl->maxs, clipmaxs);
596 f = d_lightstylevalue[wl->style] * (1.0f / 256.0f);
597 VectorScale(wl->light, f, lightcolor);
600 f = 2 + sin(realtime * M_PI * 4.0);
601 VectorScale(lightcolor, f, lightcolor);
604 if (wl->castshadows && (gl_stencil || visiblevolumes))
607 R_Shadow_Stage_ShadowVolumes();
608 ent = &cl_entities[0].render;
609 if (wl->shadowvolume && r_shadow_staticworldlights.integer)
610 R_Shadow_DrawWorldLightShadowVolume(&ent->matrix, wl);
612 R_TestAndDrawShadowVolume(ent, wl->origin, cullradius, lightradius, wl->mins, wl->maxs, clipmins, clipmaxs, true);
613 if (r_drawentities.integer)
614 for (i = 0;i < r_refdef.numentities;i++)
615 R_TestAndDrawShadowVolume(r_refdef.entities[i], wl->origin, cullradius, lightradius, wl->mins, wl->maxs, clipmins, clipmaxs, true);
620 if (wl->castshadows && gl_stencil)
621 R_Shadow_Stage_LightWithShadows();
623 R_Shadow_Stage_LightWithoutShadows();
625 // calculate world to filter matrix
626 Matrix4x4_CreateFromQuakeEntity(&matrix, wl->origin[0], wl->origin[1], wl->origin[2], wl->angles[0], wl->angles[1], wl->angles[2], lightradius);
627 Matrix4x4_Invert_Simple(&matrix_worldtofilter, &matrix);
628 // calculate world to attenuationxyz/xy matrix
629 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5, 0.5, 0.5, 0, 0, 0, 0.5);
630 Matrix4x4_Concat(&matrix_worldtoattenuationxyz, &matrix, &matrix_worldtofilter);
631 // calculate world to attenuationz matrix
632 matrix.m[0][0] = 0;matrix.m[0][1] = 0;matrix.m[0][2] = 0.5;matrix.m[0][3] = 0.5;
633 matrix.m[1][0] = 0;matrix.m[1][1] = 0;matrix.m[1][2] = 0 ;matrix.m[1][3] = 0.5;
634 matrix.m[2][0] = 0;matrix.m[2][1] = 0;matrix.m[2][2] = 0 ;matrix.m[2][3] = 0.5;
635 matrix.m[3][0] = 0;matrix.m[3][1] = 0;matrix.m[3][2] = 0 ;matrix.m[3][3] = 1;
636 Matrix4x4_Concat(&matrix_worldtoattenuationz, &matrix, &matrix_worldtofilter);
638 ent = &cl_entities[0].render;
639 if (ent->model && ent->model->DrawLight)
641 Matrix4x4_Transform(&ent->inversematrix, wl->origin, relativelightorigin);
642 Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin);
643 Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
644 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
645 Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
647 R_Model_Brush_DrawLightForSurfaceList(ent, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, wl->surfaces, wl->numsurfaces, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
649 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
651 if (r_drawentities.integer)
653 for (i = 0;i < r_refdef.numentities;i++)
655 ent = r_refdef.entities[i];
656 if (ent->visframe == r_framecount && ent->model && ent->model->DrawLight
657 && BoxesOverlap(ent->mins, ent->maxs, clipmins, clipmaxs)
658 && !(ent->effects & EF_ADDITIVE) && ent->alpha == 1)
660 Matrix4x4_Transform(&ent->inversematrix, wl->origin, relativelightorigin);
661 Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin);
662 Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
663 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
664 Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
665 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
672 if (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer)
674 for (lnum = 0, rd = r_dlight;lnum < r_numdlights;lnum++, rd++)
676 lightradius = rd->cullradius;
677 clipmins[0] = rd->origin[0] - lightradius;
678 clipmins[1] = rd->origin[1] - lightradius;
679 clipmins[2] = rd->origin[2] - lightradius;
680 clipmaxs[0] = rd->origin[0] + lightradius;
681 clipmaxs[1] = rd->origin[1] + lightradius;
682 clipmaxs[2] = rd->origin[2] + lightradius;
683 if (VIS_CullBox(clipmins, clipmaxs) || R_Shadow_ScissorForBBox(clipmins, clipmaxs))
686 cullradius = RadiusFromBoundsAndOrigin(clipmins, clipmaxs, rd->origin);
687 VectorScale(rd->light, (1.0f / 4096.0f), lightcolor);
689 if (gl_stencil || visiblevolumes)
692 R_Shadow_Stage_ShadowVolumes();
693 ent = &cl_entities[0].render;
694 R_TestAndDrawShadowVolume(ent, rd->origin, cullradius, lightradius, clipmins, clipmaxs, clipmins, clipmaxs, false);
695 if (r_drawentities.integer)
697 for (i = 0;i < r_refdef.numentities;i++)
699 ent = r_refdef.entities[i];
701 R_TestAndDrawShadowVolume(ent, rd->origin, cullradius, lightradius, clipmins, clipmaxs, clipmins, clipmaxs, false);
709 R_Shadow_Stage_LightWithShadows();
711 R_Shadow_Stage_LightWithoutShadows();
713 // calculate world to filter matrix
714 Matrix4x4_CreateFromQuakeEntity(&matrix, rd->origin[0], rd->origin[1], rd->origin[2], 0, 0, 0, lightradius);
715 Matrix4x4_Invert_Simple(&matrix_worldtofilter, &matrix);
716 // calculate world to attenuationxyz/xy matrix
717 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5, 0.5, 0.5, 0, 0, 0, 0.5);
718 Matrix4x4_Concat(&matrix_worldtoattenuationxyz, &matrix, &matrix_worldtofilter);
719 // calculate world to attenuationz matrix
720 matrix.m[0][0] = 0;matrix.m[0][1] = 0;matrix.m[0][2] = 0.5;matrix.m[0][3] = 0.5;
721 matrix.m[1][0] = 0;matrix.m[1][1] = 0;matrix.m[1][2] = 0 ;matrix.m[1][3] = 0.5;
722 matrix.m[2][0] = 0;matrix.m[2][1] = 0;matrix.m[2][2] = 0 ;matrix.m[2][3] = 0.5;
723 matrix.m[3][0] = 0;matrix.m[3][1] = 0;matrix.m[3][2] = 0 ;matrix.m[3][3] = 1;
724 Matrix4x4_Concat(&matrix_worldtoattenuationz, &matrix, &matrix_worldtofilter);
726 ent = &cl_entities[0].render;
727 if (ent->model && ent->model->DrawLight)
729 Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin);
730 Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin);
731 Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
732 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
733 Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
734 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
736 if (r_drawentities.integer)
738 for (i = 0;i < r_refdef.numentities;i++)
740 ent = r_refdef.entities[i];
741 if (ent->visframe == r_framecount && ent->model && ent->model->DrawLight
742 && BoxesOverlap(ent->mins, ent->maxs, clipmins, clipmaxs)
743 && !(ent->effects & EF_ADDITIVE) && ent->alpha == 1)
745 Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin);
746 Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin);
747 Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
748 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
749 Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
750 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
759 qglEnable(GL_CULL_FACE);
761 R_Shadow_Stage_End();
762 qglDisable(GL_SCISSOR_TEST);
765 static void R_SetFrustum (void)
767 // LordHavoc: note to all quake engine coders, the special case for 90
768 // degrees assumed a square view (wrong), so I removed it, Quake2 has it
771 // rotate VPN right by FOV_X/2 degrees
772 RotatePointAroundVector( frustum[0].normal, vup, vpn, -(90-r_refdef.fov_x / 2 ) );
773 frustum[0].dist = DotProduct (r_origin, frustum[0].normal);
774 PlaneClassify(&frustum[0]);
776 // rotate VPN left by FOV_X/2 degrees
777 RotatePointAroundVector( frustum[1].normal, vup, vpn, 90-r_refdef.fov_x / 2 );
778 frustum[1].dist = DotProduct (r_origin, frustum[1].normal);
779 PlaneClassify(&frustum[1]);
781 // rotate VPN up by FOV_X/2 degrees
782 RotatePointAroundVector( frustum[2].normal, vright, vpn, 90-r_refdef.fov_y / 2 );
783 frustum[2].dist = DotProduct (r_origin, frustum[2].normal);
784 PlaneClassify(&frustum[2]);
786 // rotate VPN down by FOV_X/2 degrees
787 RotatePointAroundVector( frustum[3].normal, vright, vpn, -( 90 - r_refdef.fov_y / 2 ) );
788 frustum[3].dist = DotProduct (r_origin, frustum[3].normal);
789 PlaneClassify(&frustum[3]);
797 static void R_SetupFrame (void)
799 // don't allow cheats in multiplayer
802 if (r_fullbright.integer != 0)
803 Cvar_Set ("r_fullbright", "0");
804 if (r_ambient.value != 0)
805 Cvar_Set ("r_ambient", "0");
810 // build the transformation matrix for the given view angles
811 VectorCopy (r_refdef.vieworg, r_origin);
813 AngleVectors (r_refdef.viewangles, vpn, vright, vup);
819 static void R_BlendView(void)
825 if (r_refdef.viewblend[3] < 0.01f)
828 R_Mesh_Matrix(&r_identitymatrix);
830 memset(&m, 0, sizeof(m));
831 R_Mesh_State_Texture(&m);
833 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
835 GL_DepthTest(false); // magic
836 GL_VertexPointer(vertex3f);
837 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
839 vertex3f[0] = r_origin[0] + vpn[0] * 1.5 - vright[0] * r - vup[0] * r;
840 vertex3f[1] = r_origin[1] + vpn[1] * 1.5 - vright[1] * r - vup[1] * r;
841 vertex3f[2] = r_origin[2] + vpn[2] * 1.5 - vright[2] * r - vup[2] * r;
842 vertex3f[3] = r_origin[0] + vpn[0] * 1.5 - vright[0] * r + vup[0] * r * 3;
843 vertex3f[4] = r_origin[1] + vpn[1] * 1.5 - vright[1] * r + vup[1] * r * 3;
844 vertex3f[5] = r_origin[2] + vpn[2] * 1.5 - vright[2] * r + vup[2] * r * 3;
845 vertex3f[6] = r_origin[0] + vpn[0] * 1.5 + vright[0] * r * 3 - vup[0] * r;
846 vertex3f[7] = r_origin[1] + vpn[1] * 1.5 + vright[1] * r * 3 - vup[1] * r;
847 vertex3f[8] = r_origin[2] + vpn[2] * 1.5 + vright[2] * r * 3 - vup[2] * r;
848 R_Mesh_Draw(3, 1, polygonelements);
855 r_refdef must be set before the first call
858 extern void R_DrawLightningBeams (void);
859 void R_RenderView (void)
861 entity_render_t *world;
862 if (!r_refdef.entities/* || !cl.worldmodel*/)
863 return; //Host_Error ("R_RenderView: NULL worldmodel");
865 if (r_shadow_realtime_world.integer)
869 Con_Printf("Stencil not enabled, turning off r_shadow_realtime_world, please type vid_stencil 1;vid_bitsperpixel 32;vid_restart and try again\n");
870 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
874 world = &cl_entities[0].render;
876 // FIXME: move to client
878 R_TimeReport("mexplosion");
886 R_TimeReport("setup");
888 if (cl.worldmodel && cl.worldmodel->brush.FatPVS)
889 cl.worldmodel->brush.FatPVS(cl.worldmodel, r_origin, 2, r_pvsbits, sizeof(r_pvsbits));
891 R_WorldVisibility(world);
892 R_TimeReport("worldvis");
894 R_FarClip_Start(r_origin, vpn, 768.0f);
896 r_farclip = R_FarClip_Finish() + 256.0f;
897 R_TimeReport("markentity");
899 GL_SetupView_ViewPort(r_refdef.x, r_refdef.y, r_refdef.width, r_refdef.height);
900 if (r_shadow_realtime_world.integer || gl_stencil)
901 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.fov_x, r_refdef.fov_y, 1.0f);
903 GL_SetupView_Mode_Perspective(r_refdef.fov_x, r_refdef.fov_y, 1.0f, r_farclip);
904 GL_SetupView_Orientation_FromEntity (r_refdef.vieworg, r_refdef.viewangles);
905 qglDepthFunc(GL_LEQUAL);
908 R_MeshQueue_BeginScene();
910 R_Shadow_UpdateWorldLightSelection();
912 if (R_DrawBrushModelsSky())
913 R_TimeReport("bmodelsky");
915 // must occur early because it can draw sky
917 R_TimeReport("world");
919 // don't let sound skip if going slow
920 if (!intimerefresh && !r_speeds.integer)
924 R_TimeReport("models");
926 if (r_shadows.integer == 1 && !r_shadow_realtime_world.integer)
929 R_TimeReport("fakeshadow");
932 if (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer)
934 R_ShadowVolumeLighting(false);
935 R_TimeReport("dynlight");
938 R_DrawLightningBeams();
939 R_TimeReport("lightning");
942 R_TimeReport("particles");
945 R_TimeReport("explosions");
947 R_MeshQueue_RenderTransparent();
948 R_TimeReport("drawtrans");
951 R_TimeReport("coronas");
953 R_DrawWorldCrosshair();
954 R_TimeReport("crosshair");
957 R_TimeReport("blendview");
959 R_MeshQueue_Render();
960 R_MeshQueue_EndScene();
962 if (r_shadow_visiblevolumes.integer)
964 R_ShadowVolumeLighting(true);
965 R_TimeReport("shadowvolume");
969 R_TimeReport("meshfinish");
973 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
976 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
978 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
981 R_Mesh_Matrix(&r_identitymatrix);
983 memset(&m, 0, sizeof(m));
984 R_Mesh_State_Texture(&m);
987 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
988 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
989 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
990 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
991 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
992 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
993 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
994 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
995 GL_ColorPointer(color);
996 R_FillColors(color, 8, cr, cg, cb, ca);
999 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1001 VectorSubtract(v, r_origin, diff);
1002 f2 = exp(fogdensity/DotProduct(diff, diff));
1004 c[0] = c[0] * f1 + fogcolor[0] * f2;
1005 c[1] = c[1] * f1 + fogcolor[1] * f2;
1006 c[2] = c[2] * f1 + fogcolor[2] * f2;
1013 int nomodelelements[24] =
1025 float nomodelvertex3f[6*3] =
1035 float nomodelcolor4f[6*4] =
1037 0.0f, 0.0f, 0.5f, 1.0f,
1038 0.0f, 0.0f, 0.5f, 1.0f,
1039 0.0f, 0.5f, 0.0f, 1.0f,
1040 0.0f, 0.5f, 0.0f, 1.0f,
1041 0.5f, 0.0f, 0.0f, 1.0f,
1042 0.5f, 0.0f, 0.0f, 1.0f
1045 void R_DrawNoModelCallback(const void *calldata1, int calldata2)
1047 const entity_render_t *ent = calldata1;
1049 float f1, f2, *c, diff[3];
1052 R_Mesh_Matrix(&ent->matrix);
1054 memset(&m, 0, sizeof(m));
1055 R_Mesh_State_Texture(&m);
1057 if (ent->flags & EF_ADDITIVE)
1059 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1060 GL_DepthMask(false);
1062 else if (ent->alpha < 1)
1064 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1065 GL_DepthMask(false);
1069 GL_BlendFunc(GL_ONE, GL_ZERO);
1073 GL_VertexPointer(nomodelvertex3f);
1076 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1077 GL_ColorPointer(color4f);
1078 VectorSubtract(ent->origin, r_origin, diff);
1079 f2 = exp(fogdensity/DotProduct(diff, diff));
1081 for (i = 0, c = color4f;i < 6;i++, c += 4)
1083 c[0] = (c[0] * f1 + fogcolor[0] * f2);
1084 c[1] = (c[1] * f1 + fogcolor[1] * f2);
1085 c[2] = (c[2] * f1 + fogcolor[2] * f2);
1089 else if (ent->alpha != 1)
1091 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1092 GL_ColorPointer(color4f);
1093 for (i = 0, c = color4f;i < 6;i++, c += 4)
1097 GL_ColorPointer(nomodelcolor4f);
1098 R_Mesh_Draw(6, 8, nomodelelements);
1101 void R_DrawNoModel(entity_render_t *ent)
1103 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1104 R_MeshQueue_AddTransparent(ent->origin, R_DrawNoModelCallback, ent, 0);
1106 // R_DrawNoModelCallback(ent, 0);
1109 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1111 vec3_t right1, right2, diff, normal;
1113 VectorSubtract (org2, org1, normal);
1114 VectorNormalizeFast (normal);
1116 // calculate 'right' vector for start
1117 VectorSubtract (r_origin, org1, diff);
1118 VectorNormalizeFast (diff);
1119 CrossProduct (normal, diff, right1);
1121 // calculate 'right' vector for end
1122 VectorSubtract (r_origin, org2, diff);
1123 VectorNormalizeFast (diff);
1124 CrossProduct (normal, diff, right2);
1126 vert[ 0] = org1[0] + width * right1[0];
1127 vert[ 1] = org1[1] + width * right1[1];
1128 vert[ 2] = org1[2] + width * right1[2];
1129 vert[ 3] = org1[0] - width * right1[0];
1130 vert[ 4] = org1[1] - width * right1[1];
1131 vert[ 5] = org1[2] - width * right1[2];
1132 vert[ 6] = org2[0] - width * right2[0];
1133 vert[ 7] = org2[1] - width * right2[1];
1134 vert[ 8] = org2[2] - width * right2[2];
1135 vert[ 9] = org2[0] + width * right2[0];
1136 vert[10] = org2[1] + width * right2[1];
1137 vert[11] = org2[2] + width * right2[2];
1140 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
1142 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)
1149 VectorSubtract(origin, r_origin, diff);
1150 ca *= 1 - exp(fogdensity/DotProduct(diff,diff));
1153 R_Mesh_Matrix(&r_identitymatrix);
1154 GL_Color(cr, cg, cb, ca);
1155 GL_VertexPointer(varray_vertex3f);
1156 GL_BlendFunc(blendfunc1, blendfunc2);
1157 GL_DepthMask(false);
1158 GL_DepthTest(!depthdisable);
1160 memset(&m, 0, sizeof(m));
1161 m.tex[0] = R_GetTexture(texture);
1162 m.pointer_texcoord[0] = spritetexcoord2f;
1163 R_Mesh_State_Texture(&m);
1165 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
1166 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
1167 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
1168 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
1169 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
1170 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
1171 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
1172 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
1173 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
1174 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
1175 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
1176 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
1177 R_Mesh_Draw(4, 2, polygonelements);