使用OpenGL-ES绘制点线画的方法

8
我有一个应用程序,绘制标记线以显示各种特征的三维地图视图。我正在将地图移植到OpenGL-ES架构中,但在如何显示虚线方面遇到了一些问题。
通过大量的谷歌搜索,我发现许多参考资料提到,OpenGL-ES已经删除了绘制虚线和多边形的功能,因为可以使用纹理三角形轻松模拟。这很好,但我找不到任何实际执行此模拟并/或具有所涉及步骤描述的人。
例如,我遇到的一个问题是透视会将我的线条压缩到看不见,当它们朝着地平线走去时。使用LINE_STRIP,这种情况不会发生,并且线在地图上保持恒定宽度。
如何在透视视图中实现虚线恒定宽度线条?任何建议都将不胜感激。

你尝试过普通的线条吗?它们会在地平线上消失吗,还是只有当你使用纹理时才会消失? - Kornel Kisielewicz
正常的线条能够正确地绘制,但我无法使用它们。我尝试将纹理应用于LINE_STRIP,但似乎没有任何效果。在寻找解决方法时,我发现有建议表明这种方法行不通,而使用纹理三角形则是正确的做法。 如果可以让纹理LINE_STRIP起作用,那就太好了。 PS- 我正在使用egl 1.1。 - Piklor
2个回答

5
我相信你可以对一条线进行贴图,而不仅仅是三角形。你需要为线的每个端点设置纹理坐标;纹理将沿着线性插值进行。
这种解决方案的有效性应该与您使用线还是线条无关 - 线条只是创建具有较少顶点的线的一种方式。
还有一个问题:随着线远离相机,纹理图案变得紧凑的倾向。这是因为纹理坐标插值即使对于线条也是透视校正的(请参见GL规范的第3.5节)。
有两种方法可以解决这个问题:
1. 如果您可以为纹理计算“q”坐标以消除透视,则可以恢复屏幕空间纹理。但是,这种技术可能过于耗费性能。 2. 您可以在眼空间中投影纹理(例如glTexGen)。
当然,在GLES 1.1中不提供纹理坐标生成,但如果您使用顶点数组,可以通过以下方式模拟它:
- 将纹理坐标数组设置为顶点坐标数组 - 使用纹理矩阵来“转换”顶点
这种技术的缺点是纹理图案将位于固定的屏幕空间 - 也就是说,纹理不会穿过线。

谢谢,我会试一试。之前我尝试过给线条上纹理,但没有成功 - 也许我放弃得太早了。我希望纹理能够重复出现,这样无论线条变长多少,都能保持一致的虚线效果。 - Piklor
1
没有着色器,我认为你无法在不每帧计算ST坐标的情况下完成此操作。使用着色器,您需要:
  • 在网格上将线的方向编码为模型空间。
  • 在顶点着色器中,将其转换为眼空间坐标。
  • 在屏幕空间(每像素)中生成实际的UV映射。
  • 通过变换(并归一化)线方向向量旋转UV映射的采样。
可以说,如果您对矩阵变换和坐标空间不太熟悉,这是相当复杂的。 :-(
- Ben Supnik
1
另外,您可能想看一下这个链接:http://homepage.mac.com/arekkusu/bugs/invariance/HWAA.html看起来很多消费级GPU在各种情况下都无法正确地执行点画模式。对于水平和垂直的点画模式(它们中少数几个能够正确执行的情况之一),只需投影一个棋盘格重复纹理即可。 - Ben Supnik
1
看起来我在这方面正在逆流而行,用OpenGL-ES实现我想要的功能是不可行的。 我想要的效果似乎需要复杂的操作,但并不值得。画出渐变消失的纹理三角形应该是一个可以接受的替代方案。谢谢你的帮助。 - Piklor

3
如果你只想绘制虚线,只需从GL_LINE_STRIP更改为GL_LINES。这样,OpenGL将连接顶点1和2、3和4、5和6,但不连接3和4或4和5之间的空格。实质上它将成为一条半/半比例的点状线——相当于glLineStipple(1,0101)的粗略等价物。
例如,在顶点数组中:
[0,0,1,1,2,2,3,3,4,4,5,5,6,6]
OpenGL将连接(0,0)到(1,1),但不会连接(1,1)到(2,2)[与GL_LINE_STRIP相反]。然后,它将连接(3,3)到(4,4),但不连接(4,4)到(5,5)。最后的连接将是(5,5)到(6,6)。
我做的时候就是这样的: 在Android上绘制虚线 这条线不是50/50的点和空,因为在我的情况下,它代表每帧游戏实体的位置 - 而游戏帧不一定长度相等,因此导致了不一致的线:空间比例。
绘制该线的代码如下:

public void draw(GL10 gl) { gl.glDisable(GL10.GL_TEXTURE_2D);

  gl.glColor4f(color[0], color[1], color[2], color[3] / fade);
          //pointsBuffer holds the points on the line
  gl.glVertexPointer(2, GL10.GL_FLOAT, 0, pointsBuffer); 

  gl.glDrawArrays(GL10.GL_LINES, 0, points.length/2);

  gl.glEnable(GL10.GL_TEXTURE_2D);

}

一种创建更有意图的图案点彩的替代方法是通过使用索引数组(glDrawElements)跳过某些顶点进行绘制。不过,我没有这方面的示例可以展示给您。 :/

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接