Drawing Stippled Lines using OpenGL-ES

2019-06-16 10:39发布

I have an application that draws 3-d map view marked up lines that show various features. I am porting the map over to an OpenGL-ES architecture, but am having a bit of trouble working out how to display dashed lines.

Doing a lot of googling, I've found many references to the idea that drawing dashed lines and polygons were removed from OpenGL-ES as they can be easily emulated using textures triangles. That's great, but I can't find anyone that actually does this emulation and/or has a description of the steps involved.

An example, of one problem I have encountered trying to prototype out this concept is perspective squeezes my lines to invisible as they go towards the horizon. Using LINE_STRIP, this doesn't happen, and the lines remain a constant width in the map.

Any advice on how to achieve dashed constant width lines in a perspective view would be much appreciated.

2条回答
Evening l夕情丶
2楼-- · 2019-06-16 11:41

If all you want is to draw dashed lines, just change from GL_LINE_STRIP to GL_LINES. That way, open GL will connect vertices 1&2, 3&4, 5&6, but not 3&4, or 4&5 leaving spaces there. It will in essence be a half/half ratio dotted line-- the rough equivalent of glLineStipple(1, 0101);

IE: in the vertex array

[0,0,1,1,2,2,3,3,4,4,5,5,6,6]

OpenGL will connect (0,0) to (1,1), but will not connect (1,1) to (2,2) [whereas it would with GL_LINE_STRIP]. It will then connect (3,3) to (4,4), but NOT (4,4) to (5,5). The final connection will be (5,5) to (6,6).

This is what it looks like when I did it:

Dotted Lines on Android

The line is not 50/50 dotted/empty because in my case, it represents the position of a game entity each game frame-- and game frames are not necessarily all of equal length, thus the inconsistent line:space ratio.

The code looks like this to draw it:

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);

}

An alternative idea to create a more intentionally patterned stipple would be to skip certain vertices by instead drawing with an indices array (glDrawElements). However, I don't have an example of that to show you. :/

查看更多
我欲成王,谁敢阻挡
3楼-- · 2019-06-16 11:42

I believe you can apply a texture to a line, not just a triangle. You'll need to set texture coordinates for each end of the line; the texture will be interpolated linearly along the line.

The effectiveness of this solution should be invariant of whether you use lines or line strips - line strips are just a way to create lines with fewer vertices.

There is one other problem: the tendency of the texture pattern to become compact as a line goes away from the camera. This happens because texture coordinate interpolation is perspective-correct even for lines (see section 3.5 of the GL spec).

There are two ways to get around this:

  1. If you can calculate a "q" coordinate for your texture that undoes the perspective, you can restore screen-space texturing. This technique is probably too performance-expensive.

  2. You can project the texture in eye space (e.g. glTexGen).

Texture coordinate generation is of course not available in GLES 1.1, but if you are using vertices by array, you can fake it by:

  • Setting your texture coordinate array to be your vertex coordinate array and
  • Using the texture matrix to "transform" the vertices.

The disadvantage of this technique is that the texture pattern will be in fixed screen space - that is, the texture won't run across the lines.

查看更多
登录 后发表回答