You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SDL多边形填充渲染算法出现异常渐变问题排查

扫描线算法多边形填充的颜色渐变异常问题

我基于扫描线算法在SDL中实现了一个多边形填充渲染函数,能在纹理画布上绘制填充多边形。着色规则按课程要求实现:

  • 顶点颜色由独立函数绘制,这部分正常
  • 边缘颜色增量用公式 (Color2-Color1)/(y2-y1) 计算
  • 内部颜色增量用公式 (final color - initial color)/(final x - initial x) 计算

但现在遇到两个问题:部分颜色渐变效果异常,黑色系颜色还出现大量负值;左上角渐变异常明显,且所有图形边缘都不光滑。我推测是精度问题或者着色逻辑错误,扫描线首尾像素位置已经按指定规则取整了。

核心实现代码如下:

// Scanline Algorithm
void scanline_fill()
{
    for (Polygon *polygon : polygons)
    {
        std::vector<Active_Edge> active_table;
        std::vector<Edge*> _temp_edges = polygon->edges;
        for (int y = polygon->y_min; y < polygon->y_max; y++)
        {
            // Interception
            for (int i = 0; i < _temp_edges.size(); i++)
            {
                if (y == _temp_edges[i]->y_min)
                {
                    active_table.push_back({(float)_temp_edges[i]->y_max, (float)_temp_edges[i]->x_y_min, _temp_edges[i]->m_inversed, _temp_edges[i]});
                    _temp_edges.erase(_temp_edges.begin() + i--);
                }
            }
            for (int i = 0; i < active_table.size(); i++)
            {
                // Remove y == y_max
                if (active_table[i].y_max == y)
                    active_table.erase(active_table.begin() + i--);
            }
            std::sort(active_table.begin(), active_table.end(), table_comparison);
            // Drawing
            for (int i = 0; i + 1 < active_table.size(); i += 2)
            {
                if (active_table[i].x_y_min != active_table[i + 1].x_y_min)
                {
                    int start = std::ceil(active_table[i].x_y_min);
                    int end;
                    if (active_table[i + 1].x_y_min - std::floor(active_table[i + 1].x_y_min) != 0)
                        end = std::floor(active_table[i + 1].x_y_min);
                    else
                        end = active_table[i + 1].x_y_min - 1;
                    // Colors
                    float ri = (float)(active_table[i].edge->a->color.r - active_table[i].edge->b->color.r) / (float)(active_table[i].edge->a->y - active_table[i].edge->b->y);
                    float gi = (float)(active_table[i].edge->a->color.g - active_table[i].edge->b->color.g) / (float)(active_table[i].edge->a->y - active_table[i].edge->b->y);
                    float bi = (float)(active_table[i].edge->a->color.b - active_table[i].edge->b->color.b) / (float)(active_table[i].edge->a->y - active_table[i].edge->b->y);
                    float rf = (float)(active_table[i + 1].edge->a->color.r - active_table[i + 1].edge->b->color.r) / (float)(active_table[i + 1].edge->a->y - active_table[i + 1].edge->b->y);
                    float gf = (float)(active_table[i + 1].edge->a->color.g - active_table[i + 1].edge->b->color.g) / (float)(active_table[i + 1].edge->a->y - active_table[i + 1].edge->b->y);
                    float bf = (float)(active_table[i + 1].edge->a->color.b - active_table[i + 1].edge->b->color.b) / (float)(active_table[i + 1].edge->a->y - active_table[i + 1].edge->b->y);
                    float redi = (float)active_table[i].edge->x_y_min_vertex->color.r + ri * (float)(y - active_table[i].edge->y_min);
                    float greeni = (float)active_table[i].edge->x_y_min_vertex->color.g + gi * (float)(y - active_table[i].edge->y_min);
                    float bluei = (float)active_table[i].edge->x_y_min_vertex->color.b + bi * (float)(y - active_table[i].edge->y_min);
                    SDL_SetRenderDrawColor(renderer, redi, greeni, bluei, 255);
                    SDL_RenderDrawPoint(renderer, start, y);
                    float redf = (float)active_table[i + 1].edge->x_y_min_vertex->color.r + rf * (float)(y - active_table[i + 1].edge->y_min);
                    float greenf = (float)active_table[i + 1].edge->x_y_min_vertex->color.g + gf * (float)(y - active_table[i + 1].edge->y_min);
                    float bluef = (float)active_table[i + 1].edge->x_y_min_vertex->color.b + bf * (float)(y - active_table[i + 1].edge->y_min);
                    SDL_SetRenderDrawColor(renderer, rf, gf, bf, 255);
                    SDL_RenderDrawPoint(renderer, end - 1, y);
                    float txr = (redf - redi) / (active_table[i].x_y_min - active_table[i + 1].x_y_min);
                    float txg = (greenf - greeni) / (active_table[i].x_y_min - active_table[i + 1].x_y_min);
                    float txb = (bluef - bluei) / (active_table[i].x_y_min - active_table[i + 1].x_y_min);
                    for (int x = start + 1; x < end - 1; x++)
                    {
                        SDL_SetRenderDrawColor(renderer, (float)(x - start + 1) * txr, (float)(x - start + 1) * txg, (float)(x - start + 1) * txb, 255);
                        SDL_RenderDrawPoint(renderer, x, y);
                    }
                }
                // Incrementing
                active_table[i].x_y_min = active_table[i].x_y_min + active_table[i].m_inversed;
                active_table[i + 1].x_y_min = active_table[i + 1].x_y_min + active_table[i + 1].m_inversed;
            }
        }
    }
}

效果截图:
渐变异常的三角形

内容的提问来源于stack exchange,提问作者Oz_Magician

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 04:19:55