Small speedup...

This commit is contained in:
Shpoike 2024-03-01 08:09:56 +00:00
parent 169c47b30d
commit 3aa4ceb4f4
20 changed files with 1426 additions and 140 deletions

View file

@ -239,7 +239,7 @@ typedef struct texinfo_s
{ {
float vecs[2][4]; // [s/t][xyz offset] float vecs[2][4]; // [s/t][xyz offset]
int miptex; int miptex;
int flags; int flags; //TEX_SPECIAL
} texinfo_t; } texinfo_t;
#define TEX_SPECIAL 1 // sky or slime, no lightmap or 256 subdivision #define TEX_SPECIAL 1 // sky or slime, no lightmap or 256 subdivision
#define TEX_MISSING 2 // johnfitz -- this texinfo does not have a texture #define TEX_MISSING 2 // johnfitz -- this texinfo does not have a texture

View file

@ -255,7 +255,7 @@ void CL_Record_Prespawn(void)
//static ents //static ents
for (idx = 1; idx < cl.num_statics; idx++) for (idx = 1; idx < cl.num_statics; idx++)
{ {
MSG_WriteStaticOrBaseLine(&net_message, -1, &cl.static_entities[idx]->baseline, cl.protocol_pext2, cl.protocol, cl.protocolflags); MSG_WriteStaticOrBaseLine(&net_message, -1, &cl.static_entities[idx].ent->baseline, cl.protocol_pext2, cl.protocol, cl.protocolflags);
if (net_message.cursize > 4096) if (net_message.cursize > 4096)
{ //periodically flush so that large maps don't need larger than vanilla limits { //periodically flush so that large maps don't need larger than vanilla limits

View file

@ -78,8 +78,8 @@ void CL_ClearTrailStates(void)
int i; int i;
for (i = 0; i < cl.num_statics; i++) for (i = 0; i < cl.num_statics; i++)
{ {
PScript_DelinkTrailstate(&(cl.static_entities[i]->trailstate)); PScript_DelinkTrailstate(&(cl.static_entities[i].ent->trailstate));
PScript_DelinkTrailstate(&(cl.static_entities[i]->emitstate)); PScript_DelinkTrailstate(&(cl.static_entities[i].ent->emitstate));
} }
for (i = 0; i < cl.max_edicts; i++) for (i = 0; i < cl.max_edicts; i++)
{ {
@ -147,6 +147,8 @@ void CL_ClearState (void)
PScript_Shutdown(); PScript_Shutdown();
#endif #endif
RSceneCache_Shutdown();
if (!sv.active) if (!sv.active)
Draw_ReloadTextures(false); Draw_ReloadTextures(false);
} }
@ -1203,10 +1205,10 @@ qboolean CL_CheckDownloads(void)
//make sure ents have the correct models, now that they're actually loaded. //make sure ents have the correct models, now that they're actually loaded.
for (i = 0; i < cl.num_statics; i++) for (i = 0; i < cl.num_statics; i++)
{ {
if (cl.static_entities[i]->model) if (cl.static_entities[i].ent->model)
continue; continue;
cl.static_entities[i]->model = cl.model_precache[cl.static_entities[i]->netstate.modelindex]; cl.static_entities[i].ent->model = cl.model_precache[cl.static_entities[i].ent->netstate.modelindex];
R_AddEfrags (cl.static_entities[i]); CL_LinkStaticEnt(&cl.static_entities[i]);
} }
return true; return true;
} }

View file

@ -2005,16 +2005,16 @@ static void CL_ParseStatic (int version) //johnfitz -- added a parameter
if (i >= cl.max_static_entities) if (i >= cl.max_static_entities)
{ {
int ec = 64; int ec = 64;
entity_t **newstatics = realloc(cl.static_entities, sizeof(*newstatics) * (cl.max_static_entities+ec)); struct cl_static_entities_s *newstatics = realloc(cl.static_entities, sizeof(*newstatics) * (cl.max_static_entities+ec));
entity_t *newents = Hunk_Alloc(sizeof(*newents) * ec); entity_t *newents = Hunk_Alloc(sizeof(*newents) * ec);
if (!newstatics || !newents) if (!newstatics || !newents)
Host_Error ("Too many static entities"); Host_Error ("Too many static entities");
cl.static_entities = newstatics; cl.static_entities = newstatics;
while (ec--) while (ec--)
cl.static_entities[cl.max_static_entities++] = newents++; cl.static_entities[cl.max_static_entities++].ent = newents++;
} }
ent = cl.static_entities[i]; ent = cl.static_entities[i].ent;
cl.num_statics++; cl.num_statics++;
CL_ParseBaseline (ent, version); //johnfitz -- added second parameter CL_ParseBaseline (ent, version); //johnfitz -- added second parameter
@ -2034,8 +2034,7 @@ static void CL_ParseStatic (int version) //johnfitz -- added a parameter
ent->alpha = ent->baseline.alpha; //johnfitz -- alpha ent->alpha = ent->baseline.alpha; //johnfitz -- alpha
VectorCopy (ent->baseline.origin, ent->origin); VectorCopy (ent->baseline.origin, ent->origin);
VectorCopy (ent->baseline.angles, ent->angles); VectorCopy (ent->baseline.angles, ent->angles);
if (ent->model) CL_LinkStaticEnt(&cl.static_entities[i]);
R_AddEfrags (ent);
} }
/* /*

View file

@ -74,7 +74,7 @@ typedef struct
{ {
vec3_t origin; vec3_t origin;
float radius; float radius;
float die; // stop lighting after this time double die; // stop lighting after this time
float decay; // drop this each second float decay; // drop this each second
float minlight; // don't add when contributing less float minlight; // don't add when contributing less
int key; int key;
@ -249,7 +249,13 @@ typedef struct
int max_edicts; int max_edicts;
int num_entities; int num_entities;
entity_t **static_entities; //spike -- was static struct cl_static_entities_s
{
entity_t *ent;
unsigned int num_clusters;
int clusternums[MAX_ENT_LEAFS];
vec3_t absmin, absmax;
} *static_entities; //spike -- was static
int max_static_entities; int max_static_entities;
int num_statics; int num_statics;

View file

@ -247,6 +247,7 @@ void Mod_ClearAll (void)
mod->needload = true; mod->needload = true;
TexMgr_FreeTexturesForOwner (mod); //johnfitz TexMgr_FreeTexturesForOwner (mod); //johnfitz
PScript_ClearSurfaceParticles(mod); PScript_ClearSurfaceParticles(mod);
RSceneCache_Cleanup(mod);
} }
} }
} }
@ -265,6 +266,7 @@ void Mod_ResetAll (void)
{ {
TexMgr_FreeTexturesForOwner (mod); TexMgr_FreeTexturesForOwner (mod);
PScript_ClearSurfaceParticles(mod); PScript_ClearSurfaceParticles(mod);
RSceneCache_Cleanup(mod);
} }
memset(mod, 0, sizeof(qmodel_t)); memset(mod, 0, sizeof(qmodel_t));
} }
@ -1411,16 +1413,14 @@ static void Mod_LoadTexinfo (lump_t *l)
if (miptex >= loadmodel->numtextures-1 || !loadmodel->textures[miptex]) if (miptex >= loadmodel->numtextures-1 || !loadmodel->textures[miptex])
{ {
if (out->flags & TEX_SPECIAL) if (out->flags & TEX_SPECIAL)
out->texture = loadmodel->textures[loadmodel->numtextures-1]; miptex = loadmodel->numtextures-1;
else else
out->texture = loadmodel->textures[loadmodel->numtextures-2]; miptex = loadmodel->numtextures-2;
out->flags |= TEX_MISSING; out->flags |= TEX_MISSING;
missing++; missing++;
} }
else
{
out->texture = loadmodel->textures[miptex]; out->texture = loadmodel->textures[miptex];
} out->materialidx = miptex;
//johnfitz //johnfitz
} }
@ -2849,6 +2849,8 @@ visdone:
// set up the submodels (FIXME: this is confusing) // set up the submodels (FIXME: this is confusing)
// //
mod->submodelof = loadmodel;
// johnfitz -- okay, so that i stop getting confused every time i look at this loop, here's how it works: // johnfitz -- okay, so that i stop getting confused every time i look at this loop, here's how it works:
// we're looping through the submodels starting at 0. Submodel 0 is the main model, so we don't have to // we're looping through the submodels starting at 0. Submodel 0 is the main model, so we don't have to
// worry about clobbering data the first time through, since it's the same data. At the end of the loop, // worry about clobbering data the first time through, since it's the same data. At the end of the loop,
@ -2869,6 +2871,8 @@ visdone:
mod->firstmodelsurface = bm->firstface; mod->firstmodelsurface = bm->firstface;
mod->nummodelsurfaces = bm->numfaces; mod->nummodelsurfaces = bm->numfaces;
mod->submodelof = loadmodel->submodelof;
mod->submodelidx = i;
VectorCopy (bm->maxs, mod->maxs); VectorCopy (bm->maxs, mod->maxs);
VectorCopy (bm->mins, mod->mins); VectorCopy (bm->mins, mod->mins);

View file

@ -115,6 +115,7 @@ typedef struct
float vecs[2][4]; float vecs[2][4];
texture_t *texture; texture_t *texture;
int flags; int flags;
int materialidx;
} mtexinfo_t; } mtexinfo_t;
#define VERTEXSIZE 7 #define VERTEXSIZE 7
@ -495,6 +496,8 @@ typedef struct qmodel_s
int numsubmodels; int numsubmodels;
mmodel_t *submodels; mmodel_t *submodels;
struct qmodel_s *submodelof;
unsigned submodelidx;
int numplanes; int numplanes;
mplane_t *planes; mplane_t *planes;

View file

@ -165,7 +165,7 @@ void R_CheckEfrags (void)
R_AddEfrags R_AddEfrags
=========== ===========
*/ */
void R_AddEfrags (entity_t *ent) static void R_AddEfrags (entity_t *ent)
{ {
qmodel_t *entmodel; qmodel_t *entmodel;
float scale; float scale;
@ -266,3 +266,79 @@ void R_StoreEfrags (efrag_t **ppefrag)
} }
} }
static void R_FindTouchedLeafs (struct cl_static_entities_s *ent, mnode_t *node)
{
mplane_t *splitplane;
mleaf_t *leaf;
int sides;
int clusternum;
if (node->contents == CONTENTS_SOLID)
return;
// add an efrag if the node is a leaf
if ( node->contents < 0)
{
if (ent->num_clusters < MAX_ENT_LEAFS)
{
leaf = (mleaf_t *)node;
clusternum = (leaf - cl.worldmodel->leafs) - 1;
ent->clusternums[ent->num_clusters] = clusternum;
}
ent->num_clusters++;
return;
}
// NODE_MIXED
splitplane = node->plane;
sides = BOX_ON_PLANE_SIDE(ent->absmin, ent->absmax, splitplane);
// recurse down the contacted sides
if (sides & 1)
R_FindTouchedLeafs (ent, node->children[0]);
if (sides & 2)
R_FindTouchedLeafs (ent, node->children[1]);
}
void CL_LinkStaticEnt(struct cl_static_entities_s *ent)
{
ent->num_clusters = 0;
if (!ent->ent->model)
return;
//calc its bbox...
if (ent->ent->angles[0] || ent->ent->angles[1] || ent->ent->angles[2])
{ // expand for rotation the lame way. hopefully there's an origin brush in there.
int i;
float v1,v2;
vec3_t max;
//q2 method
for (i=0 ; i<3 ; i++)
{
v1 = fabs(ent->ent->model->mins[i]);
v2 = fabs(ent->ent->model->maxs[i]);
max[i] = q_max(v1,v2);
}
v1 = sqrt(DotProduct(max,max));
for (i=0 ; i<3 ; i++)
{
ent->absmin[i] = ent->ent->origin[i] - v1;
ent->absmax[i] = ent->ent->origin[i] + v1;
}
}
else
{ //simple
VectorAdd(ent->ent->origin, ent->ent->model->mins, ent->absmin);
VectorAdd(ent->ent->origin, ent->ent->model->maxs, ent->absmax);
}
//for scenecache
R_FindTouchedLeafs(ent, cl.worldmodel->nodes);
//legacy bloat for non-scenecache.
R_AddEfrags(ent->ent);
}

