From 544356c7bb6288760533142b8ab402f4d8d966ef Mon Sep 17 00:00:00 2001 From: havoc Date: Fri, 12 May 2006 08:11:46 +0000 Subject: [PATCH] reorganized a lot of renderer variables into r_refdef, and split some things out of r_refdef into r_view and r_viewcache, this reorganization brings DP closer to being able to render to textures git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@6368 d7cf8633-e32d-0410-b094-e92efae38249 --- cl_input.c | 8 +- cl_main.c | 16 +- cl_parse.c | 10 +- cl_particles.c | 22 +- cl_screen.c | 136 +++++---- client.h | 138 ++++++++- clvm_cmds.c | 39 +-- gl_backend.c | 10 +- gl_draw.c | 11 +- gl_rmain.c | 741 ++++++++++++++++++++----------------------------- gl_rsurf.c | 57 ++-- host.c | 11 +- meshqueue.c | 150 ++-------- meshqueue.h | 6 +- prvm_cmds.c | 2 +- r_crosshairs.c | 4 +- r_explosion.c | 11 +- r_light.c | 12 +- r_lightning.c | 8 +- r_shadow.c | 92 +++--- r_sky.c | 4 +- r_sprites.c | 44 +-- render.h | 89 +----- view.c | 16 +- 24 files changed, 706 insertions(+), 931 deletions(-) diff --git a/cl_input.c b/cl_input.c index 6235e25d..d9a06165 100644 --- a/cl_input.c +++ b/cl_input.c @@ -495,8 +495,8 @@ void CL_UpdatePrydonCursor(void) 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 @@ -505,9 +505,9 @@ void CL_UpdatePrydonCursor(void) // 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); } diff --git a/cl_main.c b/cl_main.c index 3cba5cb7..2c0c4ffe 100644 --- a/cl_main.c +++ b/cl_main.c @@ -850,7 +850,7 @@ void CL_LinkNetworkEntity(entity_t *e) 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) { @@ -1557,7 +1557,7 @@ int CL_ReadFromServer(void) 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) { @@ -1621,13 +1621,13 @@ static void CL_Fog_f (void) { 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)); } /* @@ -1649,7 +1649,7 @@ static void CL_TimeRefresh_f (void) 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; diff --git a/cl_parse.c b/cl_parse.c index ffa7274b..11688acc 100644 --- a/cl_parse.c +++ b/cl_parse.c @@ -341,15 +341,15 @@ void CL_ParseEntityLump(char *entdata) 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); } } diff --git a/cl_particles.c b/cl_particles.c index a957f103..30278b16 100644 --- a/cl_particles.c +++ b/cl_particles.c @@ -2069,18 +2069,18 @@ void R_DrawParticle_TransparentCallback(const entity_render_t *ent, const rtligh 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; @@ -2093,8 +2093,8 @@ void R_DrawParticle_TransparentCallback(const entity_render_t *ent, const rtligh 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]; @@ -2115,7 +2115,7 @@ void R_DrawParticle_TransparentCallback(const entity_render_t *ent, const rtligh 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); @@ -2223,15 +2223,15 @@ void R_DrawParticles (void) 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); } } diff --git a/cl_screen.c b/cl_screen.c index eccb767a..63a8e52f 100644 --- a/cl_screen.c +++ b/cl_screen.c @@ -464,15 +464,15 @@ void R_TimeReport_Frame(void) 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) { @@ -951,15 +951,19 @@ static void R_Envmap_f (void) 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); @@ -968,19 +972,19 @@ static void R_Envmap_f (void) 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; } //============================================================================= @@ -1114,9 +1118,9 @@ void R_ClearScreen(void) { // 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 { @@ -1157,6 +1161,8 @@ void SCR_DrawScreen (void) if (r_timereport_active) R_TimeReport("setup"); + R_UpdateVariables(); + if (cls.signon == SIGNONS) { float size; @@ -1166,19 +1172,23 @@ void SCR_DrawScreen (void) 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) @@ -1187,11 +1197,11 @@ void SCR_DrawScreen (void) // 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(); @@ -1202,16 +1212,18 @@ void SCR_DrawScreen (void) { 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(); @@ -1220,10 +1232,12 @@ void SCR_DrawScreen (void) 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 @@ -1380,9 +1394,9 @@ void CL_UpdateScreen(void) 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"); @@ -1405,40 +1419,40 @@ void CL_UpdateScreen(void) 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(); diff --git a/client.h b/client.h index 246d425e..02053f21 100644 --- a/client.h +++ b/client.h @@ -259,8 +259,6 @@ typedef struct entity_render_s // 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 @@ -1132,21 +1130,47 @@ void R_NewExplosion(const vec3_t org); #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]; @@ -1176,11 +1200,99 @@ typedef struct refdef_s // 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 diff --git a/clvm_cmds.c b/clvm_cmds.c index 59c34d5a..011de9b3 100644 --- a/clvm_cmds.c +++ b/clvm_cmds.c @@ -729,8 +729,8 @@ static void CSQC_R_RecalcView (void) { 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); } @@ -774,25 +774,28 @@ void VM_R_SetView (void) 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! @@ -886,8 +889,8 @@ void VM_CL_unproject (void) 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) @@ -899,9 +902,9 @@ void VM_CL_project (void) 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) diff --git a/gl_backend.c b/gl_backend.c index 414911f0..4bea75d7 100644 --- a/gl_backend.c +++ b/gl_backend.c @@ -735,9 +735,9 @@ void GL_TransformToScreen(const vec4_t in, vec4_t out) 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 @@ -889,8 +889,8 @@ void R_Mesh_Draw(int firstvertex, int numvertices, int numtriangles, const int * 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; diff --git a/gl_draw.c b/gl_draw.c index 38c65365..95f9e7bd 100644 --- a/gl_draw.c +++ b/gl_draw.c @@ -493,17 +493,10 @@ void GL_Draw_Init (void) 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); diff --git a/gl_rmain.c b/gl_rmain.c index 7e192157..6b1e3cd5 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -26,49 +26,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 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"}; @@ -140,6 +103,9 @@ r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_COUNT]; // 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; @@ -167,59 +133,6 @@ void R_FillColors(float *out, int verts, float r, float g, float b, float a) } } -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) { @@ -231,7 +144,7 @@ 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? @@ -257,7 +170,7 @@ void FOG_registercvars(void) 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); } } @@ -886,7 +799,7 @@ int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting) } if (specularscale > 0) permutation |= SHADERPERMUTATION_SPECULAR; - if (fogenabled) + if (r_refdef.fogenabled) permutation |= SHADERPERMUTATION_FOG; if (rsurface_texture->colormapping) permutation |= SHADERPERMUTATION_COLORMAPPING; @@ -946,8 +859,8 @@ int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting) 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)); @@ -965,7 +878,7 @@ int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting) 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) @@ -982,7 +895,7 @@ int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting) 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 @@ -1035,7 +948,6 @@ void gl_main_newmap(void) // 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)); @@ -1103,46 +1015,6 @@ void GL_Main_Init(void) 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); @@ -1162,7 +1034,6 @@ void Render_Init(void) { gl_backend_init(); R_Textures_Init(); - R_MeshQueue_Init(); GL_Main_Init(); GL_Draw_Init(); R_Shadow_Init(); @@ -1202,7 +1073,7 @@ int R_CullBox(const vec3_t mins, const vec3_t maxs) mplane_t *p; for (i = 0;i < 4;i++) { - p = frustum + i; + p = r_view.frustum + i; switch(p->signbits) { default: @@ -1257,15 +1128,15 @@ static void R_UpdateEntityLighting(entity_render_t *ent) 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; @@ -1273,23 +1144,14 @@ static void R_MarkEntities (void) 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 @@ -1298,15 +1160,7 @@ static void R_MarkEntities (void) 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); } } } @@ -1323,12 +1177,13 @@ int R_DrawBrushModelsSky (void) 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; } @@ -1344,138 +1199,148 @@ void R_DrawModels(void) 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; @@ -1512,7 +1377,7 @@ static void R_BlendView(void) { 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); @@ -1520,15 +1385,15 @@ static void R_BlendView(void) 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; @@ -1547,24 +1412,24 @@ static void R_BlendView(void) // 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 @@ -1572,8 +1437,8 @@ static void R_BlendView(void) 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; @@ -1599,14 +1464,14 @@ static void R_BlendView(void) 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 @@ -1633,16 +1498,16 @@ static void R_BlendView(void) 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); @@ -1659,14 +1524,14 @@ static void R_BlendView(void) 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) { @@ -1682,6 +1547,87 @@ void R_RenderScene(void); 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 @@ -1692,54 +1638,21 @@ void R_RenderView(void) 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) @@ -1756,60 +1669,27 @@ void CSQC_R_ClearScreen (void) 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"); @@ -1823,47 +1703,33 @@ extern void R_DrawLightningBeams (void); 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) { @@ -1924,6 +1790,8 @@ void R_RenderScene(void) R_TimeReport("explosions"); } + VM_AddPolygonsToMeshQueue(); + R_MeshQueue_RenderTransparent(); if (r_timereport_active) R_TimeReport("drawtrans"); @@ -1941,12 +1809,6 @@ void R_RenderScene(void) 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 (); @@ -1956,6 +1818,8 @@ void R_RenderScene(void) { qglUseProgramObjectARB(0);CHECKGLERROR } + qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR + qglDisable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR } /* @@ -1977,15 +1841,15 @@ void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, floa 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); @@ -2053,17 +1917,17 @@ void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight } 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; } } @@ -2083,7 +1947,7 @@ void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight 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); } @@ -2095,12 +1959,12 @@ void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, flo 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); @@ -2125,8 +1989,8 @@ void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, rtexture_ 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); @@ -2159,7 +2023,7 @@ void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, rtexture_ { 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); } } @@ -2365,12 +2229,12 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t) { 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); @@ -2386,7 +2250,7 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t) // 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); @@ -2405,7 +2269,7 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t) } 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. @@ -2418,7 +2282,7 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t) // 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); } } } @@ -2487,13 +2351,13 @@ qboolean rsurface_glsl_uselightmap; 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) @@ -2581,9 +2445,9 @@ void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generateta 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++) { @@ -2924,9 +2788,9 @@ static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **te // 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) @@ -2942,19 +2806,10 @@ static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **te // 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); } } @@ -3256,7 +3111,7 @@ static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **textur 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)) @@ -3340,7 +3195,7 @@ void R_QueueTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfa 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); } } } @@ -3397,7 +3252,7 @@ void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces) 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) { @@ -3462,7 +3317,7 @@ void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces) } 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) @@ -3477,14 +3332,14 @@ void R_DrawSurfaces(entity_render_t *ent, qboolean 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) @@ -3505,7 +3360,7 @@ void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces) 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) diff --git a/gl_rsurf.c b/gl_rsurf.c index a8448d6d..e02f0554 100644 --- a/gl_rsurf.c +++ b/gl_rsurf.c @@ -32,17 +32,6 @@ cvar_t r_lockvisibility = {0, "r_lockvisibility", "0", "disables visibility upda 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 @@ -381,7 +370,7 @@ static void R_DrawPortals(void) 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) @@ -401,7 +390,7 @@ static void R_DrawPortals(void) } } -void R_WorldVisibility(void) +void R_View_WorldVisibility(void) { int i, j, *mark; mleaf_t *leaf; @@ -412,18 +401,18 @@ void R_WorldVisibility(void) 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. @@ -432,17 +421,17 @@ void R_WorldVisibility(void) // 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; } } } @@ -457,13 +446,13 @@ void R_WorldVisibility(void) 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; } } } @@ -485,13 +474,13 @@ void R_WorldVisibility(void) 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) @@ -501,8 +490,8 @@ void R_WorldVisibility(void) // (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; } } @@ -824,7 +813,7 @@ static void R_Q1BSP_DrawLight_TransparentBatch(int batchnumsurfaces, msurface_t 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); } } @@ -848,10 +837,10 @@ void R_Q1BSP_DrawLight(entity_render_t *ent, int numsurfaces, const int *surface 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) diff --git a/host.c b/host.c index e0883aeb..0623c1ac 100644 --- a/host.c +++ b/host.c @@ -653,8 +653,15 @@ void Host_Main(void) // 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; @@ -786,7 +793,7 @@ void Host_Main(void) csqc_usecsqclistener = false; } else - S_Update(&r_refdef.viewentitymatrix); + S_Update(&r_view.matrix); CDAudio_Update(); } diff --git a/meshqueue.c b/meshqueue.c index 6b6ff076..f1d01edc 100644 --- a/meshqueue.c +++ b/meshqueue.c @@ -2,10 +2,6 @@ #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; @@ -19,108 +15,38 @@ meshqueue_t; 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); } @@ -137,8 +63,6 @@ void R_MeshQueue_RenderTransparent(void) 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)); @@ -182,43 +106,3 @@ void R_MeshQueue_RenderTransparent(void) 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(); - } -} - diff --git a/meshqueue.h b/meshqueue.h index be2e3f08..8e5b36e7 100644 --- a/meshqueue.h +++ b/meshqueue.h @@ -2,12 +2,8 @@ #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 diff --git a/prvm_cmds.c b/prvm_cmds.c index 0ea7436e..8533991a 100644 --- a/prvm_cmds.c +++ b/prvm_cmds.c @@ -3075,7 +3075,7 @@ void VM_AddPolygonsToMeshQueue (void) 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; } diff --git a/r_crosshairs.c b/r_crosshairs.c index e0fd5b2a..c47f34b2 100644 --- a/r_crosshairs.c +++ b/r_crosshairs.c @@ -80,14 +80,14 @@ void R_DrawWorldCrosshair(void) // 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) diff --git a/r_explosion.c b/r_explosion.c index a486f42d..6f2c36ec 100644 --- a/r_explosion.c +++ b/r_explosion.c @@ -151,7 +151,7 @@ void R_NewExplosion(const vec3_t org) 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; @@ -215,6 +215,11 @@ static void R_MoveExplosion(explosion_t *e) 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]) @@ -242,7 +247,7 @@ void R_MoveExplosions(void) { int i; for (i = 0;i < MAX_EXPLOSIONS;i++) - if (cl.time < explosion[i].endtime) + if (explosion[i].alpha) R_MoveExplosion(&explosion[i]); } @@ -253,7 +258,7 @@ void R_DrawExplosions(void) 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); } diff --git a/r_light.c b/r_light.c index ecab72ac..944988ec 100644 --- a/r_light.c +++ b/r_light.c @@ -80,21 +80,21 @@ void R_DrawCoronas(void) 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; @@ -103,7 +103,7 @@ void R_DrawCoronas(void) 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); } } } diff --git a/r_lightning.c b/r_lightning.c index 8bc56007..68f6b8f5 100644 --- a/r_lightning.c +++ b/r_lightning.c @@ -219,7 +219,7 @@ void R_FogLightningBeam_Vertex3f_Color4f(const float *v, float *c, int numverts, 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; @@ -246,7 +246,7 @@ void R_DrawLightningBeam_TransparentCallback(const entity_render_t *ent, const r r_lightningbeams_setuptexture(); R_Mesh_VertexPointer(vertex3f); - if (fogenabled) + if (r_refdef.fogenabled) { // per vertex colors if fog is used R_Mesh_ColorPointer(color4f); @@ -284,7 +284,7 @@ void R_DrawLightningBeam_TransparentCallback(const entity_render_t *ent, const r // 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); @@ -325,7 +325,7 @@ void R_DrawLightningBeam_TransparentCallback(const entity_render_t *ent, const r 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); diff --git a/r_shadow.c b/r_shadow.c index e1a736e4..5541bfd9 100644 --- a/r_shadow.c +++ b/r_shadow.c @@ -659,7 +659,7 @@ void R_Shadow_VolumeFromList(int numverts, int numtris, const float *invertex3f, 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); } @@ -708,7 +708,7 @@ void R_Shadow_RenderVolume(int numvertices, int numtriangles, const float *verte 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); @@ -825,7 +825,7 @@ void R_Shadow_RenderMode_Begin(void) 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; @@ -871,7 +871,7 @@ void R_Shadow_RenderMode_StencilShadowVolumes(void) 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 @@ -896,7 +896,7 @@ void R_Shadow_RenderMode_StencilShadowVolumes(void) 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) @@ -906,10 +906,10 @@ 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 @@ -949,7 +949,7 @@ void R_Shadow_RenderMode_Lighting(qboolean stenciltest, qboolean transparent) 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 } } @@ -961,9 +961,9 @@ void R_Shadow_RenderMode_VisibleShadowVolumes(void) 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 @@ -978,9 +978,9 @@ void R_Shadow_RenderMode_VisibleLighting(qboolean stenciltest, qboolean transpar 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 @@ -1010,11 +1010,11 @@ void R_Shadow_RenderMode_End(void) 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 @@ -1039,18 +1039,18 @@ qboolean R_Shadow_ScissorForBBox(const float *mins, const float *maxs) 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]; @@ -1102,10 +1102,10 @@ qboolean R_Shadow_ScissorForBBox(const float *mins, const float *maxs) //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) @@ -1115,7 +1115,7 @@ qboolean R_Shadow_ScissorForBBox(const float *mins, const float *maxs) 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; } @@ -1138,7 +1138,7 @@ static void R_Shadow_RenderSurfacesLighting_Light_Vertex_Shading(const msurface_ 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); @@ -1171,7 +1171,7 @@ static void R_Shadow_RenderSurfacesLighting_Light_Vertex_Shading(const msurface_ 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); @@ -1205,7 +1205,7 @@ static void R_Shadow_RenderSurfacesLighting_Light_Vertex_Shading(const msurface_ 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); @@ -1308,7 +1308,7 @@ static void R_Shadow_RenderSurfacesLighting_Light_Dot3_Finalize(int numsurfaces, { // 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); @@ -2204,7 +2204,7 @@ void R_Shadow_DrawEntityShadow(entity_render_t *ent, int numsurfaces, int *surfa 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) @@ -2348,7 +2348,7 @@ void R_DrawRTLight(rtlight_t *rtlight, qboolean visible) 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; @@ -2381,7 +2381,7 @@ void R_DrawRTLight(rtlight_t *rtlight, qboolean visible) // 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; } } @@ -2398,10 +2398,10 @@ void R_DrawRTLight(rtlight_t *rtlight, qboolean visible) // 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 @@ -2451,7 +2451,7 @@ void R_ShadowVolumeLighting(qboolean visible) 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) @@ -2462,7 +2462,7 @@ void R_ShadowVolumeLighting(qboolean visible) 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); @@ -2661,7 +2661,7 @@ void R_Shadow_DrawCursor_TransparentCallback(const entity_render_t *ent, const r { // 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) @@ -2675,7 +2675,7 @@ void R_Shadow_DrawLightSprite_TransparentCallback(const entity_render_t *ent, co 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) @@ -2696,12 +2696,12 @@ void R_Shadow_SelectLightInView(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; @@ -3127,8 +3127,8 @@ void R_Shadow_SetCursorLocationForView(void) 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; @@ -3136,7 +3136,7 @@ void R_Shadow_SetCursorLocationForView(void) 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 diff --git a/r_sky.c b/r_sky.c index a5053726..487ebb5c 100644 --- a/r_sky.c +++ b/r_sky.c @@ -56,7 +56,7 @@ void R_SkyStartFrame(void) 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; @@ -406,7 +406,7 @@ void R_Sky(void) 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) { diff --git a/r_sprites.c b/r_sprites.c index 02f7f2e1..5530a591 100644 --- a/r_sprites.c +++ b/r_sprites.c @@ -11,17 +11,17 @@ void R_Model_Sprite_Draw_TransparentCallback(const entity_render_t *ent, const r 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; @@ -30,9 +30,9 @@ void R_Model_Sprite_Draw_TransparentCallback(const entity_render_t *ent, const r 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; @@ -44,12 +44,12 @@ void R_Model_Sprite_Draw_TransparentCallback(const entity_render_t *ent, const r 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 @@ -65,12 +65,12 @@ void R_Model_Sprite_Draw_TransparentCallback(const entity_render_t *ent, const r // 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; } @@ -104,6 +104,6 @@ void R_Model_Sprite_Draw(entity_render_t *ent) 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); } diff --git a/render.h b/render.h index 0a092a04..5f22191d 100644 --- a/render.h +++ b/render.h @@ -21,26 +21,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #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; @@ -109,42 +94,6 @@ void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *plane //============================================================================= -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 @@ -160,27 +109,6 @@ extern cvar_t r_showdisabledepthtest; // // 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; @@ -189,13 +117,13 @@ extern cvar_t r_wateralpha; 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); @@ -204,17 +132,6 @@ 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" diff --git a/view.c b/view.c index b00c3443..dfcba088 100644 --- a/view.c +++ b/view.c @@ -327,7 +327,7 @@ void V_CalcRefdef (void) 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) @@ -355,13 +355,13 @@ void V_CalcRefdef (void) { // 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 { @@ -511,9 +511,9 @@ void V_CalcRefdef (void) } // 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); @@ -549,7 +549,7 @@ void V_CalcViewBlend(void) // 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) { -- 2.39.2