Im trying to write an Software Renderer using this tutorial series: https://www.youtube.com/watch?v=2U-4_vpw1lQ&list=PLEETnX-uPtBUbVOok816vTl1K9vV1GgH5&index=13
But the problem is I try to render a Ico Sphere but it doesn't look right. See image: Rendered Sphere
The code for the rasterizer is:
void GRE_Edge(GTE_Vec4* MinVertY, GTE_Vec4* MaxVertY, GRE_EdgeData* Data)
{
Data->EdgeStartY = (uint32_t)ceilf(MinVertY->y);
Data->EdgeEndY = (uint32_t)ceilf(MaxVertY->y);
Data->EdgeStepX = (MaxVertY->x - MinVertY->x) / (MaxVertY->y - MinVertY->y);
Data->EdgeCurX = MinVertY->x + (Data->EdgeStartY - MinVertY->y) * Data->EdgeStepX;
}
void GRE_ScanEdge(GRE_EdgeData* a, GRE_EdgeData* b, bool Handedness, GRE_Framebuffer* Framebuffer)
{
GRE_EdgeData Left = *a;
GRE_EdgeData Right = *b;
if (Handedness)
{
GRE_EdgeData Temp = Left;
Left = Right;
Right = Temp;
}
for (uint32_t y = b->EdgeStartY; y < b->EdgeEndY; y++)
{
for (uint32_t x = (uint32_t)ceilf(Left.EdgeCurX); x < (uint32_t)ceilf(Right.EdgeCurX); x++)
GRE_DrawPixel(x, y, 255, 0, 255, Framebuffer);
Left.EdgeCurX += Left.EdgeStepX;
Right.EdgeCurX += Right.EdgeStepX;
}
}
void GRE_ScanTriangle(GTE_Vec4* MinVertY, GTE_Vec4* MidVertY, GTE_Vec4* MaxVertY, bool Handedness, GRE_Framebuffer* Framebuffer)
{
GRE_EdgeData TopToBottom;
GRE_Edge(MinVertY, MaxVertY, &TopToBottom);
GRE_EdgeData TopToMiddle;
GRE_Edge(MinVertY, MidVertY, &TopToMiddle);
GRE_EdgeData MiddleToBottom;
GRE_Edge(MidVertY, MaxVertY, &MiddleToBottom);
GRE_ScanEdge(&TopToBottom, &TopToMiddle, Handedness, Framebuffer);
GRE_ScanEdge(&TopToBottom, &MiddleToBottom, Handedness, Framebuffer);
}
float GRE_TriangleAreaTimesTwo(GTE_Vec4* a, GTE_Vec4* b, GTE_Vec4* c)
{
return ((b->x - a->x) * (c->y - a->y) - (c->x - a->x) * (b->y - a->y));
}
void GRE_FillTriangle(GTE_Vec4* v1, GTE_Vec4* v2, GTE_Vec4* v3, GRE_Framebuffer* Framebuffer)
{
GTE_Mat4 ScreenSpaceMatrix;
GTE_Mat4LoadScreenSpaceTransform(&ScreenSpaceMatrix, Framebuffer->Width * 0.5, Framebuffer->Height * 0.5);
GTE_Vec4 MinVertY;
GTE_Vec4MultiplyMat4(v1, &ScreenSpaceMatrix, &MinVertY);
GTE_Vec4PerspectiveDivide(&MinVertY);
GTE_Vec4 MidVertY;
GTE_Vec4MultiplyMat4(v2, &ScreenSpaceMatrix, &MidVertY);
GTE_Vec4PerspectiveDivide(&MidVertY);
GTE_Vec4 MaxVertY;
GTE_Vec4MultiplyMat4(v3, &ScreenSpaceMatrix, &MaxVertY);
GTE_Vec4PerspectiveDivide(&MaxVertY);
//Backface Culling
if (GRE_TriangleAreaTimesTwo(&MinVertY, &MaxVertY, &MidVertY) >= 0)
return;
GTE_Vec4 TmpVec;
if (MaxVertY.y < MidVertY.y)
{
TmpVec = MaxVertY;
MaxVertY = MidVertY;
MidVertY = TmpVec;
}
if (MidVertY.y < MinVertY.y)
{
TmpVec = MidVertY;
MidVertY = MinVertY;
MinVertY = TmpVec;
}
if (MaxVertY.y < MidVertY.y)
{
TmpVec = MaxVertY;
MaxVertY = MidVertY;
MidVertY = TmpVec;
}
GRE_ScanTriangle(&MinVertY, &MidVertY, &MaxVertY, GRE_TriangleAreaTimesTwo(&MinVertY, &MaxVertY, &MidVertY) >= 0, Framebuffer);
}
I can't find any problems with this code, so I hope someone can help me.