X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=gl_rmain.c;h=ebebd6c3eaea67dcbcb2adce069024d5e75e5ee0;hb=f1319d4e655eb486d830e0337d9b4e25bad79ee4;hp=4e76b8952358836ed90330d837a72b541a07dd79;hpb=f13419f00e3f8335e9a25498560a433597f28f50;p=xonotic%2Fdarkplaces.git diff --git a/gl_rmain.c b/gl_rmain.c index 4e76b895..ebebd6c3 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -256,6 +256,10 @@ cvar_t r_buffermegs[R_BUFFERDATA_COUNT] = {CF_CLIENT | CF_ARCHIVE, "r_buffermegs_uniform", "0.25", "uniform buffer size for one frame"}, }; +cvar_t r_q1bsp_lightmap_updates_enabled = {CF_CLIENT | CF_ARCHIVE, "r_q1bsp_lightmap_updates_enabled", "1", "allow lightmaps to be updated on Q1BSP maps (don't turn this off except for debugging)"}; +cvar_t r_q1bsp_lightmap_updates_combine = {CF_CLIENT | CF_ARCHIVE, "r_q1bsp_lightmap_updates_combine", "2", "combine lightmap texture updates to make fewer glTexSubImage2D calls, modes: 0 = immediately upload lightmaps (may be thousands of small 3x3 updates), 1 = combine to one call, 2 = combine to one full texture update (glTexImage2D) which tells the driver it does not need to lock the resource (faster on most drivers)"}; +cvar_t r_q1bsp_lightmap_updates_hidden_surfaces = {CF_CLIENT | CF_ARCHIVE, "r_q1bsp_lightmap_updates_hidden_surfaces", "0", "update lightmaps on surfaces that are not visible, so that updates only occur on frames where lightstyles changed value (animation or light switches), only makes sense with combine = 2"}; + extern cvar_t v_glslgamma_2d; extern qbool v_flipped_state; @@ -511,8 +515,8 @@ static void R_BuildFogTexture(void) } if (r_texture_fogattenuation) { - R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1); - //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1); + R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1, 0); + //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1, 0); } else { @@ -3409,6 +3413,9 @@ void GL_Main_Init(void) for (i = 0;i < R_BUFFERDATA_COUNT;i++) Cvar_RegisterVariable(&r_buffermegs[i]); Cvar_RegisterVariable(&r_batch_dynamicbuffer); + Cvar_RegisterVariable(&r_q1bsp_lightmap_updates_enabled); + Cvar_RegisterVariable(&r_q1bsp_lightmap_updates_combine); + Cvar_RegisterVariable(&r_q1bsp_lightmap_updates_hidden_surfaces); if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE) Cvar_SetValue(&cvars_all, "r_fullbrights", 0); #ifdef DP_MOBILETOUCH @@ -3851,7 +3858,7 @@ void R_AnimCache_ClearCache(void) qbool R_AnimCache_GetEntity(entity_render_t *ent, qbool wantnormals, qbool wanttangents) { - dp_model_t *model = ent->model; + model_t *model = ent->model; int numvertices; // see if this ent is worth caching @@ -3957,7 +3964,7 @@ qbool R_CanSeeBox(int numsamples, vec_t eyejitter, vec_t entboxenlarge, vec_t en vec3_t padmins, padmaxs; vec3_t start; vec3_t end; - dp_model_t *model = r_refdef.scene.worldmodel; + model_t *model = r_refdef.scene.worldmodel; static vec3_t positions[] = { { 0.5f, 0.5f, 0.5f }, { 0.0f, 0.0f, 0.0f }, @@ -4071,6 +4078,11 @@ static void R_View_UpdateEntityVisible (void) for (i = 0;i < r_refdef.scene.numentities;i++) { ent = r_refdef.scene.entities[i]; + if (r_refdef.viewcache.world_novis && !(ent->flags & RENDER_VIEWMODEL)) + { + r_refdef.viewcache.entityvisible[i] = false; + continue; + } if (!(ent->flags & renderimask)) if (!R_CullBox(ent->mins, ent->maxs) || (ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE))) if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_WORLDOBJECT | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs)) @@ -4139,17 +4151,7 @@ static void R_DrawModels(void) continue; ent = r_refdef.scene.entities[i]; r_refdef.stats[r_stat_entities]++; - /* - if (ent->model && !strncmp(ent->model->name, "models/proto_", 13)) - { - vec3_t f, l, u, o; - Matrix4x4_ToVectors(&ent->matrix, f, l, u, o); - Con_Printf("R_DrawModels\n"); - Con_Printf("model %s O %f %f %f F %f %f %f L %f %f %f U %f %f %f\n", ent->model->name, o[0], o[1], o[2], f[0], f[1], f[2], l[0], l[1], l[2], u[0], u[1], u[2]); - Con_Printf("group: %i %f %i %f %i %f %i %f\n", ent->framegroupblend[0].frame, ent->framegroupblend[0].lerp, ent->framegroupblend[1].frame, ent->framegroupblend[1].lerp, ent->framegroupblend[2].frame, ent->framegroupblend[2].lerp, ent->framegroupblend[3].frame, ent->framegroupblend[3].lerp); - Con_Printf("blend: %i %f %i %f %i %f %i %f %i %f %i %f %i %f %i %f\n", ent->frameblend[0].subframe, ent->frameblend[0].lerp, ent->frameblend[1].subframe, ent->frameblend[1].lerp, ent->frameblend[2].subframe, ent->frameblend[2].lerp, ent->frameblend[3].subframe, ent->frameblend[3].lerp, ent->frameblend[4].subframe, ent->frameblend[4].lerp, ent->frameblend[5].subframe, ent->frameblend[5].lerp, ent->frameblend[6].subframe, ent->frameblend[6].lerp, ent->frameblend[7].subframe, ent->frameblend[7].lerp); - } - */ + if (ent->model && ent->model->Draw != NULL) ent->model->Draw(ent); else @@ -5582,7 +5584,7 @@ void R_UpdateVariables(void) } if (r_texture_gammaramps) { - R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1); + R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1, 0); } else { @@ -6598,7 +6600,7 @@ texture_t *R_GetCurrentTexture(texture_t *t) { int i, q; const entity_render_t *ent = rsurface.entity; - dp_model_t *model = ent->model; // when calling this, ent must not be NULL + model_t *model = ent->model; // when calling this, ent must not be NULL q3shaderinfo_layer_tcmod_t *tcmod; float specularscale = 0.0f; @@ -6968,7 +6970,7 @@ rsurfacestate_t rsurface; void RSurf_ActiveModelEntity(const entity_render_t *ent, qbool wantnormals, qbool wanttangents, qbool prepass) { - dp_model_t *model = ent->model; + model_t *model = ent->model; //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents))) // return; rsurface.entity = (entity_render_t *)ent; @@ -9310,7 +9312,7 @@ static void R_DecalSystem_SplatEntity(entity_render_t *ent, const vec3_t worldor matrix4x4_t projection; decalsystem_t *decalsystem; qbool dynamic; - dp_model_t *model; + model_t *model; const msurface_t *surface; const msurface_t *surfaces; const int *surfacelist; @@ -9777,7 +9779,7 @@ static void R_DrawDebugModel(void) entity_render_t *ent = rsurface.entity; int i, j, flagsmask; const msurface_t *surface; - dp_model_t *model = ent->model; + model_t *model = ent->model; if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity) return; @@ -9994,8 +9996,8 @@ int r_maxsurfacelist = 0; const msurface_t **r_surfacelist = NULL; void R_DrawModelSurfaces(entity_render_t *ent, qbool skysurfaces, qbool writedepth, qbool depthonly, qbool debug, qbool prepass, qbool ui) { - int i, j, endj, flagsmask; - dp_model_t *model = ent->model; + int i, j, flagsmask; + model_t *model = ent->model; msurface_t *surfaces; unsigned char *update; int numsurfacelist = 0; @@ -10022,22 +10024,6 @@ void R_DrawModelSurfaces(entity_render_t *ent, qbool skysurfaces, qbool writedep surfaces = model->data_surfaces; update = model->brushq1.lightmapupdateflags; - // update light styles - if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.scene.lightmapintensity > 0) - { - model_brush_lightstyleinfo_t *style; - for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++) - { - if (style->value != r_refdef.scene.lightstylevalue[style->style]) - { - int *list = style->surfacelist; - style->value = r_refdef.scene.lightstylevalue[style->style]; - for (j = 0;j < style->numsurfaces;j++) - update[list[j]] = true; - } - } - } - flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL; if (debug) @@ -10047,12 +10033,17 @@ void R_DrawModelSurfaces(entity_render_t *ent, qbool skysurfaces, qbool writedep return; } + // check if this is an empty model + if (model->nummodelsurfaces == 0) + return; + rsurface.lightmaptexture = NULL; rsurface.deluxemaptexture = NULL; rsurface.uselightmaptexture = false; rsurface.texture = NULL; rsurface.rtlight = NULL; numsurfacelist = 0; + // add visible surfaces to draw list if (ent == r_refdef.scene.worldentity) { @@ -10063,10 +10054,17 @@ void R_DrawModelSurfaces(entity_render_t *ent, qbool skysurfaces, qbool writedep if (r_refdef.viewcache.world_surfacevisible[j]) r_surfacelist[numsurfacelist++] = surfaces + j; } + + // don't do anything if there were no surfaces added (none of the world entity is visible) + if (!numsurfacelist) + { + rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity + return; + } } else if (ui) { - // for ui we have to preserve the order of surfaces + // for ui we have to preserve the order of surfaces (not using sortedmodelsurfaces) for (i = 0; i < model->nummodelsurfaces; i++) r_surfacelist[numsurfacelist++] = surfaces + model->firstmodelsurface + i; } @@ -10076,25 +10074,41 @@ void R_DrawModelSurfaces(entity_render_t *ent, qbool skysurfaces, qbool writedep for (i = 0; i < model->nummodelsurfaces; i++) r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i]; } - // don't do anything if there were no surfaces - if (!numsurfacelist) - { - rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity - return; - } - // update lightmaps if needed - if (update) + + // mark lightmaps as dirty if their lightstyle's value changed + // we do this by using style chains because most styles do not change on most frames, + // and most surfaces do not have styles on them + // map packs like Arcane Dimensions (e.g. ad_sepulcher) break this rule and animate most surfaces + if (update && !skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.scene.lightmapintensity > 0 && r_q1bsp_lightmap_updates_enabled.integer) { - int updated = 0; - for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++) + model_brush_lightstyleinfo_t* style; + // for each lightstyle, check if its value changed and mark the lightmaps as dirty if so + for (i = 0, style = model->brushq1.data_lightstyleinfo; i < model->brushq1.num_lightstyles; i++, style++) { - // Update brush entities even if not visible otherwise they'll render solid black. - if (update[j] && (r_refdef.viewcache.world_surfacevisible[j] || ent != r_refdef.scene.worldentity)) + if (style->value != r_refdef.scene.lightstylevalue[style->style]) { - updated++; - R_BuildLightMap(ent, surfaces + j); + int* list = style->surfacelist; + style->value = r_refdef.scene.lightstylevalue[style->style]; + // value changed - mark the surfaces belonging to this style chain as dirty + for (j = 0; j < style->numsurfaces; j++) + update[list[j]] = true; } } + // now check if update flags are set on any surfaces that are visible + if (r_q1bsp_lightmap_updates_hidden_surfaces.integer) + { + // we can do less frequent texture uploads (approximately 10hz for animated lightstyles) by rebuilding lightmaps on surfaces that are not currently visible + // for optimal efficiency, this includes the submodels of the worldmodel, so we use model->num_surfaces, not nummodelsurfaces + for (i = 0; i < model->num_surfaces;i++) + if (update[i]) + R_BuildLightMap(ent, surfaces + i, r_q1bsp_lightmap_updates_combine.integer); + } + else + { + for (i = 0; i < numsurfacelist; i++) + if (update[r_surfacelist[i] - surfaces]) + R_BuildLightMap(ent, (msurface_t *)r_surfacelist[i], r_q1bsp_lightmap_updates_combine.integer); + } } R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass, ui); @@ -10112,7 +10126,7 @@ void R_DrawModelSurfaces(entity_render_t *ent, qbool skysurfaces, qbool writedep void R_DebugLine(vec3_t start, vec3_t end) { - dp_model_t *mod = CL_Mesh_UI(); + model_t *mod = CL_Mesh_UI(); msurface_t *surf; int e0, e1, e2, e3; float offsetx, offsety, x1, y1, x2, y2, width = 1.0f;