Merge pull request #415 from 0lvin/for_review

Soft render speed up
This commit is contained in:
Yamagi 2019-06-25 15:21:50 +02:00 committed by GitHub
commit 75c0450508
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 448 additions and 297 deletions

View file

@ -151,14 +151,8 @@ extern oldrefdef_t r_refdef;
#define TRANSPARENT_COLOR 0xFF #define TRANSPARENT_COLOR 0xFF
#define TURB_TEX_SIZE 64 // base turbulent texture size
#define CYCLE 128 // turbulent cycle size #define CYCLE 128 // turbulent cycle size
#define SCANBUFFERPAD 0x1000
#define DS_SPAN_LIST_END -128
// flags in finalvert_t.flags // flags in finalvert_t.flags
#define ALIAS_LEFT_CLIP 0x0001 #define ALIAS_LEFT_CLIP 0x0001
#define ALIAS_TOP_CLIP 0x0002 #define ALIAS_TOP_CLIP 0x0002
@ -175,8 +169,6 @@ extern oldrefdef_t r_refdef;
#define XCENTERING (1.0 / 2.0) #define XCENTERING (1.0 / 2.0)
#define YCENTERING (1.0 / 2.0) #define YCENTERING (1.0 / 2.0)
#define CLIP_EPSILON 0.001
#define BACKFACE_EPSILON 0.01 #define BACKFACE_EPSILON 0.01
#define NEAR_CLIP 0.01 #define NEAR_CLIP 0.01
@ -184,9 +176,9 @@ extern oldrefdef_t r_refdef;
#define ALIAS_Z_CLIP_PLANE 4 #define ALIAS_Z_CLIP_PLANE 4
// turbulence stuff // turbulence stuff
#define AMP 8*0x10000 #define AMP 8*0x10000
#define AMP2 3 #define AMP2 3
#define SPEED 20 #define SPEED 20
/* /*
@ -310,19 +302,24 @@ typedef struct surf_s
// -1 = in inverted span (end before // -1 = in inverted span (end before
// start) // start)
int flags; // currentface flags int flags; // currentface flags
msurface_t *msurf; msurface_t *msurf;
entity_t *entity; entity_t *entity;
float nearzi; // nearest 1/z on surface, for mipmapping float nearzi; // nearest 1/z on surface, for mipmapping
qboolean insubmodel; qboolean insubmodel;
float d_ziorigin, d_zistepu, d_zistepv; float d_ziorigin, d_zistepu, d_zistepv;
} surf_t; } surf_t;
typedef unsigned short surfindex_t;
// surface index size
#define SURFINDEX_MAX (1 << (sizeof(surfindex_t) * 8))
typedef struct edge_s typedef struct edge_s
{ {
shift20_t u; shift20_t u;
shift20_t u_step; shift20_t u_step;
struct edge_s *prev, *next; struct edge_s *prev, *next;
unsigned short surfs[2]; surfindex_t surfs[2];
struct edge_s *nextremove; struct edge_s *nextremove;
float nearzi; float nearzi;
medge_t *owner; medge_t *owner;
@ -357,14 +354,14 @@ extern pixel_t *r_warpbuffer;
extern float scale_for_mip; extern float scale_for_mip;
extern float d_sdivzstepu, d_tdivzstepu, d_zistepu; extern float d_sdivzstepu, d_tdivzstepu;
extern float d_sdivzstepv, d_tdivzstepv, d_zistepv; extern float d_sdivzstepv, d_tdivzstepv;
extern float d_sdivzorigin, d_tdivzorigin, d_ziorigin; extern float d_sdivzorigin, d_tdivzorigin;
void D_DrawSpansPow2(espan_t *pspans); void D_DrawSpansPow2(espan_t *pspans, float d_ziorigin, float d_zistepu, float d_zistepv);
void D_DrawZSpans(espan_t *pspans); void D_DrawZSpans(espan_t *pspans, float d_ziorigin, float d_zistepu, float d_zistepv);
void TurbulentPow2(espan_t *pspan); void TurbulentPow2(espan_t *pspan, float d_ziorigin, float d_zistepu, float d_zistepv);
void NonTurbulentPow2(espan_t *pspan); void NonTurbulentPow2(espan_t *pspan, float d_ziorigin, float d_zistepu, float d_zistepv);
surfcache_t *D_CacheSurface(const entity_t *currententity, msurface_t *surface, int miplevel); surfcache_t *D_CacheSurface(const entity_t *currententity, msurface_t *surface, int miplevel);
@ -394,6 +391,8 @@ extern vec3_t vpn, base_vpn;
extern vec3_t vright, base_vright; extern vec3_t vright, base_vright;
extern surf_t *surfaces, *surface_p, *surf_max; extern surf_t *surfaces, *surface_p, *surf_max;
// allow some very large lightmaps
extern light_t *blocklights, *blocklight_max;
// surfaces are generated in back to front order by the bsp, so if a surf // surfaces are generated in back to front order by the bsp, so if a surf
// pointer is greater than another one, it should be drawn in front // pointer is greater than another one, it should be drawn in front
@ -457,14 +456,12 @@ extern msurface_t *r_alpha_surfaces;
// //
// current entity info // current entity info
// //
extern qboolean insubmodel;
void R_DrawAlphaSurfaces(const entity_t *currententity); void R_DrawAlphaSurfaces(const entity_t *currententity);
void R_DrawSprite(entity_t *currententity, const model_t *currentmodel); void R_DrawSprite(entity_t *currententity, const model_t *currentmodel);
void R_RenderFace(entity_t *currententity, const model_t *currentmodel, msurface_t *fa, int clipflags); void R_RenderFace(entity_t *currententity, const model_t *currentmodel, msurface_t *fa, int clipflags, qboolean insubmodel);
void R_RenderBmodelFace(entity_t *currententity, bedge_t *pedges, msurface_t *psurf); void R_RenderBmodelFace(entity_t *currententity, bedge_t *pedges, msurface_t *psurf, int r_currentbkey);
void R_TransformFrustum(void); void R_TransformFrustum(void);
void R_DrawSubmodelPolygons(entity_t *currententity, const model_t *currentmodel, int clipflags, mnode_t *topnode); void R_DrawSubmodelPolygons(entity_t *currententity, const model_t *currentmodel, int clipflags, mnode_t *topnode);
@ -483,7 +480,6 @@ extern int sadjust, tadjust;
extern int bbextents, bbextentt; extern int bbextents, bbextentt;
extern int r_currentkey; extern int r_currentkey;
extern int r_currentbkey;
void R_DrawParticles (void); void R_DrawParticles (void);
@ -509,7 +505,9 @@ void R_PolysetDrawSpans8_Opaque(const entity_t *currententity, spanpackage_t *ps
extern byte **warp_rowptr; extern byte **warp_rowptr;
extern int *warp_column; extern int *warp_column;
extern espan_t *edge_basespans; extern espan_t *edge_basespans;
extern espan_t *max_span_p;
extern int r_numallocatedverts; extern int r_numallocatedverts;
extern int r_numallocatededgebasespans;
extern finalvert_t *finalverts, *finalverts_max; extern finalvert_t *finalverts, *finalverts_max;
extern int r_aliasblendcolor; extern int r_aliasblendcolor;
@ -520,6 +518,8 @@ extern qboolean r_outofsurfaces;
extern qboolean r_outofedges; extern qboolean r_outofedges;
extern qboolean r_outofverts; extern qboolean r_outofverts;
extern qboolean r_outoftriangles; extern qboolean r_outoftriangles;
extern qboolean r_outoflights;
extern qboolean r_outedgebasespans;
extern mvertex_t *r_pcurrentvertbase; extern mvertex_t *r_pcurrentvertbase;
@ -530,7 +530,7 @@ void R_AliasClipTriangle(const entity_t *currententity, const finalvert_t *index
extern float r_time1; extern float r_time1;
extern float da_time1, da_time2; extern float da_time1, da_time2;
extern float dp_time1, dp_time2, db_time1, db_time2, rw_time1, rw_time2; extern float dp_time1, dp_time2, db_time1, db_time2, rw_time1, rw_time2;
extern float se_time1, se_time2, de_time1, de_time2, dv_time1, dv_time2; extern float se_time1, se_time2, de_time1, de_time2;
extern int r_viewcluster, r_oldviewcluster; extern int r_viewcluster, r_oldviewcluster;
extern int r_clipflags; extern int r_clipflags;
@ -589,6 +589,6 @@ IMPORTED FUNCTIONS
==================================================================== ====================================================================
*/ */
extern refimport_t ri; extern refimport_t ri;
#endif #endif

View file