View file

@ -23,8 +23,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "quakedef.h" #include "quakedef.h"
int r_dlightframecount;
extern cvar_t r_flatlightstyles; //johnfitz extern cvar_t r_flatlightstyles; //johnfitz
//Spike - made this a general function //Spike - made this a general function
@ -162,8 +160,6 @@ void R_RenderDlights (void)
if (!gl_flashblend.value) if (!gl_flashblend.value)
return; return;
r_dlightframecount = r_framecount + 1; // because the count hasn't
// advanced yet for this frame
glDepthMask (0); glDepthMask (0);
glDisable (GL_TEXTURE_2D); glDisable (GL_TEXTURE_2D);
glShadeModel (GL_SMOOTH); glShadeModel (GL_SMOOTH);
@ -199,7 +195,7 @@ DYNAMIC LIGHTS
R_MarkLights -- johnfitz -- rewritten to use LordHavoc's lighting speedup R_MarkLights -- johnfitz -- rewritten to use LordHavoc's lighting speedup
============= =============
*/ */
void R_MarkLights (dlight_t *light, vec3_t lightorg, int num, mnode_t *node) void R_MarkLights (dlight_t *light, vec3_t lightorg, int framecount, int num, mnode_t *node)
{ {
mplane_t *splitplane; mplane_t *splitplane;
msurface_t *surf; msurface_t *surf;
@ -247,10 +243,10 @@ start:
// compare to minimum light // compare to minimum light
if ((s*s+t*t+dist*dist) < maxdist) if ((s*s+t*t+dist*dist) < maxdist)
{ {
if (surf->dlightframe != r_dlightframecount) // not dynamic until now if (surf->dlightframe != framecount) // not dynamic until now
{ {
surf->dlightbits[num >> 5] = 1U << (num & 31); surf->dlightbits[num >> 5] = 1U << (num & 31);
surf->dlightframe = r_dlightframecount; surf->dlightframe = framecount;
} }
else // already dynamic else // already dynamic
surf->dlightbits[num >> 5] |= 1U << (num & 31); surf->dlightbits[num >> 5] |= 1U << (num & 31);
@ -258,9 +254,9 @@ start:
} }
if (node->children[0]->contents >= 0) if (node->children[0]->contents >= 0)
R_MarkLights (light, lightorg, num, node->children[0]); R_MarkLights (light, lightorg, framecount, num, node->children[0]);
if (node->children[1]->contents >= 0) if (node->children[1]->contents >= 0)
R_MarkLights (light, lightorg, num, node->children[1]); R_MarkLights (light, lightorg, framecount, num, node->children[1]);
} }
/* /*
@ -275,9 +271,6 @@ void R_PushDlights (void)
if (gl_flashblend.value) if (gl_flashblend.value)
return; return;
r_dlightframecount = r_framecount + 1; // because the count hasn't
// advanced yet for this frame
if (!r_refdef.drawworld) if (!r_refdef.drawworld)
return; return;
l = cl_dlights; l = cl_dlights;
@ -286,7 +279,7 @@ void R_PushDlights (void)
{ {
if (l->die < cl.time || !l->radius) if (l->die < cl.time || !l->radius)
continue; continue;
R_MarkLights (l, l->origin, i, cl.worldmodel->nodes); R_MarkLights (l, l->origin, r_framecount, i, cl.worldmodel->nodes);
} }
} }

View file

@ -562,11 +562,11 @@ void R_SetupView (void)
int viewcontents; //spike -- rewrote this a little int viewcontents; //spike -- rewrote this a little
int i; int i;
// Need to do those early because we now update dynamic light maps during R_MarkSurfaces
R_PushDlights ();
R_AnimateLight ();
r_framecount++; r_framecount++;
// Need to do those early because we now update dynamic light maps during R_MarkSurfaces
R_AnimateLight ();
Fog_SetupFrame (); //johnfitz Fog_SetupFrame (); //johnfitz
// build the transformation matrix for the given view angles // build the transformation matrix for the given view angles
@ -993,9 +993,12 @@ void R_RenderScene (void)
Fog_EnableGFog (); //johnfitz Fog_EnableGFog (); //johnfitz
if (r_refdef.drawworld)
{
Sky_DrawSky (); //johnfitz Sky_DrawSky (); //johnfitz
R_DrawWorld (); R_DrawWorld ();
}
currententity = NULL; currententity = NULL;
S_ExtraUpdate (); // don't let sound get messed up if going slow S_ExtraUpdate (); // don't let sound get messed up if going slow

View file

@ -43,6 +43,7 @@ extern cvar_t r_lerpmove;
extern cvar_t r_nolerp_list; extern cvar_t r_nolerp_list;
extern cvar_t r_noshadow_list; extern cvar_t r_noshadow_list;
//johnfitz //johnfitz
extern cvar_t r_scenecache;
extern cvar_t gl_zfix; // QuakeSpasm z-fighting fix extern cvar_t gl_zfix; // QuakeSpasm z-fighting fix
cvar_t r_brokenturbbias = {"r_brokenturbbias", "1", CVAR_ARCHIVE}; //replicates QS's bug where it ignores texture coord offsets for water (breaking curved water volumes). we do NOT ignore scales though. cvar_t r_brokenturbbias = {"r_brokenturbbias", "1", CVAR_ARCHIVE}; //replicates QS's bug where it ignores texture coord offsets for water (breaking curved water volumes). we do NOT ignore scales though.
@ -222,6 +223,9 @@ void R_Init (void)
Cvar_RegisterVariable (&r_noshadow_list); Cvar_RegisterVariable (&r_noshadow_list);
Cvar_SetCallback (&r_noshadow_list, R_Model_ExtraFlags_List_f); Cvar_SetCallback (&r_noshadow_list, R_Model_ExtraFlags_List_f);
//johnfitz //johnfitz
//spike -- new cvars...
Cvar_RegisterVariable (&r_scenecache);
//spike
Cvar_RegisterVariable (&gl_zfix); // QuakeSpasm z-fighting fix Cvar_RegisterVariable (&gl_zfix); // QuakeSpasm z-fighting fix
Cvar_RegisterVariable (&r_lavaalpha); Cvar_RegisterVariable (&r_lavaalpha);

View file

@ -29,6 +29,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
float Fog_GetDensity(void); float Fog_GetDensity(void);
float *Fog_GetColor(void); float *Fog_GetColor(void);
#ifndef SDL_THREADS_DISABLED
qboolean RSceneCache_DrawSkySurfDepth(void); //Draws sky surfaces.
#endif
extern int rs_skypolys; // for r_speeds readout extern int rs_skypolys; // for r_speeds readout
extern int rs_skypasses; // for r_speeds readout extern int rs_skypasses; // for r_speeds readout
@ -123,7 +127,7 @@ void Sky_LoadTexture (qmodel_t *mod, texture_t *mt, enum srcformat fmt, unsigned
memcpy(back_data+bb*i*columns, src+bb*(i*columns*2 + columns), columns*bb); memcpy(back_data+bb*i*columns, src+bb*(i*columns*2 + columns), columns*bb);
q_snprintf(texturename, sizeof(texturename), "%s:%s_back", mod->name, mt->name); q_snprintf(texturename, sizeof(texturename), "%s:%s_back", mod->name, mt->name);
solidskytexture = TexMgr_LoadImage (mod, texturename, width, height, fmt, back_data, "", (src_offset_t)back_data, TEXPREF_NONE); mt->gltexture = solidskytexture = TexMgr_LoadImage (mod, texturename, width, height, fmt, back_data, "", (src_offset_t)back_data, TEXPREF_NONE);
// extract front layer and upload // extract front layer and upload
for (i=0 ; i<rows ; i++) for (i=0 ; i<rows ; i++)
@ -137,7 +141,7 @@ void Sky_LoadTexture (qmodel_t *mod, texture_t *mt, enum srcformat fmt, unsigned
} }
} }
q_snprintf(texturename, sizeof(texturename), "%s:%s_front", mod->name, mt->name); q_snprintf(texturename, sizeof(texturename), "%s:%s_front", mod->name, mt->name);
alphaskytexture = TexMgr_LoadImage (mod, texturename, width, height, fmt, front_data, "", (src_offset_t)front_data, TEXPREF_ALPHA); mt->fullbright = alphaskytexture = TexMgr_LoadImage (mod, texturename, width, height, fmt, front_data, "", (src_offset_t)front_data, TEXPREF_ALPHA);
// calculate r_fastsky color based on average of all opaque foreground colors, if we can. // calculate r_fastsky color based on average of all opaque foreground colors, if we can.
r = g = b = count = 0; r = g = b = count = 0;
@ -190,7 +194,7 @@ void Sky_LoadTextureQ64 (qmodel_t *mod, texture_t *mt)
// Normal indexed texture for the back layer // Normal indexed texture for the back layer
q_snprintf(texturename, sizeof(texturename), "%s:%s_back", mod->name, mt->name); q_snprintf(texturename, sizeof(texturename), "%s:%s_back", mod->name, mt->name);
solidskytexture = TexMgr_LoadImage (mod, texturename, mt->width, halfheight, SRC_INDEXED, back, "", (src_offset_t)back, TEXPREF_NONE); mt->gltexture = solidskytexture = TexMgr_LoadImage (mod, texturename, mt->width, halfheight, SRC_INDEXED, back, "", (src_offset_t)back, TEXPREF_NONE);
// front layer, convert to RGBA and upload // front layer, convert to RGBA and upload
p = r = g = b = count = 0; p = r = g = b = count = 0;
@ -214,7 +218,7 @@ void Sky_LoadTextureQ64 (qmodel_t *mod, texture_t *mt)
} }
q_snprintf(texturename, sizeof(texturename), "%s:%s_front", mod->name, mt->name); q_snprintf(texturename, sizeof(texturename), "%s:%s_front", mod->name, mt->name);
alphaskytexture = TexMgr_LoadImage (mod, texturename, mt->width, halfheight, SRC_RGBA, front_rgba, "", (src_offset_t)front_rgba, TEXPREF_ALPHA); mt->fullbright = alphaskytexture = TexMgr_LoadImage (mod, texturename, mt->width, halfheight, SRC_RGBA, front_rgba, "", (src_offset_t)front_rgba, TEXPREF_ALPHA);
// calculate r_fastsky color based on average of all opaque foreground colors // calculate r_fastsky color based on average of all opaque foreground colors
skyflatcolor[0] = (float)r/(count*255); skyflatcolor[0] = (float)r/(count*255);
@ -736,6 +740,11 @@ void Sky_ProcessEntities (void)
if (!e->model || e->model->needload || e->model->type != mod_brush) if (!e->model || e->model->needload || e->model->type != mod_brush)
continue; continue;
if (e->model->submodelof == cl.worldmodel &&
skipsubmodels &&
skipsubmodels[e->model->submodelidx>>3]&(1u<<(e->model->submodelidx&7)))
return; //its in the scenecache that we're drawing. don't draw it twice (and certainly not the slow way).
if (R_CullModelForEntity(e)) if (R_CullModelForEntity(e))
continue; continue;
@ -1189,6 +1198,17 @@ void Sky_DrawSky (void)
glColor3fv (Fog_GetColor()); glColor3fv (Fog_GetColor());
else else
glColor3fv (skyflatcolor); glColor3fv (skyflatcolor);
#ifndef SDL_THREADS_DISABLED
if (skybox_name[0] && !r_fastsky.value && RSceneCache_DrawSkySurfDepth())
{ //we have no surfaces to process... fill all sides. its probably still faster.
for (i=0 ; i<6 ; i++)
{
skymins[0][i] = skymins[1][i] = -FLT_MAX;
skymaxs[0][i] = skymaxs[1][i] = FLT_MAX;
}
}
else
#endif
Sky_ProcessTextureChains (); Sky_ProcessTextureChains ();
Sky_ProcessEntities (); Sky_ProcessEntities ();
glColor3f (1, 1, 1); glColor3f (1, 1, 1);

View file

@ -31,7 +31,6 @@ static cvar_t gl_texturemode = {"gl_texturemode", "", CVAR_ARCHIVE};
static cvar_t gl_texture_anisotropy = {"gl_texture_anisotropy", "1", CVAR_ARCHIVE}; static cvar_t gl_texture_anisotropy = {"gl_texture_anisotropy", "1", CVAR_ARCHIVE};
static cvar_t gl_max_size = {"gl_max_size", "0", CVAR_NONE}; static cvar_t gl_max_size = {"gl_max_size", "0", CVAR_NONE};
static cvar_t gl_picmip = {"gl_picmip", "0", CVAR_NONE}; static cvar_t gl_picmip = {"gl_picmip", "0", CVAR_NONE};
static GLint gl_hardware_maxsize;
static int numgltextures; static int numgltextures;
static gltexture_t *active_gltextures, *free_gltextures; static gltexture_t *active_gltextures, *free_gltextures;
@ -705,9 +704,6 @@ void TexMgr_Init (void)
Cmd_AddCommand ("imagelist", &TexMgr_Imagelist_f); Cmd_AddCommand ("imagelist", &TexMgr_Imagelist_f);
Cmd_AddCommand ("imagedump", &TexMgr_Imagedump_f); Cmd_AddCommand ("imagedump", &TexMgr_Imagedump_f);
// poll max size from hardware
glGetIntegerv (GL_MAX_TEXTURE_SIZE, &gl_hardware_maxsize);
// load notexture images // load notexture images
notexture = TexMgr_LoadImage (NULL, "notexture", 2, 2, SRC_RGBA, notexture_data, "", (src_offset_t)notexture_data, TEXPREF_NEAREST | TEXPREF_PERSIST | TEXPREF_NOPICMIP); notexture = TexMgr_LoadImage (NULL, "notexture", 2, 2, SRC_RGBA, notexture_data, "", (src_offset_t)notexture_data, TEXPREF_NEAREST | TEXPREF_PERSIST | TEXPREF_NOPICMIP);
nulltexture = TexMgr_LoadImage (NULL, "nulltexture", 2, 2, SRC_RGBA, nulltexture_data, "", (src_offset_t)nulltexture_data, TEXPREF_NEAREST | TEXPREF_PERSIST | TEXPREF_NOPICMIP); nulltexture = TexMgr_LoadImage (NULL, "nulltexture", 2, 2, SRC_RGBA, nulltexture_data, "", (src_offset_t)nulltexture_data, TEXPREF_NEAREST | TEXPREF_PERSIST | TEXPREF_NOPICMIP);
@ -1507,7 +1503,7 @@ gltexture_t *TexMgr_LoadImage (qmodel_t *owner, const char *name, int width, int
return NULL; return NULL;
// cache check // cache check
if (format == SRC_EXTERNAL) if (format == SRC_EXTERNAL || format == SRC_LIGHTMAP)
crc = 0; crc = 0;
else else
crc = CRC_Block(data, TexMgr_ImageSize(width, height, format)); crc = CRC_Block(data, TexMgr_ImageSize(width, height, format));

View file

@ -112,6 +112,7 @@ qboolean gl_glsl_gamma_able = false; //ericw
qboolean gl_glsl_alias_able = false; //ericw qboolean gl_glsl_alias_able = false; //ericw
qboolean gl_glsl_water_able = false; //Spoike qboolean gl_glsl_water_able = false; //Spoike
int gl_stencilbits; int gl_stencilbits;
GLint gl_hardware_maxsize;
PFNGLMULTITEXCOORD2FARBPROC GL_MTexCoord2fFunc = NULL; //johnfitz PFNGLMULTITEXCOORD2FARBPROC GL_MTexCoord2fFunc = NULL; //johnfitz
PFNGLACTIVETEXTUREARBPROC GL_SelectTextureFunc = NULL; //johnfitz PFNGLACTIVETEXTUREARBPROC GL_SelectTextureFunc = NULL; //johnfitz
@ -121,6 +122,10 @@ PFNGLBUFFERDATAARBPROC GL_BufferDataFunc = NULL; //ericw
PFNGLBUFFERSUBDATAARBPROC GL_BufferSubDataFunc = NULL; //ericw PFNGLBUFFERSUBDATAARBPROC GL_BufferSubDataFunc = NULL; //ericw
PFNGLDELETEBUFFERSARBPROC GL_DeleteBuffersFunc = NULL; //ericw PFNGLDELETEBUFFERSARBPROC GL_DeleteBuffersFunc = NULL; //ericw
PFNGLGENBUFFERSARBPROC GL_GenBuffersFunc = NULL; //ericw PFNGLGENBUFFERSARBPROC GL_GenBuffersFunc = NULL; //ericw
PFNGLMAPBUFFERARBPROC GL_MapBufferFunc = NULL; //spike
PFNGLUNMAPBUFFERARBPROC GL_UnmapBufferFunc = NULL; //spike
PFNGLMAPBUFFERRANGEPROC GL_MapBufferRangeFunc = NULL; //spike
PFNGLBUFFERSTORAGEPROC GL_BufferStorageFunc = NULL; //spike
QS_PFNGLCREATESHADERPROC GL_CreateShaderFunc = NULL; //ericw QS_PFNGLCREATESHADERPROC GL_CreateShaderFunc = NULL; //ericw
QS_PFNGLDELETESHADERPROC GL_DeleteShaderFunc = NULL; //ericw QS_PFNGLDELETESHADERPROC GL_DeleteShaderFunc = NULL; //ericw
@ -814,6 +819,7 @@ static void VID_Restart (void)
// one of the new objects could be given the same ID as an invalid handle // one of the new objects could be given the same ID as an invalid handle
// which is later deleted. // which is later deleted.
RSceneCache_Shutdown();
TexMgr_DeleteTextureObjects (); TexMgr_DeleteTextureObjects ();
GLSLGamma_DeleteTexture (); GLSLGamma_DeleteTexture ();
R_ScaleView_DeleteTexture (); R_ScaleView_DeleteTexture ();
@ -993,6 +999,8 @@ static void GL_CheckExtensions (void)
GL_BufferSubDataFunc = (PFNGLBUFFERSUBDATAARBPROC) SDL_GL_GetProcAddress("glBufferSubDataARB"); GL_BufferSubDataFunc = (PFNGLBUFFERSUBDATAARBPROC) SDL_GL_GetProcAddress("glBufferSubDataARB");
GL_DeleteBuffersFunc = (PFNGLDELETEBUFFERSARBPROC) SDL_GL_GetProcAddress("glDeleteBuffersARB"); GL_DeleteBuffersFunc = (PFNGLDELETEBUFFERSARBPROC) SDL_GL_GetProcAddress("glDeleteBuffersARB");
GL_GenBuffersFunc = (PFNGLGENBUFFERSARBPROC) SDL_GL_GetProcAddress("glGenBuffersARB"); GL_GenBuffersFunc = (PFNGLGENBUFFERSARBPROC) SDL_GL_GetProcAddress("glGenBuffersARB");
GL_MapBufferFunc = (PFNGLMAPBUFFERARBPROC) SDL_GL_GetProcAddress("glMapBufferARB"); //spike -- grab these too.
GL_UnmapBufferFunc = (PFNGLUNMAPBUFFERARBPROC) SDL_GL_GetProcAddress("glUnmapBufferARB");
if (GL_BindBufferFunc && GL_BufferDataFunc && GL_BufferSubDataFunc && GL_DeleteBuffersFunc && GL_GenBuffersFunc) if (GL_BindBufferFunc && GL_BufferDataFunc && GL_BufferSubDataFunc && GL_DeleteBuffersFunc && GL_GenBuffersFunc)
{ {
Con_Printf("FOUND: ARB_vertex_buffer_object\n"); Con_Printf("FOUND: ARB_vertex_buffer_object\n");
@ -1004,6 +1012,21 @@ static void GL_CheckExtensions (void)
} }
} }
if (gl_version_major > 4 || (gl_version_major == 4 && gl_version_minor >= 4) || GL_ParseExtensionList(gl_extensions, "GL_ARB_buffer_storage"))
{
GL_MapBufferRangeFunc = (PFNGLMAPBUFFERRANGEPROC) SDL_GL_GetProcAddress("glMapBufferRange");
GL_BufferStorageFunc = (PFNGLBUFFERSTORAGEPROC) SDL_GL_GetProcAddress("glBufferStorage");
if (gl_vbo_able && GL_MapBufferRangeFunc && GL_BufferStorageFunc)
Con_Printf("FOUND: GL_ARB_buffer_storage\n");
else
Con_Warning ("GL_ARB_buffer_storage not available\n"); //doesn't really warrent a warning, but when in rome...
}
else
{
GL_MapBufferRangeFunc = NULL;
GL_BufferStorageFunc = NULL;
}
// multitexture // multitexture
// //
if (COM_CheckParm("-nomtex")) if (COM_CheckParm("-nomtex"))
@ -1349,6 +1372,11 @@ static void GL_Init (void)
} }
//johnfitz //johnfitz
// query max size from hardware
glGetIntegerv (GL_MAX_TEXTURE_SIZE, &gl_hardware_maxsize);
LMBLOCK_WIDTH = q_min(gl_hardware_maxsize, 512); //keeping this small potentially allows for more efficient texsubimage calls.
LMBLOCK_HEIGHT = q_min(gl_hardware_maxsize, 16384);
GLAlias_CreateShaders (); GLAlias_CreateShaders ();
GLWorld_CreateShaders (); GLWorld_CreateShaders ();
GL_ClearBufferBindings (); GL_ClearBufferBindings ();

View file

@ -190,6 +190,8 @@ extern float load_subdivide_size; //johnfitz -- remember what subdivide_size val
extern int gl_stencilbits; extern int gl_stencilbits;
extern GLint gl_hardware_maxsize;
// Multitexture // Multitexture
extern qboolean mtexenabled; extern qboolean mtexenabled;
extern qboolean gl_mtexable; extern qboolean gl_mtexable;
@ -210,8 +212,12 @@ extern PFNGLBUFFERDATAARBPROC GL_BufferDataFunc;
extern PFNGLBUFFERSUBDATAARBPROC GL_BufferSubDataFunc; extern PFNGLBUFFERSUBDATAARBPROC GL_BufferSubDataFunc;
extern PFNGLDELETEBUFFERSARBPROC GL_DeleteBuffersFunc; extern PFNGLDELETEBUFFERSARBPROC GL_DeleteBuffersFunc;
extern PFNGLGENBUFFERSARBPROC GL_GenBuffersFunc; extern PFNGLGENBUFFERSARBPROC GL_GenBuffersFunc;
extern PFNGLMAPBUFFERARBPROC GL_MapBufferFunc;
extern PFNGLUNMAPBUFFERARBPROC GL_UnmapBufferFunc;
extern qboolean gl_vbo_able; extern qboolean gl_vbo_able;
//ericw //ericw
extern PFNGLMAPBUFFERRANGEPROC GL_MapBufferRangeFunc;
extern PFNGLBUFFERSTORAGEPROC GL_BufferStorageFunc;
//ericw -- GLSL //ericw -- GLSL
@ -335,9 +341,7 @@ extern overflowtimes_t dev_overflows; //this stores the last time overflow messa
//johnfitz -- moved here from r_brush.c //johnfitz -- moved here from r_brush.c
extern int gl_lightmap_format, lightmap_bytes; extern int gl_lightmap_format, lightmap_bytes;
extern qboolean lightmaps_latecached; //we need to rebuild lightmaps and model vbos before rendering. extern qboolean lightmaps_latecached; //we need to rebuild lightmaps and model vbos before rendering.
extern int LMBLOCK_WIDTH, LMBLOCK_HEIGHT; //FIXME: use texture arrays.
#define LMBLOCK_WIDTH 256 //FIXME: make dynamic. if we have a decent card there's no real reason not to use 4k or 16k (assuming there's no lightstyles/dynamics that need uploading...)
#define LMBLOCK_HEIGHT 256 //Alternatively, use texture arrays, which would avoid the need to switch textures as often.
typedef struct glRect_s { typedef struct glRect_s {
unsigned short l,t,w,h; unsigned short l,t,w,h;
@ -349,9 +353,10 @@ struct lightmap_s
qboolean modified; qboolean modified;
glRect_t rectchange; glRect_t rectchange;
// the lightmap texture data needs to be kept in // PBO use allows us to simply copy the lightmap data into a texture on-gpu, reducing stutters. It'll be writethrough though, so we need to keep things cache-friendly.
// main memory so texsubimage can update properly //the data ptr points to a persistently mapped buffer so we can paint it from other threads while the main thread is doing other work so other than creation+upload we can just treat it like regular memory with slightly different cache properties.
byte *data;//[4*LMBLOCK_WIDTH*LMBLOCK_HEIGHT]; GLuint pbohandle;
byte *pbodata;//[4*LMBLOCK_WIDTH*LMBLOCK_HEIGHT];
}; };
extern struct lightmap_s *lightmaps; extern struct lightmap_s *lightmaps;
extern int lightmap_count; //allocated lightmaps extern int lightmap_count; //allocated lightmaps
@ -389,7 +394,7 @@ qboolean R_CullBox (vec3_t emins, vec3_t emaxs);
void R_StoreEfrags (efrag_t **ppefrag); void R_StoreEfrags (efrag_t **ppefrag);
qboolean R_CullModelForEntity (entity_t *e); qboolean R_CullModelForEntity (entity_t *e);
void R_RotateForEntity (vec3_t origin, vec3_t angles, unsigned char scale); void R_RotateForEntity (vec3_t origin, vec3_t angles, unsigned char scale);
void R_MarkLights (dlight_t *light, vec3_t lightorg, int num, mnode_t *node); void R_MarkLights (dlight_t *light, vec3_t lightorg, int framecount, int num, mnode_t *node);
void R_InitParticles (void); void R_InitParticles (void);
void R_DrawParticles (void); void R_DrawParticles (void);
@ -420,7 +425,7 @@ void R_RebuildAllLightmaps (void);
int R_LightPoint (vec3_t p); int R_LightPoint (vec3_t p);
void GL_SubdivideSurface (msurface_t *fa); void GL_SubdivideSurface (msurface_t *fa);
void R_BuildLightMap (qmodel_t *model, msurface_t *surf, byte *dest, int stride); void R_BuildLightMap (qmodel_t *model, msurface_t *surf, byte *dest, int stride, entity_t *currentent, int framecount, dlight_t *lights);
void R_RenderDynamicLightmaps (qmodel_t *model, msurface_t *fa); void R_RenderDynamicLightmaps (qmodel_t *model, msurface_t *fa);
void R_UploadLightmaps (void); void R_UploadLightmaps (void);
@ -459,6 +464,9 @@ void R_ClearTextureChains (qmodel_t *mod, texchain_t chain);
void R_ChainSurface (msurface_t *surf, texchain_t chain); void R_ChainSurface (msurface_t *surf, texchain_t chain);
void R_DrawTextureChains (qmodel_t *model, entity_t *ent, texchain_t chain); void R_DrawTextureChains (qmodel_t *model, entity_t *ent, texchain_t chain);
void R_DrawWorld_Water (void); void R_DrawWorld_Water (void);
void RSceneCache_Cleanup(qmodel_t *mod);
void RSceneCache_Shutdown(void);
extern byte *skipsubmodels;
void GL_BindBuffer (GLenum target, GLuint buffer); void GL_BindBuffer (GLenum target, GLuint buffer);
void GL_ClearBufferBindings (); void GL_ClearBufferBindings ();

View file

@ -2096,16 +2096,16 @@ static void PF_cl_makestatic (void)
if (i >= cl.max_static_entities) if (i >= cl.max_static_entities)
{ {
int ec = 64; int ec = 64;
entity_t **newstatics = realloc(cl.static_entities, sizeof(*newstatics) * (cl.max_static_entities+ec)); struct cl_static_entities_s *newstatics = realloc(cl.static_entities, sizeof(*newstatics) * (cl.max_static_entities+ec));
entity_t *newents = Hunk_Alloc(sizeof(*newents) * ec); entity_t *newents = Hunk_Alloc(sizeof(*newents) * ec);
if (!newstatics || !newents) if (!newstatics || !newents)
Host_Error ("Too many static entities"); Host_Error ("Too many static entities");
cl.static_entities = newstatics; cl.static_entities = newstatics;
while (ec--) while (ec--)
cl.static_entities[cl.max_static_entities++] = newents++; cl.static_entities[cl.max_static_entities++].ent = newents++;
} }
stat = cl.static_entities[i]; stat = cl.static_entities[i].ent;
cl.num_statics++; cl.num_statics++;
SV_BuildEntityState(NULL, ent, &stat->baseline); SV_BuildEntityState(NULL, ent, &stat->baseline);
@ -2127,8 +2127,7 @@ static void PF_cl_makestatic (void)
VectorCopy (ent->baseline.origin, stat->origin); VectorCopy (ent->baseline.origin, stat->origin);
VectorCopy (ent->baseline.angles, stat->angles); VectorCopy (ent->baseline.angles, stat->angles);
if (stat->model) CL_LinkStaticEnt(&cl.static_entities[i]);
R_AddEfrags (stat);
// throw the entity away now // throw the entity away now
ED_Free (ent); ED_Free (ent);

View file

@ -295,13 +295,16 @@ typedef struct
#if defined(USE_SDL2) #if defined(USE_SDL2)
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
#include <SDL2/SDL_opengl.h> #include <SDL2/SDL_opengl.h>
#include <SDL2/SDL_opengl_glext.h>
#else #else
#include <SDL/SDL.h> #include <SDL/SDL.h>
#include <SDL/SDL_opengl.h> #include <SDL/SDL_opengl.h>
#include <SDL/SDL_opengl_glext.h>
#endif #endif
#else #else
#include "SDL.h" #include "SDL.h"
#include "SDL_opengl.h" #include "SDL_opengl.h"
#include "SDL_opengl_glext.h"
#endif #endif
#ifndef APIENTRY #ifndef APIENTRY
#define APIENTRY #define APIENTRY

View file

@ -31,14 +31,14 @@ extern cvar_t gl_zfix; // QuakeSpasm z-fighting fix
int gl_lightmap_format; int gl_lightmap_format;
int lightmap_bytes; int lightmap_bytes;
qboolean lightmaps_latecached; qboolean lightmaps_latecached;
qboolean lightmaps_skipupdates;
#define MAX_SANITY_LIGHTMAPS (1u<<20) #define MAX_SANITY_LIGHTMAPS (1u<<20)
struct lightmap_s *lightmaps; struct lightmap_s *lightmaps;
int lightmap_count; int lightmap_count;
int last_lightmap_allocated; static int last_lightmap_allocated;
int allocated[LMBLOCK_WIDTH]; static int *allocated;
int LMBLOCK_WIDTH, LMBLOCK_HEIGHT;
unsigned blocklights[LMBLOCK_WIDTH*LMBLOCK_HEIGHT*3]; //johnfitz -- was 18*18, added lit support (*3) and loosened surface extents maximum (LMBLOCK_WIDTH*LMBLOCK_HEIGHT)
/* /*
@ -510,6 +510,12 @@ void R_DrawBrushModel (entity_t *e)
mplane_t *pplane; mplane_t *pplane;
qmodel_t *clmodel; qmodel_t *clmodel;
vec3_t lightorg; vec3_t lightorg;
extern byte *skipsubmodels;
if (e->model->submodelof == cl.worldmodel &&
skipsubmodels &&
skipsubmodels[e->model->submodelidx>>3]&(1u<<(e->model->submodelidx&7)))
return; //its in the scenecache that we're drawing. don't draw it twice (and certainly not the slow way).
if (R_CullModelForEntity(e)) if (R_CullModelForEntity(e))
return; return;
@ -535,6 +541,7 @@ void R_DrawBrushModel (entity_t *e)
// calculate dynamic lighting for bmodel if it's not an // calculate dynamic lighting for bmodel if it's not an
// instanced model // instanced model
if (clmodel->firstmodelsurface != 0 && !gl_flashblend.value) if (clmodel->firstmodelsurface != 0 && !gl_flashblend.value)
if (e->model->submodelof == cl.worldmodel) //R_MarkLights has a hacky assumption about cl.worldmodel that could crash if we imported some other model.
{ {
for (k=0 ; k<MAX_DLIGHTS ; k++) for (k=0 ; k<MAX_DLIGHTS ; k++)
{ {
@ -543,7 +550,7 @@ void R_DrawBrushModel (entity_t *e)
continue; continue;
VectorSubtract(cl_dlights[k].origin, e->origin, lightorg); VectorSubtract(cl_dlights[k].origin, e->origin, lightorg);
R_MarkLights (&cl_dlights[k], lightorg, k, R_MarkLights (&cl_dlights[k], lightorg, r_framecount, k,
clmodel->nodes + clmodel->hulls[0].firstclipnode); clmodel->nodes + clmodel->hulls[0].firstclipnode);
} }
} }
@ -704,9 +711,9 @@ dynamic:
theRect->w = (fa->light_s-theRect->l)+smax; theRect->w = (fa->light_s-theRect->l)+smax;
if ((theRect->h + theRect->t) < (fa->light_t + tmax)) if ((theRect->h + theRect->t) < (fa->light_t + tmax))
theRect->h = (fa->light_t-theRect->t)+tmax; theRect->h = (fa->light_t-theRect->t)+tmax;
base = lm->data; base = lm->pbodata;
base += fa->light_t * LMBLOCK_WIDTH * lightmap_bytes + fa->light_s * lightmap_bytes; base += fa->light_t * LMBLOCK_WIDTH * lightmap_bytes + fa->light_s * lightmap_bytes;
R_BuildLightMap (model, fa, base, LMBLOCK_WIDTH*lightmap_bytes); R_BuildLightMap (model, fa, base, LMBLOCK_WIDTH*lightmap_bytes, currententity, r_framecount, cl_dlights);
} }
} }
} }
@ -734,9 +741,18 @@ int AllocBlock (int w, int h, int *x, int *y)
lightmap_count++; lightmap_count++;
lightmaps = (struct lightmap_s *) realloc(lightmaps, sizeof(*lightmaps)*lightmap_count); lightmaps = (struct lightmap_s *) realloc(lightmaps, sizeof(*lightmaps)*lightmap_count);
memset(&lightmaps[texnum], 0, sizeof(lightmaps[texnum])); memset(&lightmaps[texnum], 0, sizeof(lightmaps[texnum]));
lightmaps[texnum].data = (byte *) calloc(1, 4*LMBLOCK_WIDTH*LMBLOCK_HEIGHT); if (GL_BufferStorageFunc)
{ //if we have bufferstorage then we have mapbufferrange+persistent+coherent
GL_GenBuffersFunc(1, &lightmaps[texnum].pbohandle);
GL_BindBufferFunc(GL_PIXEL_UNPACK_BUFFER_ARB, lightmaps[texnum].pbohandle);
GL_BufferStorageFunc(GL_PIXEL_UNPACK_BUFFER_ARB, 4*LMBLOCK_WIDTH*LMBLOCK_HEIGHT, NULL, GL_MAP_WRITE_BIT|GL_MAP_PERSISTENT_BIT|GL_MAP_COHERENT_BIT|GL_CLIENT_STORAGE_BIT);
lightmaps[texnum].pbodata = GL_MapBufferRangeFunc(GL_PIXEL_UNPACK_BUFFER_ARB, 0, 4*LMBLOCK_WIDTH*LMBLOCK_HEIGHT, GL_MAP_WRITE_BIT|GL_MAP_PERSISTENT_BIT|GL_MAP_COHERENT_BIT);
GL_BindBufferFunc(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
}
else
lightmaps[texnum].pbodata = (byte *) calloc(1, 4*LMBLOCK_WIDTH*LMBLOCK_HEIGHT);
//as we're only tracking one texture, we don't need multiple copies of allocated any more. //as we're only tracking one texture, we don't need multiple copies of allocated any more.
memset(allocated, 0, sizeof(allocated)); memset(allocated, 0, sizeof(*allocated)*LMBLOCK_WIDTH);
lightmaps[texnum].modified = true; lightmaps[texnum].modified = true;
lightmaps[texnum].rectchange.l = 0; lightmaps[texnum].rectchange.l = 0;
@ -804,9 +820,9 @@ void GL_CreateSurfaceLightmap (qmodel_t *model, msurface_t *surf)
tmax = surf->extents[1]+1; tmax = surf->extents[1]+1;
surf->lightmaptexturenum = AllocBlock (smax, tmax, &surf->light_s, &surf->light_t); surf->lightmaptexturenum = AllocBlock (smax, tmax, &surf->light_s, &surf->light_t);
base = lightmaps[surf->lightmaptexturenum].data; base = lightmaps[surf->lightmaptexturenum].pbodata;
base += (surf->light_t * LMBLOCK_WIDTH + surf->light_s) * lightmap_bytes; base += (surf->light_t * LMBLOCK_WIDTH + surf->light_s) * lightmap_bytes;
R_BuildLightMap (model, surf, base, LMBLOCK_WIDTH*lightmap_bytes); R_BuildLightMap (model, surf, base, LMBLOCK_WIDTH*lightmap_bytes, currententity, r_framecount, cl_dlights);
} }
/* /*
@ -936,6 +952,8 @@ void GL_BuildLightmaps (void)
struct lightmap_s *lm; struct lightmap_s *lm;
qmodel_t *m; qmodel_t *m;
RSceneCache_Shutdown(); //make sure there's nothing poking them off-thread.
r_framecount = 1; // no dlightcache r_framecount = 1; // no dlightcache
//Spike -- wipe out all the lightmap data (johnfitz -- the gltexture objects were already freed by Mod_ClearAll) //Spike -- wipe out all the lightmap data (johnfitz -- the gltexture objects were already freed by Mod_ClearAll)
@ -943,12 +961,21 @@ void GL_BuildLightmaps (void)
{ {
if (lightmaps[i].texture) if (lightmaps[i].texture)
TexMgr_FreeTexture(lightmaps[i].texture); TexMgr_FreeTexture(lightmaps[i].texture);
free(lightmaps[i].data); if (lightmaps[i].pbohandle)
{
GL_BindBufferFunc(GL_PIXEL_UNPACK_BUFFER_ARB, lightmaps[i].pbohandle);
GL_UnmapBufferFunc(GL_PIXEL_UNPACK_BUFFER_ARB);
GL_BindBufferFunc(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
GL_DeleteBuffersFunc(1, &lightmaps[i].pbohandle);
}
else
free(lightmaps[i].pbodata);
} }
free(lightmaps); free(lightmaps);
lightmaps = NULL; lightmaps = NULL;
last_lightmap_allocated = 0; last_lightmap_allocated = 0;
lightmap_count = 0; lightmap_count = 0;
allocated = realloc(allocated, sizeof(*allocated)*LMBLOCK_WIDTH);
if (gl_texture_e5bgr9)// && cl.worldmodel && (cl.worldmodel->flags&MOD_HDRLIGHTING)) if (gl_texture_e5bgr9)// && cl.worldmodel && (cl.worldmodel->flags&MOD_HDRLIGHTING))
gl_lightmap_format = GL_RGB9_E5; //requires gl3, allowing for hdr lighting. gl_lightmap_format = GL_RGB9_E5; //requires gl3, allowing for hdr lighting.
@ -999,8 +1026,19 @@ void GL_BuildLightmaps (void)
//johnfitz -- use texture manager //johnfitz -- use texture manager
sprintf(name, "lightmap%07i",i); sprintf(name, "lightmap%07i",i);
if (lm->pbohandle)
{
GL_BindBufferFunc(GL_PIXEL_UNPACK_BUFFER_ARB, lm->pbohandle);
lm->texture = TexMgr_LoadImage (NULL, name, LMBLOCK_WIDTH, LMBLOCK_HEIGHT, lm->texture = TexMgr_LoadImage (NULL, name, LMBLOCK_WIDTH, LMBLOCK_HEIGHT,
SRC_LIGHTMAP, lm->data, "", (src_offset_t)lm->data, TEXPREF_LINEAR | TEXPREF_NOPICMIP | TEXPREF_PERSIST); SRC_LIGHTMAP, NULL, "", (src_offset_t)lm->pbodata, TEXPREF_LINEAR | TEXPREF_NOPICMIP | TEXPREF_PERSIST);
GL_BindBufferFunc(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
}
else
{
lm->texture = TexMgr_LoadImage (NULL, name, LMBLOCK_WIDTH, LMBLOCK_HEIGHT,
SRC_LIGHTMAP, lm->pbodata, "", (src_offset_t)lm->pbodata, TEXPREF_LINEAR | TEXPREF_NOPICMIP | TEXPREF_PERSIST);
}
//johnfitz //johnfitz
} }
@ -1129,7 +1167,7 @@ void GL_BuildBModelVertexBuffer (void)
R_AddDynamicLights R_AddDynamicLights
=============== ===============
*/ */
void R_AddDynamicLights (msurface_t *surf) static void R_AddDynamicLights (msurface_t *surf, unsigned *blocklights, entity_t *currentent, dlight_t *lights)
{ {
int lnum; int lnum;
int sd, td; int sd, td;
@ -1152,11 +1190,21 @@ void R_AddDynamicLights (msurface_t *surf)
if (! (surf->dlightbits[lnum >> 5] & (1U << (lnum & 31)))) if (! (surf->dlightbits[lnum >> 5] & (1U << (lnum & 31))))
continue; // not lit by this light continue; // not lit by this light
rad = cl_dlights[lnum].radius; rad = lights[lnum].radius;
VectorSubtract(cl_dlights[lnum].origin, currententity->origin, lightofs); if (currentent->currentangles[0] || currentent->currentangles[1] || currentent->currentangles[2])
{
vec3_t temp, axis[3];
VectorSubtract(lights[lnum].origin, currentent->origin, temp);
AngleVectors(currentent->currentangles, axis[0], axis[1], axis[2]);
lightofs[0] = +DotProduct(temp, axis[0]);
lightofs[1] = -DotProduct(temp, axis[1]);
lightofs[2] = +DotProduct(temp, axis[2]);
}
else
VectorSubtract(lights[lnum].origin, currentent->origin, lightofs);
dist = DotProduct (lightofs, surf->plane->normal) - surf->plane->dist; dist = DotProduct (lightofs, surf->plane->normal) - surf->plane->dist;
rad -= fabs(dist); rad -= fabs(dist);
minlight = cl_dlights[lnum].minlight; minlight = lights[lnum].minlight;
if (rad < minlight) if (rad < minlight)
continue; continue;
minlight = rad - minlight; minlight = rad - minlight;
@ -1172,9 +1220,9 @@ void R_AddDynamicLights (msurface_t *surf)
//johnfitz -- lit support via lordhavoc //johnfitz -- lit support via lordhavoc
bl = blocklights; bl = blocklights;
cred = cl_dlights[lnum].color[0] * 256.0f; cred = lights[lnum].color[0] * 256.0f;
cgreen = cl_dlights[lnum].color[1] * 256.0f; cgreen = lights[lnum].color[1] * 256.0f;
cblue = cl_dlights[lnum].color[2] * 256.0f; cblue = lights[lnum].color[2] * 256.0f;
//johnfitz //johnfitz
for (t = 0 ; t<tmax ; t++) for (t = 0 ; t<tmax ; t++)
{ {
@ -1213,7 +1261,7 @@ R_BuildLightMap -- johnfitz -- revised for lit support via lordhavoc
Combine and scale multiple lightmaps into the 8.8 format in blocklights Combine and scale multiple lightmaps into the 8.8 format in blocklights
=============== ===============
*/ */
void R_BuildLightMap (qmodel_t *model, msurface_t *surf, byte *dest, int stride) void R_BuildLightMap (qmodel_t *model, msurface_t *surf, byte *dest, int stride, entity_t *currentent, int framecount, dlight_t *lights)
{ {
int smax, tmax; int smax, tmax;
int r,g,b; int r,g,b;
@ -1221,13 +1269,16 @@ void R_BuildLightMap (qmodel_t *model, msurface_t *surf, byte *dest, int stride)
unsigned scale; unsigned scale;
int maps; int maps;
unsigned *bl; unsigned *bl;
unsigned *blocklights; //moved this to stack, so workers working on the worldmodel won't fight the main thread processing the submodels.
surf->cached_dlight = (surf->dlightframe == r_framecount); surf->cached_dlight = (surf->dlightframe == framecount);
smax = surf->extents[0]+1; smax = surf->extents[0]+1;
tmax = surf->extents[1]+1; tmax = surf->extents[1]+1;
size = smax*tmax; size = smax*tmax;
blocklights = alloca(size*3*sizeof(*blocklights)); //alloca is unsafe, but at least we memset it... should probably memset in stack order in the hopes of getting a standard stack-overflow-segfault instead of poking completely outside what the system thinks is the stack in the case of massive surfs...
if (model->lightdata) if (model->lightdata)
{ {
// clear to no light // clear to no light
@ -1283,13 +1334,14 @@ void R_BuildLightMap (qmodel_t *model, msurface_t *surf, byte *dest, int stride)
} }
// add all the dynamic lights // add all the dynamic lights
if (surf->dlightframe == r_framecount) if (surf->dlightframe == framecount)
R_AddDynamicLights (surf); R_AddDynamicLights (surf, blocklights, currentent, lights);
} }
else else
{ {
// set to full bright if no light data // set to full bright if no light data
memset (&blocklights[0], 255, size * 3 * sizeof (unsigned int)); //johnfitz -- lit support via lordhavoc for (i=0 ; i<size ; i++)
blocklights[i] = 0xffff; //don't use memset, it oversaturates FAR too much with hdr...
} }
// bound, invert, and shift // bound, invert, and shift
@ -1404,12 +1456,26 @@ static void R_UploadLightmap(int lmap)
lm->modified = false; lm->modified = false;
if (lm->pbohandle)
{
GL_BindBufferFunc(GL_PIXEL_UNPACK_BUFFER_ARB, lm->pbohandle);
if (gl_lightmap_format == GL_RGB9_E5) if (gl_lightmap_format == GL_RGB9_E5)
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, lm->rectchange.t, LMBLOCK_WIDTH, lm->rectchange.h, GL_RGB, glTexSubImage2D(GL_TEXTURE_2D, 0, 0, lm->rectchange.t, LMBLOCK_WIDTH, lm->rectchange.h, GL_RGB,
GL_UNSIGNED_INT_5_9_9_9_REV, lm->data+lm->rectchange.t*LMBLOCK_WIDTH*lightmap_bytes); GL_UNSIGNED_INT_5_9_9_9_REV, (byte*)NULL+lm->rectchange.t*LMBLOCK_WIDTH*lightmap_bytes);
else else
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, lm->rectchange.t, LMBLOCK_WIDTH, lm->rectchange.h, gl_lightmap_format, glTexSubImage2D(GL_TEXTURE_2D, 0, 0, lm->rectchange.t, LMBLOCK_WIDTH, lm->rectchange.h, gl_lightmap_format,
GL_UNSIGNED_BYTE, lm->data+lm->rectchange.t*LMBLOCK_WIDTH*lightmap_bytes); GL_UNSIGNED_BYTE, (byte*)NULL+lm->rectchange.t*LMBLOCK_WIDTH*lightmap_bytes);
GL_BindBufferFunc(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
}
else
{
if (gl_lightmap_format == GL_RGB9_E5)
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, lm->rectchange.t, LMBLOCK_WIDTH, lm->rectchange.h, GL_RGB,
GL_UNSIGNED_INT_5_9_9_9_REV, lm->pbodata+lm->rectchange.t*LMBLOCK_WIDTH*lightmap_bytes);
else
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, lm->rectchange.t, LMBLOCK_WIDTH, lm->rectchange.h, gl_lightmap_format,
GL_UNSIGNED_BYTE, lm->pbodata+lm->rectchange.t*LMBLOCK_WIDTH*lightmap_bytes);
}
lm->rectchange.l = LMBLOCK_WIDTH; lm->rectchange.l = LMBLOCK_WIDTH;
lm->rectchange.t = LMBLOCK_HEIGHT; lm->rectchange.t = LMBLOCK_HEIGHT;
lm->rectchange.h = 0; lm->rectchange.h = 0;
@ -1429,6 +1495,9 @@ void R_UploadLightmaps (void)
lightmaps_latecached=false; lightmaps_latecached=false;
} }
if (lightmaps_skipupdates)
return;
for (lmap = 0; lmap < lightmap_count; lmap++) for (lmap = 0; lmap < lightmap_count; lmap++)
{ {
if (!lightmaps[lmap].modified) if (!lightmaps[lmap].modified)
@ -1438,9 +1507,18 @@ void R_UploadLightmaps (void)
{ {
char name[24]; char name[24];
sprintf(name, "lightmap%07i",lmap); sprintf(name, "lightmap%07i",lmap);
if (lightmaps[lmap].pbohandle)
{
GL_BindBufferFunc(GL_PIXEL_UNPACK_BUFFER_ARB, lightmaps[lmap].pbohandle);
lightmaps[lmap].texture = TexMgr_LoadImage (NULL, name, LMBLOCK_WIDTH, LMBLOCK_HEIGHT, lightmaps[lmap].texture = TexMgr_LoadImage (NULL, name, LMBLOCK_WIDTH, LMBLOCK_HEIGHT,
SRC_LIGHTMAP, lightmaps[lmap].data, "", (src_offset_t)lightmaps[lmap].data, TEXPREF_LINEAR | TEXPREF_NOPICMIP | TEXPREF_PERSIST); SRC_LIGHTMAP, NULL, "", (src_offset_t)lightmaps[lmap].pbodata, TEXPREF_LINEAR | TEXPREF_NOPICMIP | TEXPREF_PERSIST);
GL_BindBufferFunc(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
}
else
{
lightmaps[lmap].texture = TexMgr_LoadImage (NULL, name, LMBLOCK_WIDTH, LMBLOCK_HEIGHT,
SRC_LIGHTMAP, lightmaps[lmap].pbodata, "", (src_offset_t)lightmaps[lmap].pbodata, TEXPREF_LINEAR | TEXPREF_NOPICMIP | TEXPREF_PERSIST);
}
lightmaps[lmap].modified = false; lightmaps[lmap].modified = false;
lightmaps[lmap].rectchange.l = LMBLOCK_WIDTH; lightmaps[lmap].rectchange.l = LMBLOCK_WIDTH;
lightmaps[lmap].rectchange.t = LMBLOCK_HEIGHT; lightmaps[lmap].rectchange.t = LMBLOCK_HEIGHT;
@ -1480,9 +1558,9 @@ void R_RebuildAllLightmaps (void)
{ {
if (fa->flags & SURF_DRAWTILED) if (fa->flags & SURF_DRAWTILED)
continue; continue;
base = lightmaps[fa->lightmaptexturenum].data; base = lightmaps[fa->lightmaptexturenum].pbodata;
base += fa->light_t * LMBLOCK_WIDTH * lightmap_bytes + fa->light_s * lightmap_bytes; base += fa->light_t * LMBLOCK_WIDTH * lightmap_bytes + fa->light_s * lightmap_bytes;
R_BuildLightMap (mod, fa, base, LMBLOCK_WIDTH*lightmap_bytes); R_BuildLightMap (mod, fa, base, LMBLOCK_WIDTH*lightmap_bytes, currententity, r_framecount, cl_dlights);
} }
} }
@ -1493,18 +1571,42 @@ void R_RebuildAllLightmaps (void)
{ {
char name[24]; char name[24];
sprintf(name, "lightmap%07i",i); sprintf(name, "lightmap%07i",i);
if (lightmaps[i].pbohandle)
{
GL_BindBufferFunc(GL_PIXEL_UNPACK_BUFFER_ARB, lightmaps[i].pbohandle);
lightmaps[i].texture = TexMgr_LoadImage (NULL, name, LMBLOCK_WIDTH, LMBLOCK_HEIGHT, lightmaps[i].texture = TexMgr_LoadImage (NULL, name, LMBLOCK_WIDTH, LMBLOCK_HEIGHT,
SRC_LIGHTMAP, lightmaps[i].data, "", (src_offset_t)lightmaps[i].data, TEXPREF_LINEAR | TEXPREF_NOPICMIP | TEXPREF_PERSIST); SRC_LIGHTMAP, NULL, "", (src_offset_t)lightmaps[i].pbodata, TEXPREF_LINEAR | TEXPREF_NOPICMIP | TEXPREF_PERSIST);
GL_BindBufferFunc(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
}
else
{
lightmaps[i].texture = TexMgr_LoadImage (NULL, name, LMBLOCK_WIDTH, LMBLOCK_HEIGHT,
SRC_LIGHTMAP, lightmaps[i].pbodata, "", (src_offset_t)lightmaps[i].pbodata, TEXPREF_LINEAR | TEXPREF_NOPICMIP | TEXPREF_PERSIST);
}
} }
else else
{ {
GL_Bind (lightmaps[i].texture); GL_Bind (lightmaps[i].texture);
if (lightmaps[i].pbohandle)
{
GL_BindBufferFunc(GL_PIXEL_UNPACK_BUFFER_ARB, lightmaps[i].pbohandle);
if (gl_lightmap_format == GL_RGB9_E5) if (gl_lightmap_format == GL_RGB9_E5)
glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, LMBLOCK_WIDTH, LMBLOCK_HEIGHT, GL_RGB, glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, LMBLOCK_WIDTH, LMBLOCK_HEIGHT, GL_RGB,
GL_UNSIGNED_INT_5_9_9_9_REV, lightmaps[i].data); GL_UNSIGNED_INT_5_9_9_9_REV, NULL);
else else
glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, LMBLOCK_WIDTH, LMBLOCK_HEIGHT, gl_lightmap_format, glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, LMBLOCK_WIDTH, LMBLOCK_HEIGHT, gl_lightmap_format,
GL_UNSIGNED_BYTE, lightmaps[i].data); GL_UNSIGNED_BYTE, NULL);
GL_BindBufferFunc(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
}
else
{
if (gl_lightmap_format == GL_RGB9_E5)
glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, LMBLOCK_WIDTH, LMBLOCK_HEIGHT, GL_RGB,
GL_UNSIGNED_INT_5_9_9_9_REV, lightmaps[i].pbodata);
else
glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, LMBLOCK_WIDTH, LMBLOCK_HEIGHT, gl_lightmap_format,
GL_UNSIGNED_BYTE, lightmaps[i].pbodata);
}
} }
lightmaps[i].modified = false; lightmaps[i].modified = false;

File diff suppressed because it is too large Load diff

View file

@ -163,7 +163,9 @@ void R_ViewChanged (vrect_t *pvrect, int lineadj, float aspect);
//void R_InitSky (struct texture_s *mt); // called at level load //void R_InitSky (struct texture_s *mt); // called at level load
void R_CheckEfrags (void); //johnfitz void R_CheckEfrags (void); //johnfitz
void R_AddEfrags (entity_t *ent); //void R_AddEfrags (entity_t *ent);
struct cl_static_entities_s;
void CL_LinkStaticEnt(struct cl_static_entities_s *ent);
void R_NewMap (void); void R_NewMap (void);