Skip to content

Commit

Permalink
Merge pull request #940 from qw-ctf/degen
Browse files Browse the repository at this point in the history
RENDERER: Add option to filter out collinear vertices.
  • Loading branch information
dsvensson authored Sep 15, 2024
2 parents bcbf931 + 22f39e2 commit 63dfbf1
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 1 deletion.
17 changes: 17 additions & 0 deletions help_variables.json
Original file line number Diff line number Diff line change
Expand Up @@ -15627,6 +15627,23 @@
"remarks": "See also: r_nearclip.",
"type": "float"
},
"r_remove_collinear_vertices": {
"default": "0",
"desc": "Filter out vertices causing triangles to have zero area. These types of triangles are a sore spot in some GPUs that risk introducing glitches. An expected side effect is a risk of seeing a sparkling pixel.",
"group-id": "35",
"remarks": "For macOS arm64 this is force-enabled to prevent cheating. This filtering is a temporary workaround before adding code to avoid generating such triangles in the first place.",
"type": "boolean",
"values": [
{
"description": "Disable filtering of collinear vertices.",
"name": "false"
},
{
"description": "Enable filtering of collinear vertices.",
"name": "true"
}
]
},
"r_fastsky": {
"default": "0",
"group-id": "51",
Expand Down
60 changes: 59 additions & 1 deletion src/r_lightmaps.c
Original file line number Diff line number Diff line change
Expand Up @@ -590,9 +590,56 @@ static int LightmapAllocBlock(int w, int h, int *x, int *y)
return LightmapAllocBlock(w, h, x, y);
}

#define EPSILON 1e-6

// Check if triangle has a ~zero area
// https://en.wikipedia.org/wiki/Collinearity
static qbool R_ArePointsColinear(const vec3_t v1, const vec3_t v2, const vec3_t v3)
{
vec3_t d0, d1, cross;

VectorSubtract(v2, v1, d0);
VectorSubtract(v3, v2, d1);

CrossProduct(d0, d1, cross);

return DotProduct(cross, cross) < EPSILON;
}

static void R_RemoveColinearVertices(glpoly_t *poly, float new_verts[][VERTEXSIZE])
{
int i, v1_index, v2_index, v3_index, new_numverts = 0;
int numverts = poly->numverts;

v1_index = numverts - 1;
v2_index = 0;
v3_index = 1;

for (i = 0; i < numverts; i++) {
float *v1 = poly->verts[v1_index];
float *v2 = poly->verts[v2_index];
float *v3 = poly->verts[v3_index];

if (!R_ArePointsColinear(v1, v2, v3)) {
memcpy(new_verts[new_numverts], v2, sizeof(float) * VERTEXSIZE);
new_numverts++;
}

v1_index = v2_index;
v2_index = v3_index;
v3_index = (v3_index + 1) % numverts;
}

if (new_numverts > 0) {
memcpy(poly->verts, new_verts, new_numverts * sizeof(float) * VERTEXSIZE);
poly->numverts = new_numverts;
}
}

//
static void R_BuildSurfaceDisplayList(model_t* currentmodel, msurface_t *fa)
{
extern cvar_t r_remove_collinear_vertices;
int i, lindex, lnumverts;
medge_t *pedges, *r_pedge;
float *vec, s, t;
Expand Down Expand Up @@ -684,8 +731,19 @@ static void R_BuildSurfaceDisplayList(model_t* currentmodel, msurface_t *fa)
}
poly->numverts = lnumverts;

// Some GPUs misbehave if fed triangles of empty size.
if (r_remove_collinear_vertices.value) {
if (poly->numverts > 4) {
float (*new_verts)[VERTEXSIZE] = Q_malloc(poly->numverts * sizeof(float[VERTEXSIZE]));
R_RemoveColinearVertices(poly, new_verts);
Q_free(new_verts);
} else {
float new_verts[4][VERTEXSIZE];
R_RemoveColinearVertices(poly, new_verts);
}
}

R_BrushModelPolygonToTriangleStrip(poly);
return;
}

static void R_BuildLightmapData(msurface_t* surf, int surfnum)
Expand Down
13 changes: 13 additions & 0 deletions src/r_rmain.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,15 @@ static void OnDynamicLightingChange(cvar_t* var, char* value, qbool* cancel)
}
}

static void OnRemoveCollinearVerticesChanged(cvar_t* var, char* value, qbool* cancel)
{
#if defined(__APPLE__) && defined(__aarch64__)
// At least arm64 based MacBook laptops are known to require this workaround.
Cvar_SetIgnoreCallback(var, "1");
*cancel = true;
#endif
}

cvar_t cl_multiview = {"cl_multiview", "0" };
cvar_t cl_mvdisplayhud = {"cl_mvdisplayhud", "1"};
cvar_t cl_mvhudvertical = {"cl_mvhudvertical", "0"};
Expand Down Expand Up @@ -238,6 +247,8 @@ cvar_t gl_smoothmodels = {"gl_smoothmodels", "1"};

cvar_t gl_vbo_clientmemory = {"gl_vbo_clientmemory", "0", CVAR_LATCH_GFX };

cvar_t r_remove_collinear_vertices = {"r_remove_collinear_vertices", "0", 0, OnRemoveCollinearVerticesChanged};

//Returns true if the box is completely outside the frustom
qbool R_CullBox(vec3_t mins, vec3_t maxs)
{
Expand Down Expand Up @@ -750,6 +761,8 @@ void R_Init(void)
Cvar_Register(&cl_mvinset_top);
Cvar_Register(&cl_mvinset_right);

Cvar_Register(&r_remove_collinear_vertices);

Cvar_ResetCurrentGroup();

if (!hud_netgraph) {
Expand Down

0 comments on commit 63dfbf1

Please sign in to comment.