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
29 matrix4x4_t r_identitymatrix;
31 int c_alias_polys, c_light_polys, c_faces, c_nodes, c_leafs, c_models, c_bmodels, c_sprites, c_particles, c_dlights;
33 // true during envmap command capture
49 // 8.8 fraction of base light value
50 unsigned short d_lightstylevalue[256];
52 cvar_t r_drawentities = {0, "r_drawentities","1"};
53 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1"};
54 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0"};
55 cvar_t r_shadow_staticworldlights = {0, "r_shadow_staticworldlights", "1"};
56 cvar_t r_speeds = {0, "r_speeds","0"};
57 cvar_t r_fullbright = {0, "r_fullbright","0"};
58 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1"};
59 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1"};
60 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1"};
61 cvar_t r_shadow_cull = {0, "r_shadow_cull", "1"};
63 cvar_t gl_fogenable = {0, "gl_fogenable", "0"};
64 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25"};
65 cvar_t gl_fogred = {0, "gl_fogred","0.3"};
66 cvar_t gl_foggreen = {0, "gl_foggreen","0.3"};
67 cvar_t gl_fogblue = {0, "gl_fogblue","0.3"};
68 cvar_t gl_fogstart = {0, "gl_fogstart", "0"};
69 cvar_t gl_fogend = {0, "gl_fogend","0"};
71 cvar_t r_textureunits = {0, "r_textureunits", "32"};
73 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1"};
74 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1"};
75 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1"};
79 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
82 for (i = 0;i < verts;i++)
93 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
96 for (i = 0;i < verts;i++)
110 For program optimization
113 qboolean intimerefresh = 0;
114 static void R_TimeRefresh_f (void)
117 float start, stop, time;
120 start = Sys_DoubleTime ();
121 for (i = 0;i < 128;i++)
123 r_refdef.viewangles[0] = 0;
124 r_refdef.viewangles[1] = i/128.0*360.0;
125 r_refdef.viewangles[2] = 0;
129 stop = Sys_DoubleTime ();
132 Con_Printf ("%f seconds (%f fps)\n", time, 128/time);
137 float fog_density, fog_red, fog_green, fog_blue;
139 qboolean oldgl_fogenable;
140 void R_SetupFog(void)
142 if (gamemode == GAME_NEHAHRA)
144 if (gl_fogenable.integer)
146 oldgl_fogenable = true;
147 fog_density = gl_fogdensity.value;
148 fog_red = gl_fogred.value;
149 fog_green = gl_foggreen.value;
150 fog_blue = gl_fogblue.value;
152 else if (oldgl_fogenable)
154 oldgl_fogenable = false;
163 fogcolor[0] = fog_red = bound(0.0f, fog_red , 1.0f);
164 fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
165 fogcolor[2] = fog_blue = bound(0.0f, fog_blue , 1.0f);
170 fogdensity = -4000.0f / (fog_density * fog_density);
171 // fog color was already set
177 // FIXME: move this to client?
180 if (gamemode == GAME_NEHAHRA)
182 Cvar_Set("gl_fogenable", "0");
183 Cvar_Set("gl_fogdensity", "0.2");
184 Cvar_Set("gl_fogred", "0.3");
185 Cvar_Set("gl_foggreen", "0.3");
186 Cvar_Set("gl_fogblue", "0.3");
188 fog_density = fog_red = fog_green = fog_blue = 0.0f;
191 // FIXME: move this to client?
192 void FOG_registercvars(void)
194 if (gamemode == GAME_NEHAHRA)
196 Cvar_RegisterVariable (&gl_fogenable);
197 Cvar_RegisterVariable (&gl_fogdensity);
198 Cvar_RegisterVariable (&gl_fogred);
199 Cvar_RegisterVariable (&gl_foggreen);
200 Cvar_RegisterVariable (&gl_fogblue);
201 Cvar_RegisterVariable (&gl_fogstart);
202 Cvar_RegisterVariable (&gl_fogend);
206 void gl_main_start(void)
210 void gl_main_shutdown(void)
214 extern void CL_ParseEntityLump(char *entitystring);
215 void gl_main_newmap(void)
218 char *entities, entname[MAX_QPATH];
222 strcpy(entname, cl.worldmodel->name);
223 l = strlen(entname) - 4;
224 if (l >= 0 && !strcmp(entname + l, ".bsp"))
226 strcpy(entname + l, ".ent");
227 if ((entities = FS_LoadFile(entname, true)))
229 CL_ParseEntityLump(entities);
234 if (cl.worldmodel->brush.entities)
235 CL_ParseEntityLump(cl.worldmodel->brush.entities);
239 void GL_Main_Init(void)
241 Matrix4x4_CreateIdentity(&r_identitymatrix);
242 // FIXME: move this to client?
244 Cmd_AddCommand ("timerefresh", R_TimeRefresh_f);
245 Cvar_RegisterVariable (&r_drawentities);
246 Cvar_RegisterVariable (&r_drawviewmodel);
247 Cvar_RegisterVariable (&r_shadows);
248 Cvar_RegisterVariable (&r_shadow_staticworldlights);
249 Cvar_RegisterVariable (&r_speeds);
250 Cvar_RegisterVariable (&r_fullbrights);
251 Cvar_RegisterVariable (&r_wateralpha);
252 Cvar_RegisterVariable (&r_dynamic);
253 Cvar_RegisterVariable (&r_fullbright);
254 Cvar_RegisterVariable (&r_textureunits);
255 Cvar_RegisterVariable (&r_shadow_cull);
256 Cvar_RegisterVariable (&r_lerpsprites);
257 Cvar_RegisterVariable (&r_lerpmodels);
258 Cvar_RegisterVariable (&r_waterscroll);
259 if (gamemode == GAME_NEHAHRA || gamemode == GAME_NEXUIZ)
260 Cvar_SetValue("r_fullbrights", 0);
261 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
264 vec3_t r_farclip_origin;
265 vec3_t r_farclip_direction;
266 vec_t r_farclip_directiondist;
267 vec_t r_farclip_meshfarclip;
268 int r_farclip_directionbit0;
269 int r_farclip_directionbit1;
270 int r_farclip_directionbit2;
272 // start a farclip measuring session
273 void R_FarClip_Start(vec3_t origin, vec3_t direction, vec_t startfarclip)
275 VectorCopy(origin, r_farclip_origin);
276 VectorCopy(direction, r_farclip_direction);
277 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
278 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
279 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
280 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
281 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
284 // enlarge farclip to accomodate box
285 void R_FarClip_Box(vec3_t mins, vec3_t maxs)
288 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
289 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
290 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
291 if (r_farclip_meshfarclip < d)
292 r_farclip_meshfarclip = d;
295 // return farclip value
296 float R_FarClip_Finish(void)
298 return r_farclip_meshfarclip - r_farclip_directiondist;
301 extern void R_Textures_Init(void);
302 extern void Mod_RenderInit(void);
303 extern void GL_Draw_Init(void);
304 extern void GL_Main_Init(void);
305 extern void R_Shadow_Init(void);
306 extern void GL_Models_Init(void);
307 extern void R_Sky_Init(void);
308 extern void GL_Surf_Init(void);
309 extern void R_Crosshairs_Init(void);
310 extern void R_Light_Init(void);
311 extern void R_Particles_Init(void);
312 extern void R_Explosion_Init(void);
313 extern void ui_init(void);
314 extern void gl_backend_init(void);
315 extern void Sbar_Init(void);
316 extern void R_LightningBeams_Init(void);
318 void Render_Init(void)
336 R_LightningBeams_Init();
344 extern char *ENGINE_EXTENSIONS;
347 VID_CheckExtensions();
349 // LordHavoc: report supported extensions
350 Con_DPrintf("\nengine extensions: %s\n", ENGINE_EXTENSIONS);
353 int R_CullBox(const vec3_t mins, const vec3_t maxs)
357 for (i = 0;i < 4;i++)
364 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
368 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
372 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
376 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
380 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
384 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
388 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
392 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
400 int PVS_CullBox(const vec3_t mins, const vec3_t maxs)
403 mnode_t *node, *stack[4096];
404 if (cl.worldmodel == NULL)
407 stack[stackpos++] = cl.worldmodel->brushq1.nodes;
410 node = stack[--stackpos];
411 if (node->contents < 0)
413 if (((mleaf_t *)node)->pvsframe == cl.worldmodel->brushq1.pvsframecount)
418 sides = BoxOnPlaneSide(mins, maxs, node->plane);
419 if (sides & 2 && stackpos < 4096)
420 stack[stackpos++] = node->children[1];
421 if (sides & 1 && stackpos < 4096)
422 stack[stackpos++] = node->children[0];
428 int VIS_CullBox(const vec3_t mins, const vec3_t maxs)
431 mnode_t *node, *stack[4096];
432 if (R_CullBox(mins, maxs))
434 if (cl.worldmodel == NULL)
437 stack[stackpos++] = cl.worldmodel->brushq1.nodes;
440 node = stack[--stackpos];
441 if (node->contents < 0)
443 if (((mleaf_t *)node)->visframe == r_framecount)
448 sides = BoxOnPlaneSide(mins, maxs, node->plane);
449 if (sides & 2 && stackpos < 4096)
450 stack[stackpos++] = node->children[1];
451 if (sides & 1 && stackpos < 4096)
452 stack[stackpos++] = node->children[0];
458 int R_CullSphere(const vec3_t origin, vec_t radius)
460 return (DotProduct(frustum[0].normal, origin) + radius < frustum[0].dist
461 || DotProduct(frustum[1].normal, origin) + radius < frustum[1].dist
462 || DotProduct(frustum[2].normal, origin) + radius < frustum[2].dist
463 || DotProduct(frustum[3].normal, origin) + radius < frustum[3].dist);
466 int PVS_CullSphere(const vec3_t origin, vec_t radius)
469 mnode_t *node, *stack[4096];
471 if (cl.worldmodel == NULL)
474 stack[stackpos++] = cl.worldmodel->brushq1.nodes;
477 node = stack[--stackpos];
478 if (node->contents < 0)
480 if (((mleaf_t *)node)->pvsframe == cl.worldmodel->brushq1.pvsframecount)
485 dist = PlaneDiff(origin, node->plane);
487 stack[stackpos++] = node->children[1];
489 stack[stackpos++] = node->children[0];
495 int VIS_CullSphere(const vec3_t origin, vec_t radius)
498 mnode_t *node, *stack[4096];
500 if (R_CullSphere(origin, radius))
502 if (cl.worldmodel == NULL)
505 stack[stackpos++] = cl.worldmodel->brushq1.nodes;
508 node = stack[--stackpos];
509 if (node->contents < 0)
511 if (((mleaf_t *)node)->visframe == r_framecount)
516 dist = PlaneDiff(origin, node->plane);
518 stack[stackpos++] = node->children[1];
520 stack[stackpos++] = node->children[0];
527 //==================================================================================
529 static void R_MarkEntities (void)
532 entity_render_t *ent;
534 ent = &cl_entities[0].render;
535 Matrix4x4_CreateIdentity(&ent->matrix);
536 Matrix4x4_CreateIdentity(&ent->inversematrix);
539 R_FarClip_Box(cl.worldmodel->normalmins, cl.worldmodel->normalmaxs);
541 if (!r_drawentities.integer)
544 for (i = 0;i < r_refdef.numentities;i++)
546 ent = r_refdef.entities[i];
547 Mod_CheckLoaded(ent->model);
548 // some of the renderer still relies on origin...
549 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
550 // some of the renderer still relies on scale...
551 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
552 R_LerpAnimation(ent);
553 R_UpdateEntLights(ent);
554 if ((chase_active.integer || !(ent->flags & RENDER_EXTERIORMODEL))
555 && !VIS_CullSphere(ent->origin, (ent->model != NULL ? ent->model->radius : 16) * ent->scale)
556 && !VIS_CullBox(ent->mins, ent->maxs))
558 ent->visframe = r_framecount;
559 R_FarClip_Box(ent->mins, ent->maxs);
564 // only used if skyrendermasked, and normally returns false
565 int R_DrawBrushModelsSky (void)
568 entity_render_t *ent;
570 if (!r_drawentities.integer)
574 for (i = 0;i < r_refdef.numentities;i++)
576 ent = r_refdef.entities[i];
577 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
579 ent->model->DrawSky(ent);
592 void R_DrawViewModel (void)
594 entity_render_t *ent;
596 // FIXME: move these checks to client
597 if (!r_drawviewmodel.integer || chase_active.integer || envmap || !r_drawentities.integer || cl.items & IT_INVISIBILITY || cl.stats[STAT_HEALTH] <= 0 || !cl.viewent.render.model)
600 ent = &cl.viewent.render;
601 Mod_CheckLoaded(ent->model);
602 R_LerpAnimation(ent);
603 Matrix4x4_CreateFromQuakeEntity(&ent->matrix, ent->origin[0], ent->origin[1], ent->origin[2], -ent->angles[0], ent->angles[1], ent->angles[2], ent->scale);
604 Matrix4x4_Invert_Simple(&ent->inversematrix, &ent->matrix);
605 R_UpdateEntLights(ent);
606 ent->model->Draw(ent);
610 void R_DrawNoModel(entity_render_t *ent);
614 entity_render_t *ent;
616 if (!r_drawentities.integer)
619 for (i = 0;i < r_refdef.numentities;i++)
621 ent = r_refdef.entities[i];
622 if (ent->visframe == r_framecount)
624 if (ent->model && ent->model->Draw != NULL)
625 ent->model->Draw(ent);
632 void R_DrawFakeShadows (void)
635 entity_render_t *ent;
637 ent = &cl_entities[0].render;
638 if (ent->model && ent->model->DrawFakeShadow)
639 ent->model->DrawFakeShadow(ent);
641 if (!r_drawentities.integer)
643 for (i = 0;i < r_refdef.numentities;i++)
645 ent = r_refdef.entities[i];
646 if ((ent->flags & RENDER_SHADOW) && ent->model && ent->model->DrawFakeShadow)
647 ent->model->DrawFakeShadow(ent);
651 #include "r_shadow.h"
653 int shadowframecount = 0;
655 int Light_CullBox(const vec3_t mins, const vec3_t maxs)
658 mnode_t *node, *stack[4096];
659 if (cl.worldmodel == NULL)
662 stack[stackpos++] = cl.worldmodel->brushq1.nodes;
665 node = stack[--stackpos];
666 if (node->contents < 0)
668 if (((mleaf_t *)node)->worldnodeframe == shadowframecount)
673 sides = BoxOnPlaneSide(mins, maxs, node->plane);
674 if (sides & 2 && stackpos < 4096)
675 stack[stackpos++] = node->children[1];
676 if (sides & 1 && stackpos < 4096)
677 stack[stackpos++] = node->children[0];
683 int LightAndVis_CullBox(const vec3_t mins, const vec3_t maxs)
686 mnode_t *node, *stack[4096];
687 if (R_CullBox(mins, maxs))
689 if (cl.worldmodel == NULL)
692 stack[stackpos++] = cl.worldmodel->brushq1.nodes;
695 node = stack[--stackpos];
696 if (node->contents < 0)
698 if (((mleaf_t *)node)->visframe == r_framecount && ((mleaf_t *)node)->worldnodeframe == shadowframecount)
703 sides = BoxOnPlaneSide(mins, maxs, node->plane);
704 if (sides & 2 && stackpos < 4096)
705 stack[stackpos++] = node->children[1];
706 if (sides & 1 && stackpos < 4096)
707 stack[stackpos++] = node->children[0];
713 int LightAndVis_CullPointCloud(int numpoints, const float *points)
718 mnode_t *node, *stack[4096];
719 //if (R_CullBox(mins, maxs))
721 if (cl.worldmodel == NULL)
724 stack[stackpos++] = cl.worldmodel->brushq1.nodes;
727 node = stack[--stackpos];
728 if (node->contents < 0)
730 if (((mleaf_t *)node)->visframe == r_framecount && ((mleaf_t *)node)->worldnodeframe == shadowframecount)
736 for (i = 0, p = points;i < numpoints && sides != 3;i++, p += 3)
738 if (DotProduct(p, node->plane->normal) < node->plane->dist)
743 if (sides & 2 && stackpos < 4096)
744 stack[stackpos++] = node->children[1];
745 if (sides & 1 && stackpos < 4096)
746 stack[stackpos++] = node->children[0];
753 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)
755 vec3_t relativelightorigin;
759 float dist, projectdistance;
763 if (!(ent->flags & RENDER_SHADOW) || ent->model == NULL || ent->model->DrawShadowVolume == NULL)
765 if (r_shadow_cull.integer)
767 if (ent->maxs[0] < lightmins[0] || ent->mins[0] > lightmaxs[0]
768 || ent->maxs[1] < lightmins[1] || ent->mins[1] > lightmaxs[1]
769 || ent->maxs[2] < lightmins[2] || ent->mins[2] > lightmaxs[2]
770 || (lightmarked && Light_CullBox(ent->mins, ent->maxs)))
774 if (r_shadow_cull.integer)
776 projectdistance = cullradius;
777 // calculate projected bounding box and decide if it is on-screen
778 for (i = 0;i < 8;i++)
780 temp[0] = i & 1 ? ent->model->normalmaxs[0] : ent->model->normalmins[0];
781 temp[1] = i & 2 ? ent->model->normalmaxs[1] : ent->model->normalmins[1];
782 temp[2] = i & 4 ? ent->model->normalmaxs[2] : ent->model->normalmins[2];
783 Matrix4x4_Transform(&ent->matrix, temp, points[i]);
784 VectorSubtract(points[i], lightorigin, temp);
785 dist = projectdistance / sqrt(DotProduct(temp, temp));
786 VectorMA(lightorigin, dist, temp, points[i+8]);
788 if (LightAndVis_CullPointCloud(16, points[0]))
791 for (i = 0;i < 8;i++)
793 p2[0] = i & 1 ? ent->model->normalmaxs[0] : ent->model->normalmins[0];
794 p2[1] = i & 2 ? ent->model->normalmaxs[1] : ent->model->normalmins[1];
795 p2[2] = i & 4 ? ent->model->normalmaxs[2] : ent->model->normalmins[2];
796 Matrix4x4_Transform(&ent->matrix, p2, p);
797 VectorSubtract(p, lightorigin, temp);
798 dist = projectdistance / sqrt(DotProduct(temp, temp));
799 VectorMA(p, dist, temp, p2);
802 if (mins[0] > p[0]) mins[0] = p[0];if (maxs[0] < p[0]) maxs[0] = p[0];
803 if (mins[1] > p[1]) mins[1] = p[1];if (maxs[1] < p[1]) maxs[1] = p[1];
804 if (mins[2] > p[2]) mins[2] = p[2];if (maxs[2] < p[2]) maxs[2] = p[2];
811 if (mins[0] > p2[0]) mins[0] = p2[0];if (maxs[0] < p2[0]) maxs[0] = p2[0];
812 if (mins[1] > p2[1]) mins[1] = p2[1];if (maxs[1] < p2[1]) maxs[1] = p2[1];
813 if (mins[2] > p2[2]) mins[2] = p2[2];if (maxs[2] < p2[2]) maxs[2] = p2[2];
815 if (mins[0] >= clipmaxs[0] || maxs[0] <= clipmins[0]
816 || mins[1] >= clipmaxs[1] || maxs[1] <= clipmins[1]
817 || mins[2] >= clipmaxs[2] || maxs[2] <= clipmins[2]
818 || LightAndVis_CullBox(mins, maxs))
823 Matrix4x4_Transform(&ent->inversematrix, lightorigin, relativelightorigin);
824 ent->model->DrawShadowVolume (ent, relativelightorigin, lightradius);
827 void R_Shadow_DrawWorldLightShadowVolume(matrix4x4_t *matrix, worldlight_t *light);
829 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);
830 void R_ShadowVolumeLighting (int visiblevolumes)
833 entity_render_t *ent;
835 float f, lightradius, cullradius;
836 vec3_t relativelightorigin, relativeeyeorigin, lightcolor, clipmins, clipmaxs;
842 matrix4x4_t matrix_worldtofilter, matrix_worldtoattenuationxyz, matrix_worldtoattenuationz;
843 matrix4x4_t matrix_modeltofilter, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz;
847 memset(&m, 0, sizeof(m));
848 R_Mesh_State_Texture(&m);
850 GL_BlendFunc(GL_ONE, GL_ONE);
852 GL_DepthTest(r_shadow_visiblevolumes.integer < 2);
853 qglDisable(GL_CULL_FACE);
854 GL_Color(0.0 * r_colorscale, 0.0125 * r_colorscale, 0.1 * r_colorscale, 1);
857 R_Shadow_Stage_Begin();
859 if (r_shadow_realtime_world.integer)
861 R_Shadow_LoadWorldLightsIfNeeded();
862 for (lnum = 0, wl = r_shadow_worldlightchain;wl;wl = wl->next, lnum++)
864 if (d_lightstylevalue[wl->style] <= 0)
866 if (R_CullBox(wl->mins, wl->maxs))
867 //if (R_CullSphere(wl->origin, cullradius))
869 //if (R_CullBox(wl->mins, wl->maxs) || R_CullSphere(wl->origin, lightradius))
871 //if (VIS_CullBox(wl->mins, wl->maxs) || VIS_CullSphere(wl->origin, lightradius))
873 if (r_shadow_debuglight.integer >= 0 && lnum != r_shadow_debuglight.integer)
876 cullradius = wl->cullradius;
877 lightradius = wl->lightradius;
879 if (cl.worldmodel != NULL)
881 for (i = 0;i < wl->numleafs;i++)
882 if (wl->leafs[i]->visframe == r_framecount)
884 if (i == wl->numleafs)
886 leaf = wl->leafs[i++];
887 VectorCopy(leaf->mins, clipmins);
888 VectorCopy(leaf->maxs, clipmaxs);
889 for (;i < wl->numleafs;i++)
892 if (leaf->visframe == r_framecount)
894 if (clipmins[0] > leaf->mins[0]) clipmins[0] = leaf->mins[0];
895 if (clipmaxs[0] < leaf->maxs[0]) clipmaxs[0] = leaf->maxs[0];
896 if (clipmins[1] > leaf->mins[1]) clipmins[1] = leaf->mins[1];
897 if (clipmaxs[1] < leaf->maxs[1]) clipmaxs[1] = leaf->maxs[1];
898 if (clipmins[2] > leaf->mins[2]) clipmins[2] = leaf->mins[2];
899 if (clipmaxs[2] < leaf->maxs[2]) clipmaxs[2] = leaf->maxs[2];
902 if (clipmins[0] < wl->mins[0]) clipmins[0] = wl->mins[0];
903 if (clipmaxs[0] > wl->maxs[0]) clipmaxs[0] = wl->maxs[0];
904 if (clipmins[1] < wl->mins[1]) clipmins[1] = wl->mins[1];
905 if (clipmaxs[1] > wl->maxs[1]) clipmaxs[1] = wl->maxs[1];
906 if (clipmins[2] < wl->mins[2]) clipmins[2] = wl->mins[2];
907 if (clipmaxs[2] > wl->maxs[2]) clipmaxs[2] = wl->maxs[2];
911 VectorCopy(wl->mins, clipmins);
912 VectorCopy(wl->maxs, clipmaxs);
915 //if (R_Shadow_ScissorForBBoxAndSphere(clipmins, clipmaxs, wl->origin, wl->cullradius))
916 if (R_CullBox(clipmins, clipmaxs) || R_Shadow_ScissorForBBox(clipmins, clipmaxs))
919 // mark the leafs we care about so only things in those leafs will matter
920 if (cl.worldmodel != NULL)
921 for (i = 0;i < wl->numleafs;i++)
922 wl->leafs[i]->worldnodeframe = shadowframecount;
924 f = d_lightstylevalue[wl->style] * (1.0f / 256.0f);
925 VectorScale(wl->light, f, lightcolor);
928 f = 2 + sin(realtime * M_PI * 4.0);
929 VectorScale(lightcolor, f, lightcolor);
932 if (wl->castshadows && (gl_stencil || visiblevolumes))
935 R_Shadow_Stage_ShadowVolumes();
936 ent = &cl_entities[0].render;
937 if (wl->shadowvolume && r_shadow_staticworldlights.integer)
938 R_Shadow_DrawWorldLightShadowVolume(&ent->matrix, wl);
940 R_TestAndDrawShadowVolume(ent, wl->origin, cullradius, lightradius, wl->mins, wl->maxs, clipmins, clipmaxs, true);
941 if (r_drawentities.integer)
942 for (i = 0;i < r_refdef.numentities;i++)
943 R_TestAndDrawShadowVolume(r_refdef.entities[i], wl->origin, cullradius, lightradius, wl->mins, wl->maxs, clipmins, clipmaxs, true);
948 if (wl->castshadows && gl_stencil)
949 R_Shadow_Stage_LightWithShadows();
951 R_Shadow_Stage_LightWithoutShadows();
953 // calculate world to filter matrix
954 Matrix4x4_CreateFromQuakeEntity(&matrix, wl->origin[0], wl->origin[1], wl->origin[2], wl->angles[0], wl->angles[1], wl->angles[2], lightradius);
955 Matrix4x4_Invert_Simple(&matrix_worldtofilter, &matrix);
956 // calculate world to attenuationxyz/xy matrix
957 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5, 0.5, 0.5, 0, 0, 0, 0.5);
958 Matrix4x4_Concat(&matrix_worldtoattenuationxyz, &matrix, &matrix_worldtofilter);
959 // calculate world to attenuationz matrix
960 matrix.m[0][0] = 0;matrix.m[0][1] = 0;matrix.m[0][2] = 0.5;matrix.m[0][3] = 0.5;
961 matrix.m[1][0] = 0;matrix.m[1][1] = 0;matrix.m[1][2] = 0 ;matrix.m[1][3] = 0.5;
962 matrix.m[2][0] = 0;matrix.m[2][1] = 0;matrix.m[2][2] = 0 ;matrix.m[2][3] = 0.5;
963 matrix.m[3][0] = 0;matrix.m[3][1] = 0;matrix.m[3][2] = 0 ;matrix.m[3][3] = 1;
964 Matrix4x4_Concat(&matrix_worldtoattenuationz, &matrix, &matrix_worldtofilter);
966 ent = &cl_entities[0].render;
967 if (ent->model && ent->model->DrawLight)
969 Matrix4x4_Transform(&ent->inversematrix, wl->origin, relativelightorigin);
970 Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin);
971 Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
972 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
973 Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
975 R_Model_Brush_DrawLightForSurfaceList(ent, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, wl->surfaces, wl->numsurfaces, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
977 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
979 if (r_drawentities.integer)
981 for (i = 0;i < r_refdef.numentities;i++)
983 ent = r_refdef.entities[i];
984 if (ent->visframe == r_framecount && ent->model && ent->model->DrawLight
985 && BoxesOverlap(ent->mins, ent->maxs, clipmins, clipmaxs)
986 && !(ent->effects & EF_ADDITIVE) && ent->alpha == 1)
988 Matrix4x4_Transform(&ent->inversematrix, wl->origin, relativelightorigin);
989 Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin);
990 Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
991 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
992 Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
993 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
1000 if (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer)
1002 for (lnum = 0, rd = r_dlight;lnum < r_numdlights;lnum++, rd++)
1004 lightradius = rd->cullradius;
1005 clipmins[0] = rd->origin[0] - lightradius;
1006 clipmins[1] = rd->origin[1] - lightradius;
1007 clipmins[2] = rd->origin[2] - lightradius;
1008 clipmaxs[0] = rd->origin[0] + lightradius;
1009 clipmaxs[1] = rd->origin[1] + lightradius;
1010 clipmaxs[2] = rd->origin[2] + lightradius;
1011 if (VIS_CullBox(clipmins, clipmaxs) || R_Shadow_ScissorForBBox(clipmins, clipmaxs))
1014 cullradius = RadiusFromBoundsAndOrigin(clipmins, clipmaxs, rd->origin);
1015 VectorScale(rd->light, (1.0f / 4096.0f), lightcolor);
1017 if (gl_stencil || visiblevolumes)
1019 if (!visiblevolumes)
1020 R_Shadow_Stage_ShadowVolumes();
1021 ent = &cl_entities[0].render;
1022 R_TestAndDrawShadowVolume(ent, rd->origin, cullradius, lightradius, clipmins, clipmaxs, clipmins, clipmaxs, false);
1023 if (r_drawentities.integer)
1025 for (i = 0;i < r_refdef.numentities;i++)
1027 ent = r_refdef.entities[i];
1029 R_TestAndDrawShadowVolume(ent, rd->origin, cullradius, lightradius, clipmins, clipmaxs, clipmins, clipmaxs, false);
1034 if (!visiblevolumes)
1037 R_Shadow_Stage_LightWithShadows();
1039 R_Shadow_Stage_LightWithoutShadows();
1041 // calculate world to filter matrix
1042 Matrix4x4_CreateFromQuakeEntity(&matrix, rd->origin[0], rd->origin[1], rd->origin[2], 0, 0, 0, lightradius);
1043 Matrix4x4_Invert_Simple(&matrix_worldtofilter, &matrix);
1044 // calculate world to attenuationxyz/xy matrix
1045 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5, 0.5, 0.5, 0, 0, 0, 0.5);
1046 Matrix4x4_Concat(&matrix_worldtoattenuationxyz, &matrix, &matrix_worldtofilter);
1047 // calculate world to attenuationz matrix
1048 matrix.m[0][0] = 0;matrix.m[0][1] = 0;matrix.m[0][2] = 0.5;matrix.m[0][3] = 0.5;
1049 matrix.m[1][0] = 0;matrix.m[1][1] = 0;matrix.m[1][2] = 0 ;matrix.m[1][3] = 0.5;
1050 matrix.m[2][0] = 0;matrix.m[2][1] = 0;matrix.m[2][2] = 0 ;matrix.m[2][3] = 0.5;
1051 matrix.m[3][0] = 0;matrix.m[3][1] = 0;matrix.m[3][2] = 0 ;matrix.m[3][3] = 1;
1052 Matrix4x4_Concat(&matrix_worldtoattenuationz, &matrix, &matrix_worldtofilter);
1054 ent = &cl_entities[0].render;
1055 if (ent->model && ent->model->DrawLight)
1057 Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin);
1058 Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin);
1059 Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
1060 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
1061 Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
1062 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
1064 if (r_drawentities.integer)
1066 for (i = 0;i < r_refdef.numentities;i++)
1068 ent = r_refdef.entities[i];
1069 if (ent->visframe == r_framecount && ent->model && ent->model->DrawLight
1070 && BoxesOverlap(ent->mins, ent->maxs, clipmins, clipmaxs)
1071 && !(ent->effects & EF_ADDITIVE) && ent->alpha == 1)
1073 Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin);
1074 Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin);
1075 Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
1076 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
1077 Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
1078 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
1087 qglEnable(GL_CULL_FACE);
1089 R_Shadow_Stage_End();
1090 qglDisable(GL_SCISSOR_TEST);
1093 static void R_SetFrustum (void)
1095 // LordHavoc: note to all quake engine coders, the special case for 90
1096 // degrees assumed a square view (wrong), so I removed it, Quake2 has it
1097 // disabled as well.
1099 // rotate VPN right by FOV_X/2 degrees
1100 RotatePointAroundVector( frustum[0].normal, vup, vpn, -(90-r_refdef.fov_x / 2 ) );
1101 frustum[0].dist = DotProduct (r_origin, frustum[0].normal);
1102 PlaneClassify(&frustum[0]);
1104 // rotate VPN left by FOV_X/2 degrees
1105 RotatePointAroundVector( frustum[1].normal, vup, vpn, 90-r_refdef.fov_x / 2 );
1106 frustum[1].dist = DotProduct (r_origin, frustum[1].normal);
1107 PlaneClassify(&frustum[1]);
1109 // rotate VPN up by FOV_X/2 degrees
1110 RotatePointAroundVector( frustum[2].normal, vright, vpn, 90-r_refdef.fov_y / 2 );
1111 frustum[2].dist = DotProduct (r_origin, frustum[2].normal);
1112 PlaneClassify(&frustum[2]);
1114 // rotate VPN down by FOV_X/2 degrees
1115 RotatePointAroundVector( frustum[3].normal, vright, vpn, -( 90 - r_refdef.fov_y / 2 ) );
1116 frustum[3].dist = DotProduct (r_origin, frustum[3].normal);
1117 PlaneClassify(&frustum[3]);
1125 static void R_SetupFrame (void)
1127 // don't allow cheats in multiplayer
1128 if (cl.maxclients > 1)
1130 if (r_fullbright.integer != 0)
1131 Cvar_Set ("r_fullbright", "0");
1132 if (r_ambient.value != 0)
1133 Cvar_Set ("r_ambient", "0");
1138 // build the transformation matrix for the given view angles
1139 VectorCopy (r_refdef.vieworg, r_origin);
1141 AngleVectors (r_refdef.viewangles, vpn, vright, vup);
1147 static void R_BlendView(void)
1151 float vertex3f[3*3];
1153 if (r_refdef.viewblend[3] < 0.01f)
1156 R_Mesh_Matrix(&r_identitymatrix);
1158 memset(&m, 0, sizeof(m));
1159 R_Mesh_State_Texture(&m);
1161 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1163 GL_DepthTest(false); // magic
1164 GL_VertexPointer(vertex3f);
1165 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1167 vertex3f[0] = r_origin[0] + vpn[0] * 1.5 - vright[0] * r - vup[0] * r;
1168 vertex3f[1] = r_origin[1] + vpn[1] * 1.5 - vright[1] * r - vup[1] * r;
1169 vertex3f[2] = r_origin[2] + vpn[2] * 1.5 - vright[2] * r - vup[2] * r;
1170 vertex3f[3] = r_origin[0] + vpn[0] * 1.5 - vright[0] * r + vup[0] * r * 3;
1171 vertex3f[4] = r_origin[1] + vpn[1] * 1.5 - vright[1] * r + vup[1] * r * 3;
1172 vertex3f[5] = r_origin[2] + vpn[2] * 1.5 - vright[2] * r + vup[2] * r * 3;
1173 vertex3f[6] = r_origin[0] + vpn[0] * 1.5 + vright[0] * r * 3 - vup[0] * r;
1174 vertex3f[7] = r_origin[1] + vpn[1] * 1.5 + vright[1] * r * 3 - vup[1] * r;
1175 vertex3f[8] = r_origin[2] + vpn[2] * 1.5 + vright[2] * r * 3 - vup[2] * r;
1176 R_Mesh_Draw(3, 1, polygonelements);
1183 r_refdef must be set before the first call
1186 extern void R_DrawLightningBeams (void);
1187 void R_RenderView (void)
1189 entity_render_t *world;
1190 if (!r_refdef.entities/* || !cl.worldmodel*/)
1191 return; //Host_Error ("R_RenderView: NULL worldmodel");
1193 if (r_shadow_realtime_world.integer)
1197 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");
1198 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
1202 world = &cl_entities[0].render;
1204 // FIXME: move to client
1206 R_TimeReport("mexplosion");
1214 R_TimeReport("setup");
1216 R_WorldVisibility(world);
1217 R_TimeReport("worldvis");
1219 R_FarClip_Start(r_origin, vpn, 768.0f);
1221 r_farclip = R_FarClip_Finish() + 256.0f;
1222 R_TimeReport("markentity");
1224 GL_SetupView_ViewPort(r_refdef.x, r_refdef.y, r_refdef.width, r_refdef.height);
1225 if (r_shadow_realtime_world.integer || gl_stencil)
1226 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.fov_x, r_refdef.fov_y, 1.0f);
1228 GL_SetupView_Mode_Perspective(r_refdef.fov_x, r_refdef.fov_y, 1.0f, r_farclip);
1229 GL_SetupView_Orientation_FromEntity (r_refdef.vieworg, r_refdef.viewangles);
1230 qglDepthFunc(GL_LEQUAL);
1233 R_MeshQueue_BeginScene();
1235 R_Shadow_UpdateWorldLightSelection();
1237 if (R_DrawBrushModelsSky())
1238 R_TimeReport("bmodelsky");
1240 // must occur early because it can draw sky
1242 R_TimeReport("world");
1244 // don't let sound skip if going slow
1245 if (!intimerefresh && !r_speeds.integer)
1248 R_DrawModels(r_shadow_realtime_world.integer);
1249 R_TimeReport("models");
1251 if (r_shadows.integer == 1 && !r_shadow_realtime_world.integer)
1253 R_DrawFakeShadows();
1254 R_TimeReport("fakeshadow");
1257 if (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer)
1259 R_ShadowVolumeLighting(false);
1260 R_TimeReport("dynlight");
1263 R_DrawLightningBeams();
1264 R_TimeReport("lightning");
1267 R_TimeReport("particles");
1270 R_TimeReport("explosions");
1272 R_MeshQueue_RenderTransparent();
1273 R_TimeReport("drawtrans");
1276 R_TimeReport("coronas");
1278 R_DrawWorldCrosshair();
1279 R_TimeReport("crosshair");
1282 R_TimeReport("blendview");
1284 R_MeshQueue_Render();
1285 R_MeshQueue_EndScene();
1287 if (r_shadow_visiblevolumes.integer)
1289 R_ShadowVolumeLighting(true);
1290 R_TimeReport("shadowvolume");
1294 R_TimeReport("meshfinish");
1298 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1301 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1303 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1304 GL_DepthMask(false);
1306 R_Mesh_Matrix(&r_identitymatrix);
1308 memset(&m, 0, sizeof(m));
1309 R_Mesh_State_Texture(&m);
1312 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1313 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1314 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1315 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1316 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1317 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1318 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1319 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1320 GL_ColorPointer(color);
1321 R_FillColors(color, 8, cr * r_colorscale, cg * r_colorscale, cb * r_colorscale, ca);
1324 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1326 VectorSubtract(v, r_origin, diff);
1327 f2 = exp(fogdensity/DotProduct(diff, diff));
1330 c[0] = c[0] * f1 + fogcolor[0] * f2;
1331 c[1] = c[1] * f1 + fogcolor[1] * f2;
1332 c[2] = c[2] * f1 + fogcolor[2] * f2;
1339 int nomodelelements[24] =
1351 float nomodelvertex3f[6*3] =
1361 float nomodelcolor4f[6*4] =
1363 0.0f, 0.0f, 0.5f, 1.0f,
1364 0.0f, 0.0f, 0.5f, 1.0f,
1365 0.0f, 0.5f, 0.0f, 1.0f,
1366 0.0f, 0.5f, 0.0f, 1.0f,
1367 0.5f, 0.0f, 0.0f, 1.0f,
1368 0.5f, 0.0f, 0.0f, 1.0f
1371 void R_DrawNoModelCallback(const void *calldata1, int calldata2)
1373 const entity_render_t *ent = calldata1;
1375 float f1, f2, *c, diff[3];
1378 R_Mesh_Matrix(&ent->matrix);
1380 memset(&m, 0, sizeof(m));
1381 R_Mesh_State_Texture(&m);
1383 if (ent->flags & EF_ADDITIVE)
1385 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1386 GL_DepthMask(false);
1388 else if (ent->alpha < 1)
1390 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1391 GL_DepthMask(false);
1395 GL_BlendFunc(GL_ONE, GL_ZERO);
1399 GL_VertexPointer(nomodelvertex3f);
1402 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1403 GL_ColorPointer(color4f);
1404 VectorSubtract(ent->origin, r_origin, diff);
1405 f2 = exp(fogdensity/DotProduct(diff, diff));
1407 for (i = 0, c = color4f;i < 6;i++, c += 4)
1409 c[0] = (c[0] * f1 + fogcolor[0] * f2) * r_colorscale;
1410 c[1] = (c[1] * f1 + fogcolor[1] * f2) * r_colorscale;
1411 c[2] = (c[2] * f1 + fogcolor[2] * f2) * r_colorscale;
1415 else if (r_colorscale != 1 || ent->alpha != 1)
1417 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1418 GL_ColorPointer(color4f);
1419 for (i = 0, c = color4f;i < 6;i++, c += 4)
1421 c[0] *= r_colorscale;
1422 c[1] *= r_colorscale;
1423 c[2] *= r_colorscale;
1428 GL_ColorPointer(nomodelcolor4f);
1429 R_Mesh_Draw(6, 8, nomodelelements);
1432 void R_DrawNoModel(entity_render_t *ent)
1434 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1435 R_MeshQueue_AddTransparent(ent->origin, R_DrawNoModelCallback, ent, 0);
1437 // R_DrawNoModelCallback(ent, 0);
1440 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1442 vec3_t right1, right2, diff, normal;
1444 VectorSubtract (org2, org1, normal);
1445 VectorNormalizeFast (normal);
1447 // calculate 'right' vector for start
1448 VectorSubtract (r_origin, org1, diff);
1449 VectorNormalizeFast (diff);
1450 CrossProduct (normal, diff, right1);
1452 // calculate 'right' vector for end
1453 VectorSubtract (r_origin, org2, diff);
1454 VectorNormalizeFast (diff);
1455 CrossProduct (normal, diff, right2);
1457 vert[ 0] = org1[0] + width * right1[0];
1458 vert[ 1] = org1[1] + width * right1[1];
1459 vert[ 2] = org1[2] + width * right1[2];
1460 vert[ 3] = org1[0] - width * right1[0];
1461 vert[ 4] = org1[1] - width * right1[1];
1462 vert[ 5] = org1[2] - width * right1[2];
1463 vert[ 6] = org2[0] - width * right2[0];
1464 vert[ 7] = org2[1] - width * right2[1];
1465 vert[ 8] = org2[2] - width * right2[2];
1466 vert[ 9] = org2[0] + width * right2[0];
1467 vert[10] = org2[1] + width * right2[1];
1468 vert[11] = org2[2] + width * right2[2];
1471 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
1473 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)
1480 VectorSubtract(origin, r_origin, diff);
1481 ca *= 1 - exp(fogdensity/DotProduct(diff,diff));
1484 R_Mesh_Matrix(&r_identitymatrix);
1485 GL_Color(cr * r_colorscale, cg * r_colorscale, cb * r_colorscale, ca);
1486 GL_VertexPointer(varray_vertex3f);
1487 GL_BlendFunc(blendfunc1, blendfunc2);
1488 GL_DepthMask(false);
1489 GL_DepthTest(!depthdisable);
1491 memset(&m, 0, sizeof(m));
1492 m.tex[0] = R_GetTexture(texture);
1493 m.pointer_texcoord[0] = spritetexcoord2f;
1494 R_Mesh_State_Texture(&m);
1496 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
1497 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
1498 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
1499 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
1500 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
1501 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
1502 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
1503 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
1504 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
1505 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
1506 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
1507 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
1508 R_Mesh_Draw(4, 2, polygonelements);