光栅化问题

问题描述 投票:0回答:1

我最近一直在用 C 语言开发 3D 软件渲染器,并且我已经成功地使一些形状和线框正常工作。

但是我现在已经开始光栅化了,但似乎无法让它工作。我目前正在尝试将 2 个立方体放入世界中,一个绿色,一个蓝色。然而,当我尝试使用扫描线光栅化进行光栅化时,与绿色和蓝色立方体相同的 Y 位置内到处都有绿色和蓝色水平线。立方体的大部分颜色都正确,但仍然有一堆线条。 我遇到的另一个问题是,如果这些水平线中的任何一条到达屏幕的顶部或底部,那么渲染器会立即崩溃。 最后,如果我移动光标,线条会稍微闪烁。这很奇怪,因为我的程序根本不接受鼠标的输入。

Image of what the screen looks like

Image of what the screen looks like with wireframes

代码:

void FillInPolygon(struct Triangle triangle, const int WINDOWHEIGHT, Color color) {
    
    int buf_x0[WINDOWHEIGHT],buf_x1[WINDOWHEIGHT];      //These arrays will store the X start and X end of the lines
    
    LineDrawerForBuffer(buf_x0, buf_x1, triangle.v0.xProj, triangle.v0.yProj, triangle.v1.xProj, triangle.v1.yProj);    //Line drawer will get the edges of the triangle
    LineDrawerForBuffer(buf_x0, buf_x1, triangle.v1.xProj, triangle.v1.yProj, triangle.v2.xProj, triangle.v2.yProj);
    LineDrawerForBuffer(buf_x0, buf_x1, triangle.v2.xProj, triangle.v2.yProj, triangle.v0.xProj, triangle.v0.yProj);
    
    int Ay = triangle.v0.yProj;     //Y position of where the first vertex of the triangle is in 2d space
    int By = triangle.v1.yProj;     //Y position of the second
    int Cy = triangle.v2.yProj;     //Y position of the third
    
    for (int y=Min(Ay,By,Cy);y<=Max(Ay,By,Cy);y++)
        DrawLine(buf_x0[y], y, buf_x1[y], y, color);        //Draws a horizontal line between the X start and X end of the lines
    
}

LineDrawerForBuffer():

void LineDrawerForBuffer(int *buf_x0, int *buf_x1, int x1, int y1, int x2, int y2) {
    
    //Modified version of Bresenham's Line Drawing Algorithm, this one is capable of drawing lines in all directions

    int y = y1;
    int x = x1;
    
    int dx = Abs(x2-x1);
    int dy = Abs(y2-y1);
    
    int s1 = Sign(x2-x1);
    int s2 = Sign(y2-y1);
    
    bool interchange;
    
    if (dy > dx) {
        int t = dx;
        dx = dy;
        dy = t;
        interchange = true;
    }
    else {
        interchange = false;
    }
    
    int e = 2*dy-dx;
    int a = 2*dy;
    int b = 2*dy-2*dx;
    
    
    if ((dy < 0 && !interchange) || (dx < 0 && interchange)) {
        buf_x0[y] = x;
    }
    else if ((dy > 0 && !interchange) || (dx > 0 && interchange)) {
        buf_x1[y] = x;
    }
    else if ((dy == 0 && !interchange) || (dx == 0 && interchange)) {
        buf_x0[y] = x;
        buf_x1[y] = x;
    }
    
    
    for (int i = 0; i<dx; i++) {
        
        
        
        if (e < 0) {
            if (interchange) y = y + s2;
            else             x = x + s1;
            
            e = e + a;
        }
        else {
            y = y + s2;
            x = x + s1;
            e = e + b;
        }
        
        if ((dy < 0 && !interchange) || (dx < 0 && interchange)) {
            buf_x0[y] = x;
        }
        else if ((dy > 0 && !interchange) || (dx > 0 && interchange)) {
            buf_x1[y] = x;
        }
        else if ((dy == 0 && !interchange) || (dx == 0 && interchange)) {
            buf_x0[y] = x;
            buf_x1[y] = x;
        }
        
    }
    
}

一些附加信息: 渲染器使用弱透视投影,并且 我正在使用 Raylib 打开一个窗口并在其上绘图。

我尝试过摆弄线抽屉以及位置如何存储在数组中以及数组的大小。但目前还没有解决这个问题。

编辑:我已经通过使用 calloc 分配 buf_x0 和 buf_x1 设法修复了各处闪烁的细线。然而现在它是一条大线,其高度与它来自的立方体的高度相同。蓝色立方体还有一条奇怪的细线从右侧伸出。 The result after dynamically allocating buf_x0 & buf_x1

我也相当确定问题不在于我提供给光栅化器的多边形和顶点,因为当我使用内置的 Raylib 函数处理三角形时,它工作得很好。 The result when using Raylib's built in function for triangles

c 3d rasterizing raylib
1个回答
0
投票

我通过更改写入 buf_x0 和 buf_x1 的代码设法使光栅化器正常工作。而不是使用

if ((dy < 0 && !interchange) || (dx < 0 && interchange)) {
    buf_x0[y] = x;
}
else if ((dy > 0 && !interchange) || (dx > 0 && interchange)) {
    buf_x1[y] = x;
}
else if ((dy == 0 && !interchange) || (dx == 0 && interchange)) {
    buf_x0[y] = x;
    buf_x1[y] = x;
}

在 for 循环中及其之前。现在我在 for 循环的开头有一个 if 语句,如下所示:

if ((y >= 0) && (y < WINDOWHEIGHT))
{
        if (x < buf_x0[y]) buf_x0[y] = x;
        if (x > buf_x1[y]) buf_x1[y] = x;
}

这与在 FillInPolygon 函数中声明 buf_x0 和 buf_x1 后右侧的循环一起。该循环将 pos_x0 中的每个值初始化为 INT_MAX,并将 pos_x1 中的每个值初始化为 INT_MIN。我相信立方体的线条偏离一侧的原因是由于 pos_x0 被初始化为 0,以及用于写入数组的 if 语句实际上并未写入 buf_x0 (经过一些测试后发现)。意味着光栅化器将尝试从 x: 0 绘制到多边形的另一端。我写入 buf 数组的新方法还解决了以下问题:如果任何多边形的顶点位于屏幕上方或下方,我的程序就会崩溃。问题不在于 DrawLine 函数,而在于 LineDrawerForBuffer 函数。当 Y 低于 0 或高于 WINDOWHEIGHT 时,将会读取 buf 数组中不存在的索引,从而导致程序崩溃。至少我很确定是这样。

© www.soinside.com 2019 - 2024. All rights reserved.