基于ryg博客实现的重心坐标光栅器步进权重与行列式值不匹配
问题根源
你推导的边函数系数A、B、C完全正确,首个采样点计算值匹配、逐像素det函数结果正常已经验证了这一点,偏差和坐标系映射、系数推导没有任何关系,完全来自光栅化循环的增量更新时序错误。
你的代码逻辑问题非常明确:
内层x循环每处理完一个像素就累加x方向步长,当整行min_x~max_x的像素全部遍历完成时,w值已经累计累加了(max_x - min_x + 1)次x步长,对应的坐标是(max_x + 1, 当前y),已经超出了当前行的x范围。此时你直接累加y方向步长切换行,相当于把x位置偏移错误的w值直接搬到下一行,和下一行起始点(min_x, y+1)的正确w值存在固定偏差,且每遍历一行就会多累积一次整行的x步长误差,越往下遍历偏差越大。
修复方案
不需要修改任何边函数系数,只需要调整增量更新的逻辑,单独维护每行起始点的w值即可,从根源上避免x方向步进累积的偏移影响行切换:
- 初始化时计算好第一行(y=min_y)行首点
(min_x, min_y)对应的三个w值,作为行首基准值 - 每一行遍历开始时,把当前w值重置为该行的行首基准值,再开始x方向的逐像素步进累加
- 整行遍历完成后,只需要给行首基准值累加y方向步长,就能得到下一行行首的正确w值
修正后的光栅化遍历代码如下:
// 初始化第一行行首的边函数值 point_t p = (point_t)calloc(pipeline->num_attr, sizeof(float)); p[0] = min_x; p[1] = min_y; edge_t e01, e12, e20; float w0_row = init_edge(&e12, v1, v2, p); float w1_row = init_edge(&e20, v2, v0, p); float w2_row = init_edge(&e01, v0, v1, p); // 光栅化遍历 for (p[1] = min_y; p[1] <= max_y; p[1]++) { // 每次行遍历开始,重置w为当前行首的正确值 float w0 = w0_row; float w1 = w1_row; float w2 = w2_row; for (p[0] = min_x; p[0] <= max_x; p[0]++) { // 此时w0/w1/w2和逐像素计算的s0/s1/s2完全一致 if ( (w0 >= 0) && (w1 >= 0) && (w2 >= 0) ) { draw_point(pipeline, p); } // x方向步进 w0 += e12.step_x; w1 += e20.step_x; w2 += e01.step_x; } // 更新下一行行首的边函数值 w0_row += e12.step_y; w1_row += e20.step_y; w2_row += e01.step_y; }
这种写法完全符合边函数的增量计算规则,不需要额外计算x方向的回退偏移,也不会出现步进累积误差,逻辑和标准优化光栅器实现完全对齐。
内容的提问来源于stack exchange,提问作者aurreco
相关产品推荐
相关产品推荐

