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
30 matrix4x4_t r_identitymatrix;
32 int c_alias_polys, c_light_polys, c_faces, c_nodes, c_leafs, c_models, c_bmodels, c_sprites, c_particles, c_dlights, c_meshs, c_meshelements, c_rt_lights, c_rt_clears, c_rt_scissored, c_rt_shadowmeshes, c_rt_shadowtris, c_rt_lightmeshes, c_rt_lighttris, c_rtcached_shadowmeshes, c_rtcached_shadowtris, c_bloom, c_bloomcopies, c_bloomcopypixels, c_bloomdraws, c_bloomdrawpixels;
34 // true during envmap command capture
37 // maximum visible distance (recalculated from world box each frame)
39 // brightness of world lightmaps and related lighting
40 // (often reduced when world rtlights are enabled)
41 float r_lightmapintensity;
42 // whether to draw world lights realtime, dlights realtime, and their shadows
44 qboolean r_rtworldshadows;
46 qboolean r_rtdlightshadows;
49 // forces all rendering to draw triangle outlines
66 matrix4x4_t r_view_matrix;
73 // 8.8 fraction of base light value
74 unsigned short d_lightstylevalue[256];
76 cvar_t r_showtris = {0, "r_showtris", "0"};
77 cvar_t r_drawentities = {0, "r_drawentities","1"};
78 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1"};
79 cvar_t r_speeds = {0, "r_speeds","0"};
80 cvar_t r_fullbright = {0, "r_fullbright","0"};
81 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1"};
82 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1"};
83 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1"};
84 cvar_t r_drawcollisionbrushes = {0, "r_drawcollisionbrushes", "0"};
86 cvar_t gl_fogenable = {0, "gl_fogenable", "0"};
87 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25"};
88 cvar_t gl_fogred = {0, "gl_fogred","0.3"};
89 cvar_t gl_foggreen = {0, "gl_foggreen","0.3"};
90 cvar_t gl_fogblue = {0, "gl_fogblue","0.3"};
91 cvar_t gl_fogstart = {0, "gl_fogstart", "0"};
92 cvar_t gl_fogend = {0, "gl_fogend","0"};
94 cvar_t r_textureunits = {0, "r_textureunits", "32"};
96 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1"};
97 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1"};
98 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1"};
99 cvar_t r_watershader = {CVAR_SAVE, "r_watershader", "1"};
101 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0"};
102 cvar_t r_bloom_intensity = {CVAR_SAVE, "r_bloom_intensity", "2"};
103 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "8"};
104 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320"};
105 cvar_t r_bloom_power = {CVAR_SAVE, "r_bloom_power", "4"};
106 rtexturepool_t *r_main_texturepool;
107 rtexture_t *r_bloom_texture_screen;
108 rtexture_t *r_bloom_texture_bloom;
110 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
113 for (i = 0;i < verts;i++)
124 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
127 for (i = 0;i < verts;i++)
139 float fog_density, fog_red, fog_green, fog_blue;
141 qboolean oldgl_fogenable;
142 void R_UpdateFog(void)
144 if (gamemode == GAME_NEHAHRA)
146 if (gl_fogenable.integer)
148 oldgl_fogenable = true;
149 fog_density = gl_fogdensity.value;
150 fog_red = gl_fogred.value;
151 fog_green = gl_foggreen.value;
152 fog_blue = gl_fogblue.value;
154 else if (oldgl_fogenable)
156 oldgl_fogenable = false;
165 fogcolor[0] = fog_red = bound(0.0f, fog_red , 1.0f);
166 fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
167 fogcolor[2] = fog_blue = bound(0.0f, fog_blue , 1.0f);
172 fogdensity = -4000.0f / (fog_density * fog_density);
173 // fog color was already set
179 // FIXME: move this to client?
182 if (gamemode == GAME_NEHAHRA)
184 Cvar_Set("gl_fogenable", "0");
185 Cvar_Set("gl_fogdensity", "0.2");
186 Cvar_Set("gl_fogred", "0.3");
187 Cvar_Set("gl_foggreen", "0.3");
188 Cvar_Set("gl_fogblue", "0.3");
190 fog_density = fog_red = fog_green = fog_blue = 0.0f;
193 // FIXME: move this to client?
194 void FOG_registercvars(void)
196 if (gamemode == GAME_NEHAHRA)
198 Cvar_RegisterVariable (&gl_fogenable);
199 Cvar_RegisterVariable (&gl_fogdensity);
200 Cvar_RegisterVariable (&gl_fogred);
201 Cvar_RegisterVariable (&gl_foggreen);
202 Cvar_RegisterVariable (&gl_fogblue);
203 Cvar_RegisterVariable (&gl_fogstart);
204 Cvar_RegisterVariable (&gl_fogend);
208 void gl_main_start(void)
210 r_main_texturepool = R_AllocTexturePool();
211 r_bloom_texture_screen = NULL;
212 r_bloom_texture_bloom = NULL;
215 void gl_main_shutdown(void)
217 R_FreeTexturePool(&r_main_texturepool);
218 r_bloom_texture_screen = NULL;
219 r_bloom_texture_bloom = NULL;
222 extern void CL_ParseEntityLump(char *entitystring);
223 void gl_main_newmap(void)
225 // FIXME: move this code to client
227 char *entities, entname[MAX_QPATH];
231 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
232 l = strlen(entname) - 4;
233 if (l >= 0 && !strcmp(entname + l, ".bsp"))
235 strcpy(entname + l, ".ent");
236 if ((entities = FS_LoadFile(entname, tempmempool, true)))
238 CL_ParseEntityLump(entities);
243 if (cl.worldmodel->brush.entities)
244 CL_ParseEntityLump(cl.worldmodel->brush.entities);
248 void GL_Main_Init(void)
250 Matrix4x4_CreateIdentity(&r_identitymatrix);
251 // FIXME: move this to client?
253 Cvar_RegisterVariable(&r_showtris);
254 Cvar_RegisterVariable(&r_drawentities);
255 Cvar_RegisterVariable(&r_drawviewmodel);
256 Cvar_RegisterVariable(&r_speeds);
257 Cvar_RegisterVariable(&r_fullbrights);
258 Cvar_RegisterVariable(&r_wateralpha);
259 Cvar_RegisterVariable(&r_dynamic);
260 Cvar_RegisterVariable(&r_fullbright);
261 Cvar_RegisterVariable(&r_textureunits);
262 Cvar_RegisterVariable(&r_lerpsprites);
263 Cvar_RegisterVariable(&r_lerpmodels);
264 Cvar_RegisterVariable(&r_waterscroll);
265 Cvar_RegisterVariable(&r_watershader);
266 Cvar_RegisterVariable(&r_drawcollisionbrushes);
267 Cvar_RegisterVariable(&r_bloom);
268 Cvar_RegisterVariable(&r_bloom_intensity);
269 Cvar_RegisterVariable(&r_bloom_blur);
270 Cvar_RegisterVariable(&r_bloom_resolution);
271 Cvar_RegisterVariable(&r_bloom_power);
272 if (gamemode == GAME_NEHAHRA || gamemode == GAME_NEXUIZ || gamemode == GAME_TENEBRAE)
273 Cvar_SetValue("r_fullbrights", 0);
274 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
277 static vec3_t r_farclip_origin;
278 static vec3_t r_farclip_direction;
279 static vec_t r_farclip_directiondist;
280 static vec_t r_farclip_meshfarclip;
281 static int r_farclip_directionbit0;
282 static int r_farclip_directionbit1;
283 static int r_farclip_directionbit2;
285 // enlarge farclip to accomodate box
286 static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
289 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
290 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
291 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
292 if (r_farclip_meshfarclip < d)
293 r_farclip_meshfarclip = d;
296 // return farclip value
297 static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
301 VectorCopy(origin, r_farclip_origin);
302 VectorCopy(direction, r_farclip_direction);
303 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
304 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
305 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
306 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
307 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
309 if (r_refdef.worldmodel)
310 R_FarClip_Box(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
311 for (i = 0;i < r_refdef.numentities;i++)
312 R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
314 return r_farclip_meshfarclip - r_farclip_directiondist;
317 extern void R_Textures_Init(void);
318 extern void Mod_RenderInit(void);
319 extern void GL_Draw_Init(void);
320 extern void GL_Main_Init(void);
321 extern void R_Shadow_Init(void);
322 extern void GL_Models_Init(void);
323 extern void R_Sky_Init(void);
324 extern void GL_Surf_Init(void);
325 extern void R_Crosshairs_Init(void);
326 extern void R_Light_Init(void);
327 extern void R_Particles_Init(void);
328 extern void R_Explosion_Init(void);
329 extern void ui_init(void);
330 extern void gl_backend_init(void);
331 extern void Sbar_Init(void);
332 extern void R_LightningBeams_Init(void);
334 void Render_Init(void)
353 R_LightningBeams_Init();
361 extern char *ENGINE_EXTENSIONS;
364 VID_CheckExtensions();
366 // LordHavoc: report supported extensions
367 Con_DPrintf("\nengine extensions: %s\n", ENGINE_EXTENSIONS);
369 // clear to black (loading plaque will be seen over this)
370 qglClearColor(0,0,0,1);
371 qglClear(GL_COLOR_BUFFER_BIT);
374 int R_CullBox(const vec3_t mins, const vec3_t maxs)
378 for (i = 0;i < 4;i++)
385 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
389 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
393 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
397 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
401 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
405 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
409 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
413 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
421 //==================================================================================
423 static void R_MarkEntities (void)
426 entity_render_t *ent;
428 if (!r_drawentities.integer)
431 renderimask = envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
432 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
434 // worldmodel can check visibility
435 for (i = 0;i < r_refdef.numentities;i++)
437 ent = r_refdef.entities[i];
438 Mod_CheckLoaded(ent->model);
439 // some of the renderer still relies on origin...
440 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
441 // some of the renderer still relies on scale...
442 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
443 if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && ((ent->effects & EF_NODEPTHTEST) || r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.worldmodel, r_worldleafvisible, ent->mins, ent->maxs)))
445 R_UpdateEntLights(ent);
446 ent->visframe = r_framecount;
452 // no worldmodel or it can't check visibility
453 for (i = 0;i < r_refdef.numentities;i++)
455 ent = r_refdef.entities[i];
456 Mod_CheckLoaded(ent->model);
457 // some of the renderer still relies on origin...
458 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
459 // some of the renderer still relies on scale...
460 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
461 if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST))
463 R_UpdateEntLights(ent);
464 ent->visframe = r_framecount;
470 // only used if skyrendermasked, and normally returns false
471 int R_DrawBrushModelsSky (void)
474 entity_render_t *ent;
476 if (!r_drawentities.integer)
480 for (i = 0;i < r_refdef.numentities;i++)
482 ent = r_refdef.entities[i];
483 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
485 ent->model->DrawSky(ent);
492 void R_DrawNoModel(entity_render_t *ent);
493 void R_DrawModels(void)
496 entity_render_t *ent;
498 if (!r_drawentities.integer)
501 for (i = 0;i < r_refdef.numentities;i++)
503 ent = r_refdef.entities[i];
504 if (ent->visframe == r_framecount)
506 if (ent->model && ent->model->Draw != NULL)
507 ent->model->Draw(ent);
514 static void R_SetFrustum(void)
516 // break apart the view matrix into vectors for various purposes
517 Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
518 VectorNegate(r_viewleft, r_viewright);
520 // LordHavoc: note to all quake engine coders, the special case for 90
521 // degrees assumed a square view (wrong), so I removed it, Quake2 has it
524 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
525 RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_view_fov_x / 2));
526 frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
527 PlaneClassify(&frustum[0]);
529 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
530 RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_view_fov_x / 2));
531 frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
532 PlaneClassify(&frustum[1]);
534 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
535 RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_view_fov_y / 2));
536 frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
537 PlaneClassify(&frustum[2]);
539 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
540 RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_view_fov_y / 2));
541 frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
542 PlaneClassify(&frustum[3]);
545 static void R_BlendView(void)
549 if (r_refdef.viewblend[3] < 0.01f && !r_bloom.integer)
552 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
555 R_Mesh_Matrix(&r_identitymatrix);
556 varray_vertex3f[0] = 0;varray_vertex3f[1] = 0;varray_vertex3f[2] = 0;
557 varray_vertex3f[3] = 1;varray_vertex3f[4] = 0;varray_vertex3f[5] = 0;
558 varray_vertex3f[6] = 1;varray_vertex3f[7] = 1;varray_vertex3f[8] = 0;
559 varray_vertex3f[9] = 0;varray_vertex3f[10] = 1;varray_vertex3f[11] = 0;
560 if (r_bloom.integer && r_bloom_resolution.value >= 32 && r_bloom_power.integer >= 1 && r_bloom_power.integer < 100 && r_bloom_blur.value >= 0 && r_bloom_blur.value < 512)
562 int screenwidth, screenheight, bloomwidth, bloomheight, x, dobloomblend, range;
563 float xoffset, yoffset, r;
565 for (screenwidth = 1;screenwidth < vid.realwidth;screenwidth *= 2);
566 for (screenheight = 1;screenheight < vid.realheight;screenheight *= 2);
567 bloomwidth = min(r_view_width, r_bloom_resolution.integer);
568 bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
569 varray_texcoord2f[0][0] = 0;
570 varray_texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
571 varray_texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
572 varray_texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
573 varray_texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
574 varray_texcoord2f[0][5] = 0;
575 varray_texcoord2f[0][6] = 0;
576 varray_texcoord2f[0][7] = 0;
577 varray_texcoord2f[1][0] = 0;
578 varray_texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
579 varray_texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
580 varray_texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
581 varray_texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
582 varray_texcoord2f[1][5] = 0;
583 varray_texcoord2f[1][6] = 0;
584 varray_texcoord2f[1][7] = 0;
585 if (!r_bloom_texture_screen)
586 r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
587 if (!r_bloom_texture_bloom)
588 r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
589 memset(&m, 0, sizeof(m));
590 m.pointer_vertex = varray_vertex3f;
591 m.pointer_texcoord[0] = varray_texcoord2f[0];
592 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
594 // copy view to a texture
596 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.realheight - (r_view_y + r_view_height), r_view_width, r_view_height);
598 c_bloomcopypixels += r_view_width * r_view_height;
599 // now scale it down to the bloom size and raise to a power of itself
600 qglViewport(r_view_x, vid.realheight - (r_view_y + bloomheight), bloomwidth, bloomheight);
601 // TODO: optimize with multitexture or GLSL
602 GL_BlendFunc(GL_ONE, GL_ZERO);
603 GL_Color(1, 1, 1, 1);
604 R_Mesh_Draw(4, 2, polygonelements);
606 c_bloomdrawpixels += bloomwidth * bloomheight;
607 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
608 for (x = 1;x < r_bloom_power.integer;x++)
610 R_Mesh_Draw(4, 2, polygonelements);
612 c_bloomdrawpixels += bloomwidth * bloomheight;
614 // copy the bloom view to a texture
615 memset(&m, 0, sizeof(m));
616 m.pointer_vertex = varray_vertex3f;
617 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
618 m.pointer_texcoord[0] = varray_texcoord2f[2];
621 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.realheight - (r_view_y + bloomheight), bloomwidth, bloomheight);
623 c_bloomcopypixels += bloomwidth * bloomheight;
624 // blend on at multiple offsets vertically
625 // TODO: do offset blends using GLSL
626 range = r_bloom_blur.integer * bloomwidth / 320;
627 GL_BlendFunc(GL_ONE, GL_ZERO);
628 for (x = -range;x <= range;x++)
630 xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
631 yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
632 varray_texcoord2f[2][0] = xoffset+0;
633 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
634 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
635 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
636 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
637 varray_texcoord2f[2][5] = yoffset+0;
638 varray_texcoord2f[2][6] = xoffset+0;
639 varray_texcoord2f[2][7] = yoffset+0;
640 r = r_bloom_intensity.value/(range*2+1)*(1 - fabs(x*x)/(float)(range*range));
643 GL_Color(r, r, r, 1);
644 R_Mesh_Draw(4, 2, polygonelements);
646 c_bloomdrawpixels += bloomwidth * bloomheight;
647 GL_BlendFunc(GL_ONE, GL_ONE);
649 // copy the blurred bloom view to a texture
651 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.realheight - (r_view_y + bloomheight), bloomwidth, bloomheight);
653 c_bloomcopypixels += bloomwidth * bloomheight;
654 // blend on at multiple offsets horizontally
655 // TODO: do offset blends using GLSL
656 range = r_bloom_blur.integer * bloomwidth / 320;
657 GL_BlendFunc(GL_ONE, GL_ZERO);
658 for (x = -range;x <= range;x++)
660 xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
661 yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
662 varray_texcoord2f[2][0] = xoffset+0;
663 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
664 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
665 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
666 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
667 varray_texcoord2f[2][5] = yoffset+0;
668 varray_texcoord2f[2][6] = xoffset+0;
669 varray_texcoord2f[2][7] = yoffset+0;
670 r = r_bloom_intensity.value/(range*2+1)*(1 - fabs(x*x)/(float)(range*range));
673 GL_Color(r, r, r, 1);
674 R_Mesh_Draw(4, 2, polygonelements);
676 c_bloomdrawpixels += bloomwidth * bloomheight;
677 GL_BlendFunc(GL_ONE, GL_ONE);
679 // copy the blurred bloom view to a texture
681 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.realheight - (r_view_y + bloomheight), bloomwidth, bloomheight);
683 c_bloomcopypixels += bloomwidth * bloomheight;
684 // go back to full view area
685 qglViewport(r_view_x, vid.realheight - (r_view_y + r_view_height), r_view_width, r_view_height);
686 // put the original view back in place
687 memset(&m, 0, sizeof(m));
688 m.pointer_vertex = varray_vertex3f;
689 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
690 m.pointer_texcoord[0] = varray_texcoord2f[0];
692 dobloomblend = false;
694 // do both in one pass if possible
695 if (r_textureunits.integer >= 2 && gl_combine.integer)
697 dobloomblend = false;
698 m.texcombinergb[1] = GL_ADD;
699 m.tex[1] = R_GetTexture(r_bloom_texture_bloom);
700 m.pointer_texcoord[1] = varray_texcoord2f[1];
706 GL_BlendFunc(GL_ONE, GL_ZERO);
708 R_Mesh_Draw(4, 2, polygonelements);
710 c_bloomdrawpixels += r_view_width * r_view_height;
711 // now blend on the bloom texture if multipass
714 memset(&m, 0, sizeof(m));
715 m.pointer_vertex = varray_vertex3f;
716 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
717 m.pointer_texcoord[0] = varray_texcoord2f[1];
719 GL_BlendFunc(GL_ONE, GL_ONE);
721 R_Mesh_Draw(4, 2, polygonelements);
723 c_bloomdrawpixels += r_view_width * r_view_height;
726 if (r_refdef.viewblend[3] >= 0.01f)
728 // apply a color tint to the whole view
729 memset(&m, 0, sizeof(m));
730 m.pointer_vertex = varray_vertex3f;
732 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
733 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
734 R_Mesh_Draw(4, 2, polygonelements);
738 void R_RenderScene(void);
745 void R_RenderView(void)
747 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
748 return; //Host_Error ("R_RenderView: NULL worldmodel");
750 r_view_width = bound(0, r_refdef.width, vid.realwidth);
751 r_view_height = bound(0, r_refdef.height, vid.realheight);
753 r_view_x = bound(0, r_refdef.x, vid.realwidth - r_refdef.width);
754 r_view_y = bound(0, r_refdef.y, vid.realheight - r_refdef.height);
756 r_view_fov_x = bound(1, r_refdef.fov_x, 170);
757 r_view_fov_y = bound(1, r_refdef.fov_y, 170);
758 r_view_matrix = r_refdef.viewentitymatrix;
759 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
760 r_rtworld = r_shadow_realtime_world.integer;
761 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
762 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
763 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
764 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
766 // GL is weird because it's bottom to top, r_view_y is top to bottom
767 qglViewport(r_view_x, vid.realheight - (r_view_y + r_view_height), r_view_width, r_view_height);
768 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
769 GL_ScissorTest(true);
775 R_TimeReport("setup");
777 qglDepthFunc(GL_LEQUAL);
778 qglPolygonOffset(0, 0);
779 qglEnable(GL_POLYGON_OFFSET_FILL);
783 qglPolygonOffset(0, 0);
784 qglDisable(GL_POLYGON_OFFSET_FILL);
787 R_TimeReport("blendview");
789 GL_Scissor(0, 0, vid.realwidth, vid.realheight);
790 GL_ScissorTest(false);
793 extern void R_DrawLightningBeams (void);
794 void R_RenderScene(void)
796 // don't let sound skip if going slow
797 if (r_refdef.extraupdate)
802 R_MeshQueue_BeginScene();
804 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
808 r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
809 if (r_rtworldshadows || r_rtdlightshadows)
810 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view_fov_x, r_view_fov_y, 1.0f);
812 GL_SetupView_Mode_Perspective(r_view_fov_x, r_view_fov_y, 1.0f, r_farclip);
814 GL_SetupView_Orientation_FromEntity(&r_view_matrix);
819 R_TimeReport("worldvis");
822 R_TimeReport("markentity");
824 R_Shadow_UpdateWorldLightSelection();
826 // don't let sound skip if going slow
827 if (r_refdef.extraupdate)
830 GL_ShowTrisColor(0.025, 0.025, 0, 1);
831 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
833 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
834 R_TimeReport("worldsky");
837 if (R_DrawBrushModelsSky())
838 R_TimeReport("bmodelsky");
840 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
841 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
843 r_refdef.worldmodel->Draw(r_refdef.worldentity);
844 R_TimeReport("world");
847 // don't let sound skip if going slow
848 if (r_refdef.extraupdate)
851 GL_ShowTrisColor(0, 0.015, 0, 1);
854 R_TimeReport("models");
856 // don't let sound skip if going slow
857 if (r_refdef.extraupdate)
860 GL_ShowTrisColor(0, 0, 0.033, 1);
861 R_ShadowVolumeLighting(false);
862 R_TimeReport("rtlights");
864 // don't let sound skip if going slow
865 if (r_refdef.extraupdate)
868 GL_ShowTrisColor(0.1, 0, 0, 1);
870 R_DrawLightningBeams();
871 R_TimeReport("lightning");
874 R_TimeReport("particles");
877 R_TimeReport("explosions");
879 R_MeshQueue_RenderTransparent();
880 R_TimeReport("drawtrans");
883 R_TimeReport("coronas");
885 R_DrawWorldCrosshair();
886 R_TimeReport("crosshair");
888 R_MeshQueue_Render();
889 R_MeshQueue_EndScene();
891 if (r_shadow_visiblevolumes.integer && !r_showtrispass)
893 R_ShadowVolumeLighting(true);
894 R_TimeReport("shadowvolume");
897 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
899 // don't let sound skip if going slow
900 if (r_refdef.extraupdate)
905 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
908 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
910 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
913 R_Mesh_Matrix(&r_identitymatrix);
915 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
916 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
917 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
918 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
919 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
920 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
921 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
922 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
923 R_FillColors(color, 8, cr, cg, cb, ca);
926 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
928 VectorSubtract(v, r_vieworigin, diff);
929 f2 = exp(fogdensity/DotProduct(diff, diff));
931 c[0] = c[0] * f1 + fogcolor[0] * f2;
932 c[1] = c[1] * f1 + fogcolor[1] * f2;
933 c[2] = c[2] * f1 + fogcolor[2] * f2;
936 memset(&m, 0, sizeof(m));
937 m.pointer_vertex = vertex3f;
938 m.pointer_color = color;
944 int nomodelelements[24] =
956 float nomodelvertex3f[6*3] =
966 float nomodelcolor4f[6*4] =
968 0.0f, 0.0f, 0.5f, 1.0f,
969 0.0f, 0.0f, 0.5f, 1.0f,
970 0.0f, 0.5f, 0.0f, 1.0f,
971 0.0f, 0.5f, 0.0f, 1.0f,
972 0.5f, 0.0f, 0.0f, 1.0f,
973 0.5f, 0.0f, 0.0f, 1.0f
976 void R_DrawNoModelCallback(const void *calldata1, int calldata2)
978 const entity_render_t *ent = calldata1;
980 float f1, f2, *c, diff[3];
983 R_Mesh_Matrix(&ent->matrix);
985 memset(&m, 0, sizeof(m));
986 m.pointer_vertex = nomodelvertex3f;
988 if (ent->flags & EF_ADDITIVE)
990 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
993 else if (ent->alpha < 1)
995 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1000 GL_BlendFunc(GL_ONE, GL_ZERO);
1003 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
1006 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1007 m.pointer_color = color4f;
1008 VectorSubtract(ent->origin, r_vieworigin, diff);
1009 f2 = exp(fogdensity/DotProduct(diff, diff));
1011 for (i = 0, c = color4f;i < 6;i++, c += 4)
1013 c[0] = (c[0] * f1 + fogcolor[0] * f2);
1014 c[1] = (c[1] * f1 + fogcolor[1] * f2);
1015 c[2] = (c[2] * f1 + fogcolor[2] * f2);
1019 else if (ent->alpha != 1)
1021 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1022 m.pointer_color = color4f;
1023 for (i = 0, c = color4f;i < 6;i++, c += 4)
1027 m.pointer_color = nomodelcolor4f;
1029 R_Mesh_Draw(6, 8, nomodelelements);
1032 void R_DrawNoModel(entity_render_t *ent)
1034 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1035 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModelCallback, ent, 0);
1037 // R_DrawNoModelCallback(ent, 0);
1040 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1042 vec3_t right1, right2, diff, normal;
1044 VectorSubtract (org2, org1, normal);
1046 // calculate 'right' vector for start
1047 VectorSubtract (r_vieworigin, org1, diff);
1048 CrossProduct (normal, diff, right1);
1049 VectorNormalize (right1);
1051 // calculate 'right' vector for end
1052 VectorSubtract (r_vieworigin, org2, diff);
1053 CrossProduct (normal, diff, right2);
1054 VectorNormalize (right2);
1056 vert[ 0] = org1[0] + width * right1[0];
1057 vert[ 1] = org1[1] + width * right1[1];
1058 vert[ 2] = org1[2] + width * right1[2];
1059 vert[ 3] = org1[0] - width * right1[0];
1060 vert[ 4] = org1[1] - width * right1[1];
1061 vert[ 5] = org1[2] - width * right1[2];
1062 vert[ 6] = org2[0] - width * right2[0];
1063 vert[ 7] = org2[1] - width * right2[1];
1064 vert[ 8] = org2[2] - width * right2[2];
1065 vert[ 9] = org2[0] + width * right2[0];
1066 vert[10] = org2[1] + width * right2[1];
1067 vert[11] = org2[2] + width * right2[2];
1070 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
1072 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)
1079 VectorSubtract(origin, r_vieworigin, diff);
1080 ca *= 1 - exp(fogdensity/DotProduct(diff,diff));
1083 R_Mesh_Matrix(&r_identitymatrix);
1084 GL_BlendFunc(blendfunc1, blendfunc2);
1085 GL_DepthMask(false);
1086 GL_DepthTest(!depthdisable);
1088 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
1089 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
1090 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
1091 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
1092 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
1093 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
1094 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
1095 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
1096 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
1097 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
1098 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
1099 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
1101 memset(&m, 0, sizeof(m));
1102 m.tex[0] = R_GetTexture(texture);
1103 m.pointer_texcoord[0] = spritetexcoord2f;
1104 m.pointer_vertex = varray_vertex3f;
1106 GL_Color(cr, cg, cb, ca);
1107 R_Mesh_Draw(4, 2, polygonelements);