From 5f2293bf0d2837a78d357ef5ad02aa3f37ce09f6 Mon Sep 17 00:00:00 2001 From: Denis Pauk Date: Wed, 15 May 2019 22:34:53 +0300 Subject: [PATCH 1/7] limit surfaces amount to unsigned short --- src/client/refresh/soft/header/local.h | 23 ++++++++++------------- src/client/refresh/soft/header/model.h | 8 -------- src/client/refresh/soft/sw_main.c | 8 ++++++++ src/client/refresh/soft/sw_model.c | 2 ++ src/client/refresh/soft/sw_poly.c | 6 ++++-- 5 files changed, 24 insertions(+), 23 deletions(-) diff --git a/src/client/refresh/soft/header/local.h b/src/client/refresh/soft/header/local.h index dc81c521..45a8bb7a 100644 --- a/src/client/refresh/soft/header/local.h +++ b/src/client/refresh/soft/header/local.h @@ -151,14 +151,8 @@ extern oldrefdef_t r_refdef; #define TRANSPARENT_COLOR 0xFF -#define TURB_TEX_SIZE 64 // base turbulent texture size - #define CYCLE 128 // turbulent cycle size -#define SCANBUFFERPAD 0x1000 - -#define DS_SPAN_LIST_END -128 - // flags in finalvert_t.flags #define ALIAS_LEFT_CLIP 0x0001 #define ALIAS_TOP_CLIP 0x0002 @@ -175,8 +169,6 @@ extern oldrefdef_t r_refdef; #define XCENTERING (1.0 / 2.0) #define YCENTERING (1.0 / 2.0) -#define CLIP_EPSILON 0.001 - #define BACKFACE_EPSILON 0.01 #define NEAR_CLIP 0.01 @@ -184,9 +176,9 @@ extern oldrefdef_t r_refdef; #define ALIAS_Z_CLIP_PLANE 4 // turbulence stuff -#define AMP 8*0x10000 -#define AMP2 3 -#define SPEED 20 +#define AMP 8*0x10000 +#define AMP2 3 +#define SPEED 20 /* @@ -310,19 +302,24 @@ typedef struct surf_s // -1 = in inverted span (end before // start) int flags; // currentface flags - msurface_t *msurf; + msurface_t *msurf; entity_t *entity; float nearzi; // nearest 1/z on surface, for mipmapping qboolean insubmodel; float d_ziorigin, d_zistepu, d_zistepv; } surf_t; +typedef unsigned short surfindex_t; + +// surface index size +#define SURFINDEX_MAX (1 << (sizeof(surfindex_t) * 8)) + typedef struct edge_s { shift20_t u; shift20_t u_step; struct edge_s *prev, *next; - unsigned short surfs[2]; + surfindex_t surfs[2]; struct edge_s *nextremove; float nearzi; medge_t *owner; diff --git a/src/client/refresh/soft/header/model.h b/src/client/refresh/soft/header/model.h index e04f3031..89e74368 100644 --- a/src/client/refresh/soft/header/model.h +++ b/src/client/refresh/soft/header/model.h @@ -46,11 +46,6 @@ typedef struct vec3_t position; } mvertex_t; -#define SIDE_FRONT 0 -#define SIDE_BACK 1 -#define SIDE_ON 2 - - // plane_t structure typedef struct mplane_s { @@ -231,9 +226,6 @@ typedef struct model_s //============================================================================ 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); byte *Mod_ClusterPVS(int cluster, model_t *model); diff --git a/src/client/refresh/soft/sw_main.c b/src/client/refresh/soft/sw_main.c index ec0d94ec..7d552fed 100644 --- a/src/client/refresh/soft/sw_main.c +++ b/src/client/refresh/soft/sw_main.c @@ -382,6 +382,14 @@ R_ReallocateMapBuffers (void) if (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)); if (!lsurfs) { diff --git a/src/client/refresh/soft/sw_model.c b/src/client/refresh/soft/sw_model.c index 38a444e6..4ba213f8 100644 --- a/src/client/refresh/soft/sw_model.c +++ b/src/client/refresh/soft/sw_model.c @@ -1226,6 +1226,8 @@ SPRITE MODELS /* ================= Mod_LoadSpriteModel + +support for .sp2 sprites ================= */ static void diff --git a/src/client/refresh/soft/sw_poly.c b/src/client/refresh/soft/sw_poly.c index 3f89c067..57f25ac3 100644 --- a/src/client/refresh/soft/sw_poly.c +++ b/src/client/refresh/soft/sw_poly.c @@ -749,7 +749,7 @@ R_PolygonDrawSpans(espan_t *pspan, int iswater ) 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; } 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); - pspan->count = DS_SPAN_LIST_END; // mark the end of the span list + pspan->count = INT_MIN; // mark the end of the span list } /* From 25a2aff688a15b5a0ecea98eefdd51740635ea73 Mon Sep 17 00:00:00 2001 From: Denis Pauk Date: Wed, 15 May 2019 23:00:20 +0300 Subject: [PATCH 2/7] render code cleanup and allocate spans at once --- src/client/refresh/soft/header/local.h | 14 ++-- src/client/refresh/soft/sw_bsp.c | 91 ++++++++++++------------ src/client/refresh/soft/sw_edge.c | 97 +++++++++++--------------- src/client/refresh/soft/sw_main.c | 55 ++++++++++++--- src/client/refresh/soft/sw_rast.c | 96 +++++++++++++------------ 5 files changed, 194 insertions(+), 159 deletions(-) diff --git a/src/client/refresh/soft/header/local.h b/src/client/refresh/soft/header/local.h index 45a8bb7a..05e7a831 100644 --- a/src/client/refresh/soft/header/local.h +++ b/src/client/refresh/soft/header/local.h @@ -454,14 +454,12 @@ extern msurface_t *r_alpha_surfaces; // // current entity info // -extern qboolean insubmodel; - void R_DrawAlphaSurfaces(const entity_t *currententity); 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_RenderBmodelFace(entity_t *currententity, bedge_t *pedges, msurface_t *psurf); +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, int r_currentbkey); void R_TransformFrustum(void); void R_DrawSubmodelPolygons(entity_t *currententity, const model_t *currentmodel, int clipflags, mnode_t *topnode); @@ -480,7 +478,6 @@ extern int sadjust, tadjust; extern int bbextents, bbextentt; extern int r_currentkey; -extern int r_currentbkey; void R_DrawParticles (void); @@ -506,7 +503,9 @@ void R_PolysetDrawSpans8_Opaque(const entity_t *currententity, spanpackage_t *ps extern byte **warp_rowptr; extern int *warp_column; extern espan_t *edge_basespans; +extern espan_t *max_span_p; extern int r_numallocatedverts; +extern int r_numallocatededgebasespans; extern finalvert_t *finalverts, *finalverts_max; extern int r_aliasblendcolor; @@ -517,6 +516,7 @@ extern qboolean r_outofsurfaces; extern qboolean r_outofedges; extern qboolean r_outofverts; extern qboolean r_outoftriangles; +extern qboolean r_outedgebasespans; extern mvertex_t *r_pcurrentvertbase; @@ -527,7 +527,7 @@ void R_AliasClipTriangle(const entity_t *currententity, const finalvert_t *index extern float r_time1; extern float da_time1, da_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_clipflags; @@ -586,6 +586,6 @@ IMPORTED FUNCTIONS ==================================================================== */ -extern refimport_t ri; +extern refimport_t ri; #endif diff --git a/src/client/refresh/soft/sw_bsp.c b/src/client/refresh/soft/sw_bsp.c index d45cdf33..d65cbd36 100644 --- a/src/client/refresh/soft/sw_bsp.c +++ b/src/client/refresh/soft/sw_bsp.c @@ -31,8 +31,6 @@ vec3_t r_entorigin; // the currently rendering entity in world static float entity_rotation[3][3]; -int r_currentbkey; - typedef enum {touchessolid, drawnode, nodrawnode} solidstate_t; #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 @@ -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 // and exiting points // FIXME: share the clip edge by having a winding direction flag? - if (numbedges >= (MAX_BMODEL_EDGES - 1)) - { - R_Printf(PRINT_ALL,"Out of edges for bmodel\n"); - return; - } - - ptedge = &bedges[numbedges]; + ptedge = &bedges[numbedges++]; ptedge->pnext = psideedges[lastside]; psideedges[lastside] = ptedge; ptedge->v[0] = plastvert; ptedge->v[1] = ptvert; - ptedge = &bedges[numbedges + 1]; + ptedge = &bedges[numbedges++]; ptedge->pnext = psideedges[side]; psideedges[side] = ptedge; ptedge->v[0] = ptvert; 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) { @@ -266,25 +280,23 @@ R_RecursiveClipBPoly(entity_t *currententity, bedge_t *pedges, mnode_t *pnode, m // plane to both sides (but in opposite directions) if (makeclippededge && pfrontexit != pfrontenter) { - if (numbedges >= (MAX_BMODEL_EDGES - 2)) - { - R_Printf(PRINT_ALL,"Out of edges for bmodel\n"); - return; - } - - ptedge = &bedges[numbedges]; + ptedge = &bedges[numbedges++]; ptedge->pnext = psideedges[0]; psideedges[0] = ptedge; ptedge->v[0] = pfrontexit; ptedge->v[1] = pfrontenter; - ptedge = &bedges[numbedges + 1]; + ptedge = &bedges[numbedges++]; ptedge->pnext = psideedges[1]; psideedges[1] = ptedge; ptedge->v[0] = pfrontenter; 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 @@ -303,17 +315,13 @@ R_RecursiveClipBPoly(entity_t *currententity, bedge_t *pedges, mnode_t *pnode, m { if (pn->contents != CONTENTS_SOLID) { - if (r_newrefdef.areabits) - { - int area; + int r_currentbkey; - area = ((mleaf_t *)pn)->area; - if (! (r_newrefdef.areabits[area>>3] & (1<<(area&7)) ) ) - continue; // not visible - } + if (!R_AreaVisible((mleaf_t *)pn)) + continue; r_currentbkey = ((mleaf_t *)pn)->key; - R_RenderBmodelFace(currententity, psideedges[i], psurf); + R_RenderBmodelFace(currententity, psideedges[i], psurf, r_currentbkey); } } else @@ -399,14 +407,14 @@ R_DrawSolidClippedSubmodelPolygons(entity_t *currententity, const model_t *curre 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 R_RecursiveClipBPoly(currententity, pbedge, topnode, psurf); } 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; // 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 -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; vec3_t acceptpt, rejectpt; @@ -519,12 +528,8 @@ R_RecursiveWorldNode (entity_t *currententity, const model_t *currentmodel, mnod msurface_t **mark; pleaf = (mleaf_t *)node; - // check for door connected areas - if (r_newrefdef.areabits) - { - if (! (r_newrefdef.areabits[pleaf->area>>3] & (1<<(pleaf->area&7)) ) ) - return; // not visible - } + if (!R_AreaVisible(pleaf)) + return; // not visible mark = pleaf->firstmarksurface; c = pleaf->nummarksurfaces; @@ -573,7 +578,7 @@ R_RecursiveWorldNode (entity_t *currententity, const model_t *currentmodel, mnod side = 1; // 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 c = node->numsurfaces; @@ -591,7 +596,7 @@ R_RecursiveWorldNode (entity_t *currententity, const model_t *currentmodel, mnod if ((surf->flags & SURF_PLANEBACK) && (surf->visframe == r_framecount)) { - R_RenderFace (currententity, currentmodel, surf, clipflags); + R_RenderFace (currententity, currentmodel, surf, clipflags, insubmodel); } surf++; @@ -604,7 +609,7 @@ R_RecursiveWorldNode (entity_t *currententity, const model_t *currentmodel, mnod if (!(surf->flags & SURF_PLANEBACK) && (surf->visframe == r_framecount)) { - R_RenderFace (currententity, currentmodel, surf, clipflags); + R_RenderFace (currententity, currentmodel, surf, clipflags, insubmodel); } surf++; @@ -616,7 +621,7 @@ R_RecursiveWorldNode (entity_t *currententity, const model_t *currentmodel, mnod } // 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); 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); } diff --git a/src/client/refresh/soft/sw_edge.c b/src/client/refresh/soft/sw_edge.c index 81a14489..c2c96c9b 100644 --- a/src/client/refresh/soft/sw_edge.c +++ b/src/client/refresh/soft/sw_edge.c @@ -36,8 +36,9 @@ have a sentinal at both ends? edge_t **newedges; edge_t **removeedges; 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; @@ -107,7 +108,8 @@ R_BeginEdgeFrame (void) R_InsertNewEdges 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 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 @@ -214,22 +232,11 @@ static void R_CleanupSpan (void) { 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 // unfinished surfaces, so emit a span for whatever's on top surf = surfaces[1].next; - iu = 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; - } + R_InsertSpan (surf, edge_tail_u_shift20); // reset spanstate for all surfaces in the surface stack do @@ -295,17 +302,7 @@ R_LeadingEdgeBackwards (const edge_t *edge) // emit a span (obscures current top) iu = edge->u >> shift_size; - if (iu > surf2->last_u) - { - 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; - } + R_InsertSpan (surf2, iu); // set last_u on the new span surf->last_u = iu; @@ -332,8 +329,6 @@ R_TrailingEdge static void 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 // edge preceding the start edge (that is, we haven't seen the // start edge yet) @@ -345,15 +340,7 @@ R_TrailingEdge (surf_t *surf, edge_t *edge) // emit a span (current top going away) iu = edge->u >> shift_size; - 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; - } + R_InsertSpan (surf, iu); // set last_u on the surface below 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; - if (iu > surf2->last_u) - { - 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; - } + R_InsertSpan (surf2, iu); // set last_u on the new span surf->last_u = iu; @@ -623,18 +600,23 @@ void R_ScanEdges (surf_t *surface) { shift20_t iv, bottom; - espan_t *basespan_p; surf_t *s; - basespan_p = edge_basespans; - max_span_p = edge_basespans + vid.width * 2 - r_refdef.vrect.width; - if ((vid.width * 2 - r_refdef.vrect.width) < 0) + // clear the surface span pointers + for (s = &surfaces[1] ; slast_u = 0; + 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 // 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 // the next scan - if (span_p >= max_span_p) + if (span_p + r_refdef.vrect.width >= max_span_p) { // Draw stuff on screen D_DrawSurfaces (surface); @@ -696,7 +678,10 @@ R_ScanEdges (surf_t *surface) for (s = &surfaces[1] ; sspans = NULL; - span_p = basespan_p; + span_p = edge_basespans; + + // Need to more space + r_outedgebasespans = true; } if (removeedges[iv]) diff --git a/src/client/refresh/soft/sw_main.c b/src/client/refresh/soft/sw_main.c index 7d552fed..43933a2c 100644 --- a/src/client/refresh/soft/sw_main.c +++ b/src/client/refresh/soft/sw_main.c @@ -68,11 +68,13 @@ float r_time1; int r_numallocatededges; int r_numallocatedverts; int r_numallocatedtriangles; +int r_numallocatededgebasespans; float r_aliasuvscale = 1.0; qboolean r_outofsurfaces; qboolean r_outofedges; qboolean r_outofverts; qboolean r_outoftriangles; +qboolean r_outedgebasespans; qboolean r_dowarp; @@ -187,8 +189,6 @@ int cachewidth; pixel_t *d_viewbuffer; zvalue_t *d_pzbuffer; -qboolean insubmodel; - static void Draw_GetPalette (void); static void RE_BeginFrame( float camera_separation ); static void Draw_BuildGammaTable(void); @@ -401,11 +401,13 @@ R_ReallocateMapBuffers (void) surfaces = lsurfs; // set limits surf_max = &surfaces[r_cnumsurfs]; - surface_p = lsurfs; // surface 0 doesn't really exist; it's just a dummy because index 0 // is used to indicate no edge attached to surface surfaces--; + surface_p = &surfaces[2]; // background is surface 1, + // surface 0 is a dummy + R_Printf(PRINT_ALL, "Allocated %d surfaces\n", r_cnumsurfs); } @@ -495,6 +497,35 @@ R_ReallocateMapBuffers (void) 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); + } } @@ -847,7 +878,6 @@ R_DrawBEntitiesOnList (void) return; VectorCopy (modelorg, oldorigin); - insubmodel = true; for (i=0 ; ileftedge) { - r_leftclipped = true; + *r_leftclipped = true; r_leftexit = clipvert; } else if (clip->rightedge) { - r_rightclipped = true; + *r_rightclipped = true; r_rightexit = clipvert; } - R_ClipEdge (pv0, &clipvert, clip->next); + R_ClipEdge (pv0, &clipvert, clip->next, r_pedge, + r_leftclipped, r_rightclipped, + r_nearzionly); return; } else @@ -470,23 +467,25 @@ R_ClipEdge (mvertex_t *pv0, mvertex_t *pv1, clipplane_t *clip) if (clip->leftedge) { - r_leftclipped = true; + *r_leftclipped = true; r_leftenter = clipvert; } else if (clip->rightedge) { - r_rightclipped = true; + *r_rightclipped = true; r_rightenter = clipvert; } - R_ClipEdge (&clipvert, pv1, clip->next); + R_ClipEdge (&clipvert, pv1, clip->next, r_pedge, + r_leftclipped, r_rightclipped, + r_nearzionly); return; } } while ((clip = clip->next) != NULL); } // add the edge - R_EmitEdge (pv0, pv1); + R_EmitEdge (pv0, pv1, r_pedge, r_nearzionly); } /* @@ -495,7 +494,7 @@ R_EmitCachedEdge ================ */ static void -R_EmitCachedEdge (void) +R_EmitCachedEdge (medge_t *r_pedge) { edge_t *pedge_t; @@ -519,7 +518,8 @@ R_RenderFace ================ */ 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; unsigned mask; @@ -528,6 +528,9 @@ R_RenderFace (entity_t *currententity, const model_t *currentmodel, msurface_t * vec3_t p_normal; medge_t *pedges, tedge; clipplane_t *pclip; + qboolean r_leftclipped, r_rightclipped; + qboolean makeleftedge, makerightedge; + qboolean r_nearzionly; // translucent surfaces are not drawn by the edge renderer 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 if ( fa->texinfo->flags & SURF_SKY ) { - R_EmitSkyBox (currententity, currentmodel); + R_EmitSkyBox (currententity, currentmodel, insubmodel); return; } @@ -552,7 +555,7 @@ R_RenderFace (entity_t *currententity, const model_t *currentmodel, msurface_t * 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) { r_outofedges = true; @@ -589,7 +592,7 @@ R_RenderFace (entity_t *currententity, const model_t *currentmodel, msurface_t * 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 (!insubmodel) @@ -610,7 +613,7 @@ R_RenderFace (entity_t *currententity, const model_t *currentmodel, msurface_t * (((edge_t *)((uintptr_t)r_edges + r_pedge->cachededgeoffset))->owner == r_pedge)) { - R_EmitCachedEdge (); + R_EmitCachedEdge (r_pedge); r_lastvertvalid = false; continue; } @@ -622,7 +625,9 @@ R_RenderFace (entity_t *currententity, const model_t *currentmodel, msurface_t * r_leftclipped = r_rightclipped = false; R_ClipEdge (&r_pcurrentvertbase[r_pedge->v[0]], &r_pcurrentvertbase[r_pedge->v[1]], - pclip); + pclip, r_pedge, + &r_leftclipped, &r_rightclipped, + r_nearzionly); r_pedge->cachededgeoffset = cacheoffset; if (r_leftclipped) @@ -633,6 +638,8 @@ R_RenderFace (entity_t *currententity, const model_t *currentmodel, msurface_t * } else { + medge_t *r_pedge; + lindex = -lindex; r_pedge = &pedges[lindex]; // 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 + r_pedge->cachededgeoffset))->owner == r_pedge)) { - R_EmitCachedEdge (); + R_EmitCachedEdge (r_pedge); r_lastvertvalid = false; continue; } @@ -668,7 +675,9 @@ R_RenderFace (entity_t *currententity, const model_t *currentmodel, msurface_t * r_leftclipped = r_rightclipped = false; R_ClipEdge (&r_pcurrentvertbase[r_pedge->v[1]], &r_pcurrentvertbase[r_pedge->v[0]], - pclip); + pclip, r_pedge, + &r_leftclipped, &r_rightclipped, + r_nearzionly); r_pedge->cachededgeoffset = cacheoffset; if (r_leftclipped) @@ -684,18 +693,18 @@ R_RenderFace (entity_t *currententity, const model_t *currentmodel, msurface_t * // FIXME: share clipped edges? if (makeleftedge) { - r_pedge = &tedge; 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 (makerightedge) { - r_pedge = &tedge; r_lastvertvalid = false; 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 @@ -735,15 +744,18 @@ R_RenderBmodelFace ================ */ 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; mplane_t *pplane; float distinv; vec3_t p_normal; medge_t tedge; clipplane_t *pclip; + qboolean r_leftclipped, r_rightclipped; + qboolean makeleftedge, makerightedge; + qboolean r_nearzionly; if (psurf->texinfo->flags & (SURF_TRANS33|SURF_TRANS66)) { @@ -759,7 +771,7 @@ R_RenderBmodelFace(entity_t *currententity, bedge_t *pedges, msurface_t *psurf) 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) { r_outofedges = true; @@ -768,9 +780,6 @@ R_RenderBmodelFace(entity_t *currententity, bedge_t *pedges, msurface_t *psurf) c_faceclip++; - // this is a dummy to give the caching mechanism someplace to write to - r_pedge = &tedge; - // set up clip planes pclip = NULL; @@ -795,7 +804,8 @@ R_RenderBmodelFace(entity_t *currententity, bedge_t *pedges, msurface_t *psurf) for ( ; pedges ; pedges = pedges->pnext) { 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) makeleftedge = true; @@ -808,16 +818,16 @@ R_RenderBmodelFace(entity_t *currententity, bedge_t *pedges, msurface_t *psurf) // FIXME: share clipped edges? if (makeleftedge) { - r_pedge = &tedge; - 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 (makerightedge) { - r_pedge = &tedge; 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 From a2af07c9fc6e3c66f15080dd579d1c78863271a3 Mon Sep 17 00:00:00 2001 From: Denis Pauk Date: Thu, 30 May 2019 22:12:21 +0300 Subject: [PATCH 3/7] make d_ziorigin, d_zistepu, d_zistepv local --- src/client/refresh/soft/header/local.h | 14 +++---- src/client/refresh/soft/sw_edge.c | 52 +++++++------------------- src/client/refresh/soft/sw_main.c | 6 +-- src/client/refresh/soft/sw_poly.c | 18 ++++++--- src/client/refresh/soft/sw_scan.c | 8 ++-- 5 files changed, 40 insertions(+), 58 deletions(-) diff --git a/src/client/refresh/soft/header/local.h b/src/client/refresh/soft/header/local.h index 05e7a831..4f7b8d94 100644 --- a/src/client/refresh/soft/header/local.h +++ b/src/client/refresh/soft/header/local.h @@ -354,14 +354,14 @@ extern pixel_t *r_warpbuffer; extern float scale_for_mip; -extern float d_sdivzstepu, d_tdivzstepu, d_zistepu; -extern float d_sdivzstepv, d_tdivzstepv, d_zistepv; -extern float d_sdivzorigin, d_tdivzorigin, d_ziorigin; +extern float d_sdivzstepu, d_tdivzstepu; +extern float d_sdivzstepv, d_tdivzstepv; +extern float d_sdivzorigin, d_tdivzorigin; -void D_DrawSpansPow2(espan_t *pspans); -void D_DrawZSpans(espan_t *pspans); -void TurbulentPow2(espan_t *pspan); -void NonTurbulentPow2(espan_t *pspan); +void D_DrawSpansPow2(espan_t *pspans, float d_ziorigin, float d_zistepu, float d_zistepv); +void D_DrawZSpans(espan_t *pspans, float d_ziorigin, float d_zistepu, float d_zistepv); +void TurbulentPow2(espan_t *pspan, float d_ziorigin, float d_zistepu, float d_zistepv); +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); diff --git a/src/client/refresh/soft/sw_edge.c b/src/client/refresh/soft/sw_edge.c index c2c96c9b..bef978a2 100644 --- a/src/client/refresh/soft/sw_edge.c +++ b/src/client/refresh/soft/sw_edge.c @@ -778,7 +778,7 @@ D_CalcGradients ============== */ static void -D_CalcGradients (msurface_t *pface) +D_CalcGradients (msurface_t *pface, float d_ziorigin, float d_zistepu, float d_zistepv) { float mipscale; vec3_t p_temp1; @@ -840,14 +840,10 @@ The grey background filler seen when there is a hole in the map static void D_BackgroundSurf (surf_t *s) { + D_FlatFillSurface (s, (int)sw_clearcolor->value & 0xFF); // set up a gradient for the background surface that places it // effectively at infinity distance from the viewpoint - d_zistepu = 0; - d_zistepv = 0; - d_ziorigin = -0.9; - - D_FlatFillSurface (s, (int)sw_clearcolor->value & 0xFF); - D_DrawZSpans (s->spans); + D_DrawZSpans (s->spans, -0.9, 0, 0); } /* @@ -858,10 +854,6 @@ D_TurbulentSurf static void D_TurbulentSurf(surf_t *s) { - d_zistepu = s->d_zistepu; - d_zistepv = s->d_zistepv; - d_ziorigin = s->d_ziorigin; - pface = s->msurf; miplevel = 0; cacheblock = pface->texinfo->image->pixels[0]; @@ -883,17 +875,17 @@ D_TurbulentSurf(surf_t *s) // 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 if(!(pface->texinfo->flags & SURF_WARP)) - NonTurbulentPow2 (s->spans); + NonTurbulentPow2 (s->spans, s->d_ziorigin, s->d_zistepu, s->d_zistepv); 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) { @@ -926,21 +918,13 @@ D_SkySurf (surf_t *s) cacheblock = pface->texinfo->image->pixels[0]; cachewidth = 256; - d_zistepu = s->d_zistepu; - d_zistepv = s->d_zistepv; - d_ziorigin = s->d_ziorigin; + D_CalcGradients (pface, s->d_ziorigin, s->d_zistepu, s->d_zistepv); - D_CalcGradients (pface); - - D_DrawSpansPow2 (s->spans); + D_DrawSpansPow2 (s->spans, s->d_ziorigin, s->d_zistepu, s->d_zistepv); // set up a gradient for the background surface that places it // effectively at infinity distance from the viewpoint - d_zistepu = 0; - d_zistepv = 0; - d_ziorigin = -0.9; - - D_DrawZSpans (s->spans); + D_DrawZSpans (s->spans, -0.9, 0, 0); } /* @@ -955,10 +939,6 @@ D_SolidSurf (surf_t *s) { entity_t *currententity; - d_zistepu = s->d_zistepu; - d_zistepv = s->d_zistepv; - d_ziorigin = s->d_ziorigin; - if (s->insubmodel) { vec3_t local_modelorg; @@ -984,11 +964,11 @@ D_SolidSurf (surf_t *s) cacheblock = (pixel_t *)pcurrentcache->data; 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) { @@ -1024,14 +1004,10 @@ D_DrawflatSurfaces (surf_t *surface) if (!s->spans) 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 // bits of the msurface pointer D_FlatFillSurface (s, color & 0xFF); - D_DrawZSpans (s->spans); + D_DrawZSpans (s->spans, s->d_ziorigin, s->d_zistepu, s->d_zistepv); color ++; } diff --git a/src/client/refresh/soft/sw_main.c b/src/client/refresh/soft/sw_main.c index 43933a2c..e6301a15 100644 --- a/src/client/refresh/soft/sw_main.c +++ b/src/client/refresh/soft/sw_main.c @@ -178,9 +178,9 @@ static cvar_t *r_lockpvs; // FIXME: make into one big structure, like cl or sv // FIXME: do separately for refresh engine and driver -float d_sdivzstepu, d_tdivzstepu, d_zistepu; -float d_sdivzstepv, d_tdivzstepv, d_zistepv; -float d_sdivzorigin, d_tdivzorigin, d_ziorigin; +float d_sdivzstepu, d_tdivzstepu; +float d_sdivzstepv, d_tdivzstepv; +float d_sdivzorigin, d_tdivzorigin; int sadjust, tadjust, bbextents, bbextentt; diff --git a/src/client/refresh/soft/sw_poly.c b/src/client/refresh/soft/sw_poly.c index 57f25ac3..99869134 100644 --- a/src/client/refresh/soft/sw_poly.c +++ b/src/client/refresh/soft/sw_poly.c @@ -592,7 +592,7 @@ R_ClipPolyFace (int nump, clipplane_t *pclipplane) */ // iswater was qboolean. changed to allow passing more flags 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; float sdivz, tdivz, zi, z, du, dv, spancountminus1; @@ -1113,10 +1113,11 @@ R_BuildPolygonFromSurface(const entity_t *currententity, const model_t *currentm ** R_PolygonCalculateGradients */ static void -R_PolygonCalculateGradients (void) +R_PolygonCalculateGradients (float *p_ziorigin, float *p_zistepu, float *p_zistepv) { - vec3_t p_normal, p_saxis, p_taxis; - float distinv; + vec3_t p_normal, p_saxis, p_taxis; + float distinv; + float d_ziorigin, d_zistepu, d_zistepv; TransformVector (r_polydesc.vpn, p_normal); TransformVector (r_polydesc.vright, p_saxis); @@ -1142,6 +1143,10 @@ R_PolygonCalculateGradients (void) // -1 (-epsilon) so we never wander off the edge of the texture bbextents = (r_polydesc.pixel_width << SHIFT16XYZ) - 1; bbextentt = (r_polydesc.pixel_height << SHIFT16XYZ) - 1; + + *p_zistepu = d_zistepu; + *p_zistepv = d_zistepv; + *p_ziorigin = d_ziorigin; } /* @@ -1159,6 +1164,7 @@ R_DrawPoly(int iswater, espan_t *spans) int i, nump; float ymin, ymax; 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 // draw @@ -1198,11 +1204,11 @@ R_DrawPoly(int iswater, espan_t *spans) pverts = r_polydesc.pverts; pverts[nump] = pverts[0]; - R_PolygonCalculateGradients(); + R_PolygonCalculateGradients(&d_ziorigin, &d_zistepu, &d_zistepv); R_PolygonScanLeftEdge(spans); R_PolygonScanRightEdge(spans); - R_PolygonDrawSpans(spans, iswater); + R_PolygonDrawSpans(spans, iswater, d_ziorigin, d_zistepu, d_zistepv); } /* diff --git a/src/client/refresh/soft/sw_scan.c b/src/client/refresh/soft/sw_scan.c index 3ca4a57a..b536839e 100644 --- a/src/client/refresh/soft/sw_scan.c +++ b/src/client/refresh/soft/sw_scan.c @@ -184,7 +184,7 @@ TurbulentPow2 ============= */ void -TurbulentPow2 (espan_t *pspan) +TurbulentPow2 (espan_t *pspan, float d_ziorigin, float d_zistepu, float d_zistepv) { float spancountminus1; float sdivzpow2stepu, tdivzpow2stepu, zipow2stepu; @@ -338,7 +338,7 @@ NonTurbulentPow2 - this is for drawing scrolling textures. they're warping water ============= */ void -NonTurbulentPow2 (espan_t *pspan) +NonTurbulentPow2 (espan_t *pspan, float d_ziorigin, float d_zistepu, float d_zistepv) { float spancountminus1; float sdivzpow2stepu, tdivzpow2stepu, zipow2stepu; @@ -590,7 +590,7 @@ D_DrawSpansPow2 ============= */ void -D_DrawSpansPow2 (espan_t *pspan) +D_DrawSpansPow2 (espan_t *pspan, float d_ziorigin, float d_zistepu, float d_zistepv) { int spancount; pixel_t *pbase; @@ -742,7 +742,7 @@ D_DrawZSpans ============= */ void -D_DrawZSpans (espan_t *pspan) +D_DrawZSpans (espan_t *pspan, float d_ziorigin, float d_zistepu, float d_zistepv) { zvalue_t izistep; int safe_step; From 65888e6b9b7b551f13eb03c766b131c8ff76b0ea Mon Sep 17 00:00:00 2001 From: Denis Pauk Date: Wed, 5 Jun 2019 22:50:50 +0300 Subject: [PATCH 4/7] fix distance selection for mip level --- src/client/refresh/soft/sw_misc.c | 4 +--- src/client/refresh/soft/sw_model.c | 12 +++--------- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/src/client/refresh/soft/sw_misc.c b/src/client/refresh/soft/sw_misc.c index 12213eb2..bf0a5a72 100644 --- a/src/client/refresh/soft/sw_misc.c +++ b/src/client/refresh/soft/sw_misc.c @@ -43,9 +43,7 @@ D_ViewChanged static void D_ViewChanged (void) { - scale_for_mip = xscale; - if (yscale > xscale) - scale_for_mip = yscale; + scale_for_mip = sqrt(xscale*xscale + yscale*yscale); d_pix_min = r_refdef.vrect.height / 240; if (d_pix_min < 1) diff --git a/src/client/refresh/soft/sw_model.c b/src/client/refresh/soft/sw_model.c index 4ba213f8..44fb4b70 100644 --- a/src/client/refresh/soft/sw_model.c +++ b/src/client/refresh/soft/sw_model.c @@ -494,15 +494,9 @@ Mod_LoadTexinfo (lump_t *l) } len1 = VectorLength (out->vecs[0]); len2 = VectorLength (out->vecs[1]); - len1 = (len1 + len2)/2; - if (len1 < 0.32) - out->mipadjust = 4; - else if (len1 < 0.49) - out->mipadjust = 3; - else if (len1 < 0.99) - out->mipadjust = 2; - else - out->mipadjust = 1; + out->mipadjust = sqrt(len1*len1 + len2*len2); + if (out->mipadjust < 0.01) + out->mipadjust = 0.01; out->flags = LittleLong (in->flags); From 9783e7955fed6b2e71553d38180ca1ad03bc1c8d Mon Sep 17 00:00:00 2001 From: Denis Pauk Date: Tue, 11 Jun 2019 22:52:56 +0300 Subject: [PATCH 5/7] correctly check limits in RE_Draw --- src/client/refresh/soft/sw_draw.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/client/refresh/soft/sw_draw.c b/src/client/refresh/soft/sw_draw.c index 05f229f0..6bc4640a 100644 --- a/src/client/refresh/soft/sw_draw.c +++ b/src/client/refresh/soft/sw_draw.c @@ -77,13 +77,16 @@ smoothly scrolled off. void RE_Draw_CharScaled(int x, int y, int num, float scale) { - pixel_t *dest, *dest_max; + pixel_t *dest; byte *source; - int drawline; - int row, col, u, xpos, ypos, iscale; + int drawline; + int row, col, u, xpos, ypos, iscale; iscale = (int) scale; + if (iscale < 1) + return; + num &= 255; if (num == 32 || num == 32+128) @@ -109,7 +112,12 @@ RE_Draw_CharScaled(int x, int y, int num, float scale) drawline = 8; 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--) { @@ -124,12 +132,6 @@ RE_Draw_CharScaled(int x, int y, int num, float scale) } } dest += vid.width; - - // clipped last lines - if (dest >= dest_max) - { - return; - } } source += 128; } @@ -160,7 +162,7 @@ RE_Draw_GetPicSize (int *w, int *h, char *pic) RE_Draw_StretchPicImplementation ============= */ -void +static void RE_Draw_StretchPicImplementation (int x, int y, int w, int h, const image_t *pic) { pixel_t *dest; @@ -266,8 +268,8 @@ RE_Draw_PicScaled(int x, int y, char *name, float scale) } if ((x < 0) || - (x + pic->width > vid.width) || - (y + pic->height > vid.height)) + (x + pic->width * scale > vid.width) || + (y + pic->height * scale > vid.height)) { R_Printf(PRINT_ALL, "Draw_Pic: bad coordinates\n"); return; From 60f9af27f59b79b8a2ddf026d48d28e67a08d10c Mon Sep 17 00:00:00 2001 From: Denis Pauk Date: Tue, 11 Jun 2019 23:00:32 +0300 Subject: [PATCH 6/7] Dynamicly allocate lights --- src/client/refresh/soft/header/local.h | 3 ++ src/client/refresh/soft/sw_light.c | 13 +++++++- src/client/refresh/soft/sw_main.c | 42 ++++++++++++++++++++++++++ src/client/refresh/soft/sw_part.c | 5 +++ src/client/refresh/soft/sw_surf.c | 7 ++++- 5 files changed, 68 insertions(+), 2 deletions(-) diff --git a/src/client/refresh/soft/header/local.h b/src/client/refresh/soft/header/local.h index 4f7b8d94..90fd66f8 100644 --- a/src/client/refresh/soft/header/local.h +++ b/src/client/refresh/soft/header/local.h @@ -391,6 +391,8 @@ extern vec3_t vpn, base_vpn; extern vec3_t vright, base_vright; 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 // pointer is greater than another one, it should be drawn in front @@ -516,6 +518,7 @@ extern qboolean r_outofsurfaces; extern qboolean r_outofedges; extern qboolean r_outofverts; extern qboolean r_outoftriangles; +extern qboolean r_outoflights; extern qboolean r_outedgebasespans; extern mvertex_t *r_pcurrentvertbase; diff --git a/src/client/refresh/soft/sw_light.c b/src/client/refresh/soft/sw_light.c index 58918bfc..96946b4f 100644 --- a/src/client/refresh/soft/sw_light.c +++ b/src/client/refresh/soft/sw_light.c @@ -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; tex = surf->texinfo; + if (blocklight_max <= blocklights + smax*tmax) + { + r_outoflights = true; + return; + } + for (lnum=0 ; lnumextents[0]>>4)+1; tmax = (surf->extents[1]>>4)+1; size = smax*tmax; + if (blocklight_max <= blocklights + size) + { + r_outoflights = true; + return; + } if (r_fullbright->value || !r_worldmodel->lightdata) { diff --git a/src/client/refresh/soft/sw_main.c b/src/client/refresh/soft/sw_main.c index e6301a15..1dbaa3b3 100644 --- a/src/client/refresh/soft/sw_main.c +++ b/src/client/refresh/soft/sw_main.c @@ -30,6 +30,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define NUMSTACKEDGES 2048 #define NUMSTACKSURFACES 1024 #define MAXALIASVERTS 2048 +#define MAXLIGHTS 1024 // allow some very large lightmaps viddef_t vid; pixel_t *vid_buffer = NULL; @@ -68,12 +69,14 @@ float r_time1; int r_numallocatededges; int r_numallocatedverts; int r_numallocatedtriangles; +int r_numallocatedlights; int r_numallocatededgebasespans; float r_aliasuvscale = 1.0; qboolean r_outofsurfaces; qboolean r_outofedges; qboolean r_outofverts; qboolean r_outoftriangles; +qboolean r_outoflights; qboolean r_outedgebasespans; qboolean r_dowarp; @@ -411,6 +414,36 @@ R_ReallocateMapBuffers (void) 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_edges) @@ -1700,6 +1733,12 @@ RE_ShutdownContext(void) } finalverts = NULL; + if(blocklights) + { + free(blocklights); + } + blocklights = NULL; + if(r_edges) { free(r_edges); @@ -1860,18 +1899,21 @@ SWimp_CreateRender(void) r_outofedges = false; r_outofverts = false; r_outoftriangles = false; + r_outoflights = false; r_outedgebasespans = false; // pointers to allocated buffers finalverts = NULL; r_edges = NULL; lsurfs = NULL; triangle_spans = NULL; + blocklights = NULL; edge_basespans = NULL; // curently allocated items r_cnumsurfs = 0; r_numallocatededges = 0; r_numallocatedverts = 0; r_numallocatedtriangles = 0; + r_numallocatedlights = 0; r_numallocatededgebasespans = 0; R_ReallocateMapBuffers(); diff --git a/src/client/refresh/soft/sw_part.c b/src/client/refresh/soft/sw_part.c index a64d9da3..f875440c 100644 --- a/src/client/refresh/soft/sw_part.c +++ b/src/client/refresh/soft/sw_part.c @@ -101,6 +101,11 @@ R_DrawParticle(particle_t *pparticle, int level) ** render the appropriate pixels */ count = pix; + if ((pz[(vid.width * count / 2) + (count / 2)]) > izi) + { + // looks like under some object + return; + } if (custom_particle == 0) { diff --git a/src/client/refresh/soft/sw_surf.c b/src/client/refresh/soft/sw_surf.c index 83e2168a..8131c79d 100644 --- a/src/client/refresh/soft/sw_surf.c +++ b/src/client/refresh/soft/sw_surf.c @@ -31,7 +31,6 @@ static unsigned char *r_source, *r_sourcemax; static unsigned *r_lightptr; void R_BuildLightMap (drawsurf_t *drawsurf); -extern unsigned blocklights[1024]; // allow some very large lightmaps static int sc_size; static surfcache_t *sc_rover; @@ -179,6 +178,12 @@ R_DrawSurface (drawsurf_t *drawsurf) { r_lightptr = blocklights + u; + if (r_lightptr >= blocklight_max) + { + r_outoflights = true; + continue; + } + prowdestbase = pcolumndest; pbasesource = basetptr + soffset; From f8c73ca731b182d3f73dea3f6162cba605ae3a02 Mon Sep 17 00:00:00 2001 From: Denis Pauk Date: Thu, 20 Jun 2019 23:02:55 +0300 Subject: [PATCH 7/7] Flush only frame difference. --- src/client/refresh/soft/sw_draw.c | 23 ++++--- src/client/refresh/soft/sw_main.c | 110 ++++++++++++++++++++++++------ 2 files changed, 103 insertions(+), 30 deletions(-) diff --git a/src/client/refresh/soft/sw_draw.c b/src/client/refresh/soft/sw_draw.c index 6bc4640a..5e36e84e 100644 --- a/src/client/refresh/soft/sw_draw.c +++ b/src/client/refresh/soft/sw_draw.c @@ -169,7 +169,6 @@ RE_Draw_StretchPicImplementation (int x, int y, int w, int h, const image_t *pic byte *source; int v, u; int height; - int f, fstep; int skip; if ((x < 0) || @@ -191,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; - for (v=0 ; vwidth) { - int sv = (skip + v)*pic->height/h; - source = pic->pixels[0] + sv*pic->width; - if (w == pic->width) - memcpy (dest, source, w); - else + for (v=0 ; vheight/h; + source = pic->pixels[0] + sv*pic->width; + memcpy (dest, source, w); + } + } + else + { + for (v=0 ; vheight/h; + source = pic->pixels[0] + sv*pic->width; f = 0; - fstep = (pic->width * SHIFT16XYZ_MULT) / w; + fstep = (pic->width << SHIFT16XYZ) / w; for (u=0 ; u>16]; diff --git a/src/client/refresh/soft/sw_main.c b/src/client/refresh/soft/sw_main.c index 1dbaa3b3..9db54ab8 100644 --- a/src/client/refresh/soft/sw_main.c +++ b/src/client/refresh/soft/sw_main.c @@ -34,6 +34,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. viddef_t vid; 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; pixel_t *vid_colormap = NULL; pixel_t *vid_alphamap = NULL; @@ -195,6 +198,8 @@ zvalue_t *d_pzbuffer; static void Draw_GetPalette (void); static void RE_BeginFrame( float camera_separation ); static void Draw_BuildGammaTable(void); +static void RE_FlushFrame(int vmin); +static void RE_CleanFrame(void); static void RE_EndFrame(void); static void R_DrawBeam(const entity_t *e); @@ -1311,10 +1316,7 @@ RE_SetPalette(const unsigned char *palette) byte palette32[1024]; // clear screen to black to avoid any palette flash - memset(vid_buffer, 0, vid.height * vid.width * sizeof(pixel_t)); - - // flush it to the screen - RE_EndFrame (); + RE_CleanFrame(); if (palette) { @@ -1661,11 +1663,14 @@ RE_InitContext(void *win) static void RE_ShutdownContext(void) { - if (vid_buffer) + if (swap_buffers) { - free(vid_buffer); + free(swap_buffers); } + swap_buffers = NULL; vid_buffer = NULL; + swap_frames[0] = NULL; + swap_frames[1] = NULL; if (sintable) { @@ -1777,7 +1782,7 @@ point math used in R_ScanEdges() overflows at width 2048 !! char shift_size; 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; @@ -1788,10 +1793,10 @@ RE_CopyFrame (Uint32 * pixels, int pitch) Uint32 *pixels_pos; pixel_t *buffer_pos; - max_pixels = pixels + vid.height * vid.width; - buffer_pos = vid_buffer; + max_pixels = pixels + vmax * vid.width; + 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]; buffer_pos++; @@ -1802,7 +1807,7 @@ RE_CopyFrame (Uint32 * pixels, int pitch) int y,x, buffer_pos; buffer_pos = 0; - for (y=0; y < vid.height; y++) + for (y=vmin; y < vmax; y++) { for (x=0; x < vid.width; x ++) { @@ -1814,32 +1819,89 @@ RE_CopyFrame (Uint32 * pixels, int pitch) } } -/* -** RE_EndFrame -** -** This does an implementation specific copy from the backbuffer to the -** front buffer. In the Win32 case it uses BitBlt or BltFast depending -** on whether we're using DIB sections/GDI or DDRAW. -*/ +static int +RE_BufferDifferenceStart(int vmin, int vmax) +{ + int *front_buffer, *back_buffer, *back_max; + + 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 -RE_EndFrame (void) +RE_CleanFrame(void) { 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)) { Com_Printf("Can't lock texture: %s\n", SDL_GetError()); return; } - RE_CopyFrame (pixels, pitch / sizeof(Uint32)); + memset(pixels, 0, pitch * vid.height); SDL_UnlockTexture(texture); SDL_RenderCopy(renderer, texture, NULL, NULL); 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, ©_rect, ©_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 */ @@ -1882,7 +1944,11 @@ SWimp_SetMode(int *pwidth, int *pheight, int mode, int fullscreen ) static 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)); intsintable = malloc((vid.width+CYCLE) * sizeof(int));