如何在SFML中绘制VertexArray的部分顶点(类似glDrawArrays)?
在SFML中绘制VertexArray的部分顶点
SFML的VertexArray本身没有提供类似OpenGL glDrawArrays的直接参数控制,但可以通过以下两种方法实现只绘制前n个顶点:
方法一:创建临时子VertexArray(简单易用)
直接从原数组中复制前n个顶点到新的VertexArray,再绘制这个临时数组。这种方法无需操作底层OpenGL,适合大多数场景:
// 假设原VertexArray为vArr,要绘制的顶点数为n sf::VertexArray subVertexArray(vArr.getPrimitiveType(), n); std::copy(vArr.begin(), vArr.begin() + n, subVertexArray.begin()); // 绘制临时数组 window.draw(subVertexArray);
如果需要频繁绘制不同数量的顶点,这种方法会产生一定的内存拷贝开销,此时可以考虑第二种方法。
方法二:直接调用底层OpenGL(性能最优)
利用SFML的OpenGL上下文,直接调用glDrawArrays绘制原VertexArray的指定顶点。需要手动设置顶点属性(对应sf::Vertex的结构),并注意保存/恢复OpenGL状态,避免干扰SFML的正常渲染:
步骤1:映射SFML图元类型到OpenGL枚举值
首先需要一个辅助函数,把SFML的PrimitiveType转换成对应的OpenGL枚举:
GLenum sfmlToGLPrimitive(sf::PrimitiveType type) { switch(type) { case sf::PrimitiveType::Points: return GL_POINTS; case sf::PrimitiveType::Lines: return GL_LINES; case sf::PrimitiveType::LineStrip: return GL_LINE_STRIP; case sf::PrimitiveType::LineLoop: return GL_LINE_LOOP; case sf::PrimitiveType::Triangles: return GL_TRIANGLES; case sf::PrimitiveType::TriangleStrip: return GL_TRIANGLE_STRIP; case sf::PrimitiveType::TriangleFan: return GL_TRIANGLE_FAN; default: return GL_POINTS; } }
步骤2:调用OpenGL绘制指定顶点
// 保存当前OpenGL状态,避免影响SFML后续渲染 glPushAttrib(GL_ALL_ATTRIB_BITS); const sf::Vertex* vertices = vArr.getVertices(); GLenum glMode = sfmlToGLPrimitive(vArr.getPrimitiveType()); // 设置顶点位置属性 glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(2, GL_FLOAT, sizeof(sf::Vertex), &vertices[0].position); // 设置顶点颜色属性 glEnableClientState(GL_COLOR_ARRAY); glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(sf::Vertex), &vertices[0].color); // 如果原VertexArray使用了纹理,需额外设置纹理坐标属性 // glEnableClientState(GL_TEXTURE_COORD_ARRAY); // glTexCoordPointer(2, GL_FLOAT, sizeof(sf::Vertex), &vertices[0].texCoords); // 绘制前n个顶点 glDrawArrays(glMode, 0, n); // 恢复之前的OpenGL状态 glPopAttrib();
注意事项
- 确保在SFML窗口的上下文生效时调用上述代码(即窗口已创建,且在窗口的渲染循环内)。
- 如果使用纹理,需要确保纹理已绑定,并且SFML的纹理状态正确。
内容的提问来源于stack exchange,提问作者Allay466
相关产品推荐
相关产品推荐

