Short version
How can I draw short text labels in an OpenGL mapping application without having to manually recount the coordinates as the user grows and shrinks?
Long version
I have an OpenGL mapping application where I need to be able to draw datasets with an accuracy of 250 thousand points. Each dot can have a short text label, usually about 4 or 5 characters.
I am currently doing this using a single text containing all characters. For each point, I define a square for each character in my label. Thus, a dot labeled “Fred” would have four quads associated with it, and each square uses the texture coordinates in this single texture to draw the corresponding character.
When I draw a map, I draw the map points themselves in map coordinates (for example, longitude / latitude). Then I calculate the position of each point in the coordinates of the screen and update the four corner points for each of these squares of the point label, again in the coordinates of the screen. (For example, if I determine that the point is drawn on the screen point 100, 150, I could set the square for the first character in the point label as a rectangle starting at the top left point 105, 155 and having a width of 6 pixels and a height of 12 pixels, in depending on the particular character. Then the second character may begin with 120, 155, etc.). Then, when all these squares of the label characters are positioned correctly, I draw them using the projection orthogonal screen.
The problem is that the process of updating all these four-coordinate coordinates of the characters is slow, taking about half a second for a certain set of test data with 150 thousand points (which means that, since each label has a length of about four characters, 150k * [4 characters in each point] * [4 coordinate pairs per symbol], which must be set for each update.
If the map application did not include scaling, I would not need to recalculate all these coordinates with each update. I could just calculate the coordinates of the labels once, and then just shift my view rectangle to show the correct area. But with scaling, I can't figure out how to make it work without performing consistent calculations, because otherwise the characters will grow huge when you zoom in and out when you zoom out.
What I want (and what I understand, OpenGL does not provide) is a way to tell OpenGL that the square should be drawn in a fixed rectangle of the screen coordinates, but the top left position of this rectangle should be a fixed distance from the given point in the coordinate card space. Therefore, I want both a primitive hierarchy (a given point on the map to be the parent of its squares of label characters) and the ability to combine two different coordinate systems in this hierarchy.
I'm trying to figure out if there is some kind of magic transformation matrix that I can install that will do all of this from me, but I don’t see how to do it.
Another alternative that I examined is to use a shader at each point to handle the calculation of the squares of the label characters for that point. I have not worked with shaders before, and I'm just trying to understand (a) if shaders can be used for this, and (b) does it really calculate all these points in the shader code, something, (By the way, I confirmed that the big narrow the place calculates the square coordinates rather than loading the updated coordinates in the GPU.The latter takes a little time, but this calculation is the net amount of updated coordinates, which takes up the bulk of this half second.)
(Of course, another alternative is the ability to determine which labels should be drawn in this view in the first place. But now I would like to focus on the solution, assuming that all labels should be drawn.)