我的 SDL 中的多边形填充渲染算法有奇怪的渐变

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

我在 SDL 中创建了这个函数,它绘制一个纹理,该纹理有点像我的几何对象的画布/平面。它填充该画布中存在的多边形。它基于扫描线算法https://www.educative.io/answers/what-is-scanline-fill-algorithm,采用着色方法,其名称我不知道,但我有规范,这是大学的工作规格。

顶点用自己指定的颜色绘制,这是在另一个函数中完成的并且效果很好。 边缘是用“由 (Color2-Color1)/(y2-y1) 定义的递增比率绘制的,例如 (red2-red1)/(y2-y1)” 我通过将此比率添加到 y_min 到 y 的距离( redi、greeni...变量) 内部顶点以由(最终颜色 - 初始颜色)/(最终 x - 初始 x)定义的递增比率绘制 问题是,有些颜色看起来不错,而另一些颜色则产生奇怪的效果,我怀疑这可能是精确的?我相信,如果 RGB 低于 0 或高于 255,SDL 就会自动钳制。我对黑色有很多负值。 最后规格: 在“// Colors”注释之前,扫描线的第一个和最后一个像素位置以特定方式舍入

// 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; } } } }
完整版本的代码和类可以在这里找到

https://github.com/Pfzoz/FillpolyAlgorithm

我怀疑其中一个着色规范要么是精度错误,要么是逻辑错误

编辑:(用于可视化的图像,左上角确实关闭,并且都有不平滑的边缘)

c++ sdl-2
1个回答
-1
投票
主要错误是单独使用水平比率,它应该是第一个顶点颜色加上累积比率(redi + txr) 作品

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