@ -46,11 +46,6 @@ typedef struct
vec3_t position; vec3_t position;
} mvertex_t; } mvertex_t;
#define SIDE_FRONT 0
#define SIDE_BACK 1
#define SIDE_ON 2
// plane_t structure // plane_t structure
typedef struct mplane_s typedef struct mplane_s
{ {
@ -231,9 +226,6 @@ typedef struct model_s
//============================================================================ //============================================================================
void Mod_Init(void); void Mod_Init(void);
void Mod_ClearAll(void);
void *Mod_Extradata(model_t *mod); // handles caching
void Mod_TouchModel(char *name);
mleaf_t *Mod_PointInLeaf(float *p, model_t *model); mleaf_t *Mod_PointInLeaf(float *p, model_t *model);
byte *Mod_ClusterPVS(int cluster, model_t *model); byte *Mod_ClusterPVS(int cluster, model_t *model);

View file

@ -31,8 +31,6 @@ vec3_t r_entorigin; // the currently rendering entity in world
static float entity_rotation[3][3]; static float entity_rotation[3][3];
int r_currentbkey;
typedef enum {touchessolid, drawnode, nodrawnode} solidstate_t; typedef enum {touchessolid, drawnode, nodrawnode} solidstate_t;
#define MAX_BMODEL_VERTS 500 // 6K #define MAX_BMODEL_VERTS 500 // 6K
@ -141,6 +139,24 @@ R_RotateBmodel(const entity_t *currententity)
} }
static qboolean
R_AreaVisible(mleaf_t *pleaf)
{
int area;
// check for door connected areas
if (!r_newrefdef.areabits)
return true;
area = pleaf->area;
if ((r_newrefdef.areabits[area>>3] & (1<<(area&7))))
return true;
return false; // not visible
}
/* /*
================ ================
R_RecursiveClipBPoly R_RecursiveClipBPoly
@ -223,25 +239,23 @@ R_RecursiveClipBPoly(entity_t *currententity, bedge_t *pedges, mnode_t *pnode, m
// split into two edges, one on each side, and remember entering // split into two edges, one on each side, and remember entering
// and exiting points // and exiting points
// FIXME: share the clip edge by having a winding direction flag? // FIXME: share the clip edge by having a winding direction flag?
if (numbedges >= (MAX_BMODEL_EDGES - 1)) ptedge = &bedges[numbedges++];
{
R_Printf(PRINT_ALL,"Out of edges for bmodel\n");
return;
}
ptedge = &bedges[numbedges];
ptedge->pnext = psideedges[lastside]; ptedge->pnext = psideedges[lastside];
psideedges[lastside] = ptedge; psideedges[lastside] = ptedge;
ptedge->v[0] = plastvert; ptedge->v[0] = plastvert;
ptedge->v[1] = ptvert; ptedge->v[1] = ptvert;
ptedge = &bedges[numbedges + 1]; ptedge = &bedges[numbedges++];
ptedge->pnext = psideedges[side]; ptedge->pnext = psideedges[side];
psideedges[side] = ptedge; psideedges[side] = ptedge;
ptedge->v[0] = ptvert; ptedge->v[0] = ptvert;
ptedge->v[1] = pvert; ptedge->v[1] = pvert;
numbedges += 2; if (numbedges >= MAX_BMODEL_EDGES)
{
R_Printf(PRINT_ALL,"Out of edges for bmodel\n");
return;
}
if (side == 0) if (side == 0)
{ {
@ -266,25 +280,23 @@ R_RecursiveClipBPoly(entity_t *currententity, bedge_t *pedges, mnode_t *pnode, m
// plane to both sides (but in opposite directions) // plane to both sides (but in opposite directions)
if (makeclippededge && pfrontexit != pfrontenter) if (makeclippededge && pfrontexit != pfrontenter)
{ {
if (numbedges >= (MAX_BMODEL_EDGES - 2)) ptedge = &bedges[numbedges++];
{
R_Printf(PRINT_ALL,"Out of edges for bmodel\n");
return;
}
ptedge = &bedges[numbedges];
ptedge->pnext = psideedges[0]; ptedge->pnext = psideedges[0];
psideedges[0] = ptedge; psideedges[0] = ptedge;
ptedge->v[0] = pfrontexit; ptedge->v[0] = pfrontexit;
ptedge->v[1] = pfrontenter; ptedge->v[1] = pfrontenter;
ptedge = &bedges[numbedges + 1]; ptedge = &bedges[numbedges++];
ptedge->pnext = psideedges[1]; ptedge->pnext = psideedges[1];
psideedges[1] = ptedge; psideedges[1] = ptedge;
ptedge->v[0] = pfrontenter; ptedge->v[0] = pfrontenter;
ptedge->v[1] = pfrontexit; ptedge->v[1] = pfrontexit;
numbedges += 2; if (numbedges >= MAX_BMODEL_EDGES)
{
R_Printf(PRINT_ALL,"Out of edges for bmodel\n");
return;
}
} }
// draw or recurse further // draw or recurse further
@ -303,17 +315,13 @@ R_RecursiveClipBPoly(entity_t *currententity, bedge_t *pedges, mnode_t *pnode, m
{ {
if (pn->contents != CONTENTS_SOLID) if (pn->contents != CONTENTS_SOLID)
{ {
if (r_newrefdef.areabits) int r_currentbkey;
{
int area;
area = ((mleaf_t *)pn)->area; if (!R_AreaVisible((mleaf_t *)pn))
if (! (r_newrefdef.areabits[area>>3] & (1<<(area&7)) ) ) continue;
continue; // not visible
}
r_currentbkey = ((mleaf_t *)pn)->key; r_currentbkey = ((mleaf_t *)pn)->key;
R_RenderBmodelFace(currententity, psideedges[i], psurf); R_RenderBmodelFace(currententity, psideedges[i], psurf, r_currentbkey);
} }
} }
else else
@ -399,14 +407,14 @@ R_DrawSolidClippedSubmodelPolygons(entity_t *currententity, const model_t *curre
pbedge[j-1].pnext = NULL; // mark end of edges pbedge[j-1].pnext = NULL; // mark end of edges
if ( !( psurf->texinfo->flags & ( SURF_TRANS66 | SURF_TRANS33 ) ) ) if ( !( psurf->texinfo->flags & ( SURF_TRANS66 | SURF_TRANS33 ) ))
{ {
// FIXME: Fan broken in borehole // FIXME: Fan broken in borehole
R_RecursiveClipBPoly(currententity, pbedge, topnode, psurf); R_RecursiveClipBPoly(currententity, pbedge, topnode, psurf);
} }
else else
{ {
R_RenderBmodelFace(currententity, pbedge, psurf ); R_RenderBmodelFace(currententity, pbedge, psurf, ((mleaf_t *)topnode)->key);
} }
} }
} }
@ -446,7 +454,7 @@ R_DrawSubmodelPolygons(entity_t *currententity, const model_t *currentmodel, int
r_currentkey = ((mleaf_t *)topnode)->key; r_currentkey = ((mleaf_t *)topnode)->key;
// FIXME: use bounding-box-based frustum clipping info? // FIXME: use bounding-box-based frustum clipping info?
R_RenderFace(currententity, currentmodel, psurf, clipflags); R_RenderFace(currententity, currentmodel, psurf, clipflags, true);
} }
} }
} }
@ -460,7 +468,8 @@ R_RecursiveWorldNode
================ ================
*/ */
static void static void
R_RecursiveWorldNode (entity_t *currententity, const model_t *currentmodel, mnode_t *node, int clipflags) R_RecursiveWorldNode (entity_t *currententity, const model_t *currentmodel, mnode_t *node,
int clipflags, qboolean insubmodel)
{ {
int c; int c;
vec3_t acceptpt, rejectpt; vec3_t acceptpt, rejectpt;
@ -519,12 +528,8 @@ R_RecursiveWorldNode (entity_t *currententity, const model_t *currentmodel, mnod
msurface_t **mark; msurface_t **mark;
pleaf = (mleaf_t *)node; pleaf = (mleaf_t *)node;
// check for door connected areas if (!R_AreaVisible(pleaf))
if (r_newrefdef.areabits) return; // not visible
{
if (! (r_newrefdef.areabits[pleaf->area>>3] & (1<<(pleaf->area&7)) ) )
return; // not visible
}
mark = pleaf->firstmarksurface; mark = pleaf->firstmarksurface;
c = pleaf->nummarksurfaces; c = pleaf->nummarksurfaces;
@ -573,7 +578,7 @@ R_RecursiveWorldNode (entity_t *currententity, const model_t *currentmodel, mnod
side = 1; side = 1;
// recurse down the children, front side first // recurse down the children, front side first
R_RecursiveWorldNode (currententity, currentmodel, node->children[side], clipflags); R_RecursiveWorldNode (currententity, currentmodel, node->children[side], clipflags, insubmodel);
// draw stuff // draw stuff
c = node->numsurfaces; c = node->numsurfaces;
@ -591,7 +596,7 @@ R_RecursiveWorldNode (entity_t *currententity, const model_t *currentmodel, mnod
if ((surf->flags & SURF_PLANEBACK) && if ((surf->flags & SURF_PLANEBACK) &&
(surf->visframe == r_framecount)) (surf->visframe == r_framecount))
{ {
R_RenderFace (currententity, currentmodel, surf, clipflags); R_RenderFace (currententity, currentmodel, surf, clipflags, insubmodel);
} }
surf++; surf++;
@ -604,7 +609,7 @@ R_RecursiveWorldNode (entity_t *currententity, const model_t *currentmodel, mnod
if (!(surf->flags & SURF_PLANEBACK) && if (!(surf->flags & SURF_PLANEBACK) &&
(surf->visframe == r_framecount)) (surf->visframe == r_framecount))
{ {
R_RenderFace (currententity, currentmodel, surf, clipflags); R_RenderFace (currententity, currentmodel, surf, clipflags, insubmodel);
} }
surf++; surf++;
@ -616,7 +621,7 @@ R_RecursiveWorldNode (entity_t *currententity, const model_t *currentmodel, mnod
} }
// recurse down the back side // recurse down the back side
R_RecursiveWorldNode (currententity, currentmodel, node->children[!side], clipflags); R_RecursiveWorldNode (currententity, currentmodel, node->children[!side], clipflags, insubmodel);
} }
} }
@ -643,5 +648,5 @@ R_RenderWorld (void)
VectorCopy (r_origin, modelorg); VectorCopy (r_origin, modelorg);
r_pcurrentvertbase = currentmodel->vertexes; r_pcurrentvertbase = currentmodel->vertexes;
R_RecursiveWorldNode (&r_worldentity, currentmodel, currentmodel->nodes, ALIAS_XY_CLIP_MASK); R_RecursiveWorldNode (&r_worldentity, currentmodel, currentmodel->nodes, ALIAS_XY_CLIP_MASK, false);
} }

