C#OpenTK-在窗口上绘制字符串

问题描述 投票:1回答:1

我有一个大问题:我打开了一个OpenTK窗口,在其中绘制纹理,图像等。我必须以这种方式做一些电子游戏进行测试,我想在上面显示文本显示游戏信息。

实际上,我只能用文本打开Window窗体,这不是我所需要的。

是否可以在OpenTK窗口中显示文本?

我无法使用OpenTK 3.0,因此必须排除QuickFont。

我可以使用GL类。

非常感谢!

c# opentk drawtext drawstring
1个回答
0
投票

一种可能性是使用FreeType库将TrueType字体加载到纹理对象。SharpFont为C#提供跨平台的FreeType绑定。来源可在GitHub - Robmaister/SharpFont中找到。(来自MonoGame.Dependencies的x64 SharpFont.dll和freetype6.dll)

完整示例可在GitHub - Rabbid76/c_sharp_opengl中找到。示例示例基于LearnOpenGL - Text Rendering

加载字符的字体和字形信息并为每个字符创建一个纹理对象:

// initialize library
Library lib = new Library();
Face face = new Face(lib, "FreeSans.ttf");
face.SetPixelSizes(0, 32);

// set 1 byte pixel alignment 
GL.PixelStore(PixelStoreParameter.UnpackAlignment, 1);

// Load first 128 characters of ASCII set
for (uint c = 0; c < 128; c++)
{
    try
    {
        // load glyph
        //face.LoadGlyph(c, LoadFlags.Render, LoadTarget.Normal);
        face.LoadChar(c, LoadFlags.Render, LoadTarget.Normal);
        GlyphSlot glyph = face.Glyph;
        FTBitmap bitmap = glyph.Bitmap;

        // create glyph texture
        int texObj = GL.GenTexture();
        GL.BindTexture(TextureTarget.Texture2D, texObj);
        GL.TexImage2D(TextureTarget.Texture2D, 0,
                      PixelInternalFormat.R8, bitmap.Width, bitmap.Rows, 0,
                      PixelFormat.Red, PixelType.UnsignedByte, bitmap.Buffer);

        // set texture parameters
        GL.TextureParameter(texObj, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
        GL.TextureParameter(texObj, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
        GL.TextureParameter(texObj, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToEdge);
        GL.TextureParameter(texObj, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToEdge);

        // add character
        Character ch = new Character();
        ch.TextureID = texObj;
        ch.Size = new Vector2(bitmap.Width, bitmap.Rows);
        ch.Bearing = new Vector2(glyph.BitmapLeft, glyph.BitmapTop);
        ch.Advance = (int)glyph.Advance.X.Value;
        _characters.Add(c, ch);
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex);
    }
}

[创建一个Vertex Array Object,以2个三角形绘制一个四边形:

// bind default texture
GL.BindTexture(TextureTarget.Texture2D, 0);

// set default (4 byte) pixel alignment 
GL.PixelStore(PixelStoreParameter.UnpackAlignment, 4);

float[] vquad =
{
// x      y      u     v    
    0.0f, -1.0f,   0.0f, 0.0f,
    0.0f,  0.0f,   0.0f, 1.0f,
    1.0f,  0.0f,   1.0f, 1.0f,
    0.0f, -1.0f,   0.0f, 0.0f,
    1.0f,  0.0f,   1.0f, 1.0f,
    1.0f, -1.0f,   1.0f, 0.0f
};

// Create [Vertex Buffer Object](https://www.khronos.org/opengl/wiki/Vertex_Specification#Vertex_Buffer_Object)
_vbo = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ArrayBuffer, _vbo);
GL.BufferData(BufferTarget.ArrayBuffer, 4 * 6 * 4, vquad, BufferUsageHint.StaticDraw);

// [Vertex Array Object](https://www.khronos.org/opengl/wiki/Vertex_Specification#Vertex_Array_Object)
_vao = GL.GenVertexArray();
GL.BindVertexArray(_vao);
GL.EnableVertexAttribArray(0);
GL.VertexAttribPointer(0, 2, VertexAttribPointerType.Float, false, 4 * 4, 0);
GL.EnableVertexAttribArray(1);
GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, 4 * 4, 2 * 4);

