1

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.

Mori TM
  • 11
  • 4
  • try to disable Backface Culling if it maks a difference if it does than you got wrong polygon winding on the missing triangles – Spektre Dec 01 '21 at 09:35
  • If I turn of Backface Culling it looks exactly the same as before the only difference is that you can see the triangles from the back – Mori TM Dec 01 '21 at 12:39
  • then try to check out your reordering of points (by y coordinate) before rasterizing the edges into left and right buffers. If you got a bug there then triangles with certain orientation could be rendered wrongly... it looks fishy to me... Also check these https://stackoverflow.com/a/19078088/2521214 https://stackoverflow.com/a/39062479/2521214 https://stackoverflow.com/q/66503903/2521214 for some cross reference against working code – Spektre Dec 01 '21 at 14:39

0 Answers0