View file

@ -77,13 +77,16 @@ smoothly scrolled off.
void void
RE_Draw_CharScaled(int x, int y, int num, float scale) RE_Draw_CharScaled(int x, int y, int num, float scale)
{ {
pixel_t *dest, *dest_max; pixel_t *dest;
byte *source; byte *source;
int drawline; int drawline;
int row, col, u, xpos, ypos, iscale; int row, col, u, xpos, ypos, iscale;
iscale = (int) scale; iscale = (int) scale;
if (iscale < 1)
return;
num &= 255; num &= 255;
if (num == 32 || num == 32+128) if (num == 32 || num == 32+128)
@ -109,7 +112,12 @@ RE_Draw_CharScaled(int x, int y, int num, float scale)
drawline = 8; drawline = 8;
dest = vid_buffer + y * vid.width + x; dest = vid_buffer + y * vid.width + x;
dest_max = vid_buffer + vid.height * vid.width;
// clipped last lines
if ((y + iscale * (drawline + 1)) > vid.height)
{
drawline = (vid.height - y) / iscale;
}
while (drawline--) while (drawline--)
{ {
@ -124,12 +132,6 @@ RE_Draw_CharScaled(int x, int y, int num, float scale)
} }
} }
dest += vid.width; dest += vid.width;
// clipped last lines
if (dest >= dest_max)
{
return;
}
} }
source += 128; source += 128;
} }
@ -160,14 +162,13 @@ RE_Draw_GetPicSize (int *w, int *h, char *pic)
RE_Draw_StretchPicImplementation RE_Draw_StretchPicImplementation
============= =============
*/ */
void static void
RE_Draw_StretchPicImplementation (int x, int y, int w, int h, const image_t *pic) RE_Draw_StretchPicImplementation (int x, int y, int w, int h, const image_t *pic)
{ {
pixel_t *dest; pixel_t *dest;
byte *source; byte *source;
int v, u; int v, u;
int height; int height;
int f, fstep;
int skip; int skip;
if ((x < 0) || if ((x < 0) ||
@ -189,16 +190,24 @@ RE_Draw_StretchPicImplementation (int x, int y, int w, int h, const image_t *pic
dest = vid_buffer + y * vid.width + x; dest = vid_buffer + y * vid.width + x;
for (v=0 ; v<height ; v++, dest += vid.width) if (w == pic->width)
{ {
int sv = (skip + v)*pic->height/h; for (v=0 ; v<height ; v++, dest += vid.width)
source = pic->pixels[0] + sv*pic->width;
if (w == pic->width)
memcpy (dest, source, w);
else
{ {
int sv = (skip + v)*pic->height/h;
source = pic->pixels[0] + sv*pic->width;
memcpy (dest, source, w);
}
}
else
{
for (v=0 ; v<height ; v++, dest += vid.width)
{
int f, fstep;
int sv = (skip + v)*pic->height/h;
source = pic->pixels[0] + sv*pic->width;
f = 0; f = 0;
fstep = (pic->width * SHIFT16XYZ_MULT) / w; fstep = (pic->width << SHIFT16XYZ) / w;
for (u=0 ; u<w ; u++) for (u=0 ; u<w ; u++)
{ {
dest[u] = source[f>>16]; dest[u] = source[f>>16];
@ -266,8 +275,8 @@ RE_Draw_PicScaled(int x, int y, char *name, float scale)
} }
if ((x < 0) || if ((x < 0) ||
(x + pic->width > vid.width) || (x + pic->width * scale > vid.width) ||
(y + pic->height > vid.height)) (y + pic->height * scale > vid.height))
{ {
R_Printf(PRINT_ALL, "Draw_Pic: bad coordinates\n"); R_Printf(PRINT_ALL, "Draw_Pic: bad coordinates\n");
return; return;

View file

@ -36,8 +36,9 @@ have a sentinal at both ends?
edge_t **newedges; edge_t **newedges;
edge_t **removeedges; edge_t **removeedges;
espan_t *edge_basespans; espan_t *edge_basespans;
espan_t *max_span_p;
static espan_t *span_p, *max_span_p; static espan_t *span_p;
int r_currentkey; int r_currentkey;
@ -107,7 +108,8 @@ R_BeginEdgeFrame (void)
R_InsertNewEdges R_InsertNewEdges
Adds the edges in the linked list edgestoadd, adding them to the edges in the Adds the edges in the linked list edgestoadd, adding them to the edges in the
linked list edgelist. edgestoadd is assumed to be sorted on u, and non-empty (this is actually newedges[v]). edgelist is assumed to be sorted on u, with a linked list edgelist. edgestoadd is assumed to be sorted on u, and non-empty
(this is actually newedges[v]). edgelist is assumed to be sorted on u, with a
sentinel at the end (actually, this is the active edge table starting at sentinel at the end (actually, this is the active edge table starting at
edge_head.next). edge_head.next).
============== ==============
@ -205,6 +207,22 @@ R_StepActiveU (edge_t *pedge)
} }
} }
static void
R_InsertSpan (surf_t *surf, shift20_t iu)
{
if (iu > surf->last_u)
{
espan_t *span;
span = span_p++;
span->u = surf->last_u;
span->count = iu - span->u;
span->v = current_iv;
span->pnext = surf->spans;
surf->spans = span;
}
}
/* /*
============== ==============
R_CleanupSpan R_CleanupSpan
@ -214,22 +232,11 @@ static void
R_CleanupSpan (void) R_CleanupSpan (void)
{ {
surf_t *surf; surf_t *surf;
shift20_t iu;
espan_t *span;
// now that we've reached the right edge of the screen, we're done with any // now that we've reached the right edge of the screen, we're done with any
// unfinished surfaces, so emit a span for whatever's on top // unfinished surfaces, so emit a span for whatever's on top
surf = surfaces[1].next; surf = surfaces[1].next;
iu = edge_tail_u_shift20; R_InsertSpan (surf, edge_tail_u_shift20);
if (iu > surf->last_u)
{
span = span_p++;
span->u = surf->last_u;
span->count = iu - span->u;
span->v = current_iv;
span->pnext = surf->spans;
surf->spans = span;
}
// reset spanstate for all surfaces in the surface stack // reset spanstate for all surfaces in the surface stack
do do
@ -295,17 +302,7 @@ R_LeadingEdgeBackwards (const edge_t *edge)
// emit a span (obscures current top) // emit a span (obscures current top)
iu = edge->u >> shift_size; iu = edge->u >> shift_size;
if (iu > surf2->last_u) R_InsertSpan (surf2, iu);
{
espan_t *span;
span = span_p++;
span->u = surf2->last_u;
span->count = iu - span->u;
span->v = current_iv;
span->pnext = surf2->spans;
surf2->spans = span;
}
// set last_u on the new span // set last_u on the new span
surf->last_u = iu; surf->last_u = iu;
@ -332,8 +329,6 @@ R_TrailingEdge
static void static void
R_TrailingEdge (surf_t *surf, edge_t *edge) R_TrailingEdge (surf_t *surf, edge_t *edge)
{ {
espan_t *span;
// don't generate a span if this is an inverted span, with the end // don't generate a span if this is an inverted span, with the end
// edge preceding the start edge (that is, we haven't seen the // edge preceding the start edge (that is, we haven't seen the
// start edge yet) // start edge yet)
@ -345,15 +340,7 @@ R_TrailingEdge (surf_t *surf, edge_t *edge)
// emit a span (current top going away) // emit a span (current top going away)
iu = edge->u >> shift_size; iu = edge->u >> shift_size;
if (iu > surf->last_u) R_InsertSpan (surf, iu);
{
span = span_p++;
span->u = surf->last_u;
span->count = iu - span->u;
span->v = current_iv;
span->pnext = surf->spans;
surf->spans = span;
}
// set last_u on the surface below // set last_u on the surface below
surf->next->last_u = iu; surf->next->last_u = iu;
@ -451,17 +438,7 @@ R_EmitSpanBeforeTop(const edge_t *edge, surf_t *surf, surf_t *surf2)
iu = edge->u >> shift_size; iu = edge->u >> shift_size;
if (iu > surf2->last_u) R_InsertSpan (surf2, iu);
{
espan_t *span;
span = span_p++;
span->u = surf2->last_u;
span->count = iu - span->u;
span->v = current_iv;
span->pnext = surf2->spans;
surf2->spans = span;
}
// set last_u on the new span // set last_u on the new span
surf->last_u = iu; surf->last_u = iu;
@ -623,18 +600,23 @@ void
R_ScanEdges (surf_t *surface) R_ScanEdges (surf_t *surface)
{ {
shift20_t iv, bottom; shift20_t iv, bottom;
espan_t *basespan_p;
surf_t *s; surf_t *s;
basespan_p = edge_basespans; // clear the surface span pointers
max_span_p = edge_basespans + vid.width * 2 - r_refdef.vrect.width; for (s = &surfaces[1] ; s<surf_max ; s++)
if ((vid.width * 2 - r_refdef.vrect.width) < 0)
{ {
R_Printf(PRINT_ALL,"No space in edge_basespans\n"); s->last_u = 0;
return; s->spans = NULL;
} }
span_p = basespan_p; span_p = edge_basespans;
if (span_p + r_refdef.vrect.width >= max_span_p)
{
// Need to more space
r_outedgebasespans = true;
return;
}
// clear active edges to just the background edges around the whole screen // clear active edges to just the background edges around the whole screen
// FIXME: most of this only needs to be set up once // FIXME: most of this only needs to be set up once
@ -687,7 +669,7 @@ R_ScanEdges (surf_t *surface)
// flush the span list if we can't be sure we have enough spans left for // flush the span list if we can't be sure we have enough spans left for
// the next scan // the next scan
if (span_p >= max_span_p) if (span_p + r_refdef.vrect.width >= max_span_p)
{ {
// Draw stuff on screen // Draw stuff on screen
D_DrawSurfaces (surface); D_DrawSurfaces (surface);
@ -696,7 +678,10 @@ R_ScanEdges (surf_t *surface)
for (s = &surfaces[1] ; s<surface ; s++) for (s = &surfaces[1] ; s<surface ; s++)
s->spans = NULL; s->spans = NULL;
span_p = basespan_p; span_p = edge_basespans;
// Need to more space
r_outedgebasespans = true;
} }
if (removeedges[iv]) if (removeedges[iv])
@ -793,7 +778,7 @@ D_CalcGradients
============== ==============
*/ */
static void static void
D_CalcGradients (msurface_t *pface) D_CalcGradients (msurface_t *pface, float d_ziorigin, float d_zistepu, float d_zistepv)
{ {
float mipscale; float mipscale;
vec3_t p_temp1; vec3_t p_temp1;
@ -855,14 +840,10 @@ The grey background filler seen when there is a hole in the map
static void static void
D_BackgroundSurf (surf_t *s) D_BackgroundSurf (surf_t *s)
{ {
D_FlatFillSurface (s, (int)sw_clearcolor->value & 0xFF);
// set up a gradient for the background surface that places it // set up a gradient for the background surface that places it
// effectively at infinity distance from the viewpoint // effectively at infinity distance from the viewpoint
d_zistepu = 0; D_DrawZSpans (s->spans, -0.9, 0, 0);
d_zistepv = 0;
d_ziorigin = -0.9;
D_FlatFillSurface (s, (int)sw_clearcolor->value & 0xFF);
D_DrawZSpans (s->spans);
} }
/* /*
@ -873,10 +854,6 @@ D_TurbulentSurf
static void static void
D_TurbulentSurf(surf_t *s) D_TurbulentSurf(surf_t *s)
{ {
d_zistepu = s->d_zistepu;
d_zistepv = s->d_zistepv;
d_ziorigin = s->d_ziorigin;
pface = s->msurf; pface = s->msurf;
miplevel = 0; miplevel = 0;
cacheblock = pface->texinfo->image->pixels[0]; cacheblock = pface->texinfo->image->pixels[0];
@ -898,17 +875,17 @@ D_TurbulentSurf(surf_t *s)
// make entity passed in // make entity passed in
} }
D_CalcGradients (pface); D_CalcGradients (pface, s->d_ziorigin, s->d_zistepu, s->d_zistepv);
//============ //============
// textures that aren't warping are just flowing. Use NonTurbulentPow2 instead // textures that aren't warping are just flowing. Use NonTurbulentPow2 instead
if(!(pface->texinfo->flags & SURF_WARP)) if(!(pface->texinfo->flags & SURF_WARP))
NonTurbulentPow2 (s->spans); NonTurbulentPow2 (s->spans, s->d_ziorigin, s->d_zistepu, s->d_zistepv);
else else
TurbulentPow2 (s->spans); TurbulentPow2 (s->spans, s->d_ziorigin, s->d_zistepu, s->d_zistepv);
//============ //============
D_DrawZSpans (s->spans); D_DrawZSpans (s->spans, s->d_ziorigin, s->d_zistepu, s->d_zistepv);
if (s->insubmodel) if (s->insubmodel)
{ {
@ -941,21 +918,13 @@ D_SkySurf (surf_t *s)
cacheblock = pface->texinfo->image->pixels[0]; cacheblock = pface->texinfo->image->pixels[0];
cachewidth = 256; cachewidth = 256;
d_zistepu = s->d_zistepu; D_CalcGradients (pface, s->d_ziorigin, s->d_zistepu, s->d_zistepv);
d_zistepv = s->d_zistepv;
d_ziorigin = s->d_ziorigin;
D_CalcGradients (pface); D_DrawSpansPow2 (s->spans, s->d_ziorigin, s->d_zistepu, s->d_zistepv);
D_DrawSpansPow2 (s->spans);
// set up a gradient for the background surface that places it // set up a gradient for the background surface that places it
// effectively at infinity distance from the viewpoint // effectively at infinity distance from the viewpoint
d_zistepu = 0; D_DrawZSpans (s->spans, -0.9, 0, 0);
d_zistepv = 0;
d_ziorigin = -0.9;
D_DrawZSpans (s->spans);
} }
/* /*
@ -970,10 +939,6 @@ D_SolidSurf (surf_t *s)
{ {
entity_t *currententity; entity_t *currententity;
d_zistepu = s->d_zistepu;
d_zistepv = s->d_zistepv;
d_ziorigin = s->d_ziorigin;
if (s->insubmodel) if (s->insubmodel)
{ {
vec3_t local_modelorg; vec3_t local_modelorg;
@ -999,11 +964,11 @@ D_SolidSurf (surf_t *s)
cacheblock = (pixel_t *)pcurrentcache->data; cacheblock = (pixel_t *)pcurrentcache->data;
cachewidth = pcurrentcache->width; cachewidth = pcurrentcache->width;
D_CalcGradients (pface); D_CalcGradients (pface, s->d_ziorigin, s->d_zistepu, s->d_zistepv);
D_DrawSpansPow2 (s->spans); D_DrawSpansPow2 (s->spans, s->d_ziorigin, s->d_zistepu, s->d_zistepv);
D_DrawZSpans (s->spans); D_DrawZSpans (s->spans, s->d_ziorigin, s->d_zistepu, s->d_zistepv);
if (s->insubmodel) if (s->insubmodel)
{ {
@ -1039,14 +1004,10 @@ D_DrawflatSurfaces (surf_t *surface)
if (!s->spans) if (!s->spans)
continue; continue;
d_zistepu = s->d_zistepu;
d_zistepv = s->d_zistepv;
d_ziorigin = s->d_ziorigin;
// make a stable color for each surface by taking the low // make a stable color for each surface by taking the low
// bits of the msurface pointer // bits of the msurface pointer
D_FlatFillSurface (s, color & 0xFF); D_FlatFillSurface (s, color & 0xFF);
D_DrawZSpans (s->spans); D_DrawZSpans (s->spans, s->d_ziorigin, s->d_zistepu, s->d_zistepv);
color ++; color ++;
} }

View file

@ -265,7 +265,7 @@ R_LightPoint (const entity_t *currententity, vec3_t p, vec3_t color)
//=================================================================== //===================================================================
unsigned blocklights[1024]; // allow some very large lightmaps light_t *blocklights = NULL, *blocklight_max = NULL;
/* /*
=============== ===============
@ -292,6 +292,12 @@ R_AddDynamicLights (drawsurf_t* drawsurf)
tmax = (surf->extents[1]>>4)+1; tmax = (surf->extents[1]>>4)+1;
tex = surf->texinfo; tex = surf->texinfo;
if (blocklight_max <= blocklights + smax*tmax)
{
r_outoflights = true;
return;
}
for (lnum=0 ; lnum<r_newrefdef.num_dlights ; lnum++) for (lnum=0 ; lnum<r_newrefdef.num_dlights ; lnum++)
{ {
light_t *plightdest = blocklights; light_t *plightdest = blocklights;
@ -385,6 +391,11 @@ R_BuildLightMap (drawsurf_t* drawsurf)
smax = (surf->extents[0]>>4)+1; smax = (surf->extents[0]>>4)+1;
tmax = (surf->extents[1]>>4)+1; tmax = (surf->extents[1]>>4)+1;
size = smax*tmax; size = smax*tmax;
if (blocklight_max <= blocklights + size)
{
r_outoflights = true;
return;
}
if (r_fullbright->value || !r_worldmodel->lightdata) if (r_fullbright->value || !r_worldmodel->lightdata)
{ {

View file

@ -30,9 +30,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define NUMSTACKEDGES 2048 #define NUMSTACKEDGES 2048
#define NUMSTACKSURFACES 1024 #define NUMSTACKSURFACES 1024
#define MAXALIASVERTS 2048 #define MAXALIASVERTS 2048
#define MAXLIGHTS 1024 // allow some very large lightmaps
viddef_t vid; viddef_t vid;
pixel_t *vid_buffer = NULL; pixel_t *vid_buffer = NULL;
static pixel_t *swap_buffers = NULL;
static pixel_t *swap_frames[2] = {NULL, NULL};
static int swap_current = 0;
espan_t *vid_polygon_spans = NULL; espan_t *vid_polygon_spans = NULL;
pixel_t *vid_colormap = NULL; pixel_t *vid_colormap = NULL;
pixel_t *vid_alphamap = NULL; pixel_t *vid_alphamap = NULL;
@ -68,11 +72,15 @@ float r_time1;
int r_numallocatededges; int r_numallocatededges;
int r_numallocatedverts; int r_numallocatedverts;
int r_numallocatedtriangles; int r_numallocatedtriangles;
int r_numallocatedlights;
int r_numallocatededgebasespans;
float r_aliasuvscale = 1.0; float r_aliasuvscale = 1.0;
qboolean r_outofsurfaces; qboolean r_outofsurfaces;
qboolean r_outofedges; qboolean r_outofedges;
qboolean r_outofverts; qboolean r_outofverts;
qboolean r_outoftriangles; qboolean r_outoftriangles;
qboolean r_outoflights;
qboolean r_outedgebasespans;
qboolean r_dowarp; qboolean r_dowarp;
@ -176,9 +184,9 @@ static cvar_t *r_lockpvs;
// FIXME: make into one big structure, like cl or sv // FIXME: make into one big structure, like cl or sv
// FIXME: do separately for refresh engine and driver // FIXME: do separately for refresh engine and driver
float d_sdivzstepu, d_tdivzstepu, d_zistepu; float d_sdivzstepu, d_tdivzstepu;
float d_sdivzstepv, d_tdivzstepv, d_zistepv; float d_sdivzstepv, d_tdivzstepv;
float d_sdivzorigin, d_tdivzorigin, d_ziorigin; float d_sdivzorigin, d_tdivzorigin;
int sadjust, tadjust, bbextents, bbextentt; int sadjust, tadjust, bbextents, bbextentt;
@ -187,11 +195,11 @@ int cachewidth;
pixel_t *d_viewbuffer; pixel_t *d_viewbuffer;
zvalue_t *d_pzbuffer; zvalue_t *d_pzbuffer;
qboolean insubmodel;
static void Draw_GetPalette (void); static void Draw_GetPalette (void);
static void RE_BeginFrame( float camera_separation ); static void RE_BeginFrame( float camera_separation );
static void Draw_BuildGammaTable(void); static void Draw_BuildGammaTable(void);
static void RE_FlushFrame(int vmin);
static void RE_CleanFrame(void);
static void RE_EndFrame(void); static void RE_EndFrame(void);
static void R_DrawBeam(const entity_t *e); static void R_DrawBeam(const entity_t *e);
@ -382,6 +390,14 @@ R_ReallocateMapBuffers (void)
if (r_cnumsurfs < NUMSTACKSURFACES) if (r_cnumsurfs < NUMSTACKSURFACES)
r_cnumsurfs = NUMSTACKSURFACES; r_cnumsurfs = NUMSTACKSURFACES;
// edge_t->surf limited size to short
if (r_cnumsurfs > SURFINDEX_MAX)
{
r_cnumsurfs = SURFINDEX_MAX;
R_Printf(PRINT_ALL, "%s: Code has limitation to surfaces count.\n",
__func__);
}
lsurfs = malloc (r_cnumsurfs * sizeof(surf_t)); lsurfs = malloc (r_cnumsurfs * sizeof(surf_t));
if (!lsurfs) if (!lsurfs)
{ {
@ -393,14 +409,46 @@ R_ReallocateMapBuffers (void)
surfaces = lsurfs; surfaces = lsurfs;
// set limits // set limits
surf_max = &surfaces[r_cnumsurfs]; surf_max = &surfaces[r_cnumsurfs];
surface_p = lsurfs;
// surface 0 doesn't really exist; it's just a dummy because index 0 // surface 0 doesn't really exist; it's just a dummy because index 0
// is used to indicate no edge attached to surface // is used to indicate no edge attached to surface
surfaces--; surfaces--;
surface_p = &surfaces[2]; // background is surface 1,
// surface 0 is a dummy
R_Printf(PRINT_ALL, "Allocated %d surfaces\n", r_cnumsurfs); R_Printf(PRINT_ALL, "Allocated %d surfaces\n", r_cnumsurfs);
} }
if (!r_numallocatedlights || r_outoflights)
{
if (!blocklights)
{
free(blocklights);
}
if (r_outoflights)
{
r_numallocatedlights *= 2;
r_outoflights = false;
}
if (r_numallocatedlights < MAXLIGHTS)
r_numallocatedlights = MAXLIGHTS;
blocklights = malloc (r_numallocatedlights * sizeof(light_t));
if (!blocklights)
{
R_Printf(PRINT_ALL, "%s: Couldn't malloc %d bytes\n",
__func__, (int)(r_numallocatedlights * sizeof(light_t)));
return;
}
// set limits
blocklight_max = &blocklights[r_numallocatedlights];
R_Printf(PRINT_ALL, "Allocated %d lights\n", r_numallocatedlights);
}
if (!r_numallocatededges || r_outofedges) if (!r_numallocatededges || r_outofedges)
{ {
if (!r_edges) if (!r_edges)
@ -487,6 +535,35 @@ R_ReallocateMapBuffers (void)
R_Printf(PRINT_ALL, "Allocated %d triangles\n", r_numallocatedtriangles); R_Printf(PRINT_ALL, "Allocated %d triangles\n", r_numallocatedtriangles);
} }
if (!r_numallocatededgebasespans || r_outedgebasespans)
{
if (edge_basespans)
{
free(edge_basespans);
}
if (r_outedgebasespans)
{
r_numallocatededgebasespans *= 2;
r_outedgebasespans = false;
}
// used up to 8 * width spans for render, allocate once before use
if (r_numallocatededgebasespans < vid.width * 8)
r_numallocatededgebasespans = vid.width * 8;
edge_basespans = malloc(r_numallocatededgebasespans * sizeof(espan_t));
if (!edge_basespans)
{
R_Printf(PRINT_ALL, "%s: Couldn't malloc %d bytes\n",
__func__, (int)(r_numallocatededgebasespans * sizeof(espan_t)));
return;
}
max_span_p = &edge_basespans[r_numallocatededgebasespans];
R_Printf(PRINT_ALL, "Allocated %d edgespans\n", r_numallocatededgebasespans);
}
} }
@ -839,7 +916,6 @@ R_DrawBEntitiesOnList (void)
return; return;
VectorCopy (modelorg, oldorigin); VectorCopy (modelorg, oldorigin);
insubmodel = true;
for (i=0 ; i<r_newrefdef.num_entities ; i++) for (i=0 ; i<r_newrefdef.num_entities ; i++)
{ {
@ -901,8 +977,6 @@ R_DrawBEntitiesOnList (void)
VectorCopy (oldorigin, modelorg); VectorCopy (oldorigin, modelorg);
R_TransformFrustum (); R_TransformFrustum ();
} }
insubmodel = false;
} }
/* /*
@ -1242,10 +1316,7 @@ RE_SetPalette(const unsigned char *palette)
byte palette32[1024]; byte palette32[1024];
// clear screen to black to avoid any palette flash // clear screen to black to avoid any palette flash
memset(vid_buffer, 0, vid.height * vid.width * sizeof(pixel_t)); RE_CleanFrame();
// flush it to the screen
RE_EndFrame ();
if (palette) if (palette)
{ {
@ -1592,11 +1663,14 @@ RE_InitContext(void *win)
static void static void
RE_ShutdownContext(void) RE_ShutdownContext(void)
{ {
if (vid_buffer) if (swap_buffers)
{ {
free(vid_buffer); free(swap_buffers);
} }
swap_buffers = NULL;
vid_buffer = NULL; vid_buffer = NULL;
swap_frames[0] = NULL;
swap_frames[1] = NULL;
if (sintable) if (sintable)
{ {
@ -1664,6 +1738,12 @@ RE_ShutdownContext(void)
} }
finalverts = NULL; finalverts = NULL;
if(blocklights)
{
free(blocklights);
}
blocklights = NULL;
if(r_edges) if(r_edges)
{ {
free(r_edges); free(r_edges);
@ -1702,7 +1782,7 @@ point math used in R_ScanEdges() overflows at width 2048 !!
char shift_size; char shift_size;
static void static void
RE_CopyFrame (Uint32 * pixels, int pitch) RE_CopyFrame (Uint32 * pixels, int pitch, int vmin, int vmax)
{ {
Uint32 *sdl_palette = (Uint32 *)sw_state.currentpalette; Uint32 *sdl_palette = (Uint32 *)sw_state.currentpalette;
@ -1713,10 +1793,10 @@ RE_CopyFrame (Uint32 * pixels, int pitch)
Uint32 *pixels_pos; Uint32 *pixels_pos;
pixel_t *buffer_pos; pixel_t *buffer_pos;
max_pixels = pixels + vid.height * vid.width; max_pixels = pixels + vmax * vid.width;
buffer_pos = vid_buffer; buffer_pos = vid_buffer + vmin * vid.width;
for (pixels_pos = pixels; pixels_pos < max_pixels; pixels_pos++) for (pixels_pos = pixels + vmin * vid.width; pixels_pos < max_pixels; pixels_pos++)
{ {
*pixels_pos = sdl_palette[*buffer_pos]; *pixels_pos = sdl_palette[*buffer_pos];
buffer_pos++; buffer_pos++;
@ -1727,7 +1807,7 @@ RE_CopyFrame (Uint32 * pixels, int pitch)
int y,x, buffer_pos; int y,x, buffer_pos;
buffer_pos = 0; buffer_pos = 0;
for (y=0; y < vid.height; y++) for (y=vmin; y < vmax; y++)
{ {
for (x=0; x < vid.width; x ++) for (x=0; x < vid.width; x ++)
{ {
@ -1739,32 +1819,89 @@ RE_CopyFrame (Uint32 * pixels, int pitch)
} }
} }
/* static int
** RE_EndFrame RE_BufferDifferenceStart(int vmin, int vmax)
** {
** This does an implementation specific copy from the backbuffer to the int *front_buffer, *back_buffer, *back_max;
** front buffer. In the Win32 case it uses BitBlt or BltFast depending
** on whether we're using DIB sections/GDI or DDRAW. back_buffer = (int*)swap_frames[0] + vmin * vid.width;
*/ front_buffer = (int*)swap_frames[1] + vmin * vid.width;
back_max = (int*)swap_frames[0] + vmax * vid.width;
while (back_buffer < back_max && *back_buffer == *front_buffer) {
back_buffer ++;
front_buffer ++;
}
return ((pixel_t*)back_buffer - swap_frames[0]) / vid.width;
}
static void static void
RE_EndFrame (void) RE_CleanFrame(void)
{ {
int pitch; int pitch;
Uint32 * pixels; Uint32 *pixels;
memset(swap_buffers, 0, vid.height * vid.width * sizeof(pixel_t) * 2);
if (SDL_LockTexture(texture, NULL, (void**)&pixels, &pitch)) if (SDL_LockTexture(texture, NULL, (void**)&pixels, &pitch))
{ {
Com_Printf("Can't lock texture: %s\n", SDL_GetError()); Com_Printf("Can't lock texture: %s\n", SDL_GetError());
return; return;
} }
RE_CopyFrame (pixels, pitch / sizeof(Uint32)); memset(pixels, 0, pitch * vid.height);
SDL_UnlockTexture(texture); SDL_UnlockTexture(texture);
SDL_RenderCopy(renderer, texture, NULL, NULL); SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer); SDL_RenderPresent(renderer);
} }
static void
RE_FlushFrame(int vmin)
{
int pitch;
Uint32 *pixels;
SDL_Rect copy_rect;
copy_rect.x = 0;
copy_rect.y = vmin;
copy_rect.w = vid.width;
copy_rect.h = vid.height - vmin;
if (SDL_LockTexture(texture, NULL, (void**)&pixels, &pitch))
{
Com_Printf("Can't lock texture: %s\n", SDL_GetError());
return;
}
RE_CopyFrame (pixels, pitch / sizeof(Uint32), vmin, vid.height);
SDL_UnlockTexture(texture);
SDL_RenderCopy(renderer, texture, &copy_rect, &copy_rect);
SDL_RenderPresent(renderer);
// replace use next buffer
swap_current ++;
vid_buffer = swap_frames[swap_current&1];
}
/*
** RE_EndFrame
**
** This does an implementation specific copy from the backbuffer to the
** front buffer.
*/
static void
RE_EndFrame (void)
{
int vmin;
vmin = RE_BufferDifferenceStart(0, vid.height);
if (vmin >= vid.height)
{
return;
}
RE_FlushFrame(vmin);
}
/* /*
** SWimp_SetMode ** SWimp_SetMode
*/ */
@ -1807,7 +1944,11 @@ SWimp_SetMode(int *pwidth, int *pheight, int mode, int fullscreen )
static void static void
SWimp_CreateRender(void) SWimp_CreateRender(void)
{ {
vid_buffer = malloc(vid.height * vid.width * sizeof(pixel_t)); swap_current = 0;
swap_buffers = malloc(vid.height * vid.width * sizeof(pixel_t) * 2);
swap_frames[0] = swap_buffers;
swap_frames[1] = swap_buffers + vid.height * vid.width * sizeof(pixel_t);
vid_buffer = swap_frames[swap_current&1];
sintable = malloc((vid.width+CYCLE) * sizeof(int)); sintable = malloc((vid.width+CYCLE) * sizeof(int));
intsintable = malloc((vid.width+CYCLE) * sizeof(int)); intsintable = malloc((vid.width+CYCLE) * sizeof(int));
@ -1819,17 +1960,27 @@ SWimp_CreateRender(void)
warp_rowptr = malloc((vid.width+AMP2*2) * sizeof(byte*)); warp_rowptr = malloc((vid.width+AMP2*2) * sizeof(byte*));
warp_column = malloc((vid.width+AMP2*2) * sizeof(int)); warp_column = malloc((vid.width+AMP2*2) * sizeof(int));
edge_basespans = malloc((vid.width*2) * sizeof(espan_t));
// count of "out of items" // count of "out of items"
r_outofsurfaces = r_outofedges = r_outofverts = r_outoftriangles = false; r_outofsurfaces = false;
r_outofedges = false;
r_outofverts = false;
r_outoftriangles = false;
r_outoflights = false;
r_outedgebasespans = false;
// pointers to allocated buffers // pointers to allocated buffers
finalverts = NULL; finalverts = NULL;
r_edges = NULL; r_edges = NULL;
lsurfs = NULL; lsurfs = NULL;
triangle_spans = NULL; triangle_spans = NULL;
blocklights = NULL;
edge_basespans = NULL;
// curently allocated items // curently allocated items
r_cnumsurfs = r_numallocatededges = r_numallocatedverts = r_numallocatedtriangles = 0; r_cnumsurfs = 0;
r_numallocatededges = 0;
r_numallocatedverts = 0;
r_numallocatedtriangles = 0;
r_numallocatedlights = 0;
r_numallocatededgebasespans = 0;
R_ReallocateMapBuffers(); R_ReallocateMapBuffers();

View file

@ -43,9 +43,7 @@ D_ViewChanged
static void static void
D_ViewChanged (void) D_ViewChanged (void)
{ {
scale_for_mip = xscale; scale_for_mip = sqrt(xscale*xscale + yscale*yscale);
if (yscale > xscale)
scale_for_mip = yscale;
d_pix_min = r_refdef.vrect.height / 240; d_pix_min = r_refdef.vrect.height / 240;
if (d_pix_min < 1) if (d_pix_min < 1)

View file

@ -494,15 +494,9 @@ Mod_LoadTexinfo (lump_t *l)
} }
len1 = VectorLength (out->vecs[0]); len1 = VectorLength (out->vecs[0]);
len2 = VectorLength (out->vecs[1]); len2 = VectorLength (out->vecs[1]);
len1 = (len1 + len2)/2; out->mipadjust = sqrt(len1*len1 + len2*len2);
if (len1 < 0.32) if (out->mipadjust < 0.01)
out->mipadjust = 4; out->mipadjust = 0.01;
else if (len1 < 0.49)
out->mipadjust = 3;
else if (len1 < 0.99)
out->mipadjust = 2;
else
out->mipadjust = 1;
out->flags = LittleLong (in->flags); out->flags = LittleLong (in->flags);
@ -1226,6 +1220,8 @@ SPRITE MODELS
/* /*
================= =================
Mod_LoadSpriteModel Mod_LoadSpriteModel
support for .sp2 sprites
================= =================
*/ */
static void static void

View file

@ -101,6 +101,11 @@ R_DrawParticle(particle_t *pparticle, int level)
** render the appropriate pixels ** render the appropriate pixels
*/ */
count = pix; count = pix;
if ((pz[(vid.width * count / 2) + (count / 2)]) > izi)
{
// looks like under some object
return;
}
if (custom_particle == 0) if (custom_particle == 0)
{ {

View file

@ -592,7 +592,7 @@ R_ClipPolyFace (int nump, clipplane_t *pclipplane)
*/ */
// iswater was qboolean. changed to allow passing more flags // iswater was qboolean. changed to allow passing more flags
static void static void
R_PolygonDrawSpans(espan_t *pspan, int iswater ) R_PolygonDrawSpans(espan_t *pspan, int iswater, float d_ziorigin, float d_zistepu, float d_zistepv)
{ {
int snext, tnext; int snext, tnext;
float sdivz, tdivz, zi, z, du, dv, spancountminus1; float sdivz, tdivz, zi, z, du, dv, spancountminus1;
@ -749,7 +749,7 @@ R_PolygonDrawSpans(espan_t *pspan, int iswater )
pspan++; pspan++;
} while (pspan->count != DS_SPAN_LIST_END); } while (pspan->count != INT_MIN);
} }
/* /*
@ -818,6 +818,8 @@ R_PolygonScanLeftEdge (espan_t *s_polygon_spans)
i = r_polydesc.nump; i = r_polydesc.nump;
} while (i != lmaxindex); } while (i != lmaxindex);
pspan->count = INT_MIN; // mark the end of the span list
} }
/* /*
@ -903,7 +905,7 @@ R_PolygonScanRightEdge(espan_t *s_polygon_spans)
} while (i != s_maxindex); } while (i != s_maxindex);
pspan->count = DS_SPAN_LIST_END; // mark the end of the span list pspan->count = INT_MIN; // mark the end of the span list
} }
/* /*
@ -1111,10 +1113,11 @@ R_BuildPolygonFromSurface(const entity_t *currententity, const model_t *currentm
** R_PolygonCalculateGradients ** R_PolygonCalculateGradients
*/ */
static void static void
R_PolygonCalculateGradients (void) R_PolygonCalculateGradients (float *p_ziorigin, float *p_zistepu, float *p_zistepv)
{ {
vec3_t p_normal, p_saxis, p_taxis; vec3_t p_normal, p_saxis, p_taxis;
float distinv; float distinv;
float d_ziorigin, d_zistepu, d_zistepv;
TransformVector (r_polydesc.vpn, p_normal); TransformVector (r_polydesc.vpn, p_normal);
TransformVector (r_polydesc.vright, p_saxis); TransformVector (r_polydesc.vright, p_saxis);
@ -1140,6 +1143,10 @@ R_PolygonCalculateGradients (void)
// -1 (-epsilon) so we never wander off the edge of the texture // -1 (-epsilon) so we never wander off the edge of the texture
bbextents = (r_polydesc.pixel_width << SHIFT16XYZ) - 1; bbextents = (r_polydesc.pixel_width << SHIFT16XYZ) - 1;
bbextentt = (r_polydesc.pixel_height << SHIFT16XYZ) - 1; bbextentt = (r_polydesc.pixel_height << SHIFT16XYZ) - 1;
*p_zistepu = d_zistepu;
*p_zistepv = d_zistepv;
*p_ziorigin = d_ziorigin;
} }
/* /*
@ -1157,6 +1164,7 @@ R_DrawPoly(int iswater, espan_t *spans)
int i, nump; int i, nump;
float ymin, ymax; float ymin, ymax;
emitpoint_t *pverts; emitpoint_t *pverts;
float d_ziorigin, d_zistepu, d_zistepv;
// find the top and bottom vertices, and make sure there's at least one scan to // find the top and bottom vertices, and make sure there's at least one scan to
// draw // draw
@ -1196,11 +1204,11 @@ R_DrawPoly(int iswater, espan_t *spans)
pverts = r_polydesc.pverts; pverts = r_polydesc.pverts;
pverts[nump] = pverts[0]; pverts[nump] = pverts[0];
R_PolygonCalculateGradients(); R_PolygonCalculateGradients(&d_ziorigin, &d_zistepu, &d_zistepv);
R_PolygonScanLeftEdge(spans); R_PolygonScanLeftEdge(spans);
R_PolygonScanRightEdge(spans); R_PolygonScanRightEdge(spans);
R_PolygonDrawSpans(spans, iswater); R_PolygonDrawSpans(spans, iswater, d_ziorigin, d_zistepu, d_zistepv);
} }
/* /*

View file

@ -35,15 +35,9 @@ int c_faceclip; // number of faces clipped
clipplane_t view_clipplanes[4]; clipplane_t view_clipplanes[4];
medge_t *r_pedge;
edge_t *r_edges = NULL, *edge_p = NULL, *edge_max = NULL; edge_t *r_edges = NULL, *edge_p = NULL, *edge_max = NULL;
surf_t *surfaces = NULL, *surface_p = NULL, *surf_max = NULL; surf_t *surfaces = NULL, *surface_p = NULL, *surf_max = NULL;
static qboolean r_leftclipped, r_rightclipped;
static qboolean makeleftedge, makerightedge;
static qboolean r_nearzionly;
int *sintable; int *sintable;
int *intsintable; int *intsintable;
int *blanktable; int *blanktable;
@ -163,7 +157,7 @@ R_EmitSkyBox
================ ================
*/ */
static void static void
R_EmitSkyBox(entity_t *currententity, const model_t *currentmodel) R_EmitSkyBox(entity_t *currententity, const model_t *currentmodel, qboolean insubmodel)
{ {
int i, j; int i, j;
int oldkey; int oldkey;
@ -199,7 +193,7 @@ R_EmitSkyBox(entity_t *currententity, const model_t *currentmodel)
r_currentkey = 0x7ffffff0; r_currentkey = 0x7ffffff0;
for (i=0 ; i<6 ; i++) for (i=0 ; i<6 ; i++)
{ {
R_RenderFace(currententity, currentmodel, r_skyfaces + i, ALIAS_XY_CLIP_MASK); R_RenderFace(currententity, currentmodel, r_skyfaces + i, ALIAS_XY_CLIP_MASK, insubmodel);
} }
r_currentkey = oldkey; // bsp sorting order r_currentkey = oldkey; // bsp sorting order
} }
@ -210,10 +204,10 @@ R_EmitEdge
================ ================
*/ */
static void static void
R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1) R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1, medge_t *r_pedge, qboolean r_nearzionly)
{ {
edge_t *edge, *pcheck; edge_t *edge, *pcheck;
int u_check; int u_check;
float u, u_step; float u, u_step;
vec3_t local, transformed; vec3_t local, transformed;
float *world; float *world;
@ -387,14 +381,15 @@ R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1)
removeedges[v2] = edge; removeedges[v2] = edge;
} }
/* /*
================ ================
R_ClipEdge R_ClipEdge
================ ================
*/ */
static void static void
R_ClipEdge (mvertex_t *pv0, mvertex_t *pv1, clipplane_t *clip) R_ClipEdge (mvertex_t *pv0, mvertex_t *pv1, clipplane_t *clip, medge_t *r_pedge,
qboolean *r_leftclipped, qboolean *r_rightclipped,
qboolean r_nearzionly)
{ {
if (clip) if (clip)
{ {
@ -429,16 +424,18 @@ R_ClipEdge (mvertex_t *pv0, mvertex_t *pv1, clipplane_t *clip)
if (clip->leftedge) if (clip->leftedge)
{ {
r_leftclipped = true; *r_leftclipped = true;
r_leftexit = clipvert; r_leftexit = clipvert;
} }
else if (clip->rightedge) else if (clip->rightedge)
{ {
r_rightclipped = true; *r_rightclipped = true;
r_rightexit = clipvert; r_rightexit = clipvert;
} }
R_ClipEdge (pv0, &clipvert, clip->next); R_ClipEdge (pv0, &clipvert, clip->next, r_pedge,
r_leftclipped, r_rightclipped,
r_nearzionly);
return; return;
} }
else else
@ -470,23 +467,25 @@ R_ClipEdge (mvertex_t *pv0, mvertex_t *pv1, clipplane_t *clip)
if (clip->leftedge) if (clip->leftedge)
{ {
r_leftclipped = true; *r_leftclipped = true;
r_leftenter = clipvert; r_leftenter = clipvert;
} }
else if (clip->rightedge) else if (clip->rightedge)
{ {
r_rightclipped = true; *r_rightclipped = true;
r_rightenter = clipvert; r_rightenter = clipvert;
} }
R_ClipEdge (&clipvert, pv1, clip->next); R_ClipEdge (&clipvert, pv1, clip->next, r_pedge,
r_leftclipped, r_rightclipped,
r_nearzionly);
return; return;
} }
} while ((clip = clip->next) != NULL); } while ((clip = clip->next) != NULL);
} }
// add the edge // add the edge
R_EmitEdge (pv0, pv1); R_EmitEdge (pv0, pv1, r_pedge, r_nearzionly);
} }
/* /*
@ -495,7 +494,7 @@ R_EmitCachedEdge
================ ================
*/ */
static void static void
R_EmitCachedEdge (void) R_EmitCachedEdge (medge_t *r_pedge)
{ {
edge_t *pedge_t; edge_t *pedge_t;
@ -519,7 +518,8 @@ R_RenderFace
================ ================
*/ */
void void
R_RenderFace (entity_t *currententity, const model_t *currentmodel, msurface_t *fa, int clipflags) R_RenderFace (entity_t *currententity, const model_t *currentmodel, msurface_t *fa,
int clipflags, qboolean insubmodel)
{ {
int i; int i;
unsigned mask; unsigned mask;
@ -528,6 +528,9 @@ R_RenderFace (entity_t *currententity, const model_t *currentmodel, msurface_t *
vec3_t p_normal; vec3_t p_normal;
medge_t *pedges, tedge; medge_t *pedges, tedge;
clipplane_t *pclip; clipplane_t *pclip;
qboolean r_leftclipped, r_rightclipped;
qboolean makeleftedge, makerightedge;
qboolean r_nearzionly;
// translucent surfaces are not drawn by the edge renderer // translucent surfaces are not drawn by the edge renderer
if (fa->texinfo->flags & (SURF_TRANS33|SURF_TRANS66)) if (fa->texinfo->flags & (SURF_TRANS33|SURF_TRANS66))
@ -541,7 +544,7 @@ R_RenderFace (entity_t *currententity, const model_t *currentmodel, msurface_t *
// environment box surfaces to be emited // environment box surfaces to be emited
if ( fa->texinfo->flags & SURF_SKY ) if ( fa->texinfo->flags & SURF_SKY )
{ {
R_EmitSkyBox (currententity, currentmodel); R_EmitSkyBox (currententity, currentmodel, insubmodel);
return; return;
} }
@ -552,7 +555,7 @@ R_RenderFace (entity_t *currententity, const model_t *currentmodel, msurface_t *
return; return;
} }
// ditto if not enough edges left, or switch to auxedges if possible // ditto if not enough edges left
if ((edge_p + fa->numedges + 4) >= edge_max) if ((edge_p + fa->numedges + 4) >= edge_max)
{ {
r_outofedges = true; r_outofedges = true;
@ -589,7 +592,7 @@ R_RenderFace (entity_t *currententity, const model_t *currentmodel, msurface_t *
if (lindex > 0) if (lindex > 0)
{ {
r_pedge = &pedges[lindex]; medge_t *r_pedge = &pedges[lindex];
// if the edge is cached, we can just reuse the edge // if the edge is cached, we can just reuse the edge
if (!insubmodel) if (!insubmodel)
@ -610,7 +613,7 @@ R_RenderFace (entity_t *currententity, const model_t *currentmodel, msurface_t *
(((edge_t *)((uintptr_t)r_edges + (((edge_t *)((uintptr_t)r_edges +
r_pedge->cachededgeoffset))->owner == r_pedge)) r_pedge->cachededgeoffset))->owner == r_pedge))
{ {
R_EmitCachedEdge (); R_EmitCachedEdge (r_pedge);
r_lastvertvalid = false; r_lastvertvalid = false;
continue; continue;
} }
@ -622,7 +625,9 @@ R_RenderFace (entity_t *currententity, const model_t *currentmodel, msurface_t *
r_leftclipped = r_rightclipped = false; r_leftclipped = r_rightclipped = false;
R_ClipEdge (&r_pcurrentvertbase[r_pedge->v[0]], R_ClipEdge (&r_pcurrentvertbase[r_pedge->v[0]],
&r_pcurrentvertbase[r_pedge->v[1]], &r_pcurrentvertbase[r_pedge->v[1]],
pclip); pclip, r_pedge,
&r_leftclipped, &r_rightclipped,
r_nearzionly);
r_pedge->cachededgeoffset = cacheoffset; r_pedge->cachededgeoffset = cacheoffset;
if (r_leftclipped) if (r_leftclipped)
@ -633,6 +638,8 @@ R_RenderFace (entity_t *currententity, const model_t *currentmodel, msurface_t *
} }
else else
{ {
medge_t *r_pedge;
lindex = -lindex; lindex = -lindex;
r_pedge = &pedges[lindex]; r_pedge = &pedges[lindex];
// if the edge is cached, we can just reuse the edge // if the edge is cached, we can just reuse the edge
@ -656,7 +663,7 @@ R_RenderFace (entity_t *currententity, const model_t *currentmodel, msurface_t *
(((edge_t *)((uintptr_t)r_edges + (((edge_t *)((uintptr_t)r_edges +
r_pedge->cachededgeoffset))->owner == r_pedge)) r_pedge->cachededgeoffset))->owner == r_pedge))
{ {
R_EmitCachedEdge (); R_EmitCachedEdge (r_pedge);
r_lastvertvalid = false; r_lastvertvalid = false;
continue; continue;
} }
@ -668,7 +675,9 @@ R_RenderFace (entity_t *currententity, const model_t *currentmodel, msurface_t *
r_leftclipped = r_rightclipped = false; r_leftclipped = r_rightclipped = false;
R_ClipEdge (&r_pcurrentvertbase[r_pedge->v[1]], R_ClipEdge (&r_pcurrentvertbase[r_pedge->v[1]],
&r_pcurrentvertbase[r_pedge->v[0]], &r_pcurrentvertbase[r_pedge->v[0]],
pclip); pclip, r_pedge,
&r_leftclipped, &r_rightclipped,
r_nearzionly);
r_pedge->cachededgeoffset = cacheoffset; r_pedge->cachededgeoffset = cacheoffset;
if (r_leftclipped) if (r_leftclipped)
@ -684,18 +693,18 @@ R_RenderFace (entity_t *currententity, const model_t *currentmodel, msurface_t *
// FIXME: share clipped edges? // FIXME: share clipped edges?
if (makeleftedge) if (makeleftedge)
{ {
r_pedge = &tedge;
r_lastvertvalid = false; r_lastvertvalid = false;
R_ClipEdge (&r_leftexit, &r_leftenter, pclip->next); R_ClipEdge (&r_leftexit, &r_leftenter, pclip->next, &tedge,
&r_leftclipped, &r_rightclipped, r_nearzionly);
} }
// if there was a clip off the right edge, get the right r_nearzi // if there was a clip off the right edge, get the right r_nearzi
if (makerightedge) if (makerightedge)
{ {
r_pedge = &tedge;
r_lastvertvalid = false; r_lastvertvalid = false;
r_nearzionly = true; r_nearzionly = true;
R_ClipEdge (&r_rightexit, &r_rightenter, view_clipplanes[1].next); R_ClipEdge (&r_rightexit, &r_rightenter, view_clipplanes[1].next, &tedge,
&r_leftclipped, &r_rightclipped, r_nearzionly);
} }
// if no edges made it out, return without posting the surface // if no edges made it out, return without posting the surface
@ -735,15 +744,18 @@ R_RenderBmodelFace
================ ================
*/ */
void void
R_RenderBmodelFace(entity_t *currententity, bedge_t *pedges, msurface_t *psurf) R_RenderBmodelFace(entity_t *currententity, bedge_t *pedges, msurface_t *psurf, int r_currentbkey)
{ {
int i; int i;
unsigned mask; unsigned mask;
mplane_t *pplane; mplane_t *pplane;
float distinv; float distinv;
vec3_t p_normal; vec3_t p_normal;
medge_t tedge; medge_t tedge;
clipplane_t *pclip; clipplane_t *pclip;
qboolean r_leftclipped, r_rightclipped;
qboolean makeleftedge, makerightedge;
qboolean r_nearzionly;
if (psurf->texinfo->flags & (SURF_TRANS33|SURF_TRANS66)) if (psurf->texinfo->flags & (SURF_TRANS33|SURF_TRANS66))
{ {
@ -759,7 +771,7 @@ R_RenderBmodelFace(entity_t *currententity, bedge_t *pedges, msurface_t *psurf)
return; return;
} }
// ditto if not enough edges left, or switch to auxedges if possible // ditto if not enough edges left
if ((edge_p + psurf->numedges + 4) >= edge_max) if ((edge_p + psurf->numedges + 4) >= edge_max)
{ {
r_outofedges = true; r_outofedges = true;
@ -768,9 +780,6 @@ R_RenderBmodelFace(entity_t *currententity, bedge_t *pedges, msurface_t *psurf)
c_faceclip++; c_faceclip++;
// this is a dummy to give the caching mechanism someplace to write to
r_pedge = &tedge;
// set up clip planes // set up clip planes
pclip = NULL; pclip = NULL;
@ -795,7 +804,8 @@ R_RenderBmodelFace(entity_t *currententity, bedge_t *pedges, msurface_t *psurf)
for ( ; pedges ; pedges = pedges->pnext) for ( ; pedges ; pedges = pedges->pnext)
{ {
r_leftclipped = r_rightclipped = false; r_leftclipped = r_rightclipped = false;
R_ClipEdge (pedges->v[0], pedges->v[1], pclip); R_ClipEdge (pedges->v[0], pedges->v[1], pclip, &tedge,
&r_leftclipped, &r_rightclipped, r_nearzionly);
if (r_leftclipped) if (r_leftclipped)
makeleftedge = true; makeleftedge = true;
@ -808,16 +818,16 @@ R_RenderBmodelFace(entity_t *currententity, bedge_t *pedges, msurface_t *psurf)
// FIXME: share clipped edges? // FIXME: share clipped edges?
if (makeleftedge) if (makeleftedge)
{ {
r_pedge = &tedge; R_ClipEdge (&r_leftexit, &r_leftenter, pclip->next, &tedge,
R_ClipEdge (&r_leftexit, &r_leftenter, pclip->next); &r_leftclipped, &r_rightclipped, r_nearzionly);
} }
// if there was a clip off the right edge, get the right r_nearzi // if there was a clip off the right edge, get the right r_nearzi
if (makerightedge) if (makerightedge)
{ {
r_pedge = &tedge;
r_nearzionly = true; r_nearzionly = true;
R_ClipEdge (&r_rightexit, &r_rightenter, view_clipplanes[1].next); R_ClipEdge (&r_rightexit, &r_rightenter, view_clipplanes[1].next, &tedge,
&r_leftclipped, &r_rightclipped, r_nearzionly);
} }
// if no edges made it out, return without posting the surface // if no edges made it out, return without posting the surface

View file

@ -184,7 +184,7 @@ TurbulentPow2
============= =============
*/ */
void void
TurbulentPow2 (espan_t *pspan) TurbulentPow2 (espan_t *pspan, float d_ziorigin, float d_zistepu, float d_zistepv)
{ {
float spancountminus1; float spancountminus1;
float sdivzpow2stepu, tdivzpow2stepu, zipow2stepu; float sdivzpow2stepu, tdivzpow2stepu, zipow2stepu;
@ -338,7 +338,7 @@ NonTurbulentPow2 - this is for drawing scrolling textures. they're warping water
============= =============
*/ */
void void
NonTurbulentPow2 (espan_t *pspan) NonTurbulentPow2 (espan_t *pspan, float d_ziorigin, float d_zistepu, float d_zistepv)
{ {
float spancountminus1; float spancountminus1;
float sdivzpow2stepu, tdivzpow2stepu, zipow2stepu; float sdivzpow2stepu, tdivzpow2stepu, zipow2stepu;
@ -590,7 +590,7 @@ D_DrawSpansPow2
============= =============
*/ */
void void
D_DrawSpansPow2 (espan_t *pspan) D_DrawSpansPow2 (espan_t *pspan, float d_ziorigin, float d_zistepu, float d_zistepv)
{ {
int spancount; int spancount;
pixel_t *pbase; pixel_t *pbase;
@ -742,7 +742,7 @@ D_DrawZSpans
============= =============
*/ */
void void
D_DrawZSpans (espan_t *pspan) D_DrawZSpans (espan_t *pspan, float d_ziorigin, float d_zistepu, float d_zistepv)
{ {
zvalue_t izistep; zvalue_t izistep;
int safe_step; int safe_step;

View file

@ -31,7 +31,6 @@ static unsigned char *r_source, *r_sourcemax;
static unsigned *r_lightptr; static unsigned *r_lightptr;
void R_BuildLightMap (drawsurf_t *drawsurf); void R_BuildLightMap (drawsurf_t *drawsurf);
extern unsigned blocklights[1024]; // allow some very large lightmaps
static int sc_size; static int sc_size;
static surfcache_t *sc_rover; static surfcache_t *sc_rover;
@ -179,6 +178,12 @@ R_DrawSurface (drawsurf_t *drawsurf)
{ {
r_lightptr = blocklights + u; r_lightptr = blocklights + u;
if (r_lightptr >= blocklight_max)
{
r_outoflights = true;
continue;
}
prowdestbase = pcolumndest; prowdestbase = pcolumndest;
pbasesource = basetptr + soffset; pbasesource = basetptr + soffset;