tuankhoa1996
tuankhoa1996

Reputation: 131

Write text in OpenTK

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:

enter image description here

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

Answers (2)

MaxxAMillion
MaxxAMillion

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

livin_amuk
livin_amuk

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.

BitmapFont

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:

Result

Upvotes: 6

Related Questions