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
相关产品推荐
相关产品推荐

