Legacy OpenGL中使用glDrawArrays绘制GL_LINE_LOOP线条异常问题排查
问题:glDrawArrays绘制GL_LINE_LOOP点划线无法闭合的原因及解决办法
问题场景
你在Legacy OpenGL环境下,用glBegin/glEnd绘制点划线闭合循环线条完全正常:
glEnable(GL_LINE_STIPPLE); glBegin(GL_LINE_LOOP); for (size_t idx = 0; idx < m_spline_cvs.size(); idx++) { glVertex2f(m_cv_positions[0][idx].x,m_cv_positions[0][idx].y); } glEnd(); glDisable(GL_LINE_STIPPLE);
但改用glDrawArrays实现时,线条无法形成闭合循环:
std::vector <float> cv_tracker_target_line; for (size_t idx = 0; idx < m_spline_cvs.size(); idx++) { cv_tracker_target_line.push_back(m_cv_positions[0][idx].x); cv_tracker_target_line.push_back(m_cv_positions[0][idx].y); } glEnable(GL_LINE_STIPPLE); glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(2, GL_FLOAT, 0, &cv_tracker_target_line[0]); glDrawArrays(GL_LINE_LOOP, 0, cv_tracker_target_line.size()); glDisable(GL_LINE_STIPPLE); glDisableClientState(GL_VERTEX_ARRAY);
错误原因
核心问题出在glDrawArrays的最后一个参数上:这个参数需要传入的是顶点的数量,而非顶点数据数组的总元素个数。
你的cv_tracker_target_line里每个顶点用2个float存储(x和y坐标),所以顶点数量应该是数组长度除以2。但你直接传了cv_tracker_target_line.size(),相当于告诉OpenGL要绘制size()个顶点——这会让OpenGL读取超出你实际存储的顶点数据范围的垃圾值,导致线条最后一段画到了错误的位置,自然无法和起点闭合。
修复方案
把glDrawArrays的最后一个参数改成cv_tracker_target_line.size() / 2就可以了。另外,最好加个校验确保数组长度是偶数,避免出现错误:
std::vector <float> cv_tracker_target_line; for (size_t idx = 0; idx < m_spline_cvs.size(); idx++) { cv_tracker_target_line.push_back(m_cv_positions[0][idx].x); cv_tracker_target_line.push_back(m_cv_positions[0][idx].y); } // 校验数据合法性,避免奇数长度导致的错误 if (cv_tracker_target_line.size() % 2 != 0) { // 这里可以加错误处理,比如打日志或者直接返回 return; } glEnable(GL_LINE_STIPPLE); glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(2, GL_FLOAT, 0, cv_tracker_target_line.data()); // 用data()比&[0]更安全 glDrawArrays(GL_LINE_LOOP, 0, cv_tracker_target_line.size() / 2); // 关键修复:传入真实顶点数量 glDisable(GL_LINE_STIPPLE); glDisableClientState(GL_VERTEX_ARRAY);
补充个小细节:用cv_tracker_target_line.data()替代&cv_tracker_target_line[0]会更安全,尤其是当vector为空的时候(不过这里我们已经做了长度校验,所以问题不大,但养成好习惯总是没错的)。
内容的提问来源于stack exchange,提问作者Asonic84
相关产品推荐
相关产品推荐

