cl.cmd.cursor_screen[1] = bound(-1, cl.cmd.cursor_screen[1], 1);
cl.cmd.cursor_screen[2] = 1;
- scale[0] = -r_refdef.frustum_x;
- scale[1] = -r_refdef.frustum_y;
+ scale[0] = -r_view.frustum_x;
+ scale[1] = -r_view.frustum_y;
scale[2] = 1;
// trace distance
// calculate current view matrix
V_CalcRefdef();
VectorClear(temp);
- Matrix4x4_Transform(&r_refdef.viewentitymatrix, temp, cl.cmd.cursor_start);
+ Matrix4x4_Transform(&r_view.matrix, temp, cl.cmd.cursor_start);
VectorSet(temp, cl.cmd.cursor_screen[2] * scale[2], cl.cmd.cursor_screen[0] * scale[0], cl.cmd.cursor_screen[1] * scale[1]);
- Matrix4x4_Transform(&r_refdef.viewentitymatrix, temp, cl.cmd.cursor_end);
+ Matrix4x4_Transform(&r_view.matrix, temp, cl.cmd.cursor_end);
// trace from view origin to the cursor
cl.cmd.cursor_fraction = CL_SelectTraceLine(cl.cmd.cursor_start, cl.cmd.cursor_end, cl.cmd.cursor_impact, cl.cmd.cursor_normal, &cl.cmd.cursor_entitynumber, (chase_active.integer || cl.intermission) ? &cl.entities[cl.playerentity].render : NULL, false);
}
e->render.skinnum = e->state_current.skin;
if (e->render.flags & RENDER_VIEWMODEL && !e->state_current.tagentity)
{
- if (!r_drawviewmodel.integer || chase_active.integer || envmap)// || csqc_loaded)
+ if (!r_drawviewmodel.integer || chase_active.integer || r_refdef.envmap)// || csqc_loaded)
return;
if (!e->csqc)
{
r_refdef.time = cl.time;
r_refdef.extraupdate = !r_speeds.integer;
r_refdef.numentities = 0;
- r_refdef.viewentitymatrix = identitymatrix;
+ r_view.matrix = identitymatrix;
if (cls.state == ca_connected && cls.signon == SIGNONS)
{
{
if (Cmd_Argc () == 1)
{
- Con_Printf("\"fog\" is \"%f %f %f %f\"\n", fog_density, fog_red, fog_green, fog_blue);
+ Con_Printf("\"fog\" is \"%f %f %f %f\"\n", r_refdef.fog_density, r_refdef.fog_red, r_refdef.fog_green, r_refdef.fog_blue);
return;
}
- fog_density = atof(Cmd_Argv(1));
- fog_red = atof(Cmd_Argv(2));
- fog_green = atof(Cmd_Argv(3));
- fog_blue = atof(Cmd_Argv(4));
+ r_refdef.fog_density = atof(Cmd_Argv(1));
+ r_refdef.fog_red = atof(Cmd_Argv(2));
+ r_refdef.fog_green = atof(Cmd_Argv(3));
+ r_refdef.fog_blue = atof(Cmd_Argv(4));
}
/*
timestart = Sys_DoubleTime();
for (i = 0;i < 128;i++)
{
- Matrix4x4_CreateFromQuakeEntity(&r_refdef.viewentitymatrix, r_vieworigin[0], r_vieworigin[1], r_vieworigin[2], 0, i / 128.0 * 360.0, 0, 1);
+ Matrix4x4_CreateFromQuakeEntity(&r_view.matrix, r_view.origin[0], r_view.origin[1], r_view.origin[2], 0, i / 128.0 * 360.0, 0, 1);
CL_UpdateScreen();
}
timedelta = Sys_DoubleTime() - timestart;
else if (!strcmp("qlsky", key)) // non-standard, introduced by QuakeLives (EEK)
R_SetSkyBox(value);
else if (!strcmp("fog", key))
- sscanf(value, "%f %f %f %f", &fog_density, &fog_red, &fog_green, &fog_blue);
+ sscanf(value, "%f %f %f %f", &r_refdef.fog_density, &r_refdef.fog_red, &r_refdef.fog_green, &r_refdef.fog_blue);
else if (!strcmp("fog_density", key))
- fog_density = atof(value);
+ r_refdef.fog_density = atof(value);
else if (!strcmp("fog_red", key))
- fog_red = atof(value);
+ r_refdef.fog_red = atof(value);
else if (!strcmp("fog_green", key))
- fog_green = atof(value);
+ r_refdef.fog_green = atof(value);
else if (!strcmp("fog_blue", key))
- fog_blue = atof(value);
+ r_refdef.fog_blue = atof(value);
}
}
cg *= (ambient[1] + 0.5 * diffuse[1]);
cb *= (ambient[2] + 0.5 * diffuse[2]);
}
- if (fogenabled)
+ if (r_refdef.fogenabled)
{
- fog = VERTEXFOGTABLE(VectorDistance(p->org, r_vieworigin));
+ fog = VERTEXFOGTABLE(VectorDistance(p->org, r_view.origin));
ifog = 1 - fog;
cr = cr * ifog;
cg = cg * ifog;
cb = cb * ifog;
if (blendmode == PBLEND_ALPHA)
{
- cr += fogcolor[0] * fog;
- cg += fogcolor[1] * fog;
- cb += fogcolor[2] * fog;
+ cr += r_refdef.fogcolor[0] * fog;
+ cg += r_refdef.fogcolor[1] * fog;
+ cb += r_refdef.fogcolor[2] * fog;
}
}
c4f[0] = c4f[4] = c4f[8] = c4f[12] = cr;
tex = &particletexture[p->texnum];
if (p->type->orientation == PARTICLE_BILLBOARD)
{
- VectorScale(r_viewleft, -size, right);
- VectorScale(r_viewup, size, up);
+ VectorScale(r_view.left, -size, right);
+ VectorScale(r_view.up, size, up);
v3f[ 0] = org[0] - right[0] - up[0];
v3f[ 1] = org[1] - right[1] - up[1];
v3f[ 2] = org[2] - right[2] - up[2];
else if (p->type->orientation == PARTICLE_ORIENTED_DOUBLESIDED)
{
// double-sided
- if (DotProduct(p->vel, r_vieworigin) > DotProduct(p->vel, org))
+ if (DotProduct(p->vel, r_view.origin) > DotProduct(p->vel, org))
{
VectorNegate(p->vel, v);
VectorVectors(v, right, up);
if ((!cl.num_particles) || (!r_drawparticles.integer))
return;
- minparticledist = DotProduct(r_vieworigin, r_viewforward) + 4.0f;
+ minparticledist = DotProduct(r_view.origin, r_view.forward) + 4.0f;
// LordHavoc: only render if not too close
for (i = 0, p = cl.particles;i < cl.num_particles;i++, p++)
{
if (p->type)
{
- renderstats.particles++;
- if (DotProduct(p->org, r_viewforward) >= minparticledist || p->type->orientation == PARTICLE_BEAM)
+ r_refdef.stats.particles++;
+ if (DotProduct(p->org, r_view.forward) >= minparticledist || p->type->orientation == PARTICLE_BEAM)
R_MeshQueue_AddTransparent(p->org, R_DrawParticle_TransparentCallback, NULL, i, NULL);
}
}
speedstringcount = 0;
r_speeds_string[0] = 0;
r_timereport_active = false;
- sprintf(r_speeds_string + strlen(r_speeds_string), "org:'%+8.2f %+8.2f %+8.2f' dir:'%+2.3f %+2.3f %+2.3f'\n", r_vieworigin[0], r_vieworigin[1], r_vieworigin[2], r_viewforward[0], r_viewforward[1], r_viewforward[2]);
- sprintf(r_speeds_string + strlen(r_speeds_string), "%5i entities%6i surfaces%6i triangles%5i leafs%5i portals%6i particles\n", renderstats.entities, renderstats.entities_surfaces, renderstats.entities_triangles, renderstats.world_leafs, renderstats.world_portals, renderstats.particles);
- sprintf(r_speeds_string + strlen(r_speeds_string), "%4i lights%4i clears%4i scissored%7i light%7i shadow%7i dynamic\n", renderstats.lights, renderstats.lights_clears, renderstats.lights_scissored, renderstats.lights_lighttriangles, renderstats.lights_shadowtriangles, renderstats.lights_dynamicshadowtriangles);
- if (renderstats.bloom)
- sprintf(r_speeds_string + strlen(r_speeds_string), "rendered%6i meshes%8i triangles bloompixels%8i copied%8i drawn\n", renderstats.meshes, renderstats.meshes_elements / 3, renderstats.bloom_copypixels, renderstats.bloom_drawpixels);
+ sprintf(r_speeds_string + strlen(r_speeds_string), "org:'%+8.2f %+8.2f %+8.2f' dir:'%+2.3f %+2.3f %+2.3f'\n", r_view.origin[0], r_view.origin[1], r_view.origin[2], r_view.forward[0], r_view.forward[1], r_view.forward[2]);
+ sprintf(r_speeds_string + strlen(r_speeds_string), "%5i entities%6i surfaces%6i triangles%5i leafs%5i portals%6i particles\n", r_refdef.stats.entities, r_refdef.stats.entities_surfaces, r_refdef.stats.entities_triangles, r_refdef.stats.world_leafs, r_refdef.stats.world_portals, r_refdef.stats.particles);
+ sprintf(r_speeds_string + strlen(r_speeds_string), "%4i lights%4i clears%4i scissored%7i light%7i shadow%7i dynamic\n", r_refdef.stats.lights, r_refdef.stats.lights_clears, r_refdef.stats.lights_scissored, r_refdef.stats.lights_lighttriangles, r_refdef.stats.lights_shadowtriangles, r_refdef.stats.lights_dynamicshadowtriangles);
+ if (r_refdef.stats.bloom)
+ sprintf(r_speeds_string + strlen(r_speeds_string), "rendered%6i meshes%8i triangles bloompixels%8i copied%8i drawn\n", r_refdef.stats.meshes, r_refdef.stats.meshes_elements / 3, r_refdef.stats.bloom_copypixels, r_refdef.stats.bloom_drawpixels);
else
- sprintf(r_speeds_string + strlen(r_speeds_string), "rendered%6i meshes%8i triangles\n", renderstats.meshes, renderstats.meshes_elements / 3);
+ sprintf(r_speeds_string + strlen(r_speeds_string), "rendered%6i meshes%8i triangles\n", r_refdef.stats.meshes, r_refdef.stats.meshes_elements / 3);
- memset(&renderstats, 0, sizeof(renderstats));
+ memset(&r_refdef.stats, 0, sizeof(r_refdef.stats));
if (r_speeds.integer >= 2)
{
return;
}
- envmap = true;
+ r_refdef.envmap = true;
- r_refdef.x = 0;
- r_refdef.y = 0;
- r_refdef.width = size;
- r_refdef.height = size;
+ R_UpdateVariables();
- r_refdef.frustum_x = tan(90 * M_PI / 360.0);
- r_refdef.frustum_y = tan(90 * M_PI / 360.0);
+ r_view.x = 0;
+ r_view.y = 0;
+ r_view.z = 0;
+ r_view.width = size;
+ r_view.height = size;
+ r_view.depth = 1;
+
+ r_view.frustum_x = tan(90 * M_PI / 360.0);
+ r_view.frustum_y = tan(90 * M_PI / 360.0);
buffer1 = (unsigned char *)Mem_Alloc(tempmempool, size * size * 3);
buffer2 = (unsigned char *)Mem_Alloc(tempmempool, size * size * 3);
for (j = 0;j < 12;j++)
{
sprintf(filename, "env/%s%s.tga", basename, envmapinfo[j].name);
- Matrix4x4_CreateFromQuakeEntity(&r_refdef.viewentitymatrix, r_vieworigin[0], r_vieworigin[1], r_vieworigin[2], envmapinfo[j].angles[0], envmapinfo[j].angles[1], envmapinfo[j].angles[2], 1);
+ Matrix4x4_CreateFromQuakeEntity(&r_view.matrix, r_view.origin[0], r_view.origin[1], r_view.origin[2], envmapinfo[j].angles[0], envmapinfo[j].angles[1], envmapinfo[j].angles[2], 1);
R_ClearScreen();
R_Mesh_Start();
R_RenderView();
R_Mesh_Finish();
- SCR_ScreenShot(filename, buffer1, buffer2, buffer3, 0, vid.height - (r_refdef.y + r_refdef.height), size, size, envmapinfo[j].flipx, envmapinfo[j].flipy, envmapinfo[j].flipdiagonaly, false, false);
+ SCR_ScreenShot(filename, buffer1, buffer2, buffer3, 0, vid.height - (r_view.y + r_view.height), size, size, envmapinfo[j].flipx, envmapinfo[j].flipy, envmapinfo[j].flipdiagonaly, false, false);
}
Mem_Free (buffer1);
Mem_Free (buffer2);
Mem_Free (buffer3);
- envmap = false;
+ r_refdef.envmap = false;
}
//=============================================================================
{
// clear to black
CHECKGLERROR
- if (fogenabled)
+ if (r_refdef.fogenabled)
{
- qglClearColor(fogcolor[0],fogcolor[1],fogcolor[2],0);CHECKGLERROR
+ qglClearColor(r_refdef.fogcolor[0],r_refdef.fogcolor[1],r_refdef.fogcolor[2],0);CHECKGLERROR
}
else
{
if (r_timereport_active)
R_TimeReport("setup");
+ R_UpdateVariables();
+
if (cls.signon == SIGNONS)
{
float size;
if (r_stereo_sidebyside.integer)
{
- r_refdef.width = (int)(vid.width * size / 2.5);
- r_refdef.height = (int)(vid.height * size / 2.5 * (1 - bound(0, r_letterbox.value, 100) / 100));
- r_refdef.x = (int)((vid.width - r_refdef.width * 2.5) * 0.5);
- r_refdef.y = (int)((vid.height - r_refdef.height)/2);
+ r_view.width = (int)(vid.width * size / 2.5);
+ r_view.height = (int)(vid.height * size / 2.5 * (1 - bound(0, r_letterbox.value, 100) / 100));
+ r_view.depth = 1;
+ r_view.x = (int)((vid.width - r_view.width * 2.5) * 0.5);
+ r_view.y = (int)((vid.height - r_view.height)/2);
+ r_view.z = 0;
if (r_stereo_side)
- r_refdef.x += (int)(r_refdef.width * 1.5);
+ r_view.x += (int)(r_view.width * 1.5);
}
else
{
- r_refdef.width = (int)(vid.width * size);
- r_refdef.height = (int)(vid.height * size * (1 - bound(0, r_letterbox.value, 100) / 100));
- r_refdef.x = (int)((vid.width - r_refdef.width)/2);
- r_refdef.y = (int)((vid.height - r_refdef.height)/2);
+ r_view.width = (int)(vid.width * size);
+ r_view.height = (int)(vid.height * size * (1 - bound(0, r_letterbox.value, 100) / 100));
+ r_view.depth = 1;
+ r_view.x = (int)((vid.width - r_view.width)/2);
+ r_view.y = (int)((vid.height - r_view.height)/2);
+ r_view.z = 0;
}
// LordHavoc: viewzoom (zoom in for sniper rifles, etc)
// this it simply assumes the requested fov is the vertical fov
// for a 4x3 display, if the ratio is not 4x3 this makes the fov
// higher/lower according to the ratio
- r_refdef.frustum_y = tan(scr_fov.value * cl.viewzoom * M_PI / 360.0) * (3.0/4.0);
- r_refdef.frustum_x = r_refdef.frustum_y * (float)r_refdef.width / (float)r_refdef.height / vid_pixelheight.value;
+ r_view.frustum_y = tan(scr_fov.value * cl.viewzoom * M_PI / 360.0) * (3.0/4.0);
+ r_view.frustum_x = r_view.frustum_y * (float)r_view.width / (float)r_view.height / vid_pixelheight.value;
- r_refdef.frustum_x *= r_refdef.frustumscale_x;
- r_refdef.frustum_y *= r_refdef.frustumscale_y;
+ r_view.frustum_x *= r_refdef.frustumscale_x;
+ r_view.frustum_y *= r_refdef.frustumscale_y;
if(!CL_VM_UpdateView())
R_RenderView();
{
float sizex = bound(10, scr_zoomwindow_viewsizex.value, 100) / 100.0;
float sizey = bound(10, scr_zoomwindow_viewsizey.value, 100) / 100.0;
- r_refdef.width = (int)(vid.width * sizex);
- r_refdef.height = (int)(vid.height * sizey);
- r_refdef.x = (int)((vid.width - r_refdef.width)/2);
- r_refdef.y = 0;
+ r_view.width = (int)(vid.width * sizex);
+ r_view.height = (int)(vid.height * sizey);
+ r_view.depth = 1;
+ r_view.x = (int)((vid.width - r_view.width)/2);
+ r_view.y = 0;
+ r_view.z = 0;
- r_refdef.frustum_y = tan(scr_zoomwindow_fov.value * cl.viewzoom * M_PI / 360.0) * (3.0/4.0);
- r_refdef.frustum_x = r_refdef.frustum_y * vid_pixelheight.value * (float)r_refdef.width / (float)r_refdef.height;
+ r_view.frustum_y = tan(scr_zoomwindow_fov.value * cl.viewzoom * M_PI / 360.0) * (3.0/4.0);
+ r_view.frustum_x = r_view.frustum_y * vid_pixelheight.value * (float)r_view.width / (float)r_view.height;
- r_refdef.frustum_x *= r_refdef.frustumscale_x;
- r_refdef.frustum_y *= r_refdef.frustumscale_y;
+ r_view.frustum_x *= r_refdef.frustumscale_x;
+ r_view.frustum_y *= r_refdef.frustumscale_y;
if(!CL_VM_UpdateView())
R_RenderView();
if (!r_stereo_sidebyside.integer)
{
- r_refdef.width = vid.width;
- r_refdef.height = vid.height;
- r_refdef.x = 0;
- r_refdef.y = 0;
+ r_view.width = vid.width;
+ r_view.height = vid.height;
+ r_view.depth = 1;
+ r_view.x = 0;
+ r_view.y = 0;
+ r_view.z = 0;
}
// draw 2D stuff
sb_lines = 24+16+8;
}
- r_refdef.colormask[0] = 1;
- r_refdef.colormask[1] = 1;
- r_refdef.colormask[2] = 1;
+ r_view.colormask[0] = 1;
+ r_view.colormask[1] = 1;
+ r_view.colormask[2] = 1;
if (r_timereport_active)
R_TimeReport("other");
if (r_stereo_redblue.integer || r_stereo_redgreen.integer || r_stereo_redcyan.integer || r_stereo_sidebyside.integer)
{
- matrix4x4_t originalmatrix = r_refdef.viewentitymatrix;
- r_refdef.viewentitymatrix.m[0][3] = originalmatrix.m[0][3] + r_stereo_separation.value * -0.5f * r_refdef.viewentitymatrix.m[0][1];
- r_refdef.viewentitymatrix.m[1][3] = originalmatrix.m[1][3] + r_stereo_separation.value * -0.5f * r_refdef.viewentitymatrix.m[1][1];
- r_refdef.viewentitymatrix.m[2][3] = originalmatrix.m[2][3] + r_stereo_separation.value * -0.5f * r_refdef.viewentitymatrix.m[2][1];
+ matrix4x4_t originalmatrix = r_view.matrix;
+ r_view.matrix.m[0][3] = originalmatrix.m[0][3] + r_stereo_separation.value * -0.5f * r_view.matrix.m[0][1];
+ r_view.matrix.m[1][3] = originalmatrix.m[1][3] + r_stereo_separation.value * -0.5f * r_view.matrix.m[1][1];
+ r_view.matrix.m[2][3] = originalmatrix.m[2][3] + r_stereo_separation.value * -0.5f * r_view.matrix.m[2][1];
if (r_stereo_sidebyside.integer)
r_stereo_side = 0;
if (r_stereo_redblue.integer || r_stereo_redgreen.integer || r_stereo_redcyan.integer)
{
- r_refdef.colormask[0] = 1;
- r_refdef.colormask[1] = 0;
- r_refdef.colormask[2] = 0;
+ r_view.colormask[0] = 1;
+ r_view.colormask[1] = 0;
+ r_view.colormask[2] = 0;
}
SCR_DrawScreen();
- r_refdef.viewentitymatrix.m[0][3] = originalmatrix.m[0][3] + r_stereo_separation.value * 0.5f * r_refdef.viewentitymatrix.m[0][1];
- r_refdef.viewentitymatrix.m[1][3] = originalmatrix.m[1][3] + r_stereo_separation.value * 0.5f * r_refdef.viewentitymatrix.m[1][1];
- r_refdef.viewentitymatrix.m[2][3] = originalmatrix.m[2][3] + r_stereo_separation.value * 0.5f * r_refdef.viewentitymatrix.m[2][1];
+ r_view.matrix.m[0][3] = originalmatrix.m[0][3] + r_stereo_separation.value * 0.5f * r_view.matrix.m[0][1];
+ r_view.matrix.m[1][3] = originalmatrix.m[1][3] + r_stereo_separation.value * 0.5f * r_view.matrix.m[1][1];
+ r_view.matrix.m[2][3] = originalmatrix.m[2][3] + r_stereo_separation.value * 0.5f * r_view.matrix.m[2][1];
if (r_stereo_sidebyside.integer)
r_stereo_side = 1;
if (r_stereo_redblue.integer || r_stereo_redgreen.integer || r_stereo_redcyan.integer)
{
- r_refdef.colormask[0] = 0;
- r_refdef.colormask[1] = r_stereo_redcyan.integer || r_stereo_redgreen.integer;
- r_refdef.colormask[2] = r_stereo_redcyan.integer || r_stereo_redblue.integer;
+ r_view.colormask[0] = 0;
+ r_view.colormask[1] = r_stereo_redcyan.integer || r_stereo_redgreen.integer;
+ r_view.colormask[2] = r_stereo_redcyan.integer || r_stereo_redblue.integer;
}
SCR_DrawScreen();
- r_refdef.viewentitymatrix = originalmatrix;
+ r_view.matrix = originalmatrix;
}
else
SCR_DrawScreen();
// calculated by the renderer (but not persistent)
- // if visframe == r_framecount, it is visible
- int visframe;
// calculated during R_AddModelEntities
vec3_t mins, maxs;
// 4 frame numbers (-1 if not used) and their blending scalers (0-1), if interpolation is not desired, use frame instead
#define NUMCROSSHAIRS 32
extern cachepic_t *r_crosshairs[NUMCROSSHAIRS+1];
-typedef struct refdef_s
+#define FOGTABLEWIDTH 1024
+extern int fogtableindex;
+#define VERTEXFOGTABLE(dist) (fogtableindex = (int)((dist) * r_refdef.fogtabledistmultiplier), r_refdef.fogtable[bound(0, fogtableindex, FOGTABLEWIDTH - 1)])
+
+typedef struct r_refdef_stats_s
{
- // area to render in
- int x, y, width, height;
- float frustum_x, frustum_y;
+ int entities;
+ int entities_surfaces;
+ int entities_triangles;
+ int world_leafs;
+ int world_portals;
+ int particles;
+ int meshes;
+ int meshes_elements;
+ int lights;
+ int lights_clears;
+ int lights_scissored;
+ int lights_lighttriangles;
+ int lights_shadowtriangles;
+ int lights_dynamicshadowtriangles;
+ int bloom;
+ int bloom_copypixels;
+ int bloom_drawpixels;
+}
+r_refdef_stats_t;
+
+typedef struct r_refdef_s
+{
+ // these fields define the basic rendering information for the world
+ // but not the view, which could change multiple times in one rendered
+ // frame (for example when rendering textures for certain effects)
// these are set for water warping before
// frustum_x/frustum_y are calculated
float frustumscale_x, frustumscale_y;
- // view transform
- matrix4x4_t viewentitymatrix;
-
- // which color components to allow (for anaglyph glasses)
- int colormask[4];
+ // minimum visible distance (pixels closer than this disappear)
+ double nearclip;
+ // maximum visible distance (pixels further than this disappear in 16bpp modes,
+ // in 32bpp an infinite-farclip matrix is used instead)
+ double farclip;
// fullscreen color blend
float viewblend[4];
// controls intensity of dynamic lights and lightmap layers
unsigned short lightstylevalue[256]; // 8.8 fraction of base light value
+ vec3_t fogcolor;
+ vec_t fogrange;
+ vec_t fograngerecip;
+ vec_t fogtabledistmultiplier;
+ float fogtable[FOGTABLEWIDTH];
+ float fog_density;
+ float fog_red;
+ float fog_green;
+ float fog_blue;
+ qboolean fogenabled;
+ qboolean oldgl_fogenable;
+
qboolean draw2dstage;
+
+ // true during envmap command capture
+ qboolean envmap;
+
+ // brightness of world lightmaps and related lighting
+ // (often reduced when world rtlights are enabled)
+ float lightmapintensity;
+ // whether to draw world lights realtime, dlights realtime, and their shadows
+ qboolean rtworld;
+ qboolean rtworldshadows;
+ qboolean rtdlight;
+ qboolean rtdlightshadows;
+ float polygonfactor;
+ float polygonoffset;
+ float shadowpolygonfactor;
+ float shadowpolygonoffset;
+
+ // rendering stats for r_speeds display
+ // (these are incremented in many places)
+ r_refdef_stats_t stats;
+}
+r_refdef_t;
+
+typedef struct r_view_s
+{
+ // view information (changes multiple times per frame)
+ // if any of these variables change then r_viewcache must be regenerated
+ // by calling R_View_Update
+ // (which also updates viewport, scissor, colormask)
+
+ // it is safe and expected to copy this into a structure on the stack and
+ // call the renderer recursively, then restore from the stack afterward
+ // (as long as R_View_Update is called)
+
+ // eye position information
+ matrix4x4_t matrix;
+ vec3_t origin;
+ vec3_t forward;
+ vec3_t left;
+ vec3_t right;
+ vec3_t up;
+ mplane_t frustum[5];
+ float frustum_x, frustum_y;
+
+ // screen area to render in
+ int x;
+ int y;
+ int z;
+ int width;
+ int height;
+ int depth;
+
+ // which color components to allow (for anaglyph glasses)
+ int colormask[4];
+}
+r_view_t;
+
+typedef struct r_viewcache_s
+{
+ // these properties are generated by R_View_Update()
+
+ // which entities are currently visible for this viewpoint
+ // (the used range is 0...r_refdef.numentities)
+ unsigned char entityvisible[MAX_EDICTS];
+ // flag arrays used for visibility checking on world model
+ // (all other entities have no per-surface/per-leaf visibility checks)
+ // TODO: dynamic resize according to r_refdef.worldmodel->brush.num_clusters
+ unsigned char world_pvsbits[(32768+7)>>3];
+ // TODO: dynamic resize according to r_refdef.worldmodel->brush.num_leafs
+ unsigned char world_leafvisible[32768];
+ // TODO: dynamic resize according to r_refdef.worldmodel->num_surfaces
+ unsigned char world_surfacevisible[262144];
+ // if true, the view is currently in a leaf without pvs data
+ qboolean world_novis;
}
-refdef_t;
+r_viewcache_t;
-extern refdef_t r_refdef;
+extern r_refdef_t r_refdef;
+extern r_view_t r_view;
+extern r_viewcache_t r_viewcache;
#endif
{
extern matrix4x4_t viewmodelmatrix;
viewmodelmatrix = identitymatrix;
- r_refdef.viewentitymatrix = identitymatrix;
- Matrix4x4_CreateFromQuakeEntity(&r_refdef.viewentitymatrix, csqc_origin[0], csqc_origin[1], csqc_origin[2], csqc_angles[0], csqc_angles[1], csqc_angles[2], 1);
+ r_view.matrix = identitymatrix;
+ Matrix4x4_CreateFromQuakeEntity(&r_view.matrix, csqc_origin[0], csqc_origin[1], csqc_origin[2], csqc_angles[0], csqc_angles[1], csqc_angles[2], 1);
Matrix4x4_CreateFromQuakeEntity(&viewmodelmatrix, csqc_origin[0], csqc_origin[1], csqc_origin[2], csqc_angles[0], csqc_angles[1], csqc_angles[2], 0.3);
}
switch(c)
{
- case VF_MIN: r_refdef.x = (int)f[0];
- r_refdef.y = (int)f[1];
+ case VF_MIN: r_view.x = (int)f[0];
+ r_view.y = (int)f[1];
break;
- case VF_MIN_X: r_refdef.x = (int)k;
+ case VF_MIN_X: r_view.x = (int)k;
break;
- case VF_MIN_Y: r_refdef.y = (int)k;
+ case VF_MIN_Y: r_view.y = (int)k;
break;
- case VF_SIZE: r_refdef.width = (int)f[0];
- r_refdef.height = (int)f[1];
+ case VF_SIZE: r_view.width = (int)f[0];
+ r_view.height = (int)f[1];
break;
- case VF_SIZE_Y: r_refdef.width = (int)k;
+ case VF_SIZE_Y: r_view.width = (int)k;
break;
- case VF_SIZE_X: r_refdef.height = (int)k;
+ case VF_SIZE_X: r_view.height = (int)k;
break;
- case VF_VIEWPORT: r_refdef.x = (int)f[0];
- r_refdef.y = (int)f[1];
+ case VF_VIEWPORT: r_view.x = (int)f[0];
+ r_view.y = (int)f[1];
+ r_view.z = 0;
+ // TODO: make sure that view_z and view_depth are set properly even if csqc does not set them!
f = PRVM_G_VECTOR(OFS_PARM2);
- r_refdef.width = (int)f[0];
- r_refdef.height = (int)f[1];
+ r_view.width = (int)f[0];
+ r_view.height = (int)f[1];
+ r_view.depth = 1;
break;
case VF_FOV: //r_refdef.fov_x = f[0]; // FIXME!
//r_refdef.fov_y = f[1]; // FIXME!
VM_SAFEPARMCOUNT(1, VM_CL_unproject);
f = PRVM_G_VECTOR(OFS_PARM0);
- VectorSet(temp, f[2], f[0] * f[2] * -r_refdef.frustum_x * 2.0 / r_refdef.width, f[1] * f[2] * -r_refdef.frustum_y * 2.0 / r_refdef.height);
- Matrix4x4_Transform(&r_refdef.viewentitymatrix, temp, PRVM_G_VECTOR(OFS_RETURN));
+ VectorSet(temp, f[2], f[0] * f[2] * -r_view.frustum_x * 2.0 / r_view.width, f[1] * f[2] * -r_view.frustum_y * 2.0 / r_view.height);
+ Matrix4x4_Transform(&r_view.matrix, temp, PRVM_G_VECTOR(OFS_RETURN));
}
//#311 vector (vector v) cs_project (EXT_CSQC)
VM_SAFEPARMCOUNT(1, VM_CL_project);
f = PRVM_G_VECTOR(OFS_PARM0);
- Matrix4x4_Invert_Simple(&m, &r_refdef.viewentitymatrix);
+ Matrix4x4_Invert_Simple(&m, &r_view.matrix);
Matrix4x4_Transform(&m, f, v);
- VectorSet(PRVM_G_VECTOR(OFS_RETURN), v[1]/v[0]/-r_refdef.frustum_x*0.5*r_refdef.width, v[2]/v[0]/-r_refdef.frustum_y*r_refdef.height*0.5, v[0]);
+ VectorSet(PRVM_G_VECTOR(OFS_RETURN), v[1]/v[0]/-r_view.frustum_x*0.5*r_view.width, v[2]/v[0]/-r_view.frustum_y*r_view.height*0.5, v[0]);
}
//#330 float(float stnum) getstatf (EXT_CSQC)
Matrix4x4_Transform4 (&backend_viewmatrix, in, temp);
Matrix4x4_Transform4 (&backend_projectmatrix, temp, out);
iw = 1.0f / out[3];
- out[0] = r_view_x + (out[0] * iw + 1.0f) * r_view_width * 0.5f;
- out[1] = r_view_y + (out[1] * iw + 1.0f) * r_view_height * 0.5f;
- out[2] = r_view_z + (out[2] * iw + 1.0f) * r_view_depth * 0.5f;
+ out[0] = r_view.x + (out[0] * iw + 1.0f) * r_view.width * 0.5f;
+ out[1] = r_view.y + (out[1] * iw + 1.0f) * r_view.height * 0.5f;
+ out[2] = r_view.z + (out[2] * iw + 1.0f) * r_view.depth * 0.5f;
}
// called at beginning of frame
return;
}
CHECKGLERROR
- renderstats.meshes++;
- renderstats.meshes_elements += numelements;
+ r_refdef.stats.meshes++;
+ r_refdef.stats.meshes_elements += numelements;
if (gl_paranoid.integer)
{
unsigned int i, j, size;
void DrawQ_Begin(void)
{
- r_view_width = bound(0, r_refdef.width, vid.width);
- r_view_height = bound(0, r_refdef.height, vid.height);
- r_view_depth = 1;
- r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
- r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
- r_view_z = 0;
- r_view_matrix = r_refdef.viewentitymatrix;
- GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
+ GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
CHECKGLERROR
- qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);CHECKGLERROR
+ qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
GL_SetupView_Mode_Ortho(0, 0, vid_conwidth.integer, vid_conheight.integer, -10, 100);
qglDepthFunc(GL_LEQUAL);CHECKGLERROR
R_Mesh_Matrix(&identitymatrix);
mempool_t *r_main_mempool;
rtexturepool_t *r_main_texturepool;
-// used for dlight push checking and other things
-int r_framecount;
-
-mplane_t frustum[5];
-
-renderstats_t renderstats;
-
-// true during envmap command capture
-qboolean envmap;
-
-// maximum visible distance (recalculated from world box each frame)
-float r_farclip;
-// brightness of world lightmaps and related lighting
-// (often reduced when world rtlights are enabled)
-float r_lightmapintensity;
-// whether to draw world lights realtime, dlights realtime, and their shadows
-qboolean r_rtworld;
-qboolean r_rtworldshadows;
-qboolean r_rtdlight;
-qboolean r_rtdlightshadows;
-
-
-// view origin
-vec3_t r_vieworigin;
-vec3_t r_viewforward;
-vec3_t r_viewleft;
-vec3_t r_viewright;
-vec3_t r_viewup;
-int r_view_x;
-int r_view_y;
-int r_view_z;
-int r_view_width;
-int r_view_height;
-int r_view_depth;
-matrix4x4_t r_view_matrix;
-float r_polygonfactor;
-float r_polygonoffset;
-float r_shadowpolygonfactor;
-float r_shadowpolygonoffset;
//
// screen size info
//
-refdef_t r_refdef;
+r_refdef_t r_refdef;
+r_view_t r_view;
+r_viewcache_t r_viewcache;
cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "shows surfaces as different colors"};
// currently selected permutation
r_glsl_permutation_t *r_glsl_permutation;
+// temporary variable used by a macro
+int fogtableindex;
+
void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
{
int i;
}
}
-vec3_t fogcolor;
-vec_t fogdensity;
-vec_t fogrange;
-vec_t fograngerecip;
-int fogtableindex;
-vec_t fogtabledistmultiplier;
-float fogtable[FOGTABLEWIDTH];
-float fog_density, fog_red, fog_green, fog_blue;
-qboolean fogenabled;
-qboolean oldgl_fogenable;
-void R_UpdateFog(void)
-{
- if (gamemode == GAME_NEHAHRA)
- {
- if (gl_fogenable.integer)
- {
- oldgl_fogenable = true;
- fog_density = gl_fogdensity.value;
- fog_red = gl_fogred.value;
- fog_green = gl_foggreen.value;
- fog_blue = gl_fogblue.value;
- }
- else if (oldgl_fogenable)
- {
- oldgl_fogenable = false;
- fog_density = 0;
- fog_red = 0;
- fog_green = 0;
- fog_blue = 0;
- }
- }
- if (fog_density)
- {
- fogcolor[0] = fog_red = bound(0.0f, fog_red , 1.0f);
- fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
- fogcolor[2] = fog_blue = bound(0.0f, fog_blue , 1.0f);
- }
- if (fog_density)
- {
- fogenabled = true;
- fogdensity = -4000.0f / (fog_density * fog_density);
- // this is the point where the fog reaches 0.9986 alpha, which we
- // consider a good enough cutoff point for the texture
- // (0.9986 * 256 == 255.6)
- fogrange = 400 / fog_density;
- fograngerecip = 1.0f / fogrange;
- fogtabledistmultiplier = FOGTABLEWIDTH * fograngerecip;
- // fog color was already set
- }
- else
- fogenabled = false;
-}
-
// FIXME: move this to client?
void FOG_clear(void)
{
Cvar_Set("gl_foggreen", "0.3");
Cvar_Set("gl_fogblue", "0.3");
}
- fog_density = fog_red = fog_green = fog_blue = 0.0f;
+ r_refdef.fog_density = r_refdef.fog_red = r_refdef.fog_green = r_refdef.fog_blue = 0.0f;
}
// FIXME: move this to client?
alpha = exp(r / ((double)x*(double)x));
if (x == FOGTABLEWIDTH - 1)
alpha = 1;
- fogtable[x] = bound(0, alpha, 1);
+ r_refdef.fogtable[x] = bound(0, alpha, 1);
}
}
}
if (specularscale > 0)
permutation |= SHADERPERMUTATION_SPECULAR;
- if (fogenabled)
+ if (r_refdef.fogenabled)
permutation |= SHADERPERMUTATION_FOG;
if (rsurface_texture->colormapping)
permutation |= SHADERPERMUTATION_COLORMAPPING;
else
{
if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
- if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_lightmapintensity * 2.0f);
- if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_lightmapintensity * specularscale * 2.0f);
+ if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
+ if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
}
if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(rsurface_texture->skin.nmap));
if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(rsurface_texture->basetexture));
if (r_shadow_rtlight || (rsurface_texture->currentmaterialflags & MATERIALFLAG_ADD))
qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
else
- qglUniform3fARB(r_glsl_permutation->loc_FogColor, fogcolor[0], fogcolor[1], fogcolor[2]);
+ qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
}
if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface_modelorg[0], rsurface_modelorg[1], rsurface_modelorg[2]);
if (r_glsl_permutation->loc_Color_Pants >= 0)
else
qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
}
- if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, fograngerecip);
+ if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface_texture->specularpower);
if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
CHECKGLERROR
// FIXME: move this code to client
int l;
char *entities, entname[MAX_QPATH];
- r_framecount = 1;
if (cl.worldmodel)
{
strlcpy(entname, cl.worldmodel->name, sizeof(entname));
R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
}
-static vec3_t r_farclip_origin;
-static vec3_t r_farclip_direction;
-static vec_t r_farclip_directiondist;
-static vec_t r_farclip_meshfarclip;
-static int r_farclip_directionbit0;
-static int r_farclip_directionbit1;
-static int r_farclip_directionbit2;
-
-// enlarge farclip to accomodate box
-static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
-{
- float d;
- d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
- + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
- + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
- if (r_farclip_meshfarclip < d)
- r_farclip_meshfarclip = d;
-}
-
-// return farclip value
-static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
-{
- int i;
-
- VectorCopy(origin, r_farclip_origin);
- VectorCopy(direction, r_farclip_direction);
- r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
- r_farclip_directionbit0 = r_farclip_direction[0] < 0;
- r_farclip_directionbit1 = r_farclip_direction[1] < 0;
- r_farclip_directionbit2 = r_farclip_direction[2] < 0;
- r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
-
- if (r_refdef.worldmodel)
- R_FarClip_Box(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
- for (i = 0;i < r_refdef.numentities;i++)
- R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
-
- return r_farclip_meshfarclip - r_farclip_directiondist;
-}
-
extern void R_Textures_Init(void);
extern void GL_Draw_Init(void);
extern void GL_Main_Init(void);
{
gl_backend_init();
R_Textures_Init();
- R_MeshQueue_Init();
GL_Main_Init();
GL_Draw_Init();
R_Shadow_Init();
mplane_t *p;
for (i = 0;i < 4;i++)
{
- p = frustum + i;
+ p = r_view.frustum + i;
switch(p->signbits)
{
default:
VectorSet(ent->modellight_ambient, 1, 1, 1);
Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
VectorNormalize(ent->modellight_lightdir);
- ent->modellight_ambient[0] *= ent->colormod[0] * r_lightmapintensity;
- ent->modellight_ambient[1] *= ent->colormod[1] * r_lightmapintensity;
- ent->modellight_ambient[2] *= ent->colormod[2] * r_lightmapintensity;
- ent->modellight_diffuse[0] *= ent->colormod[0] * r_lightmapintensity;
- ent->modellight_diffuse[1] *= ent->colormod[1] * r_lightmapintensity;
- ent->modellight_diffuse[2] *= ent->colormod[2] * r_lightmapintensity;
+ ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
+ ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
+ ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
+ ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
+ ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
+ ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
}
-static void R_MarkEntities (void)
+static void R_View_UpdateEntityVisible (void)
{
int i, renderimask;
entity_render_t *ent;
if (!r_drawentities.integer)
return;
- r_refdef.worldentity->visframe = r_framecount;
- renderimask = envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
+ renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
{
// worldmodel can check visibility
for (i = 0;i < r_refdef.numentities;i++)
{
ent = r_refdef.entities[i];
- // some of the renderer still relies on origin...
- Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
- // some of the renderer still relies on scale...
- ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
- 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)))
- {
- ent->visframe = r_framecount;
- R_UpdateEntityLighting(ent);
- }
+ r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && ((ent->effects & EF_NODEPTHTEST) || r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.worldmodel, r_viewcache.world_leafvisible, ent->mins, ent->maxs));
}
}
else
for (i = 0;i < r_refdef.numentities;i++)
{
ent = r_refdef.entities[i];
- // some of the renderer still relies on origin...
- Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
- // some of the renderer still relies on scale...
- ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
- if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST))
- {
- ent->visframe = r_framecount;
- R_UpdateEntityLighting(ent);
- }
+ r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST);
}
}
}
sky = false;
for (i = 0;i < r_refdef.numentities;i++)
{
+ if (!r_viewcache.entityvisible[i])
+ continue;
ent = r_refdef.entities[i];
- if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
- {
- ent->model->DrawSky(ent);
- sky = true;
- }
+ if (!ent->model || !ent->model->DrawSky)
+ continue;
+ ent->model->DrawSky(ent);
+ sky = true;
}
return sky;
}
for (i = 0;i < r_refdef.numentities;i++)
{
+ if (!r_viewcache.entityvisible[i])
+ continue;
ent = r_refdef.entities[i];
- if (ent->visframe == r_framecount)
- {
- renderstats.entities++;
- if (ent->model && ent->model->Draw != NULL)
- ent->model->Draw(ent);
- else
- R_DrawNoModel(ent);
- }
+ r_refdef.stats.entities++;
+ if (ent->model && ent->model->Draw != NULL)
+ ent->model->Draw(ent);
+ else
+ R_DrawNoModel(ent);
}
}
-static void R_SetFrustum(void)
+static void R_View_SetFrustum(void)
{
// break apart the view matrix into vectors for various purposes
- Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
- VectorNegate(r_viewleft, r_viewright);
+ Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
+ VectorNegate(r_view.left, r_view.right);
#if 0
- frustum[0].normal[0] = 0 - 1.0 / r_refdef.frustum_x;
- frustum[0].normal[1] = 0 - 0;
- frustum[0].normal[2] = -1 - 0;
- frustum[1].normal[0] = 0 + 1.0 / r_refdef.frustum_x;
- frustum[1].normal[1] = 0 + 0;
- frustum[1].normal[2] = -1 + 0;
- frustum[2].normal[0] = 0 - 0;
- frustum[2].normal[1] = 0 - 1.0 / r_refdef.frustum_y;
- frustum[2].normal[2] = -1 - 0;
- frustum[3].normal[0] = 0 + 0;
- frustum[3].normal[1] = 0 + 1.0 / r_refdef.frustum_y;
- frustum[3].normal[2] = -1 + 0;
+ r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
+ r_view.frustum[0].normal[1] = 0 - 0;
+ r_view.frustum[0].normal[2] = -1 - 0;
+ r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
+ r_view.frustum[1].normal[1] = 0 + 0;
+ r_view.frustum[1].normal[2] = -1 + 0;
+ r_view.frustum[2].normal[0] = 0 - 0;
+ r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
+ r_view.frustum[2].normal[2] = -1 - 0;
+ r_view.frustum[3].normal[0] = 0 + 0;
+ r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
+ r_view.frustum[3].normal[2] = -1 + 0;
#endif
#if 0
- zNear = r_nearclip.value;
+ zNear = r_refdef.nearclip;
nudge = 1.0 - 1.0 / (1<<23);
- frustum[4].normal[0] = 0 - 0;
- frustum[4].normal[1] = 0 - 0;
- frustum[4].normal[2] = -1 - -nudge;
- frustum[4].dist = 0 - -2 * zNear * nudge;
- frustum[5].normal[0] = 0 + 0;
- frustum[5].normal[1] = 0 + 0;
- frustum[5].normal[2] = -1 + -nudge;
- frustum[5].dist = 0 + -2 * zNear * nudge;
+ r_view.frustum[4].normal[0] = 0 - 0;
+ r_view.frustum[4].normal[1] = 0 - 0;
+ r_view.frustum[4].normal[2] = -1 - -nudge;
+ r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
+ r_view.frustum[5].normal[0] = 0 + 0;
+ r_view.frustum[5].normal[1] = 0 + 0;
+ r_view.frustum[5].normal[2] = -1 + -nudge;
+ r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
#endif
#if 0
- frustum[0].normal[0] = m[3] - m[0];
- frustum[0].normal[1] = m[7] - m[4];
- frustum[0].normal[2] = m[11] - m[8];
- frustum[0].dist = m[15] - m[12];
-
- frustum[1].normal[0] = m[3] + m[0];
- frustum[1].normal[1] = m[7] + m[4];
- frustum[1].normal[2] = m[11] + m[8];
- frustum[1].dist = m[15] + m[12];
-
- frustum[2].normal[0] = m[3] - m[1];
- frustum[2].normal[1] = m[7] - m[5];
- frustum[2].normal[2] = m[11] - m[9];
- frustum[2].dist = m[15] - m[13];
-
- frustum[3].normal[0] = m[3] + m[1];
- frustum[3].normal[1] = m[7] + m[5];
- frustum[3].normal[2] = m[11] + m[9];
- frustum[3].dist = m[15] + m[13];
-
- frustum[4].normal[0] = m[3] - m[2];
- frustum[4].normal[1] = m[7] - m[6];
- frustum[4].normal[2] = m[11] - m[10];
- frustum[4].dist = m[15] - m[14];
-
- frustum[5].normal[0] = m[3] + m[2];
- frustum[5].normal[1] = m[7] + m[6];
- frustum[5].normal[2] = m[11] + m[10];
- frustum[5].dist = m[15] + m[14];
+ r_view.frustum[0].normal[0] = m[3] - m[0];
+ r_view.frustum[0].normal[1] = m[7] - m[4];
+ r_view.frustum[0].normal[2] = m[11] - m[8];
+ r_view.frustum[0].dist = m[15] - m[12];
+
+ r_view.frustum[1].normal[0] = m[3] + m[0];
+ r_view.frustum[1].normal[1] = m[7] + m[4];
+ r_view.frustum[1].normal[2] = m[11] + m[8];
+ r_view.frustum[1].dist = m[15] + m[12];
+
+ r_view.frustum[2].normal[0] = m[3] - m[1];
+ r_view.frustum[2].normal[1] = m[7] - m[5];
+ r_view.frustum[2].normal[2] = m[11] - m[9];
+ r_view.frustum[2].dist = m[15] - m[13];
+
+ r_view.frustum[3].normal[0] = m[3] + m[1];
+ r_view.frustum[3].normal[1] = m[7] + m[5];
+ r_view.frustum[3].normal[2] = m[11] + m[9];
+ r_view.frustum[3].dist = m[15] + m[13];
+
+ r_view.frustum[4].normal[0] = m[3] - m[2];
+ r_view.frustum[4].normal[1] = m[7] - m[6];
+ r_view.frustum[4].normal[2] = m[11] - m[10];
+ r_view.frustum[4].dist = m[15] - m[14];
+
+ r_view.frustum[5].normal[0] = m[3] + m[2];
+ r_view.frustum[5].normal[1] = m[7] + m[6];
+ r_view.frustum[5].normal[2] = m[11] + m[10];
+ r_view.frustum[5].dist = m[15] + m[14];
#endif
- VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_x, r_viewleft, frustum[0].normal);
- VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_x, r_viewleft, frustum[1].normal);
- VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_y, r_viewup, frustum[2].normal);
- VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_y, r_viewup, frustum[3].normal);
- VectorCopy(r_viewforward, frustum[4].normal);
- VectorNormalize(frustum[0].normal);
- VectorNormalize(frustum[1].normal);
- VectorNormalize(frustum[2].normal);
- VectorNormalize(frustum[3].normal);
- frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
- frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
- frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
- frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
- frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + r_nearclip.value;
- PlaneClassify(&frustum[0]);
- PlaneClassify(&frustum[1]);
- PlaneClassify(&frustum[2]);
- PlaneClassify(&frustum[3]);
- PlaneClassify(&frustum[4]);
+ VectorMAM(1, r_view.forward, 1.0 / -r_view.frustum_x, r_view.left, r_view.frustum[0].normal);
+ VectorMAM(1, r_view.forward, 1.0 / r_view.frustum_x, r_view.left, r_view.frustum[1].normal);
+ VectorMAM(1, r_view.forward, 1.0 / -r_view.frustum_y, r_view.up, r_view.frustum[2].normal);
+ VectorMAM(1, r_view.forward, 1.0 / r_view.frustum_y, r_view.up, r_view.frustum[3].normal);
+ VectorCopy(r_view.forward, r_view.frustum[4].normal);
+ VectorNormalize(r_view.frustum[0].normal);
+ VectorNormalize(r_view.frustum[1].normal);
+ VectorNormalize(r_view.frustum[2].normal);
+ VectorNormalize(r_view.frustum[3].normal);
+ r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
+ r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
+ r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
+ r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
+ r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
+ PlaneClassify(&r_view.frustum[0]);
+ PlaneClassify(&r_view.frustum[1]);
+ PlaneClassify(&r_view.frustum[2]);
+ PlaneClassify(&r_view.frustum[3]);
+ PlaneClassify(&r_view.frustum[4]);
// LordHavoc: note to all quake engine coders, Quake had a special case
// for 90 degrees which assumed a square view (wrong), so I removed it,
// Quake2 has it disabled as well.
// rotate R_VIEWFORWARD right by FOV_X/2 degrees
- //RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_refdef.fov_x / 2));
- //frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
+ //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
+ //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
//PlaneClassify(&frustum[0]);
// rotate R_VIEWFORWARD left by FOV_X/2 degrees
- //RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_refdef.fov_x / 2));
- //frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
+ //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
+ //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
//PlaneClassify(&frustum[1]);
// rotate R_VIEWFORWARD up by FOV_X/2 degrees
- //RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_refdef.fov_y / 2));
- //frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
+ //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
+ //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
//PlaneClassify(&frustum[2]);
// rotate R_VIEWFORWARD down by FOV_X/2 degrees
- //RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_refdef.fov_y / 2));
- //frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
+ //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
+ //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
//PlaneClassify(&frustum[3]);
// nearclip plane
- //VectorCopy(r_viewforward, frustum[4].normal);
- //frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + r_nearclip.value;
+ //VectorCopy(r_view.forward, r_view.frustum[4].normal);
+ //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
//PlaneClassify(&frustum[4]);
}
+void R_View_Update(void)
+{
+ // GL is weird because it's bottom to top, r_view.y is top to bottom
+ qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
+ GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
+ GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
+ R_View_SetFrustum();
+ R_View_WorldVisibility();
+ R_View_UpdateEntityVisible();
+}
+
static void R_BlendView(void)
{
int screenwidth, screenheight;
{
int bloomwidth, bloomheight, x, range;
float xoffset, yoffset, r;
- renderstats.bloom++;
+ r_refdef.stats.bloom++;
// allocate textures as needed
if (!r_bloom_texture_screen)
r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
// set bloomwidth and bloomheight to the bloom resolution that will be
// used (often less than the screen resolution for faster rendering)
- bloomwidth = min(r_view_width, r_bloom_resolution.integer);
- bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
+ bloomwidth = min(r_view.width, r_bloom_resolution.integer);
+ bloomheight = min(r_view.height, bloomwidth * r_view.height / r_view.width);
// set up a texcoord array for the full resolution screen image
// (we have to keep this around to copy back during final render)
texcoord2f[0][0] = 0;
- texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
- texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
- texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
- texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
+ texcoord2f[0][1] = (float)r_view.height / (float)screenheight;
+ texcoord2f[0][2] = (float)r_view.width / (float)screenwidth;
+ texcoord2f[0][3] = (float)r_view.height / (float)screenheight;
+ texcoord2f[0][4] = (float)r_view.width / (float)screenwidth;
texcoord2f[0][5] = 0;
texcoord2f[0][6] = 0;
texcoord2f[0][7] = 0;
// copy view into the full resolution screen image texture
GL_ActiveTexture(0);
CHECKGLERROR
- qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);CHECKGLERROR
- renderstats.bloom_copypixels += r_view_width * r_view_height;
+ qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
+ r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
// now scale it down to the bloom size and raise to a power of itself
// to darken it (this leaves the really bright stuff bright, and
// everything else becomes very dark)
// TODO: optimize with multitexture or GLSL
CHECKGLERROR
- qglViewport(r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
+ qglViewport(r_view.x, vid.height - (r_view.y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
GL_BlendFunc(GL_ONE, GL_ZERO);
GL_Color(1, 1, 1, 1);
R_Mesh_Draw(0, 4, 2, polygonelements);
- renderstats.bloom_drawpixels += bloomwidth * bloomheight;
+ r_refdef.stats.bloom_drawpixels += bloomwidth * bloomheight;
// render multiple times with a multiply blendfunc to raise to a power
GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
for (x = 1;x < r_bloom_power.integer;x++)
{
R_Mesh_Draw(0, 4, 2, polygonelements);
- renderstats.bloom_drawpixels += bloomwidth * bloomheight;
+ r_refdef.stats.bloom_drawpixels += bloomwidth * bloomheight;
}
// we now have a darkened bloom image in the framebuffer, copy it into
// the bloom image texture for more processing
R_Mesh_TexCoordPointer(0, 2, texcoord2f[2]);
GL_ActiveTexture(0);
CHECKGLERROR
- qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
- renderstats.bloom_copypixels += bloomwidth * bloomheight;
+ qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
+ r_refdef.stats.bloom_copypixels += bloomwidth * bloomheight;
// blend on at multiple vertical offsets to achieve a vertical blur
// TODO: do offset blends using GLSL
range = r_bloom_blur.integer * bloomwidth / 320;
continue;
GL_Color(r, r, r, 1);
R_Mesh_Draw(0, 4, 2, polygonelements);
- renderstats.bloom_drawpixels += bloomwidth * bloomheight;
+ r_refdef.stats.bloom_drawpixels += bloomwidth * bloomheight;
GL_BlendFunc(GL_ONE, GL_ONE);
}
// copy the vertically blurred bloom view to a texture
GL_ActiveTexture(0);
CHECKGLERROR
- qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
- renderstats.bloom_copypixels += bloomwidth * bloomheight;
+ qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
+ r_refdef.stats.bloom_copypixels += bloomwidth * bloomheight;
// blend the vertically blurred image at multiple offsets horizontally
// to finish the blur effect
// TODO: do offset blends using GLSL
continue;
GL_Color(r, r, r, 1);
R_Mesh_Draw(0, 4, 2, polygonelements);
- renderstats.bloom_drawpixels += bloomwidth * bloomheight;
+ r_refdef.stats.bloom_drawpixels += bloomwidth * bloomheight;
GL_BlendFunc(GL_ONE, GL_ONE);
}
// copy the blurred bloom view to a texture
GL_ActiveTexture(0);
CHECKGLERROR
- qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
- renderstats.bloom_copypixels += bloomwidth * bloomheight;
+ qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
+ r_refdef.stats.bloom_copypixels += bloomwidth * bloomheight;
// go back to full view area
- qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);CHECKGLERROR
+ qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
// put the original screen image back in place and blend the bloom
// texture on it
GL_Color(1,1,1,1);
else
{
R_Mesh_Draw(0, 4, 2, polygonelements);
- renderstats.bloom_drawpixels += r_view_width * r_view_height;
+ r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
// now blend on the bloom texture
GL_BlendFunc(GL_ONE, GL_ONE);
R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_bloom));
R_Mesh_TexCoordPointer(0, 2, texcoord2f[1]);
}
R_Mesh_Draw(0, 4, 2, polygonelements);
- renderstats.bloom_drawpixels += r_view_width * r_view_height;
+ r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
}
if (doblend)
{
matrix4x4_t r_waterscrollmatrix;
+void R_UpdateVariables(void)
+{
+ int i;
+
+ R_Textures_Frame();
+
+ r_refdef.farclip = 4096;
+ if (r_refdef.worldmodel)
+ r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
+ r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
+
+ r_refdef.polygonfactor = 0;
+ r_refdef.polygonoffset = 0;
+ r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_shadow_polygonfactor.value;
+ r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_shadow_polygonoffset.value;
+
+ r_refdef.rtworld = r_shadow_realtime_world.integer;
+ r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
+ r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
+ r_refdef.rtdlightshadows = r_refdef.rtdlight && (r_refdef.rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
+ r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
+ if (r_showsurfaces.integer)
+ {
+ r_refdef.rtworld = false;
+ r_refdef.rtworldshadows = false;
+ r_refdef.rtdlight = false;
+ r_refdef.rtdlightshadows = false;
+ r_refdef.lightmapintensity = 0;
+ }
+
+ if (gamemode == GAME_NEHAHRA)
+ {
+ if (gl_fogenable.integer)
+ {
+ r_refdef.oldgl_fogenable = true;
+ r_refdef.fog_density = gl_fogdensity.value;
+ r_refdef.fog_red = gl_fogred.value;
+ r_refdef.fog_green = gl_foggreen.value;
+ r_refdef.fog_blue = gl_fogblue.value;
+ }
+ else if (r_refdef.oldgl_fogenable)
+ {
+ r_refdef.oldgl_fogenable = false;
+ r_refdef.fog_density = 0;
+ r_refdef.fog_red = 0;
+ r_refdef.fog_green = 0;
+ r_refdef.fog_blue = 0;
+ }
+ }
+ if (r_refdef.fog_density)
+ {
+ r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red , 1.0f);
+ r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
+ r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
+ }
+ if (r_refdef.fog_density)
+ {
+ r_refdef.fogenabled = true;
+ // this is the point where the fog reaches 0.9986 alpha, which we
+ // consider a good enough cutoff point for the texture
+ // (0.9986 * 256 == 255.6)
+ r_refdef.fogrange = 400 / r_refdef.fog_density;
+ r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
+ r_refdef.fogtabledistmultiplier = FOGTABLEWIDTH * r_refdef.fograngerecip;
+ // fog color was already set
+ }
+ else
+ r_refdef.fogenabled = false;
+
+ // update some cached entity properties...
+ for (i = 0;i < r_refdef.numentities;i++)
+ {
+ entity_render_t *ent = r_refdef.entities[i];
+ // some of the renderer still relies on origin...
+ Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
+ // some of the renderer still relies on scale...
+ ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
+ R_UpdateEntityLighting(ent);
+ }
+}
+
/*
================
R_RenderView
if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
return; //Host_Error ("R_RenderView: NULL worldmodel");
- r_view_width = bound(0, r_refdef.width, vid.width);
- r_view_height = bound(0, r_refdef.height, vid.height);
- r_view_depth = 1;
- r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
- r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
- r_view_z = 0;
- r_view_matrix = r_refdef.viewentitymatrix;
- GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
- r_rtworld = r_shadow_realtime_world.integer;
- r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
- r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
- r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
- r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
- r_polygonfactor = 0;
- r_polygonoffset = 0;
- r_shadowpolygonfactor = r_polygonfactor + r_shadow_shadow_polygonfactor.value;
- r_shadowpolygonoffset = r_polygonoffset + r_shadow_shadow_polygonoffset.value;
- if (r_showsurfaces.integer)
- {
- r_rtworld = false;
- r_rtworldshadows = false;
- r_rtdlight = false;
- r_rtdlightshadows = false;
- r_lightmapintensity = 0;
- }
-
- // GL is weird because it's bottom to top, r_view_y is top to bottom
CHECKGLERROR
- qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);CHECKGLERROR
- GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
GL_ScissorTest(true);
GL_DepthMask(true);
- R_ClearScreen();
- R_Textures_Frame();
- R_UpdateFog();
if (r_timereport_active)
R_TimeReport("setup");
- CHECKGLERROR
- qglDepthFunc(GL_LEQUAL);CHECKGLERROR
- qglPolygonOffset(r_polygonfactor, r_polygonoffset);CHECKGLERROR
- qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
+ R_View_Update();
+ if (r_timereport_active)
+ R_TimeReport("visibility");
- R_RenderScene();
+ R_ClearScreen();
+ if (r_timereport_active)
+ R_TimeReport("clear");
- CHECKGLERROR
- qglPolygonOffset(r_polygonfactor, r_polygonoffset);CHECKGLERROR
- qglDisable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
+ R_RenderScene();
R_BlendView();
if (r_timereport_active)
if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
return; //Host_Error ("R_RenderView: NULL worldmodel");
- r_view_width = bound(0, r_refdef.width, vid.width);
- r_view_height = bound(0, r_refdef.height, vid.height);
- r_view_depth = 1;
- r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
- r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
- r_view_z = 0;
- r_view_matrix = r_refdef.viewentitymatrix;
- GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
- r_rtworld = r_shadow_realtime_world.integer;
- r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
- r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
- r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
- r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
- r_polygonfactor = 0;
- r_polygonoffset = 0;
- r_shadowpolygonfactor = r_polygonfactor + r_shadow_shadow_polygonfactor.value;
- r_shadowpolygonoffset = r_polygonoffset + r_shadow_shadow_polygonoffset.value;
- if (r_showsurfaces.integer)
- {
- r_rtworld = false;
- r_rtworldshadows = false;
- r_rtdlight = false;
- r_rtdlightshadows = false;
- r_lightmapintensity = 0;
- }
-
- // GL is weird because it's bottom to top, r_view_y is top to bottom
CHECKGLERROR
- qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);CHECKGLERROR
- GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
GL_ScissorTest(true);
GL_DepthMask(true);
- R_ClearScreen();
- R_Textures_Frame();
- R_UpdateFog();
if (r_timereport_active)
R_TimeReport("setup");
+
+ R_View_Update();
+ if (r_timereport_active)
+ R_TimeReport("visibility");
+
+ R_ClearScreen();
+ if (r_timereport_active)
+ R_TimeReport("clear");
CHECKGLERROR
}
//[515]: csqc
void CSQC_R_RenderScene (void)
{
- CHECKGLERROR
- qglDepthFunc(GL_LEQUAL);CHECKGLERROR
- qglPolygonOffset(r_polygonfactor, r_polygonoffset);CHECKGLERROR
- qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
-
R_RenderScene();
- CHECKGLERROR
- qglPolygonOffset(r_polygonfactor, r_polygonoffset);CHECKGLERROR
- qglDisable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
-
R_BlendView();
if (r_timereport_active)
R_TimeReport("blendview");
extern void VM_AddPolygonsToMeshQueue (void);
void R_RenderScene(void)
{
- float nearclip;
-
// don't let sound skip if going slow
if (r_refdef.extraupdate)
S_ExtraUpdate ();
- r_framecount++;
-
CHECKGLERROR
if (gl_support_fragment_shader)
{
qglUseProgramObjectARB(0);CHECKGLERROR
}
+ qglDepthFunc(GL_LEQUAL);CHECKGLERROR
+ qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
+ qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
R_MeshQueue_BeginScene();
- R_SetFrustum();
-
- r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
- nearclip = bound (0.001f, r_nearclip.value, r_farclip - 1.0f);
-
- if (r_rtworldshadows || r_rtdlightshadows)
- GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.frustum_x, r_refdef.frustum_y, nearclip);
+ if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
+ GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
else
- GL_SetupView_Mode_Perspective(r_refdef.frustum_x, r_refdef.frustum_y, nearclip, r_farclip);
+ GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
- GL_SetupView_Orientation_FromEntity(&r_view_matrix);
+ GL_SetupView_Orientation_FromEntity(&r_view.matrix);
- Matrix4x4_CreateTranslate(&r_waterscrollmatrix, sin(r_refdef.time) * 0.025 * r_waterscroll.value, sin(r_refdef.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
+ R_Shadow_UpdateWorldLightSelection();
R_SkyStartFrame();
- R_WorldVisibility();
- if (r_timereport_active)
- R_TimeReport("worldvis");
-
- R_MarkEntities();
- if (r_timereport_active)
- R_TimeReport("markentity");
-
- R_Shadow_UpdateWorldLightSelection();
+ Matrix4x4_CreateTranslate(&r_waterscrollmatrix, sin(r_refdef.time) * 0.025 * r_waterscroll.value, sin(r_refdef.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
if (cl.csqc_vidvars.drawworld)
{
R_TimeReport("explosions");
}
+ VM_AddPolygonsToMeshQueue();
+
R_MeshQueue_RenderTransparent();
if (r_timereport_active)
R_TimeReport("drawtrans");
R_TimeReport("crosshair");
}
- VM_AddPolygonsToMeshQueue();
-
- R_MeshQueue_Render();
-
- R_MeshQueue_EndScene();
-
// don't let sound skip if going slow
if (r_refdef.extraupdate)
S_ExtraUpdate ();
{
qglUseProgramObjectARB(0);CHECKGLERROR
}
+ qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
+ qglDisable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
}
/*
vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
R_FillColors(color, 8, cr, cg, cb, ca);
- if (fogenabled)
+ if (r_refdef.fogenabled)
{
for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
{
- f2 = VERTEXFOGTABLE(VectorDistance(v, r_vieworigin));
+ f2 = VERTEXFOGTABLE(VectorDistance(v, r_view.origin));
f1 = 1 - f2;
- c[0] = c[0] * f1 + fogcolor[0] * f2;
- c[1] = c[1] * f1 + fogcolor[1] * f2;
- c[2] = c[2] * f1 + fogcolor[2] * f2;
+ c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
+ c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
+ c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
}
}
R_Mesh_VertexPointer(vertex3f);
}
GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
R_Mesh_VertexPointer(nomodelvertex3f);
- if (fogenabled)
+ if (r_refdef.fogenabled)
{
memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
R_Mesh_ColorPointer(color4f);
- f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_vieworigin));
+ f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_view.origin));
f1 = 1 - f2;
for (i = 0, c = color4f;i < 6;i++, c += 4)
{
- c[0] = (c[0] * f1 + fogcolor[0] * f2);
- c[1] = (c[1] * f1 + fogcolor[1] * f2);
- c[2] = (c[2] * f1 + fogcolor[2] * f2);
+ c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
+ c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
+ c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
c[3] *= ent->alpha;
}
}
void R_DrawNoModel(entity_render_t *ent)
{
//if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
- R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
+ R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
//else
// R_DrawNoModelCallback(ent, 0);
}
VectorSubtract (org2, org1, normal);
// calculate 'right' vector for start
- VectorSubtract (r_vieworigin, org1, diff);
+ VectorSubtract (r_view.origin, org1, diff);
CrossProduct (normal, diff, right1);
VectorNormalize (right1);
// calculate 'right' vector for end
- VectorSubtract (r_vieworigin, org2, diff);
+ VectorSubtract (r_view.origin, org2, diff);
CrossProduct (normal, diff, right2);
VectorNormalize (right2);
float fog = 0.0f, ifog;
float vertex3f[12];
- if (fogenabled)
- fog = VERTEXFOGTABLE(VectorDistance(origin, r_vieworigin));
+ if (r_refdef.fogenabled)
+ fog = VERTEXFOGTABLE(VectorDistance(origin, r_view.origin));
ifog = 1 - fog;
R_Mesh_Matrix(&identitymatrix);
{
R_Mesh_TexBind(0, R_GetTexture(fogtexture));
GL_BlendFunc(blendfunc1, GL_ONE);
- GL_Color(fogcolor[0] * fog, fogcolor[1] * fog, fogcolor[2] * fog, ca);
+ GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
R_Mesh_Draw(0, 4, 2, polygonelements);
}
}
{
rtexture_t *currentbasetexture;
int layerflags = 0;
- if (fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
+ if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->skin.merged) ? t->skin.merged : t->skin.base;
if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
{
- // fullbright is not affected by r_lightmapintensity
+ // fullbright is not affected by r_refdef.lightmapintensity
R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0], ent->colormap_pantscolor[1] * ent->colormod[1], ent->colormap_pantscolor[2] * ent->colormod[2], t->currentalpha);
// applied to the color
if (ent->model->type == mod_brushq3)
colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
- colorscale *= r_lightmapintensity;
+ colorscale *= r_refdef.lightmapintensity;
R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * colorscale, ent->colormod[1] * colorscale, ent->colormod[2] * colorscale, t->currentalpha);
if (r_ambient.value >= (1.0f/64.0f))
R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), t->currentalpha);
}
if (t->skin.glow != NULL)
R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, t->currentalpha);
- if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
+ if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
{
// if this is opaque use alpha blend which will darken the earlier
// passes cheaply.
// were darkened by fog already, and we should not add fog color
// (because the background was not darkened, there is no fog color
// that was lost behind it).
- R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->skin.fog, &identitymatrix, fogcolor[0], fogcolor[1], fogcolor[2], t->currentalpha);
+ R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->skin.fog, &identitymatrix, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], t->currentalpha);
}
}
}
void RSurf_ActiveEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
{
- Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, rsurface_modelorg);
+ Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
rsurface_entity = ent;
rsurface_model = ent->model;
if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
R_Mesh_Matrix(&ent->matrix);
- Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, rsurface_modelorg);
+ Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
if ((rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0) && (rsurface_model->surfmesh.data_morphvertex3f || rsurface_model->surfmesh.data_vertexweightindex4i))
{
if (wanttangents)
int texturesurfaceindex;
float center[3], forward[3], right[3], up[3], v[4][3];
matrix4x4_t matrix1, imatrix1;
- Matrix4x4_Transform(&rsurface_entity->inversematrix, r_viewforward, forward);
- Matrix4x4_Transform(&rsurface_entity->inversematrix, r_viewright, right);
- Matrix4x4_Transform(&rsurface_entity->inversematrix, r_viewup, up);
+ Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.forward, forward);
+ Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.right, right);
+ Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.up, up);
// make deformed versions of only the vertices used by the specified surfaces
for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
{
// in Quake3 maps as it causes problems with q3map2 sky tricks,
// and skymasking also looks very bad when noclipping outside the
// level, so don't use it then either.
- if (rsurface_model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_worldnovis)
+ if (rsurface_model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
{
- GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1);
+ GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
R_Mesh_ColorPointer(NULL);
R_Mesh_ResetTextureState();
if (skyrendermasked)
// fog sky
GL_BlendFunc(GL_ONE, GL_ZERO);
}
- }
- // LordHavoc: HalfLife maps have freaky skypolys so don't use
- // skymasking on them, and Quake3 never did sky masking (unlike
- // software Quake and software Quake2), so disable the sky masking
- // in Quake3 maps as it causes problems with q3map2 sky tricks,
- // and skymasking also looks very bad when noclipping outside the
- // level, so don't use it then either.
- if (rsurface_model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_worldnovis)
- {
RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
if (skyrendermasked)
- GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
+ GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
}
}
if (rsurface_texture->currentmaterialflags & MATERIALFLAG_NODRAW)
return;
r_shadow_rtlight = NULL;
- renderstats.entities_surfaces += texturenumsurfaces;
+ r_refdef.stats.entities_surfaces += texturenumsurfaces;
CHECKGLERROR
GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
if ((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE))
tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
Matrix4x4_Transform(&rsurface_entity->matrix, tempcenter, center);
- R_MeshQueue_AddTransparent(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, R_DrawSurface_TransparentCallback, rsurface_entity, surface - rsurface_model->data_surfaces, r_shadow_rtlight);
+ R_MeshQueue_AddTransparent(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_view.origin : center, R_DrawSurface_TransparentCallback, rsurface_entity, surface - rsurface_model->data_surfaces, r_shadow_rtlight);
}
}
}
msurface_t *surface;
for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
{
- if (!r_worldsurfacevisible[j])
+ if (!r_viewcache.world_surfacevisible[j])
continue;
if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
{
}
if (numsurfacelist)
R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
- renderstats.entities_triangles += counttriangles;
+ r_refdef.stats.entities_triangles += counttriangles;
RSurf_CleanUp();
if (r_showcollisionbrushes.integer && model->brush.num_brushes && !skysurfaces)
GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
GL_DepthMask(false);
GL_DepthTest(!r_showdisabledepthtest.integer);
- qglPolygonOffset(r_polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_polygonoffset + r_showcollisionbrushes_polygonoffset.value);CHECKGLERROR
+ qglPolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);CHECKGLERROR
for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
if (brush->colbrushf && brush->colbrushf->numtriangles)
R_DrawCollisionBrush(brush->colbrushf);
for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
if (surface->num_collisiontriangles)
R_DrawCollisionSurface(ent, surface);
- qglPolygonOffset(r_polygonfactor, r_polygonoffset);CHECKGLERROR
+ qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
}
if (r_showtris.integer || r_shownormals.integer)
R_Mesh_ResetTextureState();
for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
{
- if (ent == r_refdef.worldentity && !r_worldsurfacevisible[j])
+ if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
continue;
rsurface_texture = surface->texture->currentframe;
if ((rsurface_texture->currentmaterialflags & flagsmask) && surface->num_triangles)
cvar_t r_useportalculling = {0, "r_useportalculling", "1", "use advanced portal culling visibility method to improve performance over just Potentially Visible Set, provides an even more significant speed improvement in unvised maps"};
cvar_t r_q3bsp_renderskydepth = {0, "r_q3bsp_renderskydepth", "0", "draws sky depth masking in q3 maps (as in q1 maps), this means for example that sky polygons can hide other things"};
-// flag arrays used for visibility checking on world model
-// (all other entities have no per-surface/per-leaf visibility checks)
-// TODO: dynamic resize according to r_refdef.worldmodel->brush.num_clusters
-unsigned char r_pvsbits[(32768+7)>>3];
-// TODO: dynamic resize according to r_refdef.worldmodel->brush.num_leafs
-unsigned char r_worldleafvisible[32768];
-// TODO: dynamic resize according to r_refdef.worldmodel->num_surfaces
-unsigned char r_worldsurfacevisible[262144];
-// if true, the view is currently in a leaf without pvs data
-qboolean r_worldnovis;
-
/*
===============
R_BuildLightMap
return;
for (leafnum = 0;leafnum < r_refdef.worldmodel->brush.num_leafs;leafnum++)
{
- if (r_worldleafvisible[leafnum])
+ if (r_viewcache.world_leafvisible[leafnum])
{
//for (portalnum = 0, portal = model->brush.data_portals;portalnum < model->brush.num_portals;portalnum++, portal++)
for (portal = r_refdef.worldmodel->brush.data_leafs[leafnum].portals;portal;portal = portal->next)
}
}
-void R_WorldVisibility(void)
+void R_View_WorldVisibility(void)
{
int i, j, *mark;
mleaf_t *leaf;
return;
// if possible find the leaf the view origin is in
- viewleaf = model->brush.PointInLeaf ? model->brush.PointInLeaf(model, r_vieworigin) : NULL;
+ viewleaf = model->brush.PointInLeaf ? model->brush.PointInLeaf(model, r_view.origin) : NULL;
// if possible fetch the visible cluster bits
if (!r_lockpvs.integer && model->brush.FatPVS)
- model->brush.FatPVS(model, r_vieworigin, 2, r_pvsbits, sizeof(r_pvsbits));
+ model->brush.FatPVS(model, r_view.origin, 2, r_viewcache.world_pvsbits, sizeof(r_viewcache.world_pvsbits));
if (!r_lockvisibility.integer)
{
// clear the visible surface and leaf flags arrays
- memset(r_worldsurfacevisible, 0, model->num_surfaces);
- memset(r_worldleafvisible, 0, model->brush.num_leafs);
+ memset(r_viewcache.world_surfacevisible, 0, model->num_surfaces);
+ memset(r_viewcache.world_leafvisible, 0, model->brush.num_leafs);
- r_worldnovis = false;
+ r_viewcache.world_novis = false;
// if floating around in the void (no pvs data available, and no
// portals available), simply use all on-screen leafs.
// no visibility method: (used when floating around in the void)
// simply cull each leaf to the frustum (view pyramid)
// similar to quake's RecursiveWorldNode but without cache misses
- r_worldnovis = true;
+ r_viewcache.world_novis = true;
for (j = 0, leaf = model->brush.data_leafs;j < model->brush.num_leafs;j++, leaf++)
{
// if leaf is in current pvs and on the screen, mark its surfaces
if (!R_CullBox(leaf->mins, leaf->maxs))
{
- renderstats.world_leafs++;
- r_worldleafvisible[j] = true;
+ r_refdef.stats.world_leafs++;
+ r_viewcache.world_leafvisible[j] = true;
if (leaf->numleafsurfaces)
for (i = 0, mark = leaf->firstleafsurface;i < leaf->numleafsurfaces;i++, mark++)
- r_worldsurfacevisible[*mark] = true;
+ r_viewcache.world_surfacevisible[*mark] = true;
}
}
}
for (j = 0, leaf = model->brush.data_leafs;j < model->brush.num_leafs;j++, leaf++)
{
// if leaf is in current pvs and on the screen, mark its surfaces
- if (CHECKPVSBIT(r_pvsbits, leaf->clusterindex) && !R_CullBox(leaf->mins, leaf->maxs))
+ if (CHECKPVSBIT(r_viewcache.world_pvsbits, leaf->clusterindex) && !R_CullBox(leaf->mins, leaf->maxs))
{
- renderstats.world_leafs++;
- r_worldleafvisible[j] = true;
+ r_refdef.stats.world_leafs++;
+ r_viewcache.world_leafvisible[j] = true;
if (leaf->numleafsurfaces)
for (i = 0, mark = leaf->firstleafsurface;i < leaf->numleafsurfaces;i++, mark++)
- r_worldsurfacevisible[*mark] = true;
+ r_viewcache.world_surfacevisible[*mark] = true;
}
}
}
leafstackpos = 1;
while (leafstackpos)
{
- renderstats.world_leafs++;
+ r_refdef.stats.world_leafs++;
leaf = leafstack[--leafstackpos];
- r_worldleafvisible[leaf - model->brush.data_leafs] = true;
+ r_viewcache.world_leafvisible[leaf - model->brush.data_leafs] = true;
// mark any surfaces bounding this leaf
if (leaf->numleafsurfaces)
for (i = 0, mark = leaf->firstleafsurface;i < leaf->numleafsurfaces;i++, mark++)
- r_worldsurfacevisible[*mark] = true;
+ r_viewcache.world_surfacevisible[*mark] = true;
// follow portals into other leafs
// the checks are:
// if viewer is behind portal (portal faces outward into the scene)
// (the first two checks won't cause as many cache misses as the leaf checks)
for (p = leaf->portals;p;p = p->next)
{
- renderstats.world_portals++;
- if (DotProduct(r_vieworigin, p->plane.normal) < (p->plane.dist + 1) && !R_CullBox(p->mins, p->maxs) && !r_worldleafvisible[p->past - model->brush.data_leafs] && CHECKPVSBIT(r_pvsbits, p->past->clusterindex))
+ r_refdef.stats.world_portals++;
+ if (DotProduct(r_view.origin, p->plane.normal) < (p->plane.dist + 1) && !R_CullBox(p->mins, p->maxs) && !r_viewcache.world_leafvisible[p->past - model->brush.data_leafs] && CHECKPVSBIT(r_viewcache.world_pvsbits, p->past->clusterindex))
leafstack[leafstackpos++] = p->past;
}
}
tempcenter[1] = (batchsurface->mins[1] + batchsurface->maxs[1]) * 0.5f;
tempcenter[2] = (batchsurface->mins[2] + batchsurface->maxs[2]) * 0.5f;
Matrix4x4_Transform(&rsurface_entity->matrix, tempcenter, center);
- R_MeshQueue_AddTransparent(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, R_Q1BSP_DrawLight_TransparentCallback, rsurface_entity, batchsurface - rsurface_model->data_surfaces, r_shadow_rtlight);
+ R_MeshQueue_AddTransparent(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_view.origin : center, R_Q1BSP_DrawLight_TransparentCallback, rsurface_entity, batchsurface - rsurface_model->data_surfaces, r_shadow_rtlight);
}
}
CHECKGLERROR
for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
{
- if ((ent == r_refdef.worldentity && !r_worldsurfacevisible[surfacelist[surfacelistindex]]))
+ if ((ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[surfacelist[surfacelistindex]]))
continue;
surface = model->data_surfaces + surfacelist[surfacelistindex];
- renderstats.lights_lighttriangles += surface->num_triangles;
+ r_refdef.stats.lights_lighttriangles += surface->num_triangles;
if (tex != surface->texture)
{
if (batchnumsurfaces > 0)
// don't allow simulation to run too fast or too slow or logic glitches can occur
// stop running server frames if the wall time reaches this value
- if (sys_ticrate.value <= 0 || (cl.islocalgame && !sv_fixedframeratesingleplayer.integer))
+ if (sys_ticrate.value <= 0)
advancetime = sv_timer;
+ else if (cl.islocalgame && !sv_fixedframeratesingleplayer.integer)
+ {
+ // synchronize to the client frametime, but no less than 10ms and no more than sys_ticrate
+ advancetime = bound(0.01, cl_timer, sys_ticrate.value);
+ framelimit = 10;
+ aborttime = Sys_DoubleTime() + 0.1;
+ }
else
{
advancetime = sys_ticrate.value;
csqc_usecsqclistener = false;
}
else
- S_Update(&r_refdef.viewentitymatrix);
+ S_Update(&r_view.matrix);
CDAudio_Update();
}
#include "quakedef.h"
#include "meshqueue.h"
-cvar_t r_meshqueue_entries = {CVAR_SAVE, "r_meshqueue_entries", "16", "maximum number of meshes to batch together and sort before issuing render calls (unused)"};
-cvar_t r_meshqueue_immediaterender = {0, "r_meshqueue_immediaterender", "0", "immediately render non-transparent meshes rather than batching"};
-cvar_t r_meshqueue_sort = {0, "r_meshqueue_sort", "0", "whether to sort meshes in a batch before issuing calls"};
-
typedef struct meshqueue_s
{
struct meshqueue_s *next;
float mqt_viewplanedist;
float mqt_viewmaxdist;
-meshqueue_t *mq_array, *mqt_array, *mq_listhead;
-int mq_count, mqt_count;
-int mq_total, mqt_total;
+meshqueue_t *mqt_array;
+int mqt_count;
+int mqt_total;
-void R_MeshQueue_Init(void)
+void R_MeshQueue_BeginScene(void)
{
- Cvar_RegisterVariable(&r_meshqueue_entries);
- Cvar_RegisterVariable(&r_meshqueue_immediaterender);
- Cvar_RegisterVariable(&r_meshqueue_sort);
-
- mq_total = 0;
- mqt_total = 0;
- mq_array = NULL;
- mqt_array = NULL;
+ mqt_count = 0;
+ mqt_viewplanedist = DotProduct(r_view.origin, r_view.forward);
+ mqt_viewmaxdist = 0;
}
-void R_MeshQueue_Render(void)
+void R_MeshQueue_AddTransparent(const vec3_t center, void (*callback)(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist), const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
{
- // this is only used by one piece of code in prvm_cmds, why is it used at all?
meshqueue_t *mq;
- if (!mq_count)
- return;
- for (mq = mq_listhead;mq;mq = mq->next)
- mq->callback(mq->ent, mq->rtlight, 1, &mq->surfacenumber);
- mq_count = 0;
- mq_listhead = NULL;
-}
-
-static void R_MeshQueue_EnlargeTransparentArray(int newtotal)
-{
- meshqueue_t *newarray;
- newarray = (meshqueue_t *)Mem_Alloc(cls.permanentmempool, newtotal * sizeof(meshqueue_t));
- if (mqt_array)
+ if (mqt_count >= mqt_total || !mqt_array)
{
- memcpy(newarray, mqt_array, mqt_total * sizeof(meshqueue_t));
- Mem_Free(mqt_array);
- }
- mqt_array = newarray;
- mqt_total = newtotal;
-}
-
-void R_MeshQueue_Add(void (*callback)(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist), const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
-{
- // this is only used by one piece of code in prvm_cmds, why is it used at all?
- meshqueue_t *mq, **mqnext;
- if (r_meshqueue_immediaterender.integer)
- {
- callback(ent, rtlight, 1, &surfacenumber);
- return;
- }
- if (mq_count >= mq_total)
- R_MeshQueue_Render();
- mq = &mq_array[mq_count++];
- mq->callback = callback;
- mq->ent = ent;
- mq->surfacenumber = surfacenumber;
- mq->rtlight = rtlight;
-
- if (r_meshqueue_sort.integer)
- {
- // bubble-insert sort into meshqueue
- for(mqnext = &mq_listhead;*mqnext;mqnext = &(*mqnext)->next)
+ int newtotal = max(1024, mqt_total * 2);
+ meshqueue_t *newarray = (meshqueue_t *)Mem_Alloc(cls.permanentmempool, newtotal * sizeof(meshqueue_t));
+ if (mqt_array)
{
- if (mq->callback == (*mqnext)->callback)
- {
- if (mq->ent == (*mqnext)->ent)
- {
- if (mq->surfacenumber == (*mqnext)->surfacenumber)
- {
- if (mq->rtlight <= (*mqnext)->rtlight)
- break;
- }
- else if (mq->surfacenumber < (*mqnext)->surfacenumber)
- break;
- }
- else if (mq->ent < (*mqnext)->ent)
- break;
- }
- else if (mq->callback < (*mqnext)->callback)
- break;
+ memcpy(newarray, mqt_array, mqt_total * sizeof(meshqueue_t));
+ Mem_Free(mqt_array);
}
+ mqt_array = newarray;
+ mqt_total = newtotal;
}
- else
- {
- // maintain the order
- for(mqnext = &mq_listhead;*mqnext;mqnext = &(*mqnext)->next);
- }
- mq->next = *mqnext;
- *mqnext = mq;
-}
-
-void R_MeshQueue_AddTransparent(const vec3_t center, void (*callback)(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist), const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
-{
- meshqueue_t *mq;
- if (mqt_count >= mqt_total)
- R_MeshQueue_EnlargeTransparentArray(mqt_total + 100);
mq = &mqt_array[mqt_count++];
mq->callback = callback;
mq->ent = ent;
mq->surfacenumber = surfacenumber;
mq->rtlight = rtlight;
- mq->dist = DotProduct(center, r_viewforward) - mqt_viewplanedist;
+ mq->dist = DotProduct(center, r_view.forward) - mqt_viewplanedist;
mq->next = NULL;
mqt_viewmaxdist = max(mqt_viewmaxdist, mq->dist);
}
meshqueue_t *mqt;
meshqueue_t *hash[4096], **hashpointer[4096];
int batchsurfaceindex[256];
- if (mq_count)
- R_MeshQueue_Render();
if (!mqt_count)
return;
memset(hash, 0, sizeof(hash));
callback(ent, rtlight, batchnumsurfaces, batchsurfaceindex);
mqt_count = 0;
}
-
-void R_MeshQueue_BeginScene(void)
-{
- if (r_meshqueue_entries.integer < 1)
- Cvar_SetValueQuick(&r_meshqueue_entries, 1);
- if (r_meshqueue_entries.integer > 65536)
- Cvar_SetValueQuick(&r_meshqueue_entries, 65536);
-
- if (mq_total != r_meshqueue_entries.integer || mq_array == NULL)
- {
- mq_total = r_meshqueue_entries.integer;
- if (mq_array)
- Mem_Free(mq_array);
- mq_array = (meshqueue_t *)Mem_Alloc(cls.permanentmempool, mq_total * sizeof(meshqueue_t));
- }
-
- if (mqt_array == NULL)
- mqt_array = (meshqueue_t *)Mem_Alloc(cls.permanentmempool, mqt_total * sizeof(meshqueue_t));
-
- mq_count = 0;
- mqt_count = 0;
- mq_listhead = NULL;
- mqt_viewplanedist = DotProduct(r_vieworigin, r_viewforward);
- mqt_viewmaxdist = 0;
-}
-
-void R_MeshQueue_EndScene(void)
-{
- if (mq_count)
- {
- Con_Printf("R_MeshQueue_EndScene: main mesh queue still has %i items left, flushing\n", mq_count);
- R_MeshQueue_Render();
- }
- if (mqt_count)
- {
- Con_Printf("R_MeshQueue_EndScene: transparent mesh queue still has %i items left, flushing\n", mqt_count);
- R_MeshQueue_RenderTransparent();
- }
-}
-
#ifndef MESHQUEUE_H
#define MESHQUEUE_H
-void R_MeshQueue_Init(void);
-void R_MeshQueue_Add(void (*callback)(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist), const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight);
-void R_MeshQueue_AddTransparent(const vec3_t center, void (*callback)(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist), const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight);
void R_MeshQueue_BeginScene(void);
-void R_MeshQueue_Render(void);
+void R_MeshQueue_AddTransparent(const vec3_t center, void (*callback)(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist), const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight);
void R_MeshQueue_RenderTransparent(void);
-void R_MeshQueue_EndScene(void);
#endif
if(!vm_drawpolygons_num)
return;
for(i = 0;i < vm_drawpolygons_num;i++)
- R_MeshQueue_Add(VM_DrawPolygonCallback, NULL, i, NULL);
+ VM_DrawPolygonCallback(NULL, NULL, i, NULL);
vm_drawpolygons_num = 0;
}
// get the forward vector for the gun (not the view)
AngleVectors(cl.viewangles, v2, NULL, NULL);
- //VectorCopy(r_vieworigin, v1);
+ //VectorCopy(r_view.origin, v1);
VectorMA(v1, 8192, v2, v2);
trace = CL_TraceBox(v1, vec3_origin, vec3_origin, v2, true, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_SKY, false);
spritescale = trace.fraction * (8192.0f / 40.0f) * crosshair_size.value;
VectorCopy(trace.endpos, spriteorigin);
// draw the sprite
- R_DrawSprite(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, pic->tex, NULL, true, spriteorigin, r_viewright, r_viewup, spritescale, -spritescale, -spritescale, spritescale, color[0], color[1], color[2], color[3]);
+ R_DrawSprite(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, pic->tex, NULL, true, spriteorigin, r_view.right, r_view.up, spritescale, -spritescale, -spritescale, spritescale, color[0], color[1], color[2], color[3]);
}
void R_Draw2DCrosshair(void)
fractalnoisequick(noise, EXPLOSIONGRID, 4); // adjust noise grid size according to explosion
for (i = 0, e = explosion;i < MAX_EXPLOSIONS;i++, e++)
{
- if (cl.time >= e->endtime)
+ if (!e->alpha)
{
e->starttime = cl.time;
e->endtime = cl.time + cl_explosions_lifetime.value;
frametime = cl.time - e->time;
e->time = cl.time;
e->alpha = e->alpha - (e->fade * frametime);
+ if (e->alpha < 0 || cl.time > e->endtime)
+ {
+ e->alpha = 0;
+ return;
+ }
for (i = 0;i < EXPLOSIONVERTS;i++)
{
if (e->vertvel[i][0] || e->vertvel[i][1] || e->vertvel[i][2])
{
int i;
for (i = 0;i < MAX_EXPLOSIONS;i++)
- if (cl.time < explosion[i].endtime)
+ if (explosion[i].alpha)
R_MoveExplosion(&explosion[i]);
}
if (!r_drawexplosions.integer)
return;
for (i = 0;i < MAX_EXPLOSIONS;i++)
- if (r_refdef.time < explosion[i].endtime)
+ if (explosion[i].alpha)
R_MeshQueue_AddTransparent(explosion[i].origin, R_DrawExplosion_TransparentCallback, NULL, i, NULL);
}
if (r_coronas.value < 0.01)
return;
R_Mesh_Matrix(&identitymatrix);
- viewdist = DotProduct(r_vieworigin, r_viewforward);
- flag = r_rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE;
+ viewdist = DotProduct(r_view.origin, r_view.forward);
+ flag = r_refdef.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE;
for (lnum = 0, light = r_shadow_worldlightchain;light;light = light->next, lnum++)
{
- if ((light->flags & flag) && light->corona * r_coronas.value > 0 && (r_shadow_debuglight.integer < 0 || r_shadow_debuglight.integer == lnum) && (dist = (DotProduct(light->rtlight.shadoworigin, r_viewforward) - viewdist)) >= 24.0f && CL_TraceBox(light->rtlight.shadoworigin, vec3_origin, vec3_origin, r_vieworigin, true, NULL, SUPERCONTENTS_SOLID, false).fraction == 1)
+ if ((light->flags & flag) && light->corona * r_coronas.value > 0 && (r_shadow_debuglight.integer < 0 || r_shadow_debuglight.integer == lnum) && (dist = (DotProduct(light->rtlight.shadoworigin, r_view.forward) - viewdist)) >= 24.0f && CL_TraceBox(light->rtlight.shadoworigin, vec3_origin, vec3_origin, r_view.origin, true, NULL, SUPERCONTENTS_SOLID, false).fraction == 1)
{
cscale = light->rtlight.corona * r_coronas.value * 0.25f;
scale = light->rtlight.radius * light->rtlight.coronasizescale;
- R_DrawSprite(GL_ONE, GL_ONE, lightcorona, NULL, true, light->rtlight.shadoworigin, r_viewright, r_viewup, scale, -scale, -scale, scale, light->rtlight.color[0] * cscale, light->rtlight.color[1] * cscale, light->rtlight.color[2] * cscale, 1);
+ R_DrawSprite(GL_ONE, GL_ONE, lightcorona, NULL, true, light->rtlight.shadoworigin, r_view.right, r_view.up, scale, -scale, -scale, scale, light->rtlight.color[0] * cscale, light->rtlight.color[1] * cscale, light->rtlight.color[2] * cscale, 1);
}
}
for (i = 0;i < r_refdef.numlights;i++)
{
light = r_refdef.lights[i];
- if ((light->flags & flag) && light->corona * r_coronas.value > 0 && (dist = (DotProduct(light->origin, r_viewforward) - viewdist)) >= 24.0f && CL_TraceBox(light->origin, vec3_origin, vec3_origin, r_vieworigin, true, NULL, SUPERCONTENTS_SOLID, false).fraction == 1)
+ if ((light->flags & flag) && light->corona * r_coronas.value > 0 && (dist = (DotProduct(light->origin, r_view.forward) - viewdist)) >= 24.0f && CL_TraceBox(light->origin, vec3_origin, vec3_origin, r_view.origin, true, NULL, SUPERCONTENTS_SOLID, false).fraction == 1)
{
cscale = light->corona * r_coronas.value * 0.25f;
scale = light->rtlight.radius * light->rtlight.coronasizescale;
cscale *= 4.0f;
scale *= 2.0f;
}
- R_DrawSprite(GL_ONE, GL_ONE, lightcorona, NULL, true, light->origin, r_viewright, r_viewup, scale, -scale, -scale, scale, light->color[0] * cscale, light->color[1] * cscale, light->color[2] * cscale, 1);
+ R_DrawSprite(GL_ONE, GL_ONE, lightcorona, NULL, true, light->origin, r_view.right, r_view.up, scale, -scale, -scale, scale, light->color[0] * cscale, light->color[1] * cscale, light->color[2] * cscale, 1);
}
}
}
float ifog;
for (i = 0;i < numverts;i++, v += 3, c += 4)
{
- ifog = 1 - VERTEXFOGTABLE(VectorDistance(v, r_vieworigin));
+ ifog = 1 - VERTEXFOGTABLE(VectorDistance(v, r_view.origin));
c[0] = r * ifog;
c[1] = g * ifog;
c[2] = b * ifog;
r_lightningbeams_setuptexture();
R_Mesh_VertexPointer(vertex3f);
- if (fogenabled)
+ if (r_refdef.fogenabled)
{
// per vertex colors if fog is used
R_Mesh_ColorPointer(color4f);
// calculate up vector such that it points toward viewer, and rotates around the beamdir
// get direction from start of beam to viewer
- VectorSubtract(r_vieworigin, b->start, up);
+ VectorSubtract(r_view.origin, b->start, up);
// remove the portion of the vector that moves along the beam
// (this leaves only a vector pointing directly away from the beam)
t1 = -DotProduct(up, beamdir);
R_CalcLightningBeamPolygonTexCoord2f(texcoord2f + 0, t1, t2);
R_CalcLightningBeamPolygonTexCoord2f(texcoord2f + 8, t1 + 0.33, t2 + 0.33);
R_CalcLightningBeamPolygonTexCoord2f(texcoord2f + 16, t1 + 0.66, t2 + 0.66);
- if (fogenabled)
+ if (r_refdef.fogenabled)
{
// per vertex colors if fog is used
R_FogLightningBeam_Vertex3f_Color4f(vertex3f, color4f, 12, r_lightningbeam_color_red.value, r_lightningbeam_color_green.value, r_lightningbeam_color_blue.value, 1);
if (maxshadowtriangles < nummarktris || maxshadowvertices < numverts)
R_Shadow_ResizeShadowArrays((numverts + 255) & ~255, (nummarktris + 255) & ~255);
tris = R_Shadow_ConstructShadowVolume(numverts, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, shadowvertex3f, projectorigin, projectdistance, nummarktris, marktris);
- renderstats.lights_dynamicshadowtriangles += tris;
+ r_refdef.stats.lights_dynamicshadowtriangles += tris;
R_Shadow_RenderVolume(outverts, tris, shadowvertex3f, shadowelements);
}
Mod_ShadowMesh_AddMesh(r_main_mempool, r_shadow_compilingrtlight->static_meshchain_shadow, NULL, NULL, NULL, vertex3f, NULL, NULL, NULL, NULL, numtriangles, element3i);
return;
}
- renderstats.lights_shadowtriangles += numtriangles;
+ r_refdef.stats.lights_shadowtriangles += numtriangles;
CHECKGLERROR
R_Mesh_VertexPointer(vertex3f);
GL_LockArrays(0, numvertices);
GL_Color(0, 0, 0, 1);
qglCullFace(GL_FRONT);CHECKGLERROR // quake is backwards, this culls back faces
qglEnable(GL_CULL_FACE);CHECKGLERROR
- GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
+ GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
r_shadow_rendermode = R_SHADOW_RENDERMODE_NONE;
GL_BlendFunc(GL_ONE, GL_ZERO);
GL_DepthMask(false);
GL_DepthTest(true);
- qglPolygonOffset(r_shadowpolygonfactor, r_shadowpolygonoffset);CHECKGLERROR
+ qglPolygonOffset(r_refdef.shadowpolygonfactor, r_refdef.shadowpolygonoffset);CHECKGLERROR
qglDepthFunc(GL_LESS);CHECKGLERROR
qglCullFace(GL_FRONT);CHECKGLERROR // quake is backwards, this culls back faces
qglEnable(GL_STENCIL_TEST);CHECKGLERROR
qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
}
GL_Clear(GL_STENCIL_BUFFER_BIT);
- renderstats.lights_clears++;
+ r_refdef.stats.lights_clears++;
}
void R_Shadow_RenderMode_Lighting(qboolean stenciltest, qboolean transparent)
GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
GL_DepthMask(false);
GL_DepthTest(true);
- qglPolygonOffset(r_polygonfactor, r_polygonoffset);CHECKGLERROR
+ qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
//qglDisable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
GL_Color(1, 1, 1, 1);
- GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
+ GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
if (transparent)
{
qglDepthFunc(GL_LEQUAL);CHECKGLERROR
R_Mesh_TexBind(9, R_GetTexture(r_texture_black)); // glow
//R_Mesh_TexMatrix(3, r_shadow_entitytolight); // light filter matrix
GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
- GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 0);
+ GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 0);
CHECKGLERROR
}
}
GL_BlendFunc(GL_ONE, GL_ONE);
GL_DepthMask(false);
GL_DepthTest(!r_showdisabledepthtest.integer);
- qglPolygonOffset(r_polygonfactor, r_polygonoffset);CHECKGLERROR
+ qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
GL_Color(0.0, 0.0125, 0.1, 1);
- GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
+ GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
qglDepthFunc(GL_GEQUAL);CHECKGLERROR
qglCullFace(GL_FRONT);CHECKGLERROR // this culls back
qglDisable(GL_CULL_FACE);CHECKGLERROR
GL_BlendFunc(GL_ONE, GL_ONE);
GL_DepthMask(false);
GL_DepthTest(!r_showdisabledepthtest.integer);
- qglPolygonOffset(r_polygonfactor, r_polygonoffset);CHECKGLERROR
+ qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
GL_Color(0.1, 0.0125, 0, 1);
- GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
+ GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
if (transparent)
{
qglDepthFunc(GL_LEQUAL);CHECKGLERROR
GL_BlendFunc(GL_ONE, GL_ZERO);
GL_DepthMask(true);
GL_DepthTest(true);
- qglPolygonOffset(r_polygonfactor, r_polygonoffset);CHECKGLERROR
+ qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
//qglDisable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
GL_Color(1, 1, 1, 1);
- GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
- GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
+ GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
+ GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
qglDepthFunc(GL_LEQUAL);CHECKGLERROR
qglCullFace(GL_FRONT);CHECKGLERROR // quake is backwards, this culls back faces
qglEnable(GL_CULL_FACE);CHECKGLERROR
float vertex3f[256*3];
// if view is inside the light box, just say yes it's visible
- if (BoxesOverlap(r_vieworigin, r_vieworigin, mins, maxs))
+ if (BoxesOverlap(r_view.origin, r_view.origin, mins, maxs))
{
- GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
+ GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
return false;
}
// create a temporary brush describing the area the light can affect in worldspace
- VectorNegate(frustum[0].normal, planes[ 0].normal);planes[ 0].dist = -frustum[0].dist;
- VectorNegate(frustum[1].normal, planes[ 1].normal);planes[ 1].dist = -frustum[1].dist;
- VectorNegate(frustum[2].normal, planes[ 2].normal);planes[ 2].dist = -frustum[2].dist;
- VectorNegate(frustum[3].normal, planes[ 3].normal);planes[ 3].dist = -frustum[3].dist;
- VectorNegate(frustum[4].normal, planes[ 4].normal);planes[ 4].dist = -frustum[4].dist;
+ VectorNegate(r_view.frustum[0].normal, planes[ 0].normal);planes[ 0].dist = -r_view.frustum[0].dist;
+ VectorNegate(r_view.frustum[1].normal, planes[ 1].normal);planes[ 1].dist = -r_view.frustum[1].dist;
+ VectorNegate(r_view.frustum[2].normal, planes[ 2].normal);planes[ 2].dist = -r_view.frustum[2].dist;
+ VectorNegate(r_view.frustum[3].normal, planes[ 3].normal);planes[ 3].dist = -r_view.frustum[3].dist;
+ VectorNegate(r_view.frustum[4].normal, planes[ 4].normal);planes[ 4].dist = -r_view.frustum[4].dist;
VectorSet (planes[ 5].normal, 1, 0, 0); planes[ 5].dist = maxs[0];
VectorSet (planes[ 6].normal, -1, 0, 0); planes[ 6].dist = -mins[0];
VectorSet (planes[ 7].normal, 0, 1, 0); planes[ 7].dist = maxs[1];
//Con_Printf("%f %f %f %f\n", x1, y1, x2, y2);
// clamp it to the screen
- if (ix1 < r_view_x) ix1 = r_view_x;
- if (iy1 < r_view_y) iy1 = r_view_y;
- if (ix2 > r_view_x + r_view_width) ix2 = r_view_x + r_view_width;
- if (iy2 > r_view_y + r_view_height) iy2 = r_view_y + r_view_height;
+ if (ix1 < r_view.x) ix1 = r_view.x;
+ if (iy1 < r_view.y) iy1 = r_view.y;
+ if (ix2 > r_view.x + r_view.width) ix2 = r_view.x + r_view.width;
+ if (iy2 > r_view.y + r_view.height) iy2 = r_view.y + r_view.height;
// if it is inside out, it's not visible
if (ix2 <= ix1 || iy2 <= iy1)
GL_Scissor(ix1, vid.height - iy2, ix2 - ix1, iy2 - iy1);
//qglScissor(ix1, iy1, ix2 - ix1, iy2 - iy1);CHECKGLERROR
//qglEnable(GL_SCISSOR_TEST);CHECKGLERROR
- renderstats.lights_scissored++;
+ r_refdef.stats.lights_scissored++;
return false;
}
color4f[0] = (ambientcolor[0] + shadeintensity * diffusecolor[0]);
color4f[1] = (ambientcolor[1] + shadeintensity * diffusecolor[1]);
color4f[2] = (ambientcolor[2] + shadeintensity * diffusecolor[2]);
- if (fogenabled)
+ if (r_refdef.fogenabled)
{
float f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
VectorScale(color4f, f, color4f);
color4f[1] = ambientcolor[1] * distintensity;
color4f[2] = ambientcolor[2] * distintensity;
}
- if (fogenabled)
+ if (r_refdef.fogenabled)
{
float f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
VectorScale(color4f, f, color4f);
color4f[1] = ambientcolor[1] * distintensity;
color4f[2] = ambientcolor[2] * distintensity;
}
- if (fogenabled)
+ if (r_refdef.fogenabled)
{
float f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
VectorScale(color4f, f, color4f);
{
// shared final code for all the dot3 layers
int renders;
- GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 0);
+ GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 0);
for (renders = 0;renders < 64 && (r > 0 || g > 0 || b > 0);renders++, r--, g--, b--)
{
GL_Color(bound(0, r, 1), bound(0, g, 1), bound(0, b, 1), 1);
CHECKGLERROR
for (mesh = r_shadow_rtlight->static_meshchain_shadow;mesh;mesh = mesh->next)
{
- renderstats.lights_shadowtriangles += mesh->numtriangles;
+ r_refdef.stats.lights_shadowtriangles += mesh->numtriangles;
R_Mesh_VertexPointer(mesh->vertex3f);
GL_LockArrays(0, mesh->numverts);
if (r_shadow_rendermode == R_SHADOW_RENDERMODE_STENCIL)
if (numleafs)
{
for (i = 0;i < numleafs;i++)
- if (r_worldleafvisible[leaflist[i]])
+ if (r_viewcache.world_leafvisible[leaflist[i]])
break;
if (i == numleafs)
return;
// about the VectorDistance2 - light emitting entities should not cast their own shadow
if ((ent->flags & RENDER_SHADOW) && model->DrawShadowVolume && VectorDistance2(ent->origin, rtlight->shadoworigin) > 0.1)
shadowentities[numshadowentities++] = ent;
- if (ent->visframe == r_framecount && (ent->flags & RENDER_LIGHT) && model->DrawLight)
+ if (r_viewcache.entityvisible[i] && (ent->flags & RENDER_LIGHT) && model->DrawLight)
lightentities[numlightentities++] = ent;
}
}
// make this the active rtlight for rendering purposes
R_Shadow_RenderMode_ActiveLight(rtlight);
// count this light in the r_speeds
- renderstats.lights++;
+ r_refdef.stats.lights++;
usestencil = false;
- if (numshadowentities && rtlight->shadow && (rtlight->isstatic ? r_rtworldshadows : r_rtdlightshadows))
+ if (numshadowentities && rtlight->shadow && (rtlight->isstatic ? r_refdef.rtworldshadows : r_refdef.rtdlightshadows))
{
// draw stencil shadow volumes to mask off pixels that are in shadow
// so that they won't receive lighting
R_Shadow_RenderMode_Begin();
- flag = r_rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE;
+ flag = r_refdef.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE;
if (r_shadow_debuglight.integer >= 0)
{
for (lnum = 0, light = r_shadow_worldlightchain;light;lnum++, light = light->next)
for (lnum = 0, light = r_shadow_worldlightchain;light;lnum++, light = light->next)
if (light->flags & flag)
R_DrawRTLight(&light->rtlight, visible);
- if (r_rtdlight)
+ if (r_refdef.rtdlight)
for (lnum = 0;lnum < r_refdef.numlights;lnum++)
R_DrawRTLight(&r_refdef.lights[lnum]->rtlight, visible);
{
// this is never batched (there can be only one)
float scale = r_editlights_cursorgrid.value * 0.5f;
- R_DrawSprite(GL_SRC_ALPHA, GL_ONE, r_crosshairs[1]->tex, NULL, false, r_editlights_cursorlocation, r_viewright, r_viewup, scale, -scale, -scale, scale, 1, 1, 1, 0.5f);
+ R_DrawSprite(GL_SRC_ALPHA, GL_ONE, r_crosshairs[1]->tex, NULL, false, r_editlights_cursorlocation, r_view.right, r_view.up, scale, -scale, -scale, scale, 1, 1, 1, 0.5f);
}
void R_Shadow_DrawLightSprite_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
intensity = 0.75 + 0.25 * sin(realtime * M_PI * 4.0);
if (!light->shadow)
intensity *= 0.5f;
- R_DrawSprite(GL_SRC_ALPHA, GL_ONE, r_crosshairs[surfacelist[0]]->tex, NULL, false, light->origin, r_viewright, r_viewup, 8, -8, -8, 8, intensity, intensity, intensity, 0.5);
+ R_DrawSprite(GL_SRC_ALPHA, GL_ONE, r_crosshairs[surfacelist[0]]->tex, NULL, false, light->origin, r_view.right, r_view.up, 8, -8, -8, 8, intensity, intensity, intensity, 0.5);
}
void R_Shadow_DrawLightSprites(void)
bestrating = 0;
for (light = r_shadow_worldlightchain;light;light = light->next)
{
- VectorSubtract(light->origin, r_vieworigin, temp);
- rating = (DotProduct(temp, r_viewforward) / sqrt(DotProduct(temp, temp)));
+ VectorSubtract(light->origin, r_view.origin, temp);
+ rating = (DotProduct(temp, r_view.forward) / sqrt(DotProduct(temp, temp)));
if (rating >= 0.95)
{
rating /= (1 + 0.0625f * sqrt(DotProduct(temp, temp)));
- if (bestrating < rating && CL_TraceBox(light->origin, vec3_origin, vec3_origin, r_vieworigin, true, NULL, SUPERCONTENTS_SOLID, false).fraction == 1.0f)
+ if (bestrating < rating && CL_TraceBox(light->origin, vec3_origin, vec3_origin, r_view.origin, true, NULL, SUPERCONTENTS_SOLID, false).fraction == 1.0f)
{
bestrating = rating;
best = light;
vec_t dist, push;
vec3_t dest, endpos;
trace_t trace;
- VectorMA(r_vieworigin, r_editlights_cursordistance.value, r_viewforward, dest);
- trace = CL_TraceBox(r_vieworigin, vec3_origin, vec3_origin, dest, true, NULL, SUPERCONTENTS_SOLID, false);
+ VectorMA(r_view.origin, r_editlights_cursordistance.value, r_view.forward, dest);
+ trace = CL_TraceBox(r_view.origin, vec3_origin, vec3_origin, dest, true, NULL, SUPERCONTENTS_SOLID, false);
if (trace.fraction < 1)
{
dist = trace.fraction * r_editlights_cursordistance.value;
if (push > dist)
push = dist;
push = -push;
- VectorMA(trace.endpos, push, r_viewforward, endpos);
+ VectorMA(trace.endpos, push, r_view.forward, endpos);
VectorMA(endpos, r_editlights_cursorpushoff.value, trace.plane.normal, endpos);
}
else
skyrendersphere = false;
skyrenderbox = false;
skyrendermasked = false;
- if (r_sky.integer && !fogenabled)
+ if (r_sky.integer && !r_refdef.fogenabled)
{
if (skyboxside[0] || skyboxside[1] || skyboxside[2] || skyboxside[3] || skyboxside[4] || skyboxside[5])
skyrenderbox = true;
matrix4x4_t skymatrix;
if (skyrendermasked)
{
- Matrix4x4_CreateTranslate(&skymatrix, r_vieworigin[0], r_vieworigin[1], r_vieworigin[2]);
+ Matrix4x4_CreateTranslate(&skymatrix, r_view.origin[0], r_view.origin[1], r_view.origin[2]);
R_Mesh_Matrix(&skymatrix);
if (skyrendersphere)
{
float scale;
// nudge it toward the view to make sure it isn't in a wall
- org[0] = ent->matrix.m[0][3] - r_viewforward[0];
- org[1] = ent->matrix.m[1][3] - r_viewforward[1];
- org[2] = ent->matrix.m[2][3] - r_viewforward[2];
+ org[0] = ent->matrix.m[0][3] - r_view.forward[0];
+ org[1] = ent->matrix.m[1][3] - r_view.forward[1];
+ org[2] = ent->matrix.m[2][3] - r_view.forward[2];
switch(model->sprite.sprnum_type)
{
case SPR_VP_PARALLEL_UPRIGHT:
// flames and such
// vertical beam sprite, faces view plane
- scale = ent->scale / sqrt(r_viewforward[0]*r_viewforward[0]+r_viewforward[1]*r_viewforward[1]);
- left[0] = -r_viewforward[1] * scale;
- left[1] = r_viewforward[0] * scale;
+ scale = ent->scale / sqrt(r_view.forward[0]*r_view.forward[0]+r_view.forward[1]*r_view.forward[1]);
+ left[0] = -r_view.forward[1] * scale;
+ left[1] = r_view.forward[0] * scale;
left[2] = 0;
up[0] = 0;
up[1] = 0;
case SPR_FACING_UPRIGHT:
// flames and such
// vertical beam sprite, faces viewer's origin (not the view plane)
- scale = ent->scale / sqrt((org[0] - r_vieworigin[0])*(org[0] - r_vieworigin[0])+(org[1] - r_vieworigin[1])*(org[1] - r_vieworigin[1]));
- left[0] = (org[1] - r_vieworigin[1]) * scale;
- left[1] = -(org[0] - r_vieworigin[0]) * scale;
+ scale = ent->scale / sqrt((org[0] - r_view.origin[0])*(org[0] - r_view.origin[0])+(org[1] - r_view.origin[1])*(org[1] - r_view.origin[1]));
+ left[0] = (org[1] - r_view.origin[1]) * scale;
+ left[1] = -(org[0] - r_view.origin[0]) * scale;
left[2] = 0;
up[0] = 0;
up[1] = 0;
case SPR_VP_PARALLEL:
// normal sprite
// faces view plane
- left[0] = r_viewleft[0] * ent->scale;
- left[1] = r_viewleft[1] * ent->scale;
- left[2] = r_viewleft[2] * ent->scale;
- up[0] = r_viewup[0] * ent->scale;
- up[1] = r_viewup[1] * ent->scale;
- up[2] = r_viewup[2] * ent->scale;
+ left[0] = r_view.left[0] * ent->scale;
+ left[1] = r_view.left[1] * ent->scale;
+ left[2] = r_view.left[2] * ent->scale;
+ up[0] = r_view.up[0] * ent->scale;
+ up[1] = r_view.up[1] * ent->scale;
+ up[2] = r_view.up[2] * ent->scale;
break;
case SPR_ORIENTED:
// bullet marks on walls
// I have no idea what people would use this for...
// oriented relative to view space
// FIXME: test this and make sure it mimicks software
- left[0] = ent->matrix.m[0][1] * r_viewforward[0] + ent->matrix.m[1][1] * r_viewleft[0] + ent->matrix.m[2][1] * r_viewup[0];
- left[1] = ent->matrix.m[0][1] * r_viewforward[1] + ent->matrix.m[1][1] * r_viewleft[1] + ent->matrix.m[2][1] * r_viewup[1];
- left[2] = ent->matrix.m[0][1] * r_viewforward[2] + ent->matrix.m[1][1] * r_viewleft[2] + ent->matrix.m[2][1] * r_viewup[2];
- up[0] = ent->matrix.m[0][2] * r_viewforward[0] + ent->matrix.m[1][2] * r_viewleft[0] + ent->matrix.m[2][2] * r_viewup[0];
- up[1] = ent->matrix.m[0][2] * r_viewforward[1] + ent->matrix.m[1][2] * r_viewleft[1] + ent->matrix.m[2][2] * r_viewup[1];
- up[2] = ent->matrix.m[0][2] * r_viewforward[2] + ent->matrix.m[1][2] * r_viewleft[2] + ent->matrix.m[2][2] * r_viewup[2];
+ left[0] = ent->matrix.m[0][1] * r_view.forward[0] + ent->matrix.m[1][1] * r_view.left[0] + ent->matrix.m[2][1] * r_view.up[0];
+ left[1] = ent->matrix.m[0][1] * r_view.forward[1] + ent->matrix.m[1][1] * r_view.left[1] + ent->matrix.m[2][1] * r_view.up[1];
+ left[2] = ent->matrix.m[0][1] * r_view.forward[2] + ent->matrix.m[1][1] * r_view.left[2] + ent->matrix.m[2][1] * r_view.up[2];
+ up[0] = ent->matrix.m[0][2] * r_view.forward[0] + ent->matrix.m[1][2] * r_view.left[0] + ent->matrix.m[2][2] * r_view.up[0];
+ up[1] = ent->matrix.m[0][2] * r_view.forward[1] + ent->matrix.m[1][2] * r_view.left[1] + ent->matrix.m[2][2] * r_view.up[1];
+ up[2] = ent->matrix.m[0][2] * r_view.forward[2] + ent->matrix.m[1][2] * r_view.left[2] + ent->matrix.m[2][2] * r_view.up[2];
break;
}
if (ent->frameblend[0].frame < 0)
return;
- R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_Model_Sprite_Draw_TransparentCallback, ent, 0, r_shadow_rtlight);
+ R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : ent->origin, R_Model_Sprite_Draw_TransparentCallback, ent, 0, r_shadow_rtlight);
}
#ifndef RENDER_H
#define RENDER_H
-// flag arrays used for visibility checking on world model
-// (all other entities have no per-surface/per-leaf visibility checks)
-// TODO: dynamic resize according to r_refdef.worldmodel->brush.num_clusters
-extern unsigned char r_pvsbits[(32768+7)>>3];
-// TODO: dynamic resize according to r_refdef.worldmodel->brush.num_leafs
-extern unsigned char r_worldleafvisible[32768];
-// TODO: dynamic resize according to r_refdef.worldmodel->num_surfaces
-extern unsigned char r_worldsurfacevisible[262144];
-// if true, the view is currently in a leaf without pvs data
-extern qboolean r_worldnovis;
-
// 1.0f / N table
extern float ixtable[4096];
-// far clip distance for scene
-extern float r_farclip;
-
// fog stuff
extern void FOG_clear(void);
-extern float fog_density, fog_red, fog_green, fog_blue;
// sky stuff
extern cvar_t r_sky;
//=============================================================================
-extern int r_framecount;
-extern mplane_t frustum[5];
-
-typedef struct renderstats_s
-{
- int entities;
- int entities_surfaces;
- int entities_triangles;
- int world_leafs;
- int world_portals;
- int particles;
- int meshes;
- int meshes_elements;
- int lights;
- int lights_clears;
- int lights_scissored;
- int lights_lighttriangles;
- int lights_shadowtriangles;
- int lights_dynamicshadowtriangles;
- int bloom;
- int bloom_copypixels;
- int bloom_drawpixels;
-}
-renderstats_t;
-
-extern renderstats_t renderstats;
-
-// brightness of world lightmaps and related lighting
-// (often reduced when world rtlights are enabled)
-extern float r_lightmapintensity;
-// whether to draw world lights realtime, dlights realtime, and their shadows
-extern qboolean r_rtworld;
-extern qboolean r_rtworldshadows;
-extern qboolean r_rtdlight;
-extern qboolean r_rtdlightshadows;
-
extern cvar_t r_nearclip;
// forces all rendering to draw triangle outlines
//
// view origin
//
-extern vec3_t r_vieworigin;
-extern vec3_t r_viewforward;
-extern vec3_t r_viewleft;
-extern vec3_t r_viewright;
-extern vec3_t r_viewup;
-extern int r_view_x;
-extern int r_view_y;
-extern int r_view_z;
-extern int r_view_width;
-extern int r_view_height;
-extern int r_view_depth;
-extern matrix4x4_t r_view_matrix;
-extern float r_polygonfactor;
-extern float r_polygonoffset;
-extern float r_shadowpolygonfactor;
-extern float r_shadowpolygonoffset;
-
-extern mleaf_t *r_viewleaf, *r_oldviewleaf;
-
-extern qboolean envmap;
-
extern cvar_t r_drawentities;
extern cvar_t r_drawviewmodel;
extern cvar_t r_speeds;
extern cvar_t r_dynamic;
void R_Init(void);
-void R_UpdateWorld(void); // needs no r_refdef
-void R_RenderView(void); // must call R_UpdateWorld and set r_refdef first
+void R_UpdateVariables(void); // must call after setting up most of r_refdef, but before calling R_RenderView
+void R_RenderView(void); // must set r_refdef and call R_UpdateVariables first
void R_InitSky (unsigned char *src, int bytesperpixel); // called at level load
-void R_WorldVisibility();
+void R_View_WorldVisibility();
void R_DrawParticles(void);
void R_DrawExplosions(void);
int R_CullBox(const vec3_t mins, const vec3_t maxs);
-#define FOGTABLEWIDTH 1024
-extern vec3_t fogcolor;
-extern vec_t fogdensity;
-extern vec_t fogrange;
-extern vec_t fograngerecip;
-extern int fogtableindex;
-extern vec_t fogtabledistmultiplier;
-extern float fogtable[FOGTABLEWIDTH];
-extern qboolean fogenabled;
-#define VERTEXFOGTABLE(dist) (fogtableindex = (int)((dist) * fogtabledistmultiplier), fogtable[bound(0, fogtableindex, FOGTABLEWIDTH - 1)])
-
#include "r_modules.h"
#include "meshqueue.h"
return;
VectorClear(gunorg);
viewmodelmatrix = identitymatrix;
- r_refdef.viewentitymatrix = identitymatrix;
+ r_view.matrix = identitymatrix;
if (cls.state == ca_connected && cls.signon == SIGNONS)
{
// ent is the view entity (visible when out of body)
{
// entity is a fixed camera, just copy the matrix
if (cls.protocol == PROTOCOL_QUAKEWORLD)
- Matrix4x4_CreateFromQuakeEntity(&r_refdef.viewentitymatrix, cl.qw_intermission_origin[0], cl.qw_intermission_origin[1], cl.qw_intermission_origin[2], cl.qw_intermission_angles[0], cl.qw_intermission_angles[1], cl.qw_intermission_angles[2], 1);
+ Matrix4x4_CreateFromQuakeEntity(&r_view.matrix, cl.qw_intermission_origin[0], cl.qw_intermission_origin[1], cl.qw_intermission_origin[2], cl.qw_intermission_angles[0], cl.qw_intermission_angles[1], cl.qw_intermission_angles[2], 1);
else
{
- r_refdef.viewentitymatrix = ent->render.matrix;
- r_refdef.viewentitymatrix.m[2][3] += cl.stats[STAT_VIEWHEIGHT];
+ r_view.matrix = ent->render.matrix;
+ r_view.matrix.m[2][3] += cl.stats[STAT_VIEWHEIGHT];
}
- viewmodelmatrix = r_refdef.viewentitymatrix;
+ viewmodelmatrix = r_view.matrix;
}
else
{
}
// calculate a view matrix for rendering the scene
if (v_idlescale.value)
- Matrix4x4_CreateFromQuakeEntity(&r_refdef.viewentitymatrix, vieworg[0], vieworg[1], vieworg[2], viewangles[0] + v_idlescale.value * sin(cl.time*v_ipitch_cycle.value) * v_ipitch_level.value, viewangles[1] + v_idlescale.value * sin(cl.time*v_iyaw_cycle.value) * v_iyaw_level.value, viewangles[2] + v_idlescale.value * sin(cl.time*v_iroll_cycle.value) * v_iroll_level.value, 1);
+ Matrix4x4_CreateFromQuakeEntity(&r_view.matrix, vieworg[0], vieworg[1], vieworg[2], viewangles[0] + v_idlescale.value * sin(cl.time*v_ipitch_cycle.value) * v_ipitch_level.value, viewangles[1] + v_idlescale.value * sin(cl.time*v_iyaw_cycle.value) * v_iyaw_level.value, viewangles[2] + v_idlescale.value * sin(cl.time*v_iroll_cycle.value) * v_iroll_level.value, 1);
else
- Matrix4x4_CreateFromQuakeEntity(&r_refdef.viewentitymatrix, vieworg[0], vieworg[1], vieworg[2], viewangles[0], viewangles[1], viewangles[2] + v_idlescale.value * sin(cl.time*v_iroll_cycle.value) * v_iroll_level.value, 1);
+ Matrix4x4_CreateFromQuakeEntity(&r_view.matrix, vieworg[0], vieworg[1], vieworg[2], viewangles[0], viewangles[1], viewangles[2] + v_idlescale.value * sin(cl.time*v_iroll_cycle.value) * v_iroll_level.value, 1);
// calculate a viewmodel matrix for use in view-attached entities
Matrix4x4_CreateFromQuakeEntity(&viewmodelmatrix, gunorg[0], gunorg[1], gunorg[2], viewangles[0], viewangles[1], viewangles[2], 0.3);
VectorCopy(vieworg, csqc_origin);
// set contents color
int supercontents;
vec3_t vieworigin;
- Matrix4x4_OriginFromMatrix(&r_refdef.viewentitymatrix, vieworigin);
+ Matrix4x4_OriginFromMatrix(&r_view.matrix, vieworigin);
supercontents = CL_PointSuperContents(vieworigin);
if (supercontents & SUPERCONTENTS_LIQUIDSMASK)
{