1
\$\begingroup\$

Starting off the class in question is here:

using System;

public class FontService
{
    private int[] characterTextures;

    public void InitalizeTextures()
    {
        characterTextures = new int[94];
        var font = new FontFace(File.OpenRead(Path.Combine(Environment.GetFolderPath(
            Environment.SpecialFolder.ApplicationData), @"RyuFs\system\fonts\FontStandard.ttf")));

        for (int i = 33; i < 127; i++)
        {
            var surface = RenderSurface((char)i, font);

            characterTextures[i - 33] = LoadTexture(surface);
        }
    }

    public void DrawText(string text)
    {
        GL.Viewport(0, 0, 500, 500);
        GL.BindTexture(TextureTarget.Texture2D, characterTextures[text[0] - 33]);

        GL.Enable(EnableCap.Blend);
        GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
        GL.Enable(EnableCap.DepthTest);
        GL.DepthFunc(DepthFunction.Lequal);
        GL.Enable(EnableCap.Texture2D);

        GL.ClearDepth(1);
        GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
        GL.ClearColor(Color.White);


        GL.Begin(PrimitiveType.Triangles);
        GL.Color4(Color.White);

        GL.TexCoord2(0, 0); GL.Vertex2(100, 100);
        GL.TexCoord2(0, 64); GL.Vertex2(100, 164);
        GL.TexCoord2(32, 64); GL.Vertex2(132, 164);

        GL.TexCoord2(32, 64); GL.Vertex2(132, 164);
        GL.TexCoord2(32, 0); GL.Vertex2(132, 100);
        GL.TexCoord2(0, 0); GL.Vertex2(100, 100);
        GL.End();

        GL.BindTexture(TextureTarget.Texture2D, 0);
        GL.Disable(EnableCap.Texture2D);
        GL.Disable(EnableCap.DepthTest);

    }

    public unsafe Surface RenderSurface(char c, FontFace font)
    {
        var glyph = font.GetGlyph(c, 32);
        var surface = new Surface
        {
            Bits = Marshal.AllocHGlobal(glyph.RenderWidth * glyph.RenderHeight),
            Width = glyph.RenderWidth,
            Height = glyph.RenderHeight,
            Pitch = glyph.RenderWidth
        };

        var stuff = (byte*)surface.Bits;
        for (int i = 0; i < surface.Width * surface.Height; i++)
            *stuff++ = 0;

        glyph.RenderTo(surface);

        return surface;
    }

    private unsafe int LoadTexture(Surface surface)
    {
        int width = 32; //surface.Width;
        int height = 64; //surface.Height;
        int len = width * height;
        byte[] data = new byte[len];
        //Marshal.Copy(surface.Bits, data, 0, len);
        int[] pixels = new int[len];

        int index = 0;
        for (int i = 0; i < len; i++)
        {
            int c = (byte)i; //data[i];
            pixels[i] = (byte.MaxValue << 24) | (c << 16) | (c << 8) | c;
        }

        GL.Enable(EnableCap.Texture2D);
        int textureID = GL.GenTexture();
        GL.BindTexture(TextureTarget.Texture2D, textureID);

        GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
        GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
        GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Clamp);
        GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Clamp);

        fixed (int* dataptr = pixels)
            GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, width, height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, (IntPtr)dataptr);
        GL.BindTexture(TextureTarget.Texture2D, 0);
        GL.Disable(EnableCap.Texture2D);

        Marshal.FreeHGlobal(surface.Bits); //Give the memory back!
        return textureID;
    }
}

Currently I get this output (It's an odd shaped window): https://puu.sh/CBMIm/a55ef28299.png

What I expect the code to do is generate rainbow textures with constant Alpha on line 96:

int index = 0;
for (int i = 0; i < len; i++)
{
    int c = (byte)i; //data[i];
    pixels[i] = (byte.MaxValue << 24) | (c << 16) | (c << 8) | c;
}

After that I expect it to convert the data into a texture on line 113:

fixed (int* dataptr = pixels)
    GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, width, height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, (IntPtr)dataptr);

Finally DrawText should render just the first char of the string, 'H' in my example but as it's just got a dummy texture it should render a rainbow square.

I would also like to be able to blend it properly with respect to alpha so 0 alpha is totally transparent and 100% alpha is totally opaque.

Some extra info that may help you, help me:

  • Running under .Net Core 2.0
  • OpenTK window host
  • Using Open GL ES 2.0
  • InitalizeTextures is called on GL load
  • DrawText is called with help in gldraw. The only other gl calls are a clearcolor to white (prior) and a frame swap (post)
  • No shaders are loaded
  • Orthographic viewport where 1 pixel = 1 unit

So to sum it all up, what's wrong with my code causing these issues? I know it's messy, I will clean it up on commit :)

Thank you for reading this far and any help would be appreciated.

\$\endgroup\$
  • \$\begingroup\$ Please embed the relevant code and image example in your question itself, not as external links. This may involve whittling your problem down to a minimal complete verifiable example. \$\endgroup\$ – DMGregory Jan 24 at 22:11
  • \$\begingroup\$ Your texture creation code won't make a rainbow. It will either make a gray ramp or a ramp from transparent red to solid white, depending on whether it's ARGB or RGBA (or possible transparent blue to solid white if it's BGRA). \$\endgroup\$ – user1118321 Jan 25 at 4:45
2
\$\begingroup\$

Turns out there are a couple issues with my code: the fact that it doesn't generate a rainbow box but a grey gradient as user1118321 said in a comment; the wrong pixel type, byte, not uint8888; and probably more.

But the real issue was the texture coordinates. I failed to realize they are always from (0,0) to (1,1) and not the size of the of the texture as I had been using them. Anyway with that done it's all fixed. I don't have the code as I ended up completely rewriting it for its actual use.

\$\endgroup\$

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.