此外,还创建了一种在给定方向的指定位置绘制字符串的方法:

public void RenderText(string text, float x, float y, float scale, Vector2 dir)
{
    GL.ActiveTexture(TextureUnit.Texture0);
    GL.BindVertexArray(_vao);

    float angle_rad = (float)Math.Atan2(dir.Y, dir.X);
    Matrix4 rotateM = Matrix4.CreateRotationZ(angle_rad);
    Matrix4 transOriginM = Matrix4.CreateTranslation(new Vector3(x, y, 0f));

    // Iterate through all characters
    float char_x = 0.0f;
    foreach (var c in text) 
    {
        if (_characters.ContainsKey(c) == false)
            continue;
        Character ch = _characters[c];

        float w = ch.Size.X * scale;
        float h = ch.Size.Y * scale;
        float xrel = char_x + ch.Bearing.X * scale;
        float yrel = (ch.Size.Y - ch.Bearing.Y) * scale;

        // Now advance cursors for next glyph (note that advance is number of 1/64 pixels)
        char_x += (ch.Advance >> 6) * scale; // Bitshift by 6 to get value in pixels (2^6 = 64 (divide amount of 1/64th pixels by 64 to get amount of pixels))

        Matrix4 scaleM = Matrix4.CreateScale(new Vector3(w, h, 1.0f));
        Matrix4 transRelM = Matrix4.CreateTranslation(new Vector3(xrel, yrel, 0.0f));

        Matrix4 modelM = scaleM * transRelM * rotateM * transOriginM; // OpenTK `*`-operator is reversed
        GL.UniformMatrix4(0, false, ref modelM);

        // Render glyph texture over quad
        GL.BindTexture(TextureTarget.Texture2D, ch.TextureID);

        // Render quad
        GL.DrawArrays(PrimitiveType.Triangles, 0, 6);
    }

    GL.BindVertexArray(0);
    GL.BindTexture(TextureTarget.Texture2D, 0);
}

顶点着色器:

#version 460

layout (location = 0) in vec2 in_pos;
layout (location = 1) in vec2 in_uv;

out vec2 vUV;

layout (location = 0) uniform mat4 model;
layout (location = 1) uniform mat4 projection;

void main()
{
    vUV         = in_uv.xy;
    gl_Position = projection * model * vec4(in_pos.xy, 0.0, 1.0);
}

片段着色器:

#version 460

in vec2 vUV;

layout (binding=0) uniform sampler2D u_texture;

  layout (location = 2) uniform vec3 textColor;

out vec4 fragColor;

void main()
{
    vec2 uv = vUV.xy;
    float text = texture(u_texture, uv).r;
    fragColor = vec4(textColor.rgb*text, text);
}

请参见示例:

enter image description here

Matrix4 projectionM = Matrix4.CreateScale(new Vector3(1f/this.Width, 1f/this.Height, 1.0f));
projectionM = Matrix4.CreateOrthographicOffCenter(0.0f, this.Width, this.Height, 0.0f, -1.0f, 1.0f);

GL.ClearColor(0.2f, 0.3f, 0.3f, 1.0f);
GL.Clear(ClearBufferMask.ColorBufferBit);

GL.Enable(EnableCap.Blend);
GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);

text_prog.Use();
GL.UniformMatrix4(1, false, ref projectionM);

GL.Uniform3(2, new Vector3(0.5f, 0.8f, 0.2f));
font.RenderText("This is sample text", 25.0f, 50.0f, 1.2f, new Vector2(1f, 0f));

GL.Uniform3(2, new Vector3(0.3f, 0.7f, 0.9f));
font.RenderText("(C) LearnOpenGL.com", 50.0f, 200.0f, 0.9f, new Vector2(1.0f, -0.25f));
© www.soinside.com 2019 - 2024. All rights reserved.