take all edge cases into account for XMin/XMax calculation

This commit is contained in:
RSDuck 2023-04-22 01:00:30 +02:00
parent 2b52b45f66
commit e3495011bf
4 changed files with 73 additions and 82 deletions

View File

@ -307,7 +307,7 @@ void ComputeRenderer::SetupAttrs(SpanSetupY* span, Polygon* poly, int from, int
span->TexcoordV1 = poly->Vertices[to]->TexCoords[1];
}
void ComputeRenderer::SetupYSpanDummy(SpanSetupY* span, Polygon* poly, int vertex, int side, s32 positions[10][2])
void ComputeRenderer::SetupYSpanDummy(RenderPolygon* rp, SpanSetupY* span, Polygon* poly, int vertex, int side, s32 positions[10][2])
{
s32 x0 = positions[vertex][0];
if (side)
@ -325,6 +325,17 @@ void ComputeRenderer::SetupYSpanDummy(SpanSetupY* span, Polygon* poly, int verte
span->XMax = x0;
span->Y0 = span->Y1 = positions[vertex][1];
if (span->XMin < rp->XMin)
{
rp->XMin = span->XMin;
rp->XMinY = span->Y0;
}
if (span->XMax > rp->XMax)
{
rp->XMax = span->XMax;
rp->XMaxY = span->Y0;
}
span->Increment = 0;
span->I0 = span->I1 = span->IRecip = 0;
@ -337,7 +348,7 @@ void ComputeRenderer::SetupYSpanDummy(SpanSetupY* span, Polygon* poly, int verte
SetupAttrs(span, poly, vertex, vertex);
}
void ComputeRenderer::SetupYSpan(int polynum, SpanSetupY* span, Polygon* poly, int from, int to, u32 y, int side, s32 positions[10][2])
void ComputeRenderer::SetupYSpan(RenderPolygon* rp, SpanSetupY* span, Polygon* poly, int from, int to, int side, s32 positions[10][2])
{
span->X0 = positions[from][0];
span->X1 = positions[to][0];
@ -346,23 +357,45 @@ void ComputeRenderer::SetupYSpan(int polynum, SpanSetupY* span, Polygon* poly, i
SetupAttrs(span, poly, from, to);
s32 minXY, maxXY;
bool negative = false;
if (span->X1 > span->X0)
{
span->XMin = span->X0;
span->XMax = span->X1-1;
minXY = span->Y0;
maxXY = span->Y1;
}
else if (span->X1 < span->X0)
{
span->XMin = span->X1;
span->XMax = span->X0-1;
negative = true;
minXY = span->Y1;
maxXY = span->Y0;
}
else
{
span->XMin = span->X0;
if (side) span->XMin--;
span->XMax = span->XMin;
// doesn't matter for completely vertical slope
minXY = span->Y0;
maxXY = span->Y0;
}
if (span->XMin < rp->XMin)
{
rp->XMin = span->XMin;
rp->XMinY = minXY;
}
if (span->XMax > rp->XMax)
{
rp->XMax = span->XMax;
rp->XMaxY = maxXY;
}
span->IsDummy = false;
@ -1072,18 +1105,15 @@ void ComputeRenderer::RenderFrame()
s32 ytop = ScreenHeight, ybot = 0;
for (int i = 0; i < polygon->NumVertices; i++)
{
scaledPositions[i][0] = (polygon->Vertices[i]->HiresPosition[0] * ScaleFactor) >> 4;
scaledPositions[i][1] = (polygon->Vertices[i]->HiresPosition[1] * ScaleFactor) >> 4;
scaledPositions[i][0] = (polygon->Vertices[i]->FinalPosition[0] * ScaleFactor);
scaledPositions[i][1] = (polygon->Vertices[i]->FinalPosition[1] * ScaleFactor);
ytop = std::min(scaledPositions[i][1], ytop);
ybot = std::max(scaledPositions[i][1], ybot);
}
RenderPolygons[i].YTop = ytop;
RenderPolygons[i].YBot = ybot;
s32 minX = scaledPositions[vtop][0];
s32 minXY = scaledPositions[vtop][1];
s32 maxX = scaledPositions[vtop][0];
s32 maxXY = scaledPositions[vtop][1];
RenderPolygons[i].XMin = ScreenWidth;
RenderPolygons[i].XMax = 0;
if (ybot == ytop)
{
@ -1101,20 +1131,10 @@ void ComputeRenderer::RenderFrame()
assert(numYSpans < MaxYSpanSetups);
u32 curSpanL = numYSpans;
SetupYSpanDummy(&YSpanSetups[numYSpans++], polygon, vtop, 0, scaledPositions);
SetupYSpanDummy(&RenderPolygons[i], &YSpanSetups[numYSpans++], polygon, vtop, 0, scaledPositions);
assert(numYSpans < MaxYSpanSetups);
u32 curSpanR = numYSpans;
SetupYSpanDummy(&YSpanSetups[numYSpans++], polygon, vbot, 1, scaledPositions);
minX = YSpanSetups[curSpanL].X0;
minXY = YSpanSetups[curSpanL].Y0;
maxX = YSpanSetups[curSpanR].X0;
maxXY = YSpanSetups[curSpanR].Y0;
if (maxX < minX)
{
std::swap(minX, maxX);
std::swap(minXY, maxXY);
}
SetupYSpanDummy(&RenderPolygons[i], &YSpanSetups[numYSpans++], polygon, vbot, 1, scaledPositions);
YSpanIndices[numSetupIndices].PolyIdx = i;
YSpanIndices[numSetupIndices].SpanIdxL = curSpanL;
@ -1126,10 +1146,10 @@ void ComputeRenderer::RenderFrame()
{
u32 curSpanL = numYSpans;
assert(numYSpans < MaxYSpanSetups);
SetupYSpan(i, &YSpanSetups[numYSpans++], polygon, curVL, nextVL, ytop, 0, scaledPositions);
SetupYSpan(&RenderPolygons[i], &YSpanSetups[numYSpans++], polygon, curVL, nextVL, 0, scaledPositions);
u32 curSpanR = numYSpans;
assert(numYSpans < MaxYSpanSetups);
SetupYSpan(i, &YSpanSetups[numYSpans++], polygon, curVR, nextVR, ytop, 1, scaledPositions);
SetupYSpan(&RenderPolygons[i], &YSpanSetups[numYSpans++], polygon, curVR, nextVR, 1, scaledPositions);
for (u32 y = ytop; y < ybot; y++)
{
@ -1152,20 +1172,10 @@ void ComputeRenderer::RenderFrame()
}
}
if (scaledPositions[curVL][0] < minX)
{
minX = scaledPositions[curVL][0];
minXY = scaledPositions[curVL][1];
}
if (scaledPositions[curVL][0] > maxX)
{
maxX = scaledPositions[curVL][0];
maxXY = scaledPositions[curVL][1];
}
assert(numYSpans < MaxYSpanSetups);
curSpanL = numYSpans;
SetupYSpan(i,&YSpanSetups[numYSpans++], polygon, curVL, nextVL, y, 0, scaledPositions);
SetupYSpan(&RenderPolygons[i], &YSpanSetups[numYSpans++], polygon, curVL, nextVL, 0, scaledPositions);
}
if (y >= scaledPositions[nextVR][1] && curVR != polygon->VBottom)
{
@ -1186,20 +1196,9 @@ void ComputeRenderer::RenderFrame()
}
}
if (scaledPositions[curVR][0] < minX)
{
minX = scaledPositions[curVR][0];
minXY = scaledPositions[curVR][1];
}
if (scaledPositions[curVR][0] > maxX)
{
maxX = scaledPositions[curVR][0];
maxXY = scaledPositions[curVR][1];
}
assert(numYSpans < MaxYSpanSetups);
curSpanR = numYSpans;
SetupYSpan(i,&YSpanSetups[numYSpans++], polygon, curVR, nextVR, y, 1, scaledPositions);
SetupYSpan(&RenderPolygons[i] ,&YSpanSetups[numYSpans++], polygon, curVR, nextVR, 1, scaledPositions);
}
YSpanIndices[numSetupIndices].PolyIdx = i;
@ -1210,32 +1209,6 @@ void ComputeRenderer::RenderFrame()
}
}
if (scaledPositions[nextVL][0] < minX)
{
minX = scaledPositions[nextVL][0];
minXY = scaledPositions[nextVL][1];
}
if (scaledPositions[nextVL][0] > maxX)
{
maxX = scaledPositions[nextVL][0];
maxXY = scaledPositions[nextVL][1];
}
if (scaledPositions[nextVR][0] < minX)
{
minX = scaledPositions[nextVR][0];
minXY = scaledPositions[nextVR][1];
}
if (scaledPositions[nextVR][0] > maxX)
{
maxX = scaledPositions[nextVR][0];
maxXY = scaledPositions[nextVR][1];
}
RenderPolygons[i].XMin = minX;
RenderPolygons[i].XMinY = minXY;
RenderPolygons[i].XMax = maxX;
RenderPolygons[i].XMaxY = maxXY;
//printf("polygon min max %d %d | %d %d\n", RenderPolygons[i].XMin, RenderPolygons[i].XMinY, RenderPolygons[i].XMax, RenderPolygons[i].XMaxY);
}

