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 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
76 for (i = 0;i < verts;i++)
87 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
90 for (i = 0;i < verts;i++)
104 For program optimization
107 qboolean intimerefresh = 0;
108 static void R_TimeRefresh_f (void)
111 float start, stop, time;
114 start = Sys_DoubleTime ();
115 for (i = 0;i < 128;i++)
117 r_refdef.viewangles[0] = 0;
118 r_refdef.viewangles[1] = i/128.0*360.0;
119 r_refdef.viewangles[2] = 0;
123 stop = Sys_DoubleTime ();
126 Con_Printf ("%f seconds (%f fps)\n", time, 128/time);
131 float fog_density, fog_red, fog_green, fog_blue;
133 qboolean oldgl_fogenable;
134 void R_SetupFog(void)
136 if (gamemode == GAME_NEHAHRA)
138 if (gl_fogenable.integer)
140 oldgl_fogenable = true;
141 fog_density = gl_fogdensity.value;
142 fog_red = gl_fogred.value;
143 fog_green = gl_foggreen.value;
144 fog_blue = gl_fogblue.value;
146 else if (oldgl_fogenable)
148 oldgl_fogenable = false;
157 fogcolor[0] = fog_red = bound(0.0f, fog_red , 1.0f);
158 fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
159 fogcolor[2] = fog_blue = bound(0.0f, fog_blue , 1.0f);
164 fogdensity = -4000.0f / (fog_density * fog_density);
165 // fog color was already set
171 // FIXME: move this to client?
174 if (gamemode == GAME_NEHAHRA)
176 Cvar_Set("gl_fogenable", "0");
177 Cvar_Set("gl_fogdensity", "0.2");
178 Cvar_Set("gl_fogred", "0.3");
179 Cvar_Set("gl_foggreen", "0.3");
180 Cvar_Set("gl_fogblue", "0.3");
182 fog_density = fog_red = fog_green = fog_blue = 0.0f;
185 // FIXME: move this to client?
186 void FOG_registercvars(void)
188 if (gamemode == GAME_NEHAHRA)
190 Cvar_RegisterVariable (&gl_fogenable);
191 Cvar_RegisterVariable (&gl_fogdensity);
192 Cvar_RegisterVariable (&gl_fogred);
193 Cvar_RegisterVariable (&gl_foggreen);
194 Cvar_RegisterVariable (&gl_fogblue);
195 Cvar_RegisterVariable (&gl_fogstart);
196 Cvar_RegisterVariable (&gl_fogend);
200 void gl_main_start(void)
204 void gl_main_shutdown(void)
208 extern void CL_ParseEntityLump(char *entitystring);
209 void gl_main_newmap(void)
211 if (cl.worldmodel && cl.worldmodel->entities)
212 CL_ParseEntityLump(cl.worldmodel->entities);
216 void GL_Main_Init(void)
218 Matrix4x4_CreateIdentity(&r_identitymatrix);
219 // FIXME: move this to client?
221 Cmd_AddCommand ("timerefresh", R_TimeRefresh_f);
222 Cvar_RegisterVariable (&r_drawentities);
223 Cvar_RegisterVariable (&r_drawviewmodel);
224 Cvar_RegisterVariable (&r_shadows);
225 Cvar_RegisterVariable (&r_shadow_staticworldlights);
226 Cvar_RegisterVariable (&r_speeds);
227 Cvar_RegisterVariable (&r_fullbrights);
228 Cvar_RegisterVariable (&r_wateralpha);
229 Cvar_RegisterVariable (&r_dynamic);
230 Cvar_RegisterVariable (&r_fullbright);
231 Cvar_RegisterVariable (&r_textureunits);
232 Cvar_RegisterVariable (&r_shadow_cull);
233 if (gamemode == GAME_NEHAHRA || gamemode == GAME_NEXUIZ)
234 Cvar_SetValue("r_fullbrights", 0);
235 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
238 vec3_t r_farclip_origin;
239 vec3_t r_farclip_direction;
240 vec_t r_farclip_directiondist;
241 vec_t r_farclip_meshfarclip;
242 int r_farclip_directionbit0;
243 int r_farclip_directionbit1;
244 int r_farclip_directionbit2;
246 // start a farclip measuring session
247 void R_FarClip_Start(vec3_t origin, vec3_t direction, vec_t startfarclip)
249 VectorCopy(origin, r_farclip_origin);
250 VectorCopy(direction, r_farclip_direction);
251 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
252 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
253 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
254 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
255 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
258 // enlarge farclip to accomodate box
259 void R_FarClip_Box(vec3_t mins, vec3_t maxs)
262 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
263 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
264 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
265 if (r_farclip_meshfarclip < d)
266 r_farclip_meshfarclip = d;
269 // return farclip value
270 float R_FarClip_Finish(void)
272 return r_farclip_meshfarclip - r_farclip_directiondist;
275 extern void R_Textures_Init(void);
276 extern void Mod_RenderInit(void);
277 extern void GL_Draw_Init(void);
278 extern void GL_Main_Init(void);
279 extern void R_Shadow_Init(void);
280 extern void GL_Models_Init(void);
281 extern void R_Sky_Init(void);
282 extern void GL_Surf_Init(void);
283 extern void R_Crosshairs_Init(void);
284 extern void R_Light_Init(void);
285 extern void R_Particles_Init(void);
286 extern void R_Explosion_Init(void);
287 extern void ui_init(void);
288 extern void gl_backend_init(void);
289 extern void Sbar_Init(void);
291 void Render_Init(void)
316 extern char *ENGINE_EXTENSIONS;
319 VID_CheckExtensions();
321 // LordHavoc: report supported extensions
322 Con_DPrintf("\nengine extensions: %s\n", ENGINE_EXTENSIONS);
325 int R_CullBox(const vec3_t mins, const vec3_t maxs)
329 for (i = 0;i < 4;i++)
336 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
340 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
344 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
348 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
352 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
356 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
360 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
364 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
372 int PVS_CullBox(const vec3_t mins, const vec3_t maxs)
375 mnode_t *node, *stack[4096];
376 if (cl.worldmodel == NULL)
379 stack[stackpos++] = cl.worldmodel->nodes;
382 node = stack[--stackpos];
383 if (node->contents < 0)
385 if (((mleaf_t *)node)->pvsframe == cl.worldmodel->pvsframecount)
390 sides = BoxOnPlaneSide(mins, maxs, node->plane);
391 if (sides & 2 && stackpos < 4096)
392 stack[stackpos++] = node->children[1];
393 if (sides & 1 && stackpos < 4096)
394 stack[stackpos++] = node->children[0];
400 int VIS_CullBox(const vec3_t mins, const vec3_t maxs)
403 mnode_t *node, *stack[4096];
404 if (R_CullBox(mins, maxs))
406 if (cl.worldmodel == NULL)
409 stack[stackpos++] = cl.worldmodel->nodes;
412 node = stack[--stackpos];
413 if (node->contents < 0)
415 if (((mleaf_t *)node)->visframe == r_framecount)
420 sides = BoxOnPlaneSide(mins, maxs, node->plane);
421 if (sides & 2 && stackpos < 4096)
422 stack[stackpos++] = node->children[1];
423 if (sides & 1 && stackpos < 4096)
424 stack[stackpos++] = node->children[0];
430 int R_CullSphere(const vec3_t origin, vec_t radius)
432 return (DotProduct(frustum[0].normal, origin) + radius < frustum[0].dist
433 || DotProduct(frustum[1].normal, origin) + radius < frustum[1].dist
434 || DotProduct(frustum[2].normal, origin) + radius < frustum[2].dist
435 || DotProduct(frustum[3].normal, origin) + radius < frustum[3].dist);
438 int PVS_CullSphere(const vec3_t origin, vec_t radius)
441 mnode_t *node, *stack[4096];
443 if (cl.worldmodel == NULL)
446 stack[stackpos++] = cl.worldmodel->nodes;
449 node = stack[--stackpos];
450 if (node->contents < 0)
452 if (((mleaf_t *)node)->pvsframe == cl.worldmodel->pvsframecount)
457 dist = PlaneDiff(origin, node->plane);
459 stack[stackpos++] = node->children[1];
461 stack[stackpos++] = node->children[0];
467 int VIS_CullSphere(const vec3_t origin, vec_t radius)
470 mnode_t *node, *stack[4096];
472 if (R_CullSphere(origin, radius))
474 if (cl.worldmodel == NULL)
477 stack[stackpos++] = cl.worldmodel->nodes;
480 node = stack[--stackpos];
481 if (node->contents < 0)
483 if (((mleaf_t *)node)->visframe == r_framecount)
488 dist = PlaneDiff(origin, node->plane);
490 stack[stackpos++] = node->children[1];
492 stack[stackpos++] = node->children[0];
499 //==================================================================================
501 static void R_MarkEntities (void)
504 entity_render_t *ent;
506 ent = &cl_entities[0].render;
507 Matrix4x4_CreateIdentity(&ent->matrix);
508 Matrix4x4_CreateIdentity(&ent->inversematrix);
511 R_FarClip_Box(cl.worldmodel->normalmins, cl.worldmodel->normalmaxs);
513 if (!r_drawentities.integer)
516 for (i = 0;i < r_refdef.numentities;i++)
518 ent = r_refdef.entities[i];
519 Mod_CheckLoaded(ent->model);
520 // some of the renderer still relies on origin...
521 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
522 // some of the renderer still relies on scale...
523 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
524 R_LerpAnimation(ent);
525 R_UpdateEntLights(ent);
526 if ((chase_active.integer || !(ent->flags & RENDER_EXTERIORMODEL))
527 && !VIS_CullSphere(ent->origin, (ent->model != NULL ? ent->model->radius : 16) * ent->scale)
528 && !VIS_CullBox(ent->mins, ent->maxs))
530 ent->visframe = r_framecount;
531 R_FarClip_Box(ent->mins, ent->maxs);
536 // only used if skyrendermasked, and normally returns false
537 int R_DrawBrushModelsSky (void)
540 entity_render_t *ent;
542 if (!r_drawentities.integer)
546 for (i = 0;i < r_refdef.numentities;i++)
548 ent = r_refdef.entities[i];
549 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
551 ent->model->DrawSky(ent);
564 void R_DrawViewModel (void)
566 entity_render_t *ent;
568 // FIXME: move these checks to client
569 if (!r_drawviewmodel.integer || chase_active.integer || envmap || !r_drawentities.integer || cl.items & IT_INVISIBILITY || cl.stats[STAT_HEALTH] <= 0 || !cl.viewent.render.model)
572 ent = &cl.viewent.render;
573 Mod_CheckLoaded(ent->model);
574 R_LerpAnimation(ent);
575 Matrix4x4_CreateFromQuakeEntity(&ent->matrix, ent->origin[0], ent->origin[1], ent->origin[2], -ent->angles[0], ent->angles[1], ent->angles[2], ent->scale);
576 Matrix4x4_Invert_Simple(&ent->inversematrix, &ent->matrix);
577 R_UpdateEntLights(ent);
578 ent->model->Draw(ent);
582 void R_DrawNoModel(entity_render_t *ent);
586 entity_render_t *ent;
588 if (!r_drawentities.integer)
591 for (i = 0;i < r_refdef.numentities;i++)
593 ent = r_refdef.entities[i];
594 if (ent->visframe == r_framecount)
596 if (ent->model && ent->model->Draw != NULL)
597 ent->model->Draw(ent);
604 void R_DrawFakeShadows (void)
607 entity_render_t *ent;
609 ent = &cl_entities[0].render;
610 if (ent->model && ent->model->DrawFakeShadow)
611 ent->model->DrawFakeShadow(ent);
613 if (!r_drawentities.integer)
615 for (i = 0;i < r_refdef.numentities;i++)
617 ent = r_refdef.entities[i];
618 if ((ent->flags & RENDER_SHADOW) && ent->model && ent->model->DrawFakeShadow)
619 ent->model->DrawFakeShadow(ent);
623 #include "r_shadow.h"
625 int shadowframecount = 0;
627 int Light_CullBox(const vec3_t mins, const vec3_t maxs)
630 mnode_t *node, *stack[4096];
631 if (cl.worldmodel == NULL)
634 stack[stackpos++] = cl.worldmodel->nodes;
637 node = stack[--stackpos];
638 if (node->contents < 0)
640 if (((mleaf_t *)node)->worldnodeframe == shadowframecount)
645 sides = BoxOnPlaneSide(mins, maxs, node->plane);
646 if (sides & 2 && stackpos < 4096)
647 stack[stackpos++] = node->children[1];
648 if (sides & 1 && stackpos < 4096)
649 stack[stackpos++] = node->children[0];
655 int LightAndVis_CullBox(const vec3_t mins, const vec3_t maxs)
658 mnode_t *node, *stack[4096];
659 if (R_CullBox(mins, maxs))
661 if (cl.worldmodel == NULL)
664 stack[stackpos++] = cl.worldmodel->nodes;
667 node = stack[--stackpos];
668 if (node->contents < 0)
670 if (((mleaf_t *)node)->visframe == r_framecount && ((mleaf_t *)node)->worldnodeframe == shadowframecount)
675 sides = BoxOnPlaneSide(mins, maxs, node->plane);
676 if (sides & 2 && stackpos < 4096)
677 stack[stackpos++] = node->children[1];
678 if (sides & 1 && stackpos < 4096)
679 stack[stackpos++] = node->children[0];
685 int LightAndVis_CullPointCloud(int numpoints, const float *points)
690 mnode_t *node, *stack[4096];
691 //if (R_CullBox(mins, maxs))
693 if (cl.worldmodel == NULL)
696 stack[stackpos++] = cl.worldmodel->nodes;
699 node = stack[--stackpos];
700 if (node->contents < 0)
702 if (((mleaf_t *)node)->visframe == r_framecount && ((mleaf_t *)node)->worldnodeframe == shadowframecount)
708 for (i = 0, p = points;i < numpoints && sides != 3;i++, p += 3)
710 if (DotProduct(p, node->plane->normal) < node->plane->dist)
715 if (sides & 2 && stackpos < 4096)
716 stack[stackpos++] = node->children[1];
717 if (sides & 1 && stackpos < 4096)
718 stack[stackpos++] = node->children[0];
725 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)
727 vec3_t relativelightorigin;
731 float dist, projectdistance;
735 if (!(ent->flags & RENDER_SHADOW) || ent->model == NULL || ent->model->DrawShadowVolume == NULL)
737 if (r_shadow_cull.integer)
739 if (ent->maxs[0] < lightmins[0] || ent->mins[0] > lightmaxs[0]
740 || ent->maxs[1] < lightmins[1] || ent->mins[1] > lightmaxs[1]
741 || ent->maxs[2] < lightmins[2] || ent->mins[2] > lightmaxs[2]
742 || (lightmarked && Light_CullBox(ent->mins, ent->maxs)))
746 if (r_shadow_cull.integer)
748 projectdistance = cullradius;
749 // calculate projected bounding box and decide if it is on-screen
750 for (i = 0;i < 8;i++)
752 temp[0] = i & 1 ? ent->model->normalmaxs[0] : ent->model->normalmins[0];
753 temp[1] = i & 2 ? ent->model->normalmaxs[1] : ent->model->normalmins[1];
754 temp[2] = i & 4 ? ent->model->normalmaxs[2] : ent->model->normalmins[2];
755 Matrix4x4_Transform(&ent->matrix, temp, points[i]);
756 VectorSubtract(points[i], lightorigin, temp);
757 dist = projectdistance / sqrt(DotProduct(temp, temp));
758 VectorMA(lightorigin, dist, temp, points[i+8]);
760 if (LightAndVis_CullPointCloud(16, points[0]))
763 for (i = 0;i < 8;i++)
765 p2[0] = i & 1 ? ent->model->normalmaxs[0] : ent->model->normalmins[0];
766 p2[1] = i & 2 ? ent->model->normalmaxs[1] : ent->model->normalmins[1];
767 p2[2] = i & 4 ? ent->model->normalmaxs[2] : ent->model->normalmins[2];
768 Matrix4x4_Transform(&ent->matrix, p2, p);
769 VectorSubtract(p, lightorigin, temp);
770 dist = projectdistance / sqrt(DotProduct(temp, temp));
771 VectorMA(p, dist, temp, p2);
774 if (mins[0] > p[0]) mins[0] = p[0];if (maxs[0] < p[0]) maxs[0] = p[0];
775 if (mins[1] > p[1]) mins[1] = p[1];if (maxs[1] < p[1]) maxs[1] = p[1];
776 if (mins[2] > p[2]) mins[2] = p[2];if (maxs[2] < p[2]) maxs[2] = p[2];
783 if (mins[0] > p2[0]) mins[0] = p2[0];if (maxs[0] < p2[0]) maxs[0] = p2[0];
784 if (mins[1] > p2[1]) mins[1] = p2[1];if (maxs[1] < p2[1]) maxs[1] = p2[1];
785 if (mins[2] > p2[2]) mins[2] = p2[2];if (maxs[2] < p2[2]) maxs[2] = p2[2];
787 if (mins[0] >= clipmaxs[0] || maxs[0] <= clipmins[0]
788 || mins[1] >= clipmaxs[1] || maxs[1] <= clipmins[1]
789 || mins[2] >= clipmaxs[2] || maxs[2] <= clipmins[2]
790 || LightAndVis_CullBox(mins, maxs))
795 Matrix4x4_Transform(&ent->inversematrix, lightorigin, relativelightorigin);
796 ent->model->DrawShadowVolume (ent, relativelightorigin, lightradius);
799 void R_Shadow_DrawWorldLightShadowVolume(matrix4x4_t *matrix, worldlight_t *light);
801 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);
802 void R_ShadowVolumeLighting (int visiblevolumes)
805 entity_render_t *ent;
807 float f, lightradius, cullradius;
808 vec3_t relativelightorigin, relativeeyeorigin, lightcolor, clipmins, clipmaxs;
814 matrix4x4_t matrix_worldtofilter, matrix_worldtoattenuationxyz, matrix_worldtoattenuationz;
815 matrix4x4_t matrix_modeltofilter, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz;
819 memset(&m, 0, sizeof(m));
820 R_Mesh_State_Texture(&m);
822 GL_BlendFunc(GL_ONE, GL_ONE);
824 GL_DepthTest(r_shadow_visiblevolumes.integer < 2);
825 qglDisable(GL_CULL_FACE);
826 GL_Color(0.0 * r_colorscale, 0.0125 * r_colorscale, 0.1 * r_colorscale, 1);
829 R_Shadow_Stage_Begin();
831 if (r_shadow_realtime_world.integer)
833 R_Shadow_LoadWorldLightsIfNeeded();
834 for (lnum = 0, wl = r_shadow_worldlightchain;wl;wl = wl->next, lnum++)
836 if (d_lightstylevalue[wl->style] <= 0)
838 if (R_CullBox(wl->mins, wl->maxs))
839 //if (R_CullSphere(wl->origin, cullradius))
841 //if (R_CullBox(wl->mins, wl->maxs) || R_CullSphere(wl->origin, lightradius))
843 //if (VIS_CullBox(wl->mins, wl->maxs) || VIS_CullSphere(wl->origin, lightradius))
845 if (r_shadow_debuglight.integer >= 0 && lnum != r_shadow_debuglight.integer)
848 cullradius = wl->cullradius;
849 lightradius = wl->lightradius;
851 if (cl.worldmodel != NULL)
853 for (i = 0;i < wl->numleafs;i++)
854 if (wl->leafs[i]->visframe == r_framecount)
856 if (i == wl->numleafs)
858 leaf = wl->leafs[i++];
859 VectorCopy(leaf->mins, clipmins);
860 VectorCopy(leaf->maxs, clipmaxs);
861 for (;i < wl->numleafs;i++)
864 if (leaf->visframe == r_framecount)
866 if (clipmins[0] > leaf->mins[0]) clipmins[0] = leaf->mins[0];
867 if (clipmaxs[0] < leaf->maxs[0]) clipmaxs[0] = leaf->maxs[0];
868 if (clipmins[1] > leaf->mins[1]) clipmins[1] = leaf->mins[1];
869 if (clipmaxs[1] < leaf->maxs[1]) clipmaxs[1] = leaf->maxs[1];
870 if (clipmins[2] > leaf->mins[2]) clipmins[2] = leaf->mins[2];
871 if (clipmaxs[2] < leaf->maxs[2]) clipmaxs[2] = leaf->maxs[2];
874 if (clipmins[0] < wl->mins[0]) clipmins[0] = wl->mins[0];
875 if (clipmaxs[0] > wl->maxs[0]) clipmaxs[0] = wl->maxs[0];
876 if (clipmins[1] < wl->mins[1]) clipmins[1] = wl->mins[1];
877 if (clipmaxs[1] > wl->maxs[1]) clipmaxs[1] = wl->maxs[1];
878 if (clipmins[2] < wl->mins[2]) clipmins[2] = wl->mins[2];
879 if (clipmaxs[2] > wl->maxs[2]) clipmaxs[2] = wl->maxs[2];
883 VectorCopy(wl->mins, clipmins);
884 VectorCopy(wl->maxs, clipmaxs);
887 //if (R_Shadow_ScissorForBBoxAndSphere(clipmins, clipmaxs, wl->origin, wl->cullradius))
888 if (R_CullBox(clipmins, clipmaxs) || R_Shadow_ScissorForBBox(clipmins, clipmaxs))
891 // mark the leafs we care about so only things in those leafs will matter
892 if (cl.worldmodel != NULL)
893 for (i = 0;i < wl->numleafs;i++)
894 wl->leafs[i]->worldnodeframe = shadowframecount;
896 f = d_lightstylevalue[wl->style] * (1.0f / 256.0f);
897 VectorScale(wl->light, f, lightcolor);
900 f = 2 + sin(realtime * M_PI * 4.0);
901 VectorScale(lightcolor, f, lightcolor);
904 if (wl->castshadows && (gl_stencil || visiblevolumes))
907 R_Shadow_Stage_ShadowVolumes();
908 ent = &cl_entities[0].render;
909 if (wl->shadowvolume && r_shadow_staticworldlights.integer)
910 R_Shadow_DrawWorldLightShadowVolume(&ent->matrix, wl);
912 R_TestAndDrawShadowVolume(ent, wl->origin, cullradius, lightradius, wl->mins, wl->maxs, clipmins, clipmaxs, true);
913 if (r_drawentities.integer)
914 for (i = 0;i < r_refdef.numentities;i++)
915 R_TestAndDrawShadowVolume(r_refdef.entities[i], wl->origin, cullradius, lightradius, wl->mins, wl->maxs, clipmins, clipmaxs, true);
920 if (wl->castshadows && gl_stencil)
921 R_Shadow_Stage_LightWithShadows();
923 R_Shadow_Stage_LightWithoutShadows();
925 // calculate world to filter matrix
926 Matrix4x4_CreateFromQuakeEntity(&matrix, wl->origin[0], wl->origin[1], wl->origin[2], wl->angles[0], wl->angles[1], wl->angles[2], lightradius);
927 Matrix4x4_Invert_Simple(&matrix_worldtofilter, &matrix);
928 // calculate world to attenuationxyz/xy matrix
929 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5, 0.5, 0.5, 0, 0, 0, 0.5);
930 Matrix4x4_Concat(&matrix_worldtoattenuationxyz, &matrix, &matrix_worldtofilter);
931 // calculate world to attenuationz matrix
932 matrix.m[0][0] = 0;matrix.m[0][1] = 0;matrix.m[0][2] = 0.5;matrix.m[0][3] = 0.5;
933 matrix.m[1][0] = 0;matrix.m[1][1] = 0;matrix.m[1][2] = 0 ;matrix.m[1][3] = 0.5;
934 matrix.m[2][0] = 0;matrix.m[2][1] = 0;matrix.m[2][2] = 0 ;matrix.m[2][3] = 0.5;
935 matrix.m[3][0] = 0;matrix.m[3][1] = 0;matrix.m[3][2] = 0 ;matrix.m[3][3] = 1;
936 Matrix4x4_Concat(&matrix_worldtoattenuationz, &matrix, &matrix_worldtofilter);
938 ent = &cl_entities[0].render;
939 if (ent->model && ent->model->DrawLight)
941 Matrix4x4_Transform(&ent->inversematrix, wl->origin, relativelightorigin);
942 Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin);
943 Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
944 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
945 Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
947 R_Model_Brush_DrawLightForSurfaceList(ent, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, wl->surfaces, wl->numsurfaces, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
949 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
951 if (r_drawentities.integer)
953 for (i = 0;i < r_refdef.numentities;i++)
955 ent = r_refdef.entities[i];
956 if (ent->visframe == r_framecount && ent->model && ent->model->DrawLight
957 && BoxesOverlap(ent->mins, ent->maxs, clipmins, clipmaxs)
958 && !(ent->effects & EF_ADDITIVE) && ent->alpha == 1)
960 Matrix4x4_Transform(&ent->inversematrix, wl->origin, relativelightorigin);
961 Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin);
962 Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
963 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
964 Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
965 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
972 if (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer)
974 for (lnum = 0, rd = r_dlight;lnum < r_numdlights;lnum++, rd++)
976 lightradius = rd->cullradius;
977 clipmins[0] = rd->origin[0] - lightradius;
978 clipmins[1] = rd->origin[1] - lightradius;
979 clipmins[2] = rd->origin[2] - lightradius;
980 clipmaxs[0] = rd->origin[0] + lightradius;
981 clipmaxs[1] = rd->origin[1] + lightradius;
982 clipmaxs[2] = rd->origin[2] + lightradius;
983 if (VIS_CullBox(clipmins, clipmaxs) || R_Shadow_ScissorForBBox(clipmins, clipmaxs))
986 cullradius = RadiusFromBoundsAndOrigin(clipmins, clipmaxs, rd->origin);
987 VectorScale(rd->light, (1.0f / 4096.0f), lightcolor);
989 if (gl_stencil || visiblevolumes)
992 R_Shadow_Stage_ShadowVolumes();
993 ent = &cl_entities[0].render;
994 R_TestAndDrawShadowVolume(ent, rd->origin, cullradius, lightradius, clipmins, clipmaxs, clipmins, clipmaxs, false);
995 if (r_drawentities.integer)
997 for (i = 0;i < r_refdef.numentities;i++)
999 ent = r_refdef.entities[i];
1001 R_TestAndDrawShadowVolume(ent, rd->origin, cullradius, lightradius, clipmins, clipmaxs, clipmins, clipmaxs, false);
1006 if (!visiblevolumes)
1009 R_Shadow_Stage_LightWithShadows();
1011 R_Shadow_Stage_LightWithoutShadows();
1013 // calculate world to filter matrix
1014 Matrix4x4_CreateFromQuakeEntity(&matrix, rd->origin[0], rd->origin[1], rd->origin[2], 0, 0, 0, lightradius);
1015 Matrix4x4_Invert_Simple(&matrix_worldtofilter, &matrix);
1016 // calculate world to attenuationxyz/xy matrix
1017 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5, 0.5, 0.5, 0, 0, 0, 0.5);
1018 Matrix4x4_Concat(&matrix_worldtoattenuationxyz, &matrix, &matrix_worldtofilter);
1019 // calculate world to attenuationz matrix
1020 matrix.m[0][0] = 0;matrix.m[0][1] = 0;matrix.m[0][2] = 0.5;matrix.m[0][3] = 0.5;
1021 matrix.m[1][0] = 0;matrix.m[1][1] = 0;matrix.m[1][2] = 0 ;matrix.m[1][3] = 0.5;
1022 matrix.m[2][0] = 0;matrix.m[2][1] = 0;matrix.m[2][2] = 0 ;matrix.m[2][3] = 0.5;
1023 matrix.m[3][0] = 0;matrix.m[3][1] = 0;matrix.m[3][2] = 0 ;matrix.m[3][3] = 1;
1024 Matrix4x4_Concat(&matrix_worldtoattenuationz, &matrix, &matrix_worldtofilter);
1026 ent = &cl_entities[0].render;
1027 if (ent->model && ent->model->DrawLight)
1029 Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin);
1030 Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin);
1031 Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
1032 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
1033 Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
1034 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
1036 if (r_drawentities.integer)
1038 for (i = 0;i < r_refdef.numentities;i++)
1040 ent = r_refdef.entities[i];
1041 if (ent->visframe == r_framecount && ent->model && ent->model->DrawLight
1042 && BoxesOverlap(ent->mins, ent->maxs, clipmins, clipmaxs)
1043 && !(ent->effects & EF_ADDITIVE) && ent->alpha == 1)
1045 Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin);
1046 Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin);
1047 Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
1048 Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
1049 Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
1050 ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
1059 qglEnable(GL_CULL_FACE);
1061 R_Shadow_Stage_End();
1062 qglDisable(GL_SCISSOR_TEST);
1065 static void R_SetFrustum (void)
1067 // LordHavoc: note to all quake engine coders, the special case for 90
1068 // degrees assumed a square view (wrong), so I removed it, Quake2 has it
1069 // disabled as well.
1071 // rotate VPN right by FOV_X/2 degrees
1072 RotatePointAroundVector( frustum[0].normal, vup, vpn, -(90-r_refdef.fov_x / 2 ) );
1073 frustum[0].dist = DotProduct (r_origin, frustum[0].normal);
1074 PlaneClassify(&frustum[0]);
1076 // rotate VPN left by FOV_X/2 degrees
1077 RotatePointAroundVector( frustum[1].normal, vup, vpn, 90-r_refdef.fov_x / 2 );
1078 frustum[1].dist = DotProduct (r_origin, frustum[1].normal);
1079 PlaneClassify(&frustum[1]);
1081 // rotate VPN up by FOV_X/2 degrees
1082 RotatePointAroundVector( frustum[2].normal, vright, vpn, 90-r_refdef.fov_y / 2 );
1083 frustum[2].dist = DotProduct (r_origin, frustum[2].normal);
1084 PlaneClassify(&frustum[2]);
1086 // rotate VPN down by FOV_X/2 degrees
1087 RotatePointAroundVector( frustum[3].normal, vright, vpn, -( 90 - r_refdef.fov_y / 2 ) );
1088 frustum[3].dist = DotProduct (r_origin, frustum[3].normal);
1089 PlaneClassify(&frustum[3]);
1097 static void R_SetupFrame (void)
1099 // don't allow cheats in multiplayer
1100 if (cl.maxclients > 1)
1102 if (r_fullbright.integer != 0)
1103 Cvar_Set ("r_fullbright", "0");
1104 if (r_ambient.value != 0)
1105 Cvar_Set ("r_ambient", "0");
1110 // build the transformation matrix for the given view angles
1111 VectorCopy (r_refdef.vieworg, r_origin);
1113 AngleVectors (r_refdef.viewangles, vpn, vright, vup);
1119 static void R_BlendView(void)
1123 float vertex3f[3*3];
1125 if (r_refdef.viewblend[3] < 0.01f)
1128 R_Mesh_Matrix(&r_identitymatrix);
1130 memset(&m, 0, sizeof(m));
1131 R_Mesh_State_Texture(&m);
1133 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1135 GL_DepthTest(false); // magic
1136 GL_VertexPointer(vertex3f);
1137 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1139 vertex3f[0] = r_origin[0] + vpn[0] * 1.5 - vright[0] * r - vup[0] * r;
1140 vertex3f[1] = r_origin[1] + vpn[1] * 1.5 - vright[1] * r - vup[1] * r;
1141 vertex3f[2] = r_origin[2] + vpn[2] * 1.5 - vright[2] * r - vup[2] * r;
1142 vertex3f[3] = r_origin[0] + vpn[0] * 1.5 - vright[0] * r + vup[0] * r * 3;
1143 vertex3f[4] = r_origin[1] + vpn[1] * 1.5 - vright[1] * r + vup[1] * r * 3;
1144 vertex3f[5] = r_origin[2] + vpn[2] * 1.5 - vright[2] * r + vup[2] * r * 3;
1145 vertex3f[6] = r_origin[0] + vpn[0] * 1.5 + vright[0] * r * 3 - vup[0] * r;
1146 vertex3f[7] = r_origin[1] + vpn[1] * 1.5 + vright[1] * r * 3 - vup[1] * r;
1147 vertex3f[8] = r_origin[2] + vpn[2] * 1.5 + vright[2] * r * 3 - vup[2] * r;
1148 R_Mesh_Draw(3, 1, polygonelements);
1155 r_refdef must be set before the first call
1158 extern void R_DrawLightningBeams (void);
1159 void R_RenderView (void)
1161 entity_render_t *world;
1162 if (!r_refdef.entities/* || !cl.worldmodel*/)
1163 return; //Host_Error ("R_RenderView: NULL worldmodel");
1165 if (r_shadow_realtime_world.integer)
1169 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");
1170 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
1174 world = &cl_entities[0].render;
1176 // FIXME: move to client
1178 R_TimeReport("mexplosion");
1186 R_TimeReport("setup");
1188 R_WorldVisibility(world);
1189 R_TimeReport("worldvis");
1191 R_FarClip_Start(r_origin, vpn, 768.0f);
1193 r_farclip = R_FarClip_Finish() + 256.0f;
1194 R_TimeReport("markentity");
1196 GL_SetupView_ViewPort(r_refdef.x, r_refdef.y, r_refdef.width, r_refdef.height);
1197 if (r_shadow_realtime_world.integer || gl_stencil)
1198 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.fov_x, r_refdef.fov_y, 1.0f);
1200 GL_SetupView_Mode_Perspective(r_refdef.fov_x, r_refdef.fov_y, 1.0f, r_farclip);
1201 GL_SetupView_Orientation_FromEntity (r_refdef.vieworg, r_refdef.viewangles);
1202 qglDepthFunc(GL_LEQUAL);
1205 R_MeshQueue_BeginScene();
1207 R_Shadow_UpdateWorldLightSelection();
1209 if (R_DrawBrushModelsSky())
1210 R_TimeReport("bmodelsky");
1212 // must occur early because it can draw sky
1214 R_TimeReport("world");
1216 // don't let sound skip if going slow
1217 if (!intimerefresh && !r_speeds.integer)
1220 R_DrawModels(r_shadow_realtime_world.integer);
1221 R_TimeReport("models");
1223 if (r_shadows.integer == 1 && !r_shadow_realtime_world.integer)
1225 R_DrawFakeShadows();
1226 R_TimeReport("fakeshadow");
1229 if (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer)
1231 R_ShadowVolumeLighting(false);
1232 R_TimeReport("dynlight");
1235 R_DrawLightningBeams();
1236 R_TimeReport("lightning");
1239 R_TimeReport("particles");
1242 R_TimeReport("explosions");
1244 R_MeshQueue_RenderTransparent();
1245 R_TimeReport("drawtrans");
1248 R_TimeReport("coronas");
1250 R_DrawWorldCrosshair();
1251 R_TimeReport("crosshair");
1254 R_TimeReport("blendview");
1256 R_MeshQueue_Render();
1257 R_MeshQueue_EndScene();
1259 if (r_shadow_visiblevolumes.integer)
1261 R_ShadowVolumeLighting(true);
1262 R_TimeReport("shadowvolume");
1266 R_TimeReport("meshfinish");
1270 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1273 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1275 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1276 GL_DepthMask(false);
1278 R_Mesh_Matrix(&r_identitymatrix);
1280 memset(&m, 0, sizeof(m));
1281 R_Mesh_State_Texture(&m);
1284 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1285 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1286 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1287 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1288 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1289 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1290 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1291 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1292 GL_ColorPointer(color);
1293 R_FillColors(color, 8, cr * r_colorscale, cg * r_colorscale, cb * r_colorscale, ca);
1296 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1298 VectorSubtract(v, r_origin, diff);
1299 f2 = exp(fogdensity/DotProduct(diff, diff));
1302 c[0] = c[0] * f1 + fogcolor[0] * f2;
1303 c[1] = c[1] * f1 + fogcolor[1] * f2;
1304 c[2] = c[2] * f1 + fogcolor[2] * f2;
1311 int nomodelelements[24] =
1323 float nomodelvertex3f[6*3] =
1333 float nomodelcolor4f[6*4] =
1335 0.0f, 0.0f, 0.5f, 1.0f,
1336 0.0f, 0.0f, 0.5f, 1.0f,
1337 0.0f, 0.5f, 0.0f, 1.0f,
1338 0.0f, 0.5f, 0.0f, 1.0f,
1339 0.5f, 0.0f, 0.0f, 1.0f,
1340 0.5f, 0.0f, 0.0f, 1.0f
1343 void R_DrawNoModelCallback(const void *calldata1, int calldata2)
1345 const entity_render_t *ent = calldata1;
1347 float f1, f2, *c, diff[3];
1350 R_Mesh_Matrix(&ent->matrix);
1352 memset(&m, 0, sizeof(m));
1353 R_Mesh_State_Texture(&m);
1355 if (ent->flags & EF_ADDITIVE)
1357 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1358 GL_DepthMask(false);
1360 else if (ent->alpha < 1)
1362 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1363 GL_DepthMask(false);
1367 GL_BlendFunc(GL_ONE, GL_ZERO);
1371 GL_VertexPointer(nomodelvertex3f);
1374 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1375 GL_ColorPointer(color4f);
1376 VectorSubtract(ent->origin, r_origin, diff);
1377 f2 = exp(fogdensity/DotProduct(diff, diff));
1379 for (i = 0, c = color4f;i < 6;i++, c += 4)
1381 c[0] = (c[0] * f1 + fogcolor[0] * f2) * r_colorscale;
1382 c[1] = (c[1] * f1 + fogcolor[1] * f2) * r_colorscale;
1383 c[2] = (c[2] * f1 + fogcolor[2] * f2) * r_colorscale;
1387 else if (r_colorscale != 1 || ent->alpha != 1)
1389 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1390 GL_ColorPointer(color4f);
1391 for (i = 0, c = color4f;i < 6;i++, c += 4)
1393 c[0] *= r_colorscale;
1394 c[1] *= r_colorscale;
1395 c[2] *= r_colorscale;
1400 GL_ColorPointer(nomodelcolor4f);
1401 R_Mesh_Draw(6, 8, nomodelelements);
1404 void R_DrawNoModel(entity_render_t *ent)
1406 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1407 R_MeshQueue_AddTransparent(ent->origin, R_DrawNoModelCallback, ent, 0);
1409 // R_DrawNoModelCallback(ent, 0);
1412 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1414 vec3_t right1, right2, diff, normal;
1416 VectorSubtract (org2, org1, normal);
1417 VectorNormalizeFast (normal);
1419 // calculate 'right' vector for start
1420 VectorSubtract (r_origin, org1, diff);
1421 VectorNormalizeFast (diff);
1422 CrossProduct (normal, diff, right1);
1424 // calculate 'right' vector for end
1425 VectorSubtract (r_origin, org2, diff);
1426 VectorNormalizeFast (diff);
1427 CrossProduct (normal, diff, right2);
1429 vert[ 0] = org1[0] + width * right1[0];
1430 vert[ 1] = org1[1] + width * right1[1];
1431 vert[ 2] = org1[2] + width * right1[2];
1432 vert[ 3] = org1[0] - width * right1[0];
1433 vert[ 4] = org1[1] - width * right1[1];
1434 vert[ 5] = org1[2] - width * right1[2];
1435 vert[ 6] = org2[0] - width * right2[0];
1436 vert[ 7] = org2[1] - width * right2[1];
1437 vert[ 8] = org2[2] - width * right2[2];
1438 vert[ 9] = org2[0] + width * right2[0];
1439 vert[10] = org2[1] + width * right2[1];
1440 vert[11] = org2[2] + width * right2[2];
1443 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
1445 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)
1452 VectorSubtract(origin, r_origin, diff);
1453 ca *= 1 - exp(fogdensity/DotProduct(diff,diff));
1456 R_Mesh_Matrix(&r_identitymatrix);
1457 GL_Color(cr * r_colorscale, cg * r_colorscale, cb * r_colorscale, ca);
1458 GL_VertexPointer(varray_vertex3f);
1459 GL_BlendFunc(blendfunc1, blendfunc2);
1460 GL_DepthMask(false);
1461 GL_DepthTest(!depthdisable);
1463 memset(&m, 0, sizeof(m));
1464 m.tex[0] = R_GetTexture(texture);
1465 m.pointer_texcoord[0] = spritetexcoord2f;
1466 R_Mesh_State_Texture(&m);
1468 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
1469 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
1470 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
1471 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
1472 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
1473 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
1474 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
1475 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
1476 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
1477 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
1478 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
1479 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
1480 R_Mesh_Draw(4, 2, polygonelements);