Reputation: 131
I'm creating a Graph Drawing program using OpenTK to complete my Computer Graphics exercise.
The problem is i have to write text to glcontrol to indicate point's coordinates just like this picture:
Please help!
Here is my code:
private void glControl1_Paint(object sender, PaintEventArgs e)
{
if (!loaded) // Play nice
return;
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.LineWidth(2);
DrawingObjects.DrawOxy(leftOr, rightOr, topOr, bottomOr);
color = Color.Red;
GL.Color3(color);
glControl1.SwapBuffers();
}
public static void DrawOxy(int lO, int rO, int tO, int bO)
{
GL.Color3(Color.Blue);
GL.Begin(BeginMode.Lines);
GL.Vertex2(lO, 0);
GL.Vertex2(rO, 0);
GL.Vertex2(0, tO);
GL.Vertex2(0, bO);
for (int i = lO; i < rO; i+=2)
{
GL.Vertex2(i, 0.5);
GL.Vertex2(i, -0.5);
}
for (int j = bO; j < tO; j+=2)
{
GL.Vertex2(0.2, j);
GL.Vertex2(-0.2, j);
}
GL.End();
}
Sorry about my english!
Upvotes: 0
Views: 10152
Reputation: 128
OpenGL and OpenTK do not support any built-in text rendering. Essentially, they are too "low-level" for that. Nevertheless, many applications, such as yours, require text rendering, and significant work has been done to find efficient ways to render text via OpenGL (and OpenTK as well, of course). One popular technique is based on "distance fields," made famous by a 2007 SIGGRAPH paper, from Chris Green. In my own applications, I have implemented support for text rendering on top of OpenTK using techniques based on distance fields, and have been very pleased by the overall quality, performance, and flexibility of this approach:
https://cdn.cloudflare.steamstatic.com/apps/valve/2007/SIGGRAPH2007_AlphaTestedMagnification.pdf
Upvotes: 3
Reputation: 1353
Contrary to what you might expect, rendering a simple string is quite difficult with a low-level library like OpenGL. But basically, you iterate through the string, rendering a textured quad for each character.
My approach is this, store every possible character in a string.
static string CharSheet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()-=_+[]{}\\|;:'\".,<>/?`~ ";
Create a texture containing those characters. Retaining to a single line simplifies calculations.
Then, when the application loads, create a VAO for each character, containing the vertex positions (size of the quad) and it's texture co-ordinates. This font is monospaced so the vertex positions are simply:
float h = charHeight / (screenHeight / 2);
float w = charWidth / (screenWidth / 2);
Vector2[] vertices = new Vector2[]{
new Vector2( 0, h),
new Vector2( w, h),
new Vector2( w, 0),
new Vector2( 0, h),
new Vector2( w, 0),
new Vector2( 0, 0)
};
The texture co-ordinates however, are dependant on the character's index in CharSheet
:
float x1 = (charWidth / textureWidth) * i;
float x2 = (charWidth / textureWidth) * (i + 1);
Vector2[] textureData = new Vector2[] {
new Vector2 (x1, 0),
new Vector2 (x2, 0),
new Vector2 (x2, 1),
new Vector2 (x1, 0),
new Vector2 (x2, 1),
new Vector2 (x1, 1)
};
And to draw a character, it's simply a matter of specifying that same index, and the desired X,Y screen co-ordinates:
public static void draw(Shader shader, char character, float x, float y)
{
// Convert to pixel Co-ordinates
x = x / (screenWidth/2) - 1;
y = (screenHeight - y - charHeight) / (screenHeight/2) - 1;
Vector3 Position = new Vector3 (x, y, 0);
// Update shader with quad position
Matrix4 modelMatrix = Matrix4.CreateScale (scale) * Matrix4.CreateTranslation(Position);
GL.UniformMatrix4(shader.modelviewMatrixLocation, false, ref modelMatrix);
// Draw
GL.BindVertexArray( VAOs[ CharSheet.IndexOf( character ) ] );
GL.DrawArrays (PrimitiveType.Triangles, 0, 6);
}
Resulting in this:
Upvotes: 6