View File

@ -230,8 +230,8 @@ private:
void DeleteShaders();
void SetupAttrs(SpanSetupY* span, Polygon* poly, int from, int to);
void SetupYSpan(int polynum, SpanSetupY* span, Polygon* poly, int from, int to, u32 y, int side, s32 positions[10][2]);
void SetupYSpanDummy(SpanSetupY* span, Polygon* poly, int vertex, int side, s32 positions[10][2]);
void SetupYSpan(RenderPolygon* rp, SpanSetupY* span, Polygon* poly, int from, int to, int side, s32 positions[10][2]);
void SetupYSpanDummy(RenderPolygon* rp, SpanSetupY* span, Polygon* poly, int vertex, int side, s32 positions[10][2]);
bool CompileShader(GLuint& shader, const char* source, const std::initializer_list<const char*>& defines);
};

View File

@ -208,6 +208,7 @@ buffer TilesBuffer
};
#endif
#if defined(DepthBlend) || defined(FinalPass)
layout (std430, binding = 5)
#ifdef DepthBlend
writeonly
@ -221,6 +222,7 @@ buffer RasterResult
uint DepthResult[ScreenWidth*ScreenHeight*2];
uint AttrResult[ScreenWidth*ScreenHeight*2];
};
#endif
layout (std140, binding = 0) uniform MetaUniform
{
@ -835,6 +837,28 @@ bool BinPolygon(Polygon polygon, ivec2 topLeft, ivec2 botRight)
int polygonHeight = polygon.YBot - polygon.YTop;
/*
All (good) polygons are convex. So the following holds true:
Starting from the top most point where both edges originate
the X coordinate of the left edge will stay the same or falls until
the minimum X-axis coordinate is reached. Then it stays the same or
rises until the point it meets with the right edge.
The same applies to the right edge, except that it first may rise or stay equal and
after the maximum point may only fall or stay the same.
This means that for every tile which doesn't contain the point where the direction changes
we can just get the maximum point by sampling the top most and bottom most coordinate
within the tile.
For a tile which is that the height of the direction change
As a sidenote another consequence of this design decision is
that malformed polygons aren't binned properly.
As a note bottom Y is exclusive!
*/
int polyInnerTopY = clamp(topLeft.y - polygon.YTop, 0, max(polygonHeight-1, 0));
int polyInnerBotY = clamp(botRight.y - polygon.YTop, 0, max(polygonHeight-1, 0));
@ -1557,8 +1581,8 @@ void main()
// else
// color.x = 0U;
//if (gl_LocalInvocationID.x == 7 || gl_LocalInvocationID.y == 7)
//color.x = 0x1F00001FU | 0x40000000U;
//if ((gl_GlobalInvocationID.y % 8) == 7 || (gl_GlobalInvocationID.y % 8) == 7)
// color.x = 0x1F00001FU | 0x40000000U;
vec4 result = vec4(bitfieldExtract(color.x, 16, 8), bitfieldExtract(color.x, 8, 8), color.x & 0x3FU, bitfieldExtract(color.x, 24, 8));
result /= vec4(63.0, 63.0, 63.0, 31.0);

View File

@ -24,8 +24,6 @@ using Platform::LogLevel;
namespace OpenGL
{
#define checkGLError() if (glGetError() != GL_NO_ERROR) printf("error %d\n", __LINE__)
bool CompilerShader(GLuint& id, const char* source, const char* name, const char* type)
{
int len;
@ -39,12 +37,9 @@ bool CompilerShader(GLuint& id, const char* source, const char* name, const char
len = strlen(source);
glShaderSource(id, 1, &source, &len);
checkGLError();
glCompileShader(id);
checkGLError();
glGetShaderiv(id, GL_COMPILE_STATUS, &res);
checkGLError();
if (res != GL_TRUE)
{
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &res);
@ -74,7 +69,6 @@ bool LinkProgram(GLuint& result, GLuint* ids, int numIds)
for (int i = 0; i < numIds; i++)
{
glAttachShader(result, ids[i]);
checkGLError();
}
glLinkProgram(result);