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.
25 // used for dlight push checking and other things
28 // used for visibility checking
29 qbyte r_pvsbits[(MAX_MAP_LEAFS+7)>>3];
33 matrix4x4_t r_identitymatrix;
35 int c_alias_polys, c_light_polys, c_faces, c_nodes, c_leafs, c_models, c_bmodels, c_sprites, c_particles, c_dlights;
37 // true during envmap command capture
54 // 8.8 fraction of base light value
55 unsigned short d_lightstylevalue[256];
57 cvar_t r_drawentities = {0, "r_drawentities","1"};
58 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1"};
59 cvar_t r_speeds = {0, "r_speeds","0"};
60 cvar_t r_fullbright = {0, "r_fullbright","0"};
61 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1"};
62 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1"};
63 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1"};
64 cvar_t r_drawcollisionbrushes = {0, "r_drawcollisionbrushes", "0"};
66 cvar_t gl_fogenable = {0, "gl_fogenable", "0"};
67 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25"};
68 cvar_t gl_fogred = {0, "gl_fogred","0.3"};
69 cvar_t gl_foggreen = {0, "gl_foggreen","0.3"};
70 cvar_t gl_fogblue = {0, "gl_fogblue","0.3"};
71 cvar_t gl_fogstart = {0, "gl_fogstart", "0"};
72 cvar_t gl_fogend = {0, "gl_fogend","0"};
74 cvar_t r_textureunits = {0, "r_textureunits", "32"};
76 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1"};
77 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1"};
78 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1"};
79 cvar_t r_watershader = {CVAR_SAVE, "r_watershader", "1"};
82 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
85 for (i = 0;i < verts;i++)
96 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
99 for (i = 0;i < verts;i++)
113 For program optimization
116 qboolean intimerefresh = 0;
117 static void R_TimeRefresh_f (void)
120 float timestart, timedelta, oldangles[3];
123 VectorCopy(cl.viewangles, oldangles);
124 VectorClear(cl.viewangles);
126 timestart = Sys_DoubleTime();
127 for (i = 0;i < 128;i++)
129 Matrix4x4_CreateFromQuakeEntity(&r_refdef.viewentitymatrix, r_vieworigin[0], r_vieworigin[1], r_vieworigin[2], 0, i / 128.0 * 360.0, 0, 1);
132 timedelta = Sys_DoubleTime() - timestart;
134 VectorCopy(oldangles, cl.viewangles);
136 Con_Printf ("%f seconds (%f fps)\n", timedelta, 128/timedelta);
141 float fog_density, fog_red, fog_green, fog_blue;
143 qboolean oldgl_fogenable;
144 void R_UpdateFog(void)
146 if (gamemode == GAME_NEHAHRA)
148 if (gl_fogenable.integer)
150 oldgl_fogenable = true;
151 fog_density = gl_fogdensity.value;
152 fog_red = gl_fogred.value;
153 fog_green = gl_foggreen.value;
154 fog_blue = gl_fogblue.value;
156 else if (oldgl_fogenable)
158 oldgl_fogenable = false;
167 fogcolor[0] = fog_red = bound(0.0f, fog_red , 1.0f);
168 fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
169 fogcolor[2] = fog_blue = bound(0.0f, fog_blue , 1.0f);
174 fogdensity = -4000.0f / (fog_density * fog_density);
175 // fog color was already set
181 // FIXME: move this to client?
184 if (gamemode == GAME_NEHAHRA)
186 Cvar_Set("gl_fogenable", "0");
187 Cvar_Set("gl_fogdensity", "0.2");
188 Cvar_Set("gl_fogred", "0.3");
189 Cvar_Set("gl_foggreen", "0.3");
190 Cvar_Set("gl_fogblue", "0.3");
192 fog_density = fog_red = fog_green = fog_blue = 0.0f;
195 // FIXME: move this to client?
196 void FOG_registercvars(void)
198 if (gamemode == GAME_NEHAHRA)
200 Cvar_RegisterVariable (&gl_fogenable);
201 Cvar_RegisterVariable (&gl_fogdensity);
202 Cvar_RegisterVariable (&gl_fogred);
203 Cvar_RegisterVariable (&gl_foggreen);
204 Cvar_RegisterVariable (&gl_fogblue);
205 Cvar_RegisterVariable (&gl_fogstart);
206 Cvar_RegisterVariable (&gl_fogend);
210 void gl_main_start(void)
214 void gl_main_shutdown(void)
218 extern void CL_ParseEntityLump(char *entitystring);
219 void gl_main_newmap(void)
222 char *entities, entname[MAX_QPATH];
226 strcpy(entname, cl.worldmodel->name);
227 l = strlen(entname) - 4;
228 if (l >= 0 && !strcmp(entname + l, ".bsp"))
230 strcpy(entname + l, ".ent");
231 if ((entities = FS_LoadFile(entname, true)))
233 CL_ParseEntityLump(entities);
238 if (cl.worldmodel->brush.entities)
239 CL_ParseEntityLump(cl.worldmodel->brush.entities);
243 void GL_Main_Init(void)
245 Matrix4x4_CreateIdentity(&r_identitymatrix);
246 // FIXME: move this to client?
248 Cmd_AddCommand("timerefresh", R_TimeRefresh_f);
249 Cvar_RegisterVariable(&r_drawentities);
250 Cvar_RegisterVariable(&r_drawviewmodel);
251 Cvar_RegisterVariable(&r_speeds);
252 Cvar_RegisterVariable(&r_fullbrights);
253 Cvar_RegisterVariable(&r_wateralpha);
254 Cvar_RegisterVariable(&r_dynamic);
255 Cvar_RegisterVariable(&r_fullbright);
256 Cvar_RegisterVariable(&r_textureunits);
257 Cvar_RegisterVariable(&r_lerpsprites);
258 Cvar_RegisterVariable(&r_lerpmodels);
259 Cvar_RegisterVariable(&r_waterscroll);
260 Cvar_RegisterVariable(&r_watershader);
261 Cvar_RegisterVariable(&r_drawcollisionbrushes);
262 if (gamemode == GAME_NEHAHRA || gamemode == GAME_NEXUIZ || gamemode == GAME_TENEBRAE)
263 Cvar_SetValue("r_fullbrights", 0);
264 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
267 static vec3_t r_farclip_origin;
268 static vec3_t r_farclip_direction;
269 static vec_t r_farclip_directiondist;
270 static vec_t r_farclip_meshfarclip;
271 static int r_farclip_directionbit0;
272 static int r_farclip_directionbit1;
273 static int r_farclip_directionbit2;
275 // enlarge farclip to accomodate box
276 static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
279 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
280 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
281 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
282 if (r_farclip_meshfarclip < d)
283 r_farclip_meshfarclip = d;
286 // return farclip value
287 static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
291 VectorCopy(origin, r_farclip_origin);
292 VectorCopy(direction, r_farclip_direction);
293 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
294 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
295 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
296 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
297 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
300 R_FarClip_Box(cl.worldmodel->normalmins, cl.worldmodel->normalmaxs);
301 for (i = 0;i < r_refdef.numentities;i++)
302 R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
304 return r_farclip_meshfarclip - r_farclip_directiondist;
307 extern void R_Textures_Init(void);
308 extern void Mod_RenderInit(void);
309 extern void GL_Draw_Init(void);
310 extern void GL_Main_Init(void);
311 extern void R_Shadow_Init(void);
312 extern void GL_Models_Init(void);
313 extern void R_Sky_Init(void);
314 extern void GL_Surf_Init(void);
315 extern void R_Crosshairs_Init(void);
316 extern void R_Light_Init(void);
317 extern void R_Particles_Init(void);
318 extern void R_Explosion_Init(void);
319 extern void ui_init(void);
320 extern void gl_backend_init(void);
321 extern void Sbar_Init(void);
322 extern void R_LightningBeams_Init(void);
324 void Render_Init(void)
343 R_LightningBeams_Init();
351 extern char *ENGINE_EXTENSIONS;
354 VID_CheckExtensions();
356 // LordHavoc: report supported extensions
357 Con_DPrintf("\nengine extensions: %s\n", ENGINE_EXTENSIONS);
360 int R_CullBox(const vec3_t mins, const vec3_t maxs)
364 for (i = 0;i < 4;i++)
371 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
375 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
379 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
383 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
387 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
391 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
395 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
399 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
407 //==================================================================================
409 static void R_MarkEntities (void)
412 entity_render_t *ent;
414 ent = &cl_entities[0].render;
415 Matrix4x4_CreateIdentity(&ent->matrix);
416 Matrix4x4_CreateIdentity(&ent->inversematrix);
418 if (!r_drawentities.integer)
421 for (i = 0;i < r_refdef.numentities;i++)
423 ent = r_refdef.entities[i];
424 Mod_CheckLoaded(ent->model);
425 // some of the renderer still relies on origin...
426 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
427 // some of the renderer still relies on scale...
428 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
429 R_LerpAnimation(ent);
430 R_UpdateEntLights(ent);
431 if ((chase_active.integer || !(ent->flags & RENDER_EXTERIORMODEL))
432 && !VIS_CullBox(ent->mins, ent->maxs)
433 && (!envmap || !(ent->flags & (RENDER_VIEWMODEL | RENDER_EXTERIORMODEL))))
434 ent->visframe = r_framecount;
438 // only used if skyrendermasked, and normally returns false
439 int R_DrawBrushModelsSky (void)
442 entity_render_t *ent;
444 if (!r_drawentities.integer)
448 for (i = 0;i < r_refdef.numentities;i++)
450 ent = r_refdef.entities[i];
451 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
453 ent->model->DrawSky(ent);
466 void R_DrawViewModel (void)
468 entity_render_t *ent;
470 // FIXME: move these checks to client
471 if (!r_drawviewmodel.integer || chase_active.integer || envmap || !r_drawentities.integer || cl.items & IT_INVISIBILITY || cl.stats[STAT_HEALTH] <= 0 || !cl.viewent.render.model)
474 ent = &cl.viewent.render;
475 Mod_CheckLoaded(ent->model);
476 R_LerpAnimation(ent);
477 Matrix4x4_CreateFromQuakeEntity(&ent->matrix, ent->origin[0], ent->origin[1], ent->origin[2], -ent->angles[0], ent->angles[1], ent->angles[2], ent->scale);
478 Matrix4x4_Invert_Simple(&ent->inversematrix, &ent->matrix);
479 R_UpdateEntLights(ent);
480 ent->model->Draw(ent);
484 void R_DrawNoModel(entity_render_t *ent);
485 void R_DrawModels(void)
488 entity_render_t *ent;
490 if (!r_drawentities.integer)
493 for (i = 0;i < r_refdef.numentities;i++)
495 ent = r_refdef.entities[i];
496 if (ent->visframe == r_framecount)
498 if (ent->model && ent->model->Draw != NULL)
499 ent->model->Draw(ent);
506 static void R_SetFrustum(void)
508 // break apart the viewentity matrix into vectors for various purposes
509 Matrix4x4_ToVectors(&r_refdef.viewentitymatrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
510 VectorNegate(r_viewleft, r_viewright);
512 // LordHavoc: note to all quake engine coders, the special case for 90
513 // degrees assumed a square view (wrong), so I removed it, Quake2 has it
516 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
517 RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_refdef.fov_x / 2));
518 frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
519 PlaneClassify(&frustum[0]);
521 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
522 RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_refdef.fov_x / 2));
523 frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
524 PlaneClassify(&frustum[1]);
526 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
527 RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_refdef.fov_y / 2));
528 frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
529 PlaneClassify(&frustum[2]);
531 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
532 RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_refdef.fov_y / 2));
533 frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
534 PlaneClassify(&frustum[3]);
537 static void R_BlendView(void)
543 if (r_refdef.viewblend[3] < 0.01f)
546 R_Mesh_Matrix(&r_identitymatrix);
548 memset(&m, 0, sizeof(m));
549 R_Mesh_State_Texture(&m);
551 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
553 GL_DepthTest(false); // magic
554 GL_VertexPointer(vertex3f);
555 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
557 vertex3f[0] = r_vieworigin[0] + r_viewforward[0] * 1.5 + r_viewleft[0] * r - r_viewup[0] * r;
558 vertex3f[1] = r_vieworigin[1] + r_viewforward[1] * 1.5 + r_viewleft[1] * r - r_viewup[1] * r;
559 vertex3f[2] = r_vieworigin[2] + r_viewforward[2] * 1.5 + r_viewleft[2] * r - r_viewup[2] * r;
560 vertex3f[3] = r_vieworigin[0] + r_viewforward[0] * 1.5 + r_viewleft[0] * r + r_viewup[0] * r * 3;
561 vertex3f[4] = r_vieworigin[1] + r_viewforward[1] * 1.5 + r_viewleft[1] * r + r_viewup[1] * r * 3;
562 vertex3f[5] = r_vieworigin[2] + r_viewforward[2] * 1.5 + r_viewleft[2] * r + r_viewup[2] * r * 3;
563 vertex3f[6] = r_vieworigin[0] + r_viewforward[0] * 1.5 - r_viewleft[0] * r * 3 - r_viewup[0] * r;
564 vertex3f[7] = r_vieworigin[1] + r_viewforward[1] * 1.5 - r_viewleft[1] * r * 3 - r_viewup[1] * r;
565 vertex3f[8] = r_vieworigin[2] + r_viewforward[2] * 1.5 - r_viewleft[2] * r * 3 - r_viewup[2] * r;
566 R_Mesh_Draw(3, 1, polygonelements);
569 void R_UpdateWorld(void)
571 if (!r_refdef.entities/* || !cl.worldmodel*/)
572 return; //Host_Error ("R_RenderView: NULL worldmodel");
574 if (r_shadow_realtime_world.integer && !gl_stencil)
576 Con_Printf("Realtime world lighting requires 32bit color; turning off r_shadow_realtime_world, please type vid_bitsperpixel 32;vid_restart and try again\n");
577 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
580 // don't allow cheats in multiplayer
583 if (r_fullbright.integer != 0)
584 Cvar_Set ("r_fullbright", "0");
585 if (r_ambient.value != 0)
586 Cvar_Set ("r_ambient", "0");
594 void R_RenderScene(void);
601 void R_RenderView(void)
603 if (!r_refdef.entities/* || !cl.worldmodel*/)
604 return; //Host_Error ("R_RenderView: NULL worldmodel");
606 r_refdef.width = bound(0, r_refdef.width, vid.realwidth);
607 r_refdef.height = bound(0, r_refdef.height, vid.realheight);
608 r_refdef.x = bound(0, r_refdef.x, vid.realwidth - r_refdef.width);
609 r_refdef.y = bound(0, r_refdef.y, vid.realheight - r_refdef.height);
610 r_refdef.fov_x = bound(1, r_refdef.fov_x, 170);
611 r_refdef.fov_y = bound(1, r_refdef.fov_y, 170);
613 // GL is weird because it's bottom to top, r_refdef.y is top to bottom
614 qglViewport(r_refdef.x, vid.realheight - (r_refdef.y + r_refdef.height), r_refdef.width, r_refdef.height);
615 GL_Scissor(r_refdef.x, r_refdef.y, r_refdef.width, r_refdef.height);
616 GL_ScissorTest(true);
620 r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
622 if (gl_stencil && ((r_shadow_realtime_world.integer && r_shadow_worldshadows.integer) || ((r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && r_shadow_dlightshadows.integer)))
623 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.fov_x, r_refdef.fov_y, 1.0f);
625 GL_SetupView_Mode_Perspective(r_refdef.fov_x, r_refdef.fov_y, 1.0f, r_farclip);
627 GL_SetupView_Orientation_FromEntity(&r_refdef.viewentitymatrix);
629 R_TimeReport("setup");
634 R_TimeReport("blendview");
637 R_TimeReport("meshfinish");
639 GL_Scissor(0, 0, vid.realwidth, vid.realheight);
640 GL_ScissorTest(false);
643 extern void R_DrawLightningBeams (void);
644 void R_RenderScene(void)
646 entity_render_t *world;
648 // don't let sound skip if going slow
649 if (!intimerefresh && !r_speeds.integer)
656 if (cl.worldmodel && cl.worldmodel->brush.FatPVS)
657 cl.worldmodel->brush.FatPVS(cl.worldmodel, r_vieworigin, 2, r_pvsbits, sizeof(r_pvsbits));
658 world = &cl_entities[0].render;
659 R_WorldVisibility(world);
660 R_TimeReport("worldvis");
663 R_TimeReport("markentity");
665 qglDepthFunc(GL_LEQUAL);
666 qglPolygonOffset(0, 0);
667 qglEnable(GL_POLYGON_OFFSET_FILL);
669 R_MeshQueue_BeginScene();
671 R_Shadow_UpdateWorldLightSelection();
673 // don't let sound skip if going slow
674 if (!intimerefresh && !r_speeds.integer)
677 if (R_DrawBrushModelsSky())
678 R_TimeReport("bmodelsky");
680 // must occur early because it can draw sky
682 R_TimeReport("world");
684 // don't let sound skip if going slow
685 if (!intimerefresh && !r_speeds.integer)
689 R_TimeReport("models");
691 // don't let sound skip if going slow
692 if (!intimerefresh && !r_speeds.integer)
695 R_ShadowVolumeLighting(false);
696 R_TimeReport("rtlights");
698 // don't let sound skip if going slow
699 if (!intimerefresh && !r_speeds.integer)
702 R_DrawLightningBeams();
703 R_TimeReport("lightning");
706 R_TimeReport("particles");
709 R_TimeReport("explosions");
711 R_MeshQueue_RenderTransparent();
712 R_TimeReport("drawtrans");
715 R_TimeReport("coronas");
717 R_DrawWorldCrosshair();
718 R_TimeReport("crosshair");
720 R_MeshQueue_Render();
721 R_MeshQueue_EndScene();
723 if (r_shadow_visiblevolumes.integer)
725 R_ShadowVolumeLighting(true);
726 R_TimeReport("shadowvolume");
729 qglPolygonOffset(0, 0);
730 qglDisable(GL_POLYGON_OFFSET_FILL);
732 // don't let sound skip if going slow
733 if (!intimerefresh && !r_speeds.integer)
738 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
741 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
743 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
746 R_Mesh_Matrix(&r_identitymatrix);
748 memset(&m, 0, sizeof(m));
749 R_Mesh_State_Texture(&m);
752 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
753 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
754 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
755 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
756 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
757 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
758 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
759 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
760 GL_ColorPointer(color);
761 R_FillColors(color, 8, cr, cg, cb, ca);
764 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
766 VectorSubtract(v, r_vieworigin, diff);
767 f2 = exp(fogdensity/DotProduct(diff, diff));
769 c[0] = c[0] * f1 + fogcolor[0] * f2;
770 c[1] = c[1] * f1 + fogcolor[1] * f2;
771 c[2] = c[2] * f1 + fogcolor[2] * f2;
778 int nomodelelements[24] =
790 float nomodelvertex3f[6*3] =
800 float nomodelcolor4f[6*4] =
802 0.0f, 0.0f, 0.5f, 1.0f,
803 0.0f, 0.0f, 0.5f, 1.0f,
804 0.0f, 0.5f, 0.0f, 1.0f,
805 0.0f, 0.5f, 0.0f, 1.0f,
806 0.5f, 0.0f, 0.0f, 1.0f,
807 0.5f, 0.0f, 0.0f, 1.0f
810 void R_DrawNoModelCallback(const void *calldata1, int calldata2)
812 const entity_render_t *ent = calldata1;
814 float f1, f2, *c, diff[3];
817 R_Mesh_Matrix(&ent->matrix);
819 memset(&m, 0, sizeof(m));
820 R_Mesh_State_Texture(&m);
822 if (ent->flags & EF_ADDITIVE)
824 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
827 else if (ent->alpha < 1)
829 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
834 GL_BlendFunc(GL_ONE, GL_ZERO);
838 GL_VertexPointer(nomodelvertex3f);
841 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
842 GL_ColorPointer(color4f);
843 VectorSubtract(ent->origin, r_vieworigin, diff);
844 f2 = exp(fogdensity/DotProduct(diff, diff));
846 for (i = 0, c = color4f;i < 6;i++, c += 4)
848 c[0] = (c[0] * f1 + fogcolor[0] * f2);
849 c[1] = (c[1] * f1 + fogcolor[1] * f2);
850 c[2] = (c[2] * f1 + fogcolor[2] * f2);
854 else if (ent->alpha != 1)
856 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
857 GL_ColorPointer(color4f);
858 for (i = 0, c = color4f;i < 6;i++, c += 4)
862 GL_ColorPointer(nomodelcolor4f);
863 R_Mesh_Draw(6, 8, nomodelelements);
866 void R_DrawNoModel(entity_render_t *ent)
868 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
869 R_MeshQueue_AddTransparent(ent->origin, R_DrawNoModelCallback, ent, 0);
871 // R_DrawNoModelCallback(ent, 0);
874 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
876 vec3_t right1, right2, diff, normal;
878 VectorSubtract (org2, org1, normal);
879 VectorNormalizeFast (normal);
881 // calculate 'right' vector for start
882 VectorSubtract (r_vieworigin, org1, diff);
883 VectorNormalizeFast (diff);
884 CrossProduct (normal, diff, right1);
886 // calculate 'right' vector for end
887 VectorSubtract (r_vieworigin, org2, diff);
888 VectorNormalizeFast (diff);
889 CrossProduct (normal, diff, right2);
891 vert[ 0] = org1[0] + width * right1[0];
892 vert[ 1] = org1[1] + width * right1[1];
893 vert[ 2] = org1[2] + width * right1[2];
894 vert[ 3] = org1[0] - width * right1[0];
895 vert[ 4] = org1[1] - width * right1[1];
896 vert[ 5] = org1[2] - width * right1[2];
897 vert[ 6] = org2[0] - width * right2[0];
898 vert[ 7] = org2[1] - width * right2[1];
899 vert[ 8] = org2[2] - width * right2[2];
900 vert[ 9] = org2[0] + width * right2[0];
901 vert[10] = org2[1] + width * right2[1];
902 vert[11] = org2[2] + width * right2[2];
905 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
907 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)
914 VectorSubtract(origin, r_vieworigin, diff);
915 ca *= 1 - exp(fogdensity/DotProduct(diff,diff));
918 R_Mesh_Matrix(&r_identitymatrix);
919 GL_Color(cr, cg, cb, ca);
920 GL_VertexPointer(varray_vertex3f);
921 GL_BlendFunc(blendfunc1, blendfunc2);
923 GL_DepthTest(!depthdisable);
925 memset(&m, 0, sizeof(m));
926 m.tex[0] = R_GetTexture(texture);
927 m.pointer_texcoord[0] = spritetexcoord2f;
928 R_Mesh_State_Texture(&m);
930 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
931 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
932 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
933 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
934 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
935 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
936 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
937 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
938 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
939 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
940 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
941 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
942 R_Mesh_Draw(4, 2, polygonelements);