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->entities)
235 CL_ParseEntityLump(cl.worldmodel->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);
317 void Render_Init(void)
342 extern char *ENGINE_EXTENSIONS;
345 VID_CheckExtensions();
347 // LordHavoc: report supported extensions
348 Con_DPrintf("\nengine extensions: %s\n", ENGINE_EXTENSIONS);
351 int R_CullBox(const vec3_t mins, const vec3_t maxs)
355 for (i = 0;i < 4;i++)
362 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
366 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
370 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
374 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
378 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
382 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
386 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
390 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
398 int PVS_CullBox(const vec3_t mins, const vec3_t maxs)
401 mnode_t *node, *stack[4096];
402 if (cl.worldmodel == NULL)
405 stack[stackpos++] = cl.worldmodel->nodes;
408 node = stack[--stackpos];
409 if (node->contents < 0)
411 if (((mleaf_t *)node)->pvsframe == cl.worldmodel->pvsframecount)
416 sides = BoxOnPlaneSide(mins, maxs, node->plane);
417 if (sides & 2 && stackpos < 4096)
418 stack[stackpos++] = node->children[1];
419 if (sides & 1 && stackpos < 4096)
420 stack[stackpos++] = node->children[0];
426 int VIS_CullBox(const vec3_t mins, const vec3_t maxs)
429 mnode_t *node, *stack[4096];
430 if (R_CullBox(mins, maxs))
432 if (cl.worldmodel == NULL)
435 stack[stackpos++] = cl.worldmodel->nodes;
438 node = stack[--stackpos];
439 if (node->contents < 0)
441 if (((mleaf_t *)node)->visframe == r_framecount)
446 sides = BoxOnPlaneSide(mins, maxs, node->plane);
447 if (sides & 2 && stackpos < 4096)
448 stack[stackpos++] = node->children[1];
449 if (sides & 1 && stackpos < 4096)
450 stack[stackpos++] = node->children[0];
456 int R_CullSphere(const vec3_t origin, vec_t radius)
458 return (DotProduct(frustum[0].normal, origin) + radius < frustum[0].dist
459 || DotProduct(frustum[1].normal, origin) + radius < frustum[1].dist
460 || DotProduct(frustum[2].normal, origin) + radius < frustum[2].dist
461 || DotProduct(frustum[3].normal, origin) + radius < frustum[3].dist);
464 int PVS_CullSphere(const vec3_t origin, vec_t radius)
467 mnode_t *node, *stack[4096];
469 if (cl.worldmodel == NULL)
472 stack[stackpos++] = cl.worldmodel->nodes;
475 node = stack[--stackpos];
476 if (node->contents < 0)
478 if (((mleaf_t *)node)->pvsframe == cl.worldmodel->pvsframecount)
483 dist = PlaneDiff(origin, node->plane);
485 stack[stackpos++] = node->children[1];
487 stack[stackpos++] = node->children[0];
493 int VIS_CullSphere(const vec3_t origin, vec_t radius)
496 mnode_t *node, *stack[4096];
498 if (R_CullSphere(origin, radius))
500 if (cl.worldmodel == NULL)
503 stack[stackpos++] = cl.worldmodel->nodes;
506 node = stack[--stackpos];
507 if (node->contents < 0)
509 if (((mleaf_t *)node)->visframe == r_framecount)
514 dist = PlaneDiff(origin, node->plane);
516 stack[stackpos++] = node->children[1];
518 stack[stackpos++] = node->children[0];
525 //==================================================================================
527 static void R_MarkEntities (void)
530 entity_render_t *ent;
532 ent = &cl_entities[0].render;
533 Matrix4x4_CreateIdentity(&ent->matrix);
534 Matrix4x4_CreateIdentity(&ent->inversematrix);
537 R_FarClip_Box(cl.worldmodel->normalmins, cl.worldmodel->normalmaxs);
539 if (!r_drawentities.integer)
542 for (i = 0;i < r_refdef.numentities;i++)
544 ent = r_refdef.entities[i];
545 Mod_CheckLoaded(ent->model);
546 // some of the renderer still relies on origin...
547 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
548 // some of the renderer still relies on scale...
549 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
550 R_LerpAnimation(ent);
551 R_UpdateEntLights(ent);
552 if ((chase_active.integer || !(ent->flags & RENDER_EXTERIORMODEL))
553 && !VIS_CullSphere(ent->origin, (ent->model != NULL ? ent->model->radius : 16) * ent->scale)
554 && !VIS_CullBox(ent->mins, ent->maxs))
556 ent->visframe = r_framecount;
557 R_FarClip_Box(ent->mins, ent->maxs);
562 // only used if skyrendermasked, and normally returns false
563 int R_DrawBrushModelsSky (void)
566 entity_render_t *ent;
568 if (!r_drawentities.integer)
572 for (i = 0;i < r_refdef.numentities;i++)
574 ent = r_refdef.entities[i];
575 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
577 ent->model->DrawSky(ent);
590 void R_DrawViewModel (void)
592 entity_render_t *ent;
594 // FIXME: move these checks to client
595 if (!r_drawviewmodel.integer || chase_active.integer || envmap || !r_drawentities.integer || cl.items & IT_INVISIBILITY || cl.stats[STAT_HEALTH] <= 0 || !cl.viewent.render.model)
598 ent = &cl.viewent.render;
599 Mod_CheckLoaded(ent->model);
600 R_LerpAnimation(ent);
601 Matrix4x4_CreateFromQuakeEntity(&ent->matrix, ent->origin[0], ent->origin[1], ent->origin[2], -ent->angles[0], ent->angles[1], ent->angles[2], ent->scale);
602 Matrix4x4_Invert_Simple(&ent->inversematrix, &ent->matrix);
603 R_UpdateEntLights(ent);
604 ent->model->Draw(ent);
608 void R_DrawNoModel(entity_render_t *ent);
612 entity_render_t *ent;
614 if (!r_drawentities.integer)
617 for (i = 0;i < r_refdef.numentities;i++)
619 ent = r_refdef.entities[i];
620 if (ent->visframe == r_framecount)
622 if (ent->model && ent->model->Draw != NULL)
623 ent->model->Draw(ent);
630 void R_DrawFakeShadows (void)
633 entity_render_t *ent;
635 ent = &cl_entities[0].render;
636 if (ent->model && ent->model->DrawFakeShadow)
637 ent->model->DrawFakeShadow(ent);
639 if (!r_drawentities.integer)
641 for (i = 0;i < r_refdef.numentities;i++)
643 ent = r_refdef.entities[i];
644 if ((ent->flags & RENDER_SHADOW) && ent->model && ent->model->DrawFakeShadow)
645 ent->model->DrawFakeShadow(ent);
649 #include "r_shadow.h"
651 int shadowframecount = 0;
653 int Light_CullBox(const vec3_t mins, const vec3_t maxs)
656 mnode_t *node, *stack[4096];
657 if (cl.worldmodel == NULL)
660 stack[stackpos++] = cl.worldmodel->nodes;
663 node = stack[--stackpos];
664 if (node->contents < 0)
666 if (((mleaf_t *)node)->worldnodeframe == shadowframecount)
671 sides = BoxOnPlaneSide(mins, maxs, node->plane);
672 if (sides & 2 && stackpos < 4096)
673 stack[stackpos++] = node->children[1];
674 if (sides & 1 && stackpos < 4096)
675 stack[stackpos++] = node->children[0];
681 int LightAndVis_CullBox(const vec3_t mins, const vec3_t maxs)
684 mnode_t *node, *stack[4096];
685 if (R_CullBox(mins, maxs))
687 if (cl.worldmodel == NULL)
690 stack[stackpos++] = cl.worldmodel->nodes;
693 node = stack[--stackpos];
694 if (node->contents < 0)
696 if (((mleaf_t *)node)->visframe == r_framecount && ((mleaf_t *)node)->worldnodeframe == shadowframecount)
701 sides = BoxOnPlaneSide(mins, maxs, node->plane);
702 if (sides & 2 && stackpos < 4096)
703 stack[stackpos++] = node->children[1];
704 if (sides & 1 && stackpos < 4096)
705 stack[stackpos++] = node->children[0];
711 int LightAndVis_CullPointCloud(int numpoints, const float *points)
716 mnode_t *node, *stack[4096];
717 //if (R_CullBox(mins, maxs))
719 if (cl.worldmodel == NULL)
722 stack[stackpos++] = cl.worldmodel->nodes;
725 node = stack[--stackpos];
726 if (node->contents < 0)
728 if (((mleaf_t *)node)->visframe == r_framecount && ((mleaf_t *)node)->worldnodeframe == shadowframecount)
734 for (i = 0, p = points;i < numpoints && sides != 3;i++, p += 3)
736 if (DotProduct(p, node->plane->normal) < node->plane->dist)
741 if (sides & 2 && stackpos < 4096)
742 stack[stackpos++] = node->children[1];
743 if (sides & 1 && stackpos < 4096)
744 stack[stackpos++] = node->children[0];
751 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)
753 vec3_t relativelightorigin;
757 float dist, projectdistance;
761 if (!(ent->flags & RENDER_SHADOW) || ent->model == NULL || ent->model->DrawShadowVolume == NULL)
763 if (r_shadow_cull.integer)
765 if (ent->maxs[0] < lightmins[0] || ent->mins[0] > lightmaxs[0]
766 || ent->maxs[1] < lightmins[1] || ent->mins[1] > lightmaxs[1]
767 || ent->maxs[2] < lightmins[2] || ent->mins[2] > lightmaxs[2]
768 || (lightmarked && Light_CullBox(ent->mins, ent->maxs)))
772 if (r_shadow_cull.integer)
774 projectdistance = cullradius;
775 // calculate projected bounding box and decide if it is on-screen
776 for (i = 0;i < 8;i++)
778 temp[0] = i & 1 ? ent->model->normalmaxs[0] : ent->model->normalmins[0];
779 temp[1] = i & 2 ? ent->model->normalmaxs[1] : ent->model->normalmins[1];
780 temp[2] = i & 4 ? ent->model->normalmaxs[2] : ent->model->normalmins[2];
781 Matrix4x4_Transform(&ent->matrix, temp, points[i]);
782 VectorSubtract(points[i], lightorigin, temp);
783 dist = projectdistance / sqrt(DotProduct(temp, temp));
784 VectorMA(lightorigin, dist, temp, points[i+8]);
786 if (LightAndVis_CullPointCloud(16, points[0]))
789 for (i = 0;i < 8;i++)
791 p2[0] = i & 1 ? ent->model->normalmaxs[0] : ent->model->normalmins[0];
792 p2[1] = i & 2 ? ent->model->normalmaxs[1] : ent->model->normalmins[1];
793 p2[2] = i & 4 ? ent->model->normalmaxs[2] : ent->model->normalmins[2];
794 Matrix4x4_Transform(&ent->matrix, p2, p);
795 VectorSubtract(p, lightorigin, temp);
796 dist = projectdistance / sqrt(DotProduct(temp, temp));
797 VectorMA(p, dist, temp, p2);
800 if (mins[0] > p[0]) mins[0] = p[0];if (maxs[0] < p[0]) maxs[0] = p[0];
801 if (mins[1] > p[1]) mins[1] = p[1];if (maxs[1] < p[1]) maxs[1] = p[1];
802 if (mins[2] > p[2]) mins[2] = p[2];if (maxs[2] < p[2]) maxs[2] = p[2];
809 if (mins[0] > p2[0]) mins[0] = p2[0];if (maxs[0] < p2[0]) maxs[0] = p2[0];
810 if (mins[1] > p2[1]) mins[1] = p2[1];if (maxs[1] < p2[1]) maxs[1] = p2[1];
811 if (mins[2] > p2[2]) mins[2] = p2[2];if (maxs[2] < p2[2]) maxs[2] = p2[2];
813 if (mins[0] >= clipmaxs[0] || maxs[0] <= clipmins[0]
814 || mins[1] >= clipmaxs[1] || maxs[1] <= clipmins[1]
815 || mins[2] >= clipmaxs[2] || maxs[2] <= clipmins[2]
816 || LightAndVis_CullBox(mins, maxs))
821 Matrix4x4_Transform(&ent->inversematrix, lightorigin, relativelightorigin);
822 ent->model->DrawShadowVolume (ent, relativelightorigin, lightradius);
825 void R_Shadow_DrawWorldLightShadowVolume(matrix4x4_t *matrix, worldlight_t *light);
827 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);
828 void R_ShadowVolumeLighting (int visiblevolumes)
831 entity_render_t *ent;
833 float f, lightradius, cullradius;
834 vec3_t relativelightorigin, relativeeyeorigin, lightcolor, clipmins, clipmaxs;
840 matrix4x4_t matrix_worldtofilter, matrix_worldtoattenuationxyz, matrix_worldtoattenuationz;
841 matrix4x4_t matrix_modeltofilter, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz;
845 memset(&m, 0, sizeof(m));
846 R_Mesh_State_Texture(&m);
848 GL_BlendFunc(GL_ONE, GL_ONE);
850 GL_DepthTest(r_shadow_visiblevolumes.integer < 2);
851 qglDisable(GL_CULL_FACE);
852 GL_Color(0.0 * r_colorscale, 0.0125 * r_colorscale, 0.1 * r_colorscale, 1);
855 R_Shadow_Stage_Begin();
857 if (r_shadow_realtime_world.integer)
859 R_Shadow_LoadWorldLightsIfNeeded();
860 for (lnum = 0, wl = r_shadow_worldlightchain;wl;wl = wl->next, lnum++)
862 if (d_lightstylevalue[wl->style] <= 0)
864 if (R_CullBox(wl->mins, wl->maxs))
865 //if (R_CullSphere(wl->origin, cullradius))
867 //if (R_CullBox(wl->mins, wl->maxs) || R_CullSphere(wl->origin, lightradius))
869 //if (VIS_CullBox(wl->mins, wl->maxs) || VIS_CullSphere(wl->origin, lightradius))
871 if (r_shadow_debuglight.integer >= 0 && lnum != r_shadow_debuglight.integer)
874 cullradius = wl->cullradius;
875 lightradius = wl->lightradius;
877 if (cl.worldmodel != NULL)
879 for (i = 0;i < wl->numleafs;i++)
880 if (wl->leafs[i]->visframe == r_framecount)
882 if (i == wl->numleafs)
884 leaf = wl->leafs[i++];
885 VectorCopy(leaf->mins, clipmins);
886 VectorCopy(leaf->maxs, clipmaxs);
887 for (;i < wl->numleafs;i++)
890 if (leaf->visframe == r_framecount)
892 if (clipmins[0] > leaf->mins[0]) clipmins[0] = leaf->mins[0];
893 if (clipmaxs[0] < leaf->maxs[0]) clipmaxs[0] = leaf->maxs[0];
894 if (clipmins[1] > leaf->mins[1]) clipmins[1] = leaf->mins[1];
895 if (clipmaxs[1] < leaf->maxs[1]) clipmaxs[1] = leaf->maxs[1];
896 if (clipmins[2] > leaf->mins[2]) clipmins[2] = leaf->mins[2];
897 if (clipmaxs[2] < leaf->maxs[2]) clipmaxs[2] = leaf->maxs[2];
900 if (clipmins[0] < wl->mins[0]) clipmins[0] = wl->mins[0];
901 if (clipmaxs[0] > wl->maxs[0]) clipmaxs[0] = wl->maxs[0];
902 if (clipmins[1] < wl->mins[1]) clipmins[1] = wl->mins[1];
903 if (clipmaxs[1] > wl->maxs[1]) clipmaxs[1] = wl->maxs[1];
904 if (clipmins[2] < wl->mins[2]) clipmins[2] = wl->mins[2];
905 if (clipmaxs[2] > wl->maxs[2]) clipmaxs[2] = wl->maxs[2];
909 VectorCopy(wl->mins, clipmins);
910 VectorCopy(wl->maxs, clipmaxs);
913 //if (R_Shadow_ScissorForBBoxAndSphere(clipmins, clipmaxs, wl->origin, wl->cullradius))
914 if (R_CullBox(clipmins, clipmaxs) || R_Shadow_ScissorForBBox(clipmins, clipmaxs))
917 // mark the leafs we care about so only things in those leafs will matter
918 if (cl.worldmodel != NULL)
919 for (i = 0;i < wl->numleafs;i++)
920 wl->leafs[i]->worldnodeframe = shadowframecount;
922 f = d_lightstylevalue[wl->style] * (1.0f / 256.0f);
923 VectorScale(wl->light, f, lightcolor);
926 f = 2 + sin(realtime * M_PI * 4.0);
927 VectorScale(lightcolor, f, lightcolor);
930 if (wl->castshadows && (gl_stencil || visiblevolumes))
933 R_Shadow_Stage_ShadowVolumes();
934 ent = &cl_entities[0].render;
935 if (wl->shadowvolume && r_shadow_staticworldlights.integer)
936 R_Shadow_DrawWorldLightShadowVolume(&ent->matrix, wl);
938 R_TestAndDrawShadowVolume(ent, wl->origin, cullradius, lightradius, wl->mins, wl->maxs, clipmins, clipmaxs, true);
939 if (r_drawentities.integer)
940 for (i = 0;i < r_refdef.numentities;i++)
941 R_TestAndDrawShadowVolume(r_refdef.entities[i], wl->origin, cullradius, lightradius, wl->mins, wl->maxs, clipmins, clipmaxs, true);
946 if (wl->castshadows && gl_stencil)
947 R_Shadow_Stage_LightWithShadows();
949 R_Shadow_Stage_LightWithoutShadows();
951 // calculate world to filter matrix
952 Matrix4x4_CreateFromQuakeEntity(&matrix, wl->origin[0], wl->origin[1], wl->origin[2], wl->angles[0], wl->angles[1], wl->angles[2], lightradius);
953 Matrix4x4_Invert_Simple(&matrix_worldtofilter, &matrix);
954 // calculate world to attenuationxyz/xy matrix
955 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5, 0.5, 0.5, 0, 0, 0, 0.5);
956 Matrix4x4_Concat(&matrix_worldtoattenuationxyz, &matrix, &matrix_worldtofilter);
957 // calculate world to attenuationz matrix
958 matrix.m[0][0] = 0;matrix.m[0][1] = 0;matrix.m[0][2] = 0.5;matrix.m[0][3] = 0.5;
959 matrix.m[1][0] = 0;matrix.m[1][1] = 0;matrix.m[1][2] = 0 ;matrix.m[1][3] = 0.5;
960 matrix.m[2][0] = 0;matrix.m[2][1] = 0;matrix.m[2][2] = 0 ;matrix.m[2][3] = 0.5;
961 matrix.m[3][0] = 0;matrix.m[3][1] = 0;matrix.m[3][2] = 0 ;matrix.m[3][3] = 1;
962 Matrix4x4_Concat(&matrix_worldtoattenuationz, &matrix, &matrix_worldtofilter);
964 ent = &cl_entities[0].render;
965 if (ent->model && ent->model->DrawLight)
967 Matrix4x4_Transform(&ent->inversematrix, wl->origin, relativelightorigin);
968 Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin);
969 Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
970 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
971 Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
973 R_Model_Brush_DrawLightForSurfaceList(ent, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, wl->surfaces, wl->numsurfaces, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
975 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
977 if (r_drawentities.integer)
979 for (i = 0;i < r_refdef.numentities;i++)
981 ent = r_refdef.entities[i];
982 if (ent->visframe == r_framecount && ent->model && ent->model->DrawLight
983 && BoxesOverlap(ent->mins, ent->maxs, clipmins, clipmaxs)
984 && !(ent->effects & EF_ADDITIVE) && ent->alpha == 1)
986 Matrix4x4_Transform(&ent->inversematrix, wl->origin, relativelightorigin);
987 Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin);
988 Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
989 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
990 Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
991 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
998 if (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer)
1000 for (lnum = 0, rd = r_dlight;lnum < r_numdlights;lnum++, rd++)
1002 lightradius = rd->cullradius;
1003 clipmins[0] = rd->origin[0] - lightradius;
1004 clipmins[1] = rd->origin[1] - lightradius;
1005 clipmins[2] = rd->origin[2] - lightradius;
1006 clipmaxs[0] = rd->origin[0] + lightradius;
1007 clipmaxs[1] = rd->origin[1] + lightradius;
1008 clipmaxs[2] = rd->origin[2] + lightradius;
1009 if (VIS_CullBox(clipmins, clipmaxs) || R_Shadow_ScissorForBBox(clipmins, clipmaxs))
1012 cullradius = RadiusFromBoundsAndOrigin(clipmins, clipmaxs, rd->origin);
1013 VectorScale(rd->light, (1.0f / 4096.0f), lightcolor);
1015 if (gl_stencil || visiblevolumes)
1017 if (!visiblevolumes)
1018 R_Shadow_Stage_ShadowVolumes();
1019 ent = &cl_entities[0].render;
1020 R_TestAndDrawShadowVolume(ent, rd->origin, cullradius, lightradius, clipmins, clipmaxs, clipmins, clipmaxs, false);
1021 if (r_drawentities.integer)
1023 for (i = 0;i < r_refdef.numentities;i++)
1025 ent = r_refdef.entities[i];
1027 R_TestAndDrawShadowVolume(ent, rd->origin, cullradius, lightradius, clipmins, clipmaxs, clipmins, clipmaxs, false);
1032 if (!visiblevolumes)
1035 R_Shadow_Stage_LightWithShadows();
1037 R_Shadow_Stage_LightWithoutShadows();
1039 // calculate world to filter matrix
1040 Matrix4x4_CreateFromQuakeEntity(&matrix, rd->origin[0], rd->origin[1], rd->origin[2], 0, 0, 0, lightradius);
1041 Matrix4x4_Invert_Simple(&matrix_worldtofilter, &matrix);
1042 // calculate world to attenuationxyz/xy matrix
1043 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5, 0.5, 0.5, 0, 0, 0, 0.5);
1044 Matrix4x4_Concat(&matrix_worldtoattenuationxyz, &matrix, &matrix_worldtofilter);
1045 // calculate world to attenuationz matrix
1046 matrix.m[0][0] = 0;matrix.m[0][1] = 0;matrix.m[0][2] = 0.5;matrix.m[0][3] = 0.5;
1047 matrix.m[1][0] = 0;matrix.m[1][1] = 0;matrix.m[1][2] = 0 ;matrix.m[1][3] = 0.5;
1048 matrix.m[2][0] = 0;matrix.m[2][1] = 0;matrix.m[2][2] = 0 ;matrix.m[2][3] = 0.5;
1049 matrix.m[3][0] = 0;matrix.m[3][1] = 0;matrix.m[3][2] = 0 ;matrix.m[3][3] = 1;
1050 Matrix4x4_Concat(&matrix_worldtoattenuationz, &matrix, &matrix_worldtofilter);
1052 ent = &cl_entities[0].render;
1053 if (ent->model && ent->model->DrawLight)
1055 Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin);
1056 Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin);
1057 Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
1058 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
1059 Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
1060 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
1062 if (r_drawentities.integer)
1064 for (i = 0;i < r_refdef.numentities;i++)
1066 ent = r_refdef.entities[i];
1067 if (ent->visframe == r_framecount && ent->model && ent->model->DrawLight
1068 && BoxesOverlap(ent->mins, ent->maxs, clipmins, clipmaxs)
1069 && !(ent->effects & EF_ADDITIVE) && ent->alpha == 1)
1071 Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin);
1072 Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin);
1073 Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
1074 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
1075 Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
1076 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
1085 qglEnable(GL_CULL_FACE);
1087 R_Shadow_Stage_End();
1088 qglDisable(GL_SCISSOR_TEST);
1091 static void R_SetFrustum (void)
1093 // LordHavoc: note to all quake engine coders, the special case for 90
1094 // degrees assumed a square view (wrong), so I removed it, Quake2 has it
1095 // disabled as well.
1097 // rotate VPN right by FOV_X/2 degrees
1098 RotatePointAroundVector( frustum[0].normal, vup, vpn, -(90-r_refdef.fov_x / 2 ) );
1099 frustum[0].dist = DotProduct (r_origin, frustum[0].normal);
1100 PlaneClassify(&frustum[0]);
1102 // rotate VPN left by FOV_X/2 degrees
1103 RotatePointAroundVector( frustum[1].normal, vup, vpn, 90-r_refdef.fov_x / 2 );
1104 frustum[1].dist = DotProduct (r_origin, frustum[1].normal);
1105 PlaneClassify(&frustum[1]);
1107 // rotate VPN up by FOV_X/2 degrees
1108 RotatePointAroundVector( frustum[2].normal, vright, vpn, 90-r_refdef.fov_y / 2 );
1109 frustum[2].dist = DotProduct (r_origin, frustum[2].normal);
1110 PlaneClassify(&frustum[2]);
1112 // rotate VPN down by FOV_X/2 degrees
1113 RotatePointAroundVector( frustum[3].normal, vright, vpn, -( 90 - r_refdef.fov_y / 2 ) );
1114 frustum[3].dist = DotProduct (r_origin, frustum[3].normal);
1115 PlaneClassify(&frustum[3]);
1123 static void R_SetupFrame (void)
1125 // don't allow cheats in multiplayer
1126 if (cl.maxclients > 1)
1128 if (r_fullbright.integer != 0)
1129 Cvar_Set ("r_fullbright", "0");
1130 if (r_ambient.value != 0)
1131 Cvar_Set ("r_ambient", "0");
1136 // build the transformation matrix for the given view angles
1137 VectorCopy (r_refdef.vieworg, r_origin);
1139 AngleVectors (r_refdef.viewangles, vpn, vright, vup);
1145 static void R_BlendView(void)
1149 float vertex3f[3*3];
1151 if (r_refdef.viewblend[3] < 0.01f)
1154 R_Mesh_Matrix(&r_identitymatrix);
1156 memset(&m, 0, sizeof(m));
1157 R_Mesh_State_Texture(&m);
1159 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1161 GL_DepthTest(false); // magic
1162 GL_VertexPointer(vertex3f);
1163 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1165 vertex3f[0] = r_origin[0] + vpn[0] * 1.5 - vright[0] * r - vup[0] * r;
1166 vertex3f[1] = r_origin[1] + vpn[1] * 1.5 - vright[1] * r - vup[1] * r;
1167 vertex3f[2] = r_origin[2] + vpn[2] * 1.5 - vright[2] * r - vup[2] * r;
1168 vertex3f[3] = r_origin[0] + vpn[0] * 1.5 - vright[0] * r + vup[0] * r * 3;
1169 vertex3f[4] = r_origin[1] + vpn[1] * 1.5 - vright[1] * r + vup[1] * r * 3;
1170 vertex3f[5] = r_origin[2] + vpn[2] * 1.5 - vright[2] * r + vup[2] * r * 3;
1171 vertex3f[6] = r_origin[0] + vpn[0] * 1.5 + vright[0] * r * 3 - vup[0] * r;
1172 vertex3f[7] = r_origin[1] + vpn[1] * 1.5 + vright[1] * r * 3 - vup[1] * r;
1173 vertex3f[8] = r_origin[2] + vpn[2] * 1.5 + vright[2] * r * 3 - vup[2] * r;
1174 R_Mesh_Draw(3, 1, polygonelements);
1181 r_refdef must be set before the first call
1184 extern void R_DrawLightningBeams (void);
1185 void R_RenderView (void)
1187 entity_render_t *world;
1188 if (!r_refdef.entities/* || !cl.worldmodel*/)
1189 return; //Host_Error ("R_RenderView: NULL worldmodel");
1191 if (r_shadow_realtime_world.integer)
1195 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");
1196 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
1200 world = &cl_entities[0].render;
1202 // FIXME: move to client
1204 R_TimeReport("mexplosion");
1212 R_TimeReport("setup");
1214 R_WorldVisibility(world);
1215 R_TimeReport("worldvis");
1217 R_FarClip_Start(r_origin, vpn, 768.0f);
1219 r_farclip = R_FarClip_Finish() + 256.0f;
1220 R_TimeReport("markentity");
1222 GL_SetupView_ViewPort(r_refdef.x, r_refdef.y, r_refdef.width, r_refdef.height);
1223 if (r_shadow_realtime_world.integer || gl_stencil)
1224 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.fov_x, r_refdef.fov_y, 1.0f);
1226 GL_SetupView_Mode_Perspective(r_refdef.fov_x, r_refdef.fov_y, 1.0f, r_farclip);
1227 GL_SetupView_Orientation_FromEntity (r_refdef.vieworg, r_refdef.viewangles);
1228 qglDepthFunc(GL_LEQUAL);
1231 R_MeshQueue_BeginScene();
1233 R_Shadow_UpdateWorldLightSelection();
1235 if (R_DrawBrushModelsSky())
1236 R_TimeReport("bmodelsky");
1238 // must occur early because it can draw sky
1240 R_TimeReport("world");
1242 // don't let sound skip if going slow
1243 if (!intimerefresh && !r_speeds.integer)
1246 R_DrawModels(r_shadow_realtime_world.integer);
1247 R_TimeReport("models");
1249 if (r_shadows.integer == 1 && !r_shadow_realtime_world.integer)
1251 R_DrawFakeShadows();
1252 R_TimeReport("fakeshadow");
1255 if (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer)
1257 R_ShadowVolumeLighting(false);
1258 R_TimeReport("dynlight");
1261 R_DrawLightningBeams();
1262 R_TimeReport("lightning");
1265 R_TimeReport("particles");
1268 R_TimeReport("explosions");
1270 R_MeshQueue_RenderTransparent();
1271 R_TimeReport("drawtrans");
1274 R_TimeReport("coronas");
1276 R_DrawWorldCrosshair();
1277 R_TimeReport("crosshair");
1280 R_TimeReport("blendview");
1282 R_MeshQueue_Render();
1283 R_MeshQueue_EndScene();
1285 if (r_shadow_visiblevolumes.integer)
1287 R_ShadowVolumeLighting(true);
1288 R_TimeReport("shadowvolume");
1292 R_TimeReport("meshfinish");
1296 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1299 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1301 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1302 GL_DepthMask(false);
1304 R_Mesh_Matrix(&r_identitymatrix);
1306 memset(&m, 0, sizeof(m));
1307 R_Mesh_State_Texture(&m);
1310 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1311 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1312 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1313 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1314 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1315 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1316 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1317 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1318 GL_ColorPointer(color);
1319 R_FillColors(color, 8, cr * r_colorscale, cg * r_colorscale, cb * r_colorscale, ca);
1322 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1324 VectorSubtract(v, r_origin, diff);
1325 f2 = exp(fogdensity/DotProduct(diff, diff));
1328 c[0] = c[0] * f1 + fogcolor[0] * f2;
1329 c[1] = c[1] * f1 + fogcolor[1] * f2;
1330 c[2] = c[2] * f1 + fogcolor[2] * f2;
1337 int nomodelelements[24] =
1349 float nomodelvertex3f[6*3] =
1359 float nomodelcolor4f[6*4] =
1361 0.0f, 0.0f, 0.5f, 1.0f,
1362 0.0f, 0.0f, 0.5f, 1.0f,
1363 0.0f, 0.5f, 0.0f, 1.0f,
1364 0.0f, 0.5f, 0.0f, 1.0f,
1365 0.5f, 0.0f, 0.0f, 1.0f,
1366 0.5f, 0.0f, 0.0f, 1.0f
1369 void R_DrawNoModelCallback(const void *calldata1, int calldata2)
1371 const entity_render_t *ent = calldata1;
1373 float f1, f2, *c, diff[3];
1376 R_Mesh_Matrix(&ent->matrix);
1378 memset(&m, 0, sizeof(m));
1379 R_Mesh_State_Texture(&m);
1381 if (ent->flags & EF_ADDITIVE)
1383 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1384 GL_DepthMask(false);
1386 else if (ent->alpha < 1)
1388 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1389 GL_DepthMask(false);
1393 GL_BlendFunc(GL_ONE, GL_ZERO);
1397 GL_VertexPointer(nomodelvertex3f);
1400 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1401 GL_ColorPointer(color4f);
1402 VectorSubtract(ent->origin, r_origin, diff);
1403 f2 = exp(fogdensity/DotProduct(diff, diff));
1405 for (i = 0, c = color4f;i < 6;i++, c += 4)
1407 c[0] = (c[0] * f1 + fogcolor[0] * f2) * r_colorscale;
1408 c[1] = (c[1] * f1 + fogcolor[1] * f2) * r_colorscale;
1409 c[2] = (c[2] * f1 + fogcolor[2] * f2) * r_colorscale;
1413 else if (r_colorscale != 1 || ent->alpha != 1)
1415 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1416 GL_ColorPointer(color4f);
1417 for (i = 0, c = color4f;i < 6;i++, c += 4)
1419 c[0] *= r_colorscale;
1420 c[1] *= r_colorscale;
1421 c[2] *= r_colorscale;
1426 GL_ColorPointer(nomodelcolor4f);
1427 R_Mesh_Draw(6, 8, nomodelelements);
1430 void R_DrawNoModel(entity_render_t *ent)
1432 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1433 R_MeshQueue_AddTransparent(ent->origin, R_DrawNoModelCallback, ent, 0);
1435 // R_DrawNoModelCallback(ent, 0);
1438 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1440 vec3_t right1, right2, diff, normal;
1442 VectorSubtract (org2, org1, normal);
1443 VectorNormalizeFast (normal);
1445 // calculate 'right' vector for start
1446 VectorSubtract (r_origin, org1, diff);
1447 VectorNormalizeFast (diff);
1448 CrossProduct (normal, diff, right1);
1450 // calculate 'right' vector for end
1451 VectorSubtract (r_origin, org2, diff);
1452 VectorNormalizeFast (diff);
1453 CrossProduct (normal, diff, right2);
1455 vert[ 0] = org1[0] + width * right1[0];
1456 vert[ 1] = org1[1] + width * right1[1];
1457 vert[ 2] = org1[2] + width * right1[2];
1458 vert[ 3] = org1[0] - width * right1[0];
1459 vert[ 4] = org1[1] - width * right1[1];
1460 vert[ 5] = org1[2] - width * right1[2];
1461 vert[ 6] = org2[0] - width * right2[0];
1462 vert[ 7] = org2[1] - width * right2[1];
1463 vert[ 8] = org2[2] - width * right2[2];
1464 vert[ 9] = org2[0] + width * right2[0];
1465 vert[10] = org2[1] + width * right2[1];
1466 vert[11] = org2[2] + width * right2[2];
1469 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
1471 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)
1478 VectorSubtract(origin, r_origin, diff);
1479 ca *= 1 - exp(fogdensity/DotProduct(diff,diff));
1482 R_Mesh_Matrix(&r_identitymatrix);
1483 GL_Color(cr * r_colorscale, cg * r_colorscale, cb * r_colorscale, ca);
1484 GL_VertexPointer(varray_vertex3f);
1485 GL_BlendFunc(blendfunc1, blendfunc2);
1486 GL_DepthMask(false);
1487 GL_DepthTest(!depthdisable);
1489 memset(&m, 0, sizeof(m));
1490 m.tex[0] = R_GetTexture(texture);
1491 m.pointer_texcoord[0] = spritetexcoord2f;
1492 R_Mesh_State_Texture(&m);
1494 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
1495 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
1496 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
1497 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
1498 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
1499 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
1500 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
1501 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
1502 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
1503 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
1504 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
1505 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
1506 R_Mesh_Draw(4, 2, polygonelements);