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 matrix4x4_t r_view_matrix;
61 // 8.8 fraction of base light value
62 unsigned short d_lightstylevalue[256];
64 cvar_t r_drawentities = {0, "r_drawentities","1"};
65 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1"};
66 cvar_t r_speeds = {0, "r_speeds","0"};
67 cvar_t r_fullbright = {0, "r_fullbright","0"};
68 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1"};
69 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1"};
70 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1"};
71 cvar_t r_drawcollisionbrushes = {0, "r_drawcollisionbrushes", "0"};
73 cvar_t gl_fogenable = {0, "gl_fogenable", "0"};
74 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25"};
75 cvar_t gl_fogred = {0, "gl_fogred","0.3"};
76 cvar_t gl_foggreen = {0, "gl_foggreen","0.3"};
77 cvar_t gl_fogblue = {0, "gl_fogblue","0.3"};
78 cvar_t gl_fogstart = {0, "gl_fogstart", "0"};
79 cvar_t gl_fogend = {0, "gl_fogend","0"};
81 cvar_t r_textureunits = {0, "r_textureunits", "32"};
83 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1"};
84 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1"};
85 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1"};
86 cvar_t r_watershader = {CVAR_SAVE, "r_watershader", "1"};
89 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
92 for (i = 0;i < verts;i++)
103 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
106 for (i = 0;i < verts;i++)
120 For program optimization
123 qboolean intimerefresh = 0;
124 static void R_TimeRefresh_f (void)
127 float timestart, timedelta, oldangles[3];
130 VectorCopy(cl.viewangles, oldangles);
131 VectorClear(cl.viewangles);
133 timestart = Sys_DoubleTime();
134 for (i = 0;i < 128;i++)
136 Matrix4x4_CreateFromQuakeEntity(&r_refdef.viewentitymatrix, r_vieworigin[0], r_vieworigin[1], r_vieworigin[2], 0, i / 128.0 * 360.0, 0, 1);
139 timedelta = Sys_DoubleTime() - timestart;
141 VectorCopy(oldangles, cl.viewangles);
143 Con_Printf ("%f seconds (%f fps)\n", timedelta, 128/timedelta);
148 float fog_density, fog_red, fog_green, fog_blue;
150 qboolean oldgl_fogenable;
151 void R_UpdateFog(void)
153 if (gamemode == GAME_NEHAHRA)
155 if (gl_fogenable.integer)
157 oldgl_fogenable = true;
158 fog_density = gl_fogdensity.value;
159 fog_red = gl_fogred.value;
160 fog_green = gl_foggreen.value;
161 fog_blue = gl_fogblue.value;
163 else if (oldgl_fogenable)
165 oldgl_fogenable = false;
174 fogcolor[0] = fog_red = bound(0.0f, fog_red , 1.0f);
175 fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
176 fogcolor[2] = fog_blue = bound(0.0f, fog_blue , 1.0f);
181 fogdensity = -4000.0f / (fog_density * fog_density);
182 // fog color was already set
188 // FIXME: move this to client?
191 if (gamemode == GAME_NEHAHRA)
193 Cvar_Set("gl_fogenable", "0");
194 Cvar_Set("gl_fogdensity", "0.2");
195 Cvar_Set("gl_fogred", "0.3");
196 Cvar_Set("gl_foggreen", "0.3");
197 Cvar_Set("gl_fogblue", "0.3");
199 fog_density = fog_red = fog_green = fog_blue = 0.0f;
202 // FIXME: move this to client?
203 void FOG_registercvars(void)
205 if (gamemode == GAME_NEHAHRA)
207 Cvar_RegisterVariable (&gl_fogenable);
208 Cvar_RegisterVariable (&gl_fogdensity);
209 Cvar_RegisterVariable (&gl_fogred);
210 Cvar_RegisterVariable (&gl_foggreen);
211 Cvar_RegisterVariable (&gl_fogblue);
212 Cvar_RegisterVariable (&gl_fogstart);
213 Cvar_RegisterVariable (&gl_fogend);
217 void gl_main_start(void)
221 void gl_main_shutdown(void)
225 extern void CL_ParseEntityLump(char *entitystring);
226 void gl_main_newmap(void)
229 char *entities, entname[MAX_QPATH];
233 strcpy(entname, cl.worldmodel->name);
234 l = strlen(entname) - 4;
235 if (l >= 0 && !strcmp(entname + l, ".bsp"))
237 strcpy(entname + l, ".ent");
238 if ((entities = FS_LoadFile(entname, true)))
240 CL_ParseEntityLump(entities);
245 if (cl.worldmodel->brush.entities)
246 CL_ParseEntityLump(cl.worldmodel->brush.entities);
250 void GL_Main_Init(void)
252 Matrix4x4_CreateIdentity(&r_identitymatrix);
253 // FIXME: move this to client?
255 Cmd_AddCommand("timerefresh", R_TimeRefresh_f);
256 Cvar_RegisterVariable(&r_drawentities);
257 Cvar_RegisterVariable(&r_drawviewmodel);
258 Cvar_RegisterVariable(&r_speeds);
259 Cvar_RegisterVariable(&r_fullbrights);
260 Cvar_RegisterVariable(&r_wateralpha);
261 Cvar_RegisterVariable(&r_dynamic);
262 Cvar_RegisterVariable(&r_fullbright);
263 Cvar_RegisterVariable(&r_textureunits);
264 Cvar_RegisterVariable(&r_lerpsprites);
265 Cvar_RegisterVariable(&r_lerpmodels);
266 Cvar_RegisterVariable(&r_waterscroll);
267 Cvar_RegisterVariable(&r_watershader);
268 Cvar_RegisterVariable(&r_drawcollisionbrushes);
269 if (gamemode == GAME_NEHAHRA || gamemode == GAME_NEXUIZ || gamemode == GAME_TENEBRAE)
270 Cvar_SetValue("r_fullbrights", 0);
271 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
274 static vec3_t r_farclip_origin;
275 static vec3_t r_farclip_direction;
276 static vec_t r_farclip_directiondist;
277 static vec_t r_farclip_meshfarclip;
278 static int r_farclip_directionbit0;
279 static int r_farclip_directionbit1;
280 static int r_farclip_directionbit2;
282 // enlarge farclip to accomodate box
283 static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
286 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
287 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
288 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
289 if (r_farclip_meshfarclip < d)
290 r_farclip_meshfarclip = d;
293 // return farclip value
294 static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
298 VectorCopy(origin, r_farclip_origin);
299 VectorCopy(direction, r_farclip_direction);
300 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
301 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
302 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
303 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
304 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
307 R_FarClip_Box(cl.worldmodel->normalmins, cl.worldmodel->normalmaxs);
308 for (i = 0;i < r_refdef.numentities;i++)
309 R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
311 return r_farclip_meshfarclip - r_farclip_directiondist;
314 extern void R_Textures_Init(void);
315 extern void Mod_RenderInit(void);
316 extern void GL_Draw_Init(void);
317 extern void GL_Main_Init(void);
318 extern void R_Shadow_Init(void);
319 extern void GL_Models_Init(void);
320 extern void R_Sky_Init(void);
321 extern void GL_Surf_Init(void);
322 extern void R_Crosshairs_Init(void);
323 extern void R_Light_Init(void);
324 extern void R_Particles_Init(void);
325 extern void R_Explosion_Init(void);
326 extern void ui_init(void);
327 extern void gl_backend_init(void);
328 extern void Sbar_Init(void);
329 extern void R_LightningBeams_Init(void);
331 void Render_Init(void)
350 R_LightningBeams_Init();
358 extern char *ENGINE_EXTENSIONS;
361 VID_CheckExtensions();
363 // LordHavoc: report supported extensions
364 Con_DPrintf("\nengine extensions: %s\n", ENGINE_EXTENSIONS);
367 int R_CullBox(const vec3_t mins, const vec3_t maxs)
371 for (i = 0;i < 4;i++)
378 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
382 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
386 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
390 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
394 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
398 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
402 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
406 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
414 //==================================================================================
416 static void R_MarkEntities (void)
419 entity_render_t *ent;
421 ent = &cl_entities[0].render;
422 Matrix4x4_CreateIdentity(&ent->matrix);
423 Matrix4x4_CreateIdentity(&ent->inversematrix);
425 if (!r_drawentities.integer)
428 for (i = 0;i < r_refdef.numentities;i++)
430 ent = r_refdef.entities[i];
431 Mod_CheckLoaded(ent->model);
432 // some of the renderer still relies on origin...
433 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
434 // some of the renderer still relies on scale...
435 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
436 R_LerpAnimation(ent);
437 R_UpdateEntLights(ent);
438 if ((chase_active.integer || !(ent->flags & RENDER_EXTERIORMODEL))
439 && !VIS_CullBox(ent->mins, ent->maxs)
440 && (!envmap || !(ent->flags & (RENDER_VIEWMODEL | RENDER_EXTERIORMODEL))))
441 ent->visframe = r_framecount;
445 // only used if skyrendermasked, and normally returns false
446 int R_DrawBrushModelsSky (void)
449 entity_render_t *ent;
451 if (!r_drawentities.integer)
455 for (i = 0;i < r_refdef.numentities;i++)
457 ent = r_refdef.entities[i];
458 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
460 ent->model->DrawSky(ent);
473 void R_DrawViewModel (void)
475 entity_render_t *ent;
477 // FIXME: move these checks to client
478 if (!r_drawviewmodel.integer || chase_active.integer || envmap || !r_drawentities.integer || cl.items & IT_INVISIBILITY || cl.stats[STAT_HEALTH] <= 0 || !cl.viewent.render.model)
481 ent = &cl.viewent.render;
482 Mod_CheckLoaded(ent->model);
483 R_LerpAnimation(ent);
484 Matrix4x4_CreateFromQuakeEntity(&ent->matrix, ent->origin[0], ent->origin[1], ent->origin[2], -ent->angles[0], ent->angles[1], ent->angles[2], ent->scale);
485 Matrix4x4_Invert_Simple(&ent->inversematrix, &ent->matrix);
486 R_UpdateEntLights(ent);
487 ent->model->Draw(ent);
491 void R_DrawNoModel(entity_render_t *ent);
492 void R_DrawModels(void)
495 entity_render_t *ent;
497 if (!r_drawentities.integer)
500 for (i = 0;i < r_refdef.numentities;i++)
502 ent = r_refdef.entities[i];
503 if (ent->visframe == r_framecount)
505 if (ent->model && ent->model->Draw != NULL)
506 ent->model->Draw(ent);
513 static void R_SetFrustum(void)
515 // break apart the view matrix into vectors for various purposes
516 Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
517 VectorNegate(r_viewleft, r_viewright);
519 // LordHavoc: note to all quake engine coders, the special case for 90
520 // degrees assumed a square view (wrong), so I removed it, Quake2 has it
523 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
524 RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_view_fov_x / 2));
525 frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
526 PlaneClassify(&frustum[0]);
528 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
529 RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_view_fov_x / 2));
530 frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
531 PlaneClassify(&frustum[1]);
533 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
534 RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_view_fov_y / 2));
535 frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
536 PlaneClassify(&frustum[2]);
538 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
539 RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_view_fov_y / 2));
540 frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
541 PlaneClassify(&frustum[3]);
544 static void R_BlendView(void)
550 if (r_refdef.viewblend[3] < 0.01f)
553 R_Mesh_Matrix(&r_identitymatrix);
555 memset(&m, 0, sizeof(m));
556 R_Mesh_State_Texture(&m);
558 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
560 GL_DepthTest(false); // magic
561 GL_VertexPointer(vertex3f);
562 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
564 vertex3f[0] = r_vieworigin[0] + r_viewforward[0] * 1.5 + r_viewleft[0] * r - r_viewup[0] * r;
565 vertex3f[1] = r_vieworigin[1] + r_viewforward[1] * 1.5 + r_viewleft[1] * r - r_viewup[1] * r;
566 vertex3f[2] = r_vieworigin[2] + r_viewforward[2] * 1.5 + r_viewleft[2] * r - r_viewup[2] * r;
567 vertex3f[3] = r_vieworigin[0] + r_viewforward[0] * 1.5 + r_viewleft[0] * r + r_viewup[0] * r * 3;
568 vertex3f[4] = r_vieworigin[1] + r_viewforward[1] * 1.5 + r_viewleft[1] * r + r_viewup[1] * r * 3;
569 vertex3f[5] = r_vieworigin[2] + r_viewforward[2] * 1.5 + r_viewleft[2] * r + r_viewup[2] * r * 3;
570 vertex3f[6] = r_vieworigin[0] + r_viewforward[0] * 1.5 - r_viewleft[0] * r * 3 - r_viewup[0] * r;
571 vertex3f[7] = r_vieworigin[1] + r_viewforward[1] * 1.5 - r_viewleft[1] * r * 3 - r_viewup[1] * r;
572 vertex3f[8] = r_vieworigin[2] + r_viewforward[2] * 1.5 - r_viewleft[2] * r * 3 - r_viewup[2] * r;
573 R_Mesh_Draw(3, 1, polygonelements);
576 void R_UpdateWorld(void)
578 if (!r_refdef.entities/* || !cl.worldmodel*/)
579 return; //Host_Error ("R_RenderView: NULL worldmodel");
581 if (r_shadow_realtime_world.integer && !gl_stencil)
583 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");
584 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
587 // don't allow cheats in multiplayer
590 if (r_fullbright.integer != 0)
591 Cvar_Set ("r_fullbright", "0");
592 if (r_ambient.value != 0)
593 Cvar_Set ("r_ambient", "0");
601 void R_RenderScene(void);
608 void R_RenderView(void)
610 if (!r_refdef.entities/* || !cl.worldmodel*/)
611 return; //Host_Error ("R_RenderView: NULL worldmodel");
613 r_view_width = bound(0, r_refdef.width, vid.realwidth);
614 r_view_height = bound(0, r_refdef.height, vid.realheight);
615 r_view_x = bound(0, r_refdef.x, vid.realwidth - r_refdef.width);
616 r_view_y = bound(0, r_refdef.y, vid.realheight - r_refdef.height);
617 r_view_fov_x = bound(1, r_refdef.fov_x, 170);
618 r_view_fov_y = bound(1, r_refdef.fov_y, 170);
619 r_view_matrix = r_refdef.viewentitymatrix;
621 // GL is weird because it's bottom to top, r_view_y is top to bottom
622 qglViewport(r_view_x, vid.realheight - (r_view_y + r_view_height), r_view_width, r_view_height);
623 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
624 GL_ScissorTest(true);
628 R_TimeReport("setup");
630 qglDepthFunc(GL_LEQUAL);
631 qglPolygonOffset(0, 0);
632 qglEnable(GL_POLYGON_OFFSET_FILL);
636 qglPolygonOffset(0, 0);
637 qglDisable(GL_POLYGON_OFFSET_FILL);
640 R_TimeReport("blendview");
643 R_TimeReport("meshfinish");
645 GL_Scissor(0, 0, vid.realwidth, vid.realheight);
646 GL_ScissorTest(false);
649 extern void R_DrawLightningBeams (void);
650 void R_RenderScene(void)
652 entity_render_t *world;
654 // don't let sound skip if going slow
655 if (!intimerefresh && !r_speeds.integer)
662 r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
663 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)))
664 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view_fov_x, r_view_fov_y, 1.0f);
666 GL_SetupView_Mode_Perspective(r_view_fov_x, r_view_fov_y, 1.0f, r_farclip);
668 GL_SetupView_Orientation_FromEntity(&r_view_matrix);
672 if (cl.worldmodel && cl.worldmodel->brush.FatPVS)
673 cl.worldmodel->brush.FatPVS(cl.worldmodel, r_vieworigin, 2, r_pvsbits, sizeof(r_pvsbits));
674 world = &cl_entities[0].render;
675 R_WorldVisibility(world);
676 R_TimeReport("worldvis");
679 R_TimeReport("markentity");
681 R_MeshQueue_BeginScene();
683 R_Shadow_UpdateWorldLightSelection();
685 // don't let sound skip if going slow
686 if (!intimerefresh && !r_speeds.integer)
689 if (R_DrawBrushModelsSky())
690 R_TimeReport("bmodelsky");
692 // must occur early because it can draw sky
694 R_TimeReport("world");
696 // don't let sound skip if going slow
697 if (!intimerefresh && !r_speeds.integer)
701 R_TimeReport("models");
703 // don't let sound skip if going slow
704 if (!intimerefresh && !r_speeds.integer)
707 R_ShadowVolumeLighting(false);
708 R_TimeReport("rtlights");
710 // don't let sound skip if going slow
711 if (!intimerefresh && !r_speeds.integer)
714 R_DrawLightningBeams();
715 R_TimeReport("lightning");
718 R_TimeReport("particles");
721 R_TimeReport("explosions");
723 R_MeshQueue_RenderTransparent();
724 R_TimeReport("drawtrans");
727 R_TimeReport("coronas");
729 R_DrawWorldCrosshair();
730 R_TimeReport("crosshair");
732 R_MeshQueue_Render();
733 R_MeshQueue_EndScene();
735 if (r_shadow_visiblevolumes.integer)
737 R_ShadowVolumeLighting(true);
738 R_TimeReport("shadowvolume");
741 // don't let sound skip if going slow
742 if (!intimerefresh && !r_speeds.integer)
747 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
750 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
752 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
755 R_Mesh_Matrix(&r_identitymatrix);
757 memset(&m, 0, sizeof(m));
758 R_Mesh_State_Texture(&m);
761 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
762 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
763 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
764 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
765 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
766 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
767 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
768 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
769 GL_ColorPointer(color);
770 R_FillColors(color, 8, cr, cg, cb, ca);
773 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
775 VectorSubtract(v, r_vieworigin, diff);
776 f2 = exp(fogdensity/DotProduct(diff, diff));
778 c[0] = c[0] * f1 + fogcolor[0] * f2;
779 c[1] = c[1] * f1 + fogcolor[1] * f2;
780 c[2] = c[2] * f1 + fogcolor[2] * f2;
787 int nomodelelements[24] =
799 float nomodelvertex3f[6*3] =
809 float nomodelcolor4f[6*4] =
811 0.0f, 0.0f, 0.5f, 1.0f,
812 0.0f, 0.0f, 0.5f, 1.0f,
813 0.0f, 0.5f, 0.0f, 1.0f,
814 0.0f, 0.5f, 0.0f, 1.0f,
815 0.5f, 0.0f, 0.0f, 1.0f,
816 0.5f, 0.0f, 0.0f, 1.0f
819 void R_DrawNoModelCallback(const void *calldata1, int calldata2)
821 const entity_render_t *ent = calldata1;
823 float f1, f2, *c, diff[3];
826 R_Mesh_Matrix(&ent->matrix);
828 memset(&m, 0, sizeof(m));
829 R_Mesh_State_Texture(&m);
831 if (ent->flags & EF_ADDITIVE)
833 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
836 else if (ent->alpha < 1)
838 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
843 GL_BlendFunc(GL_ONE, GL_ZERO);
847 GL_VertexPointer(nomodelvertex3f);
850 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
851 GL_ColorPointer(color4f);
852 VectorSubtract(ent->origin, r_vieworigin, diff);
853 f2 = exp(fogdensity/DotProduct(diff, diff));
855 for (i = 0, c = color4f;i < 6;i++, c += 4)
857 c[0] = (c[0] * f1 + fogcolor[0] * f2);
858 c[1] = (c[1] * f1 + fogcolor[1] * f2);
859 c[2] = (c[2] * f1 + fogcolor[2] * f2);
863 else if (ent->alpha != 1)
865 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
866 GL_ColorPointer(color4f);
867 for (i = 0, c = color4f;i < 6;i++, c += 4)
871 GL_ColorPointer(nomodelcolor4f);
872 R_Mesh_Draw(6, 8, nomodelelements);
875 void R_DrawNoModel(entity_render_t *ent)
877 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
878 R_MeshQueue_AddTransparent(ent->origin, R_DrawNoModelCallback, ent, 0);
880 // R_DrawNoModelCallback(ent, 0);
883 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
885 vec3_t right1, right2, diff, normal;
887 VectorSubtract (org2, org1, normal);
888 VectorNormalizeFast (normal);
890 // calculate 'right' vector for start
891 VectorSubtract (r_vieworigin, org1, diff);
892 VectorNormalizeFast (diff);
893 CrossProduct (normal, diff, right1);
895 // calculate 'right' vector for end
896 VectorSubtract (r_vieworigin, org2, diff);
897 VectorNormalizeFast (diff);
898 CrossProduct (normal, diff, right2);
900 vert[ 0] = org1[0] + width * right1[0];
901 vert[ 1] = org1[1] + width * right1[1];
902 vert[ 2] = org1[2] + width * right1[2];
903 vert[ 3] = org1[0] - width * right1[0];
904 vert[ 4] = org1[1] - width * right1[1];
905 vert[ 5] = org1[2] - width * right1[2];
906 vert[ 6] = org2[0] - width * right2[0];
907 vert[ 7] = org2[1] - width * right2[1];
908 vert[ 8] = org2[2] - width * right2[2];
909 vert[ 9] = org2[0] + width * right2[0];
910 vert[10] = org2[1] + width * right2[1];
911 vert[11] = org2[2] + width * right2[2];
914 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
916 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)
923 VectorSubtract(origin, r_vieworigin, diff);
924 ca *= 1 - exp(fogdensity/DotProduct(diff,diff));
927 R_Mesh_Matrix(&r_identitymatrix);
928 GL_Color(cr, cg, cb, ca);
929 GL_VertexPointer(varray_vertex3f);
930 GL_BlendFunc(blendfunc1, blendfunc2);
932 GL_DepthTest(!depthdisable);
934 memset(&m, 0, sizeof(m));
935 m.tex[0] = R_GetTexture(texture);
936 m.pointer_texcoord[0] = spritetexcoord2f;
937 R_Mesh_State_Texture(&m);
939 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
940 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
941 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
942 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
943 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
944 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
945 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
946 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
947 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
948 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
949 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
950 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
951 R_Mesh_Draw(4, 2, polygonelements);