rounder8's picture

QuickFont -- Problem with resizing the window

Hello everyone,

I'm new to OpenGL and OpenTK is my first dip into the world of 3D graphics. I want to thank this community for creating these wonderful tools!

Painting text to the screen seems to be quite a complicated task with OpenGL. Luckily I found this library called QuickFont that made my life easier. I've got a problem though. When I resize the window the QFont.Print command prints into wrong X-position. The code is as follows:

class TextPrinter : GameWindow
    {
        QFont BasicFont;
 
        public TextPrinter()
            : base()
        {
            Load += new EventHandler<EventArgs>(TextPrinter_Load);
            RenderFrame += new EventHandler<FrameEventArgs>(TextPrinter_RenderFrame);
            Resize += new EventHandler<EventArgs>(TextPrinter_Resize);
            UpdateFrame += new EventHandler<FrameEventArgs>(TextPrinter_UpdateFrame);
            Mouse.WheelChanged += new EventHandler<MouseWheelEventArgs>(Mouse_WheelChanged);
            Keyboard.KeyDown += new EventHandler<KeyboardKeyEventArgs>(Keyboard_KeyDown);
        }
 
        private void SetupViewport()
        {
            GL.MatrixMode(MatrixMode.Projection);
            GL.LoadIdentity();
            GL.Ortho(0, Width, 0, Height, -1, 1);
            GL.Viewport(0, 0, Width, Height);
            GL.Disable(EnableCap.DepthTest);
        }
 
        private void TextPrinter_Load(object sender, EventArgs e)
        {
 
            // Setup the QFont
            var builderconf = new QFontBuilderConfiguration();
            builderconf.TextGenerationRenderHint = TextGenerationRenderHint.ClearTypeGridFit;
            BasicFont = new QFont(new Font("Calibri", 20f, FontStyle.Bold), builderconf);
            BasicFont.Options.Colour = new Color4(0f, 0f, 0f, 1f);
 
            SetupViewport();
 
 
        }
 
        private void TextPrinter_Resize(object sender, EventArgs e)
        {
            SetupViewport();
        }
 
 
 
        private void TextPrinter_UpdateFrame(object sender, EventArgs e)
        {
            //var mouse = 
        }
 
        // For adjusting the window width on the fly
        private void Mouse_WheelChanged(object sender, MouseWheelEventArgs e)
        {
            this.Width += e.Delta;
        }
 
        // For adjusting the window width on the fly
        private void Keyboard_KeyDown(object sender, KeyboardKeyEventArgs e)
        {
            if (e.Key == Key.Left)
            {
                this.Width -= 1;
            }
            else if (e.Key == Key.Right)
            {
                this.Width += 1;
            }
        }
 
        private void TextPrinter_RenderFrame(object sender, EventArgs e)
        {
            GL.ClearColor(Color.LightGray);
            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
 
 
            GL.MatrixMode(MatrixMode.Modelview);
            GL.LoadIdentity();
 
 
 
            GL.Color3(Color.Black);
            GL.Begin(BeginMode.Lines);
            GL.Vertex2(Width / 2.0, 0);
            GL.Vertex2(Width / 2.0, Height);
            GL.End();
 
            GL.Begin(BeginMode.Lines);
            GL.Vertex2(Width / 3.0, 0);
            GL.Vertex2(Width / 3.0, Height);
            GL.End();
 
            GL.Begin(BeginMode.Lines);
            GL.Vertex2(2f * (Width / 3.0), 0);
            GL.Vertex2(2f * (Width / 3.0), Height);
            GL.End();
 
            QFont.Begin();
            BasicFont.Print("O", QFontAlignment.Centre, new Vector2(Width / 2f, Height / 2f));
            QFont.End();
            GL.Disable(EnableCap.Texture2D);
 
            QFont.Begin();
            BasicFont.Print("O", QFontAlignment.Centre, new Vector2(Width / 3f, Height / 2f));
            QFont.End();
            GL.Disable(EnableCap.Texture2D);
 
            QFont.Begin();
            BasicFont.Print("O", QFontAlignment.Centre, new Vector2(2f *  (Width / 3f), Height / 2f));
            QFont.End();
            GL.Disable(EnableCap.Texture2D);
 
 
            SwapBuffers();
        }
 
 
        static void Main(string[] args)
        {
            using (TextPrinter win = new TextPrinter())
            {
                win.Run(100.0);
            }
        }
    }

This is a demostration of the misbehavior of the program. The printed "O" should be aligned with the lines but they are not after window gets resized.

http://megaswf.com/s/2454811

I checked what GL-commands were executed in QFont.Begin, QFont.Print and QFont.End methods and I came up with this list that you might find helpful:

QFont.Begin:

GL.MatrixMode(MatrixMode.Projection);
GL.PushMatrix(); //push projection matrix
GL.LoadIdentity();
GL.Ortho(currentVp.X, currentVp.Width, currentVp.Height, currentVp.Y, -1.0, 1.0);

GL.MatrixMode(MatrixMode.Modelview);
GL.PushMatrix(); //push modelview matrix
GL.LoadIdentity();

Print:

GL.PushMatrix();
GL.Translate(position.X, position.Y, 0f);

GL.Color4(1.0f, 1.0f, 1.0f, 1.0f);
GL.Enable(EnableCap.Texture2D);
GL.Enable(EnableCap.Blend);
GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);

GL.BindTexture(TextureTarget.Texture2D, sheet.GLTexID);

GL.Begin(BeginMode.Quads);
GL.TexCoord2(tx1, ty1); GL.Vertex2(x, y + glyph.yOffset);
GL.TexCoord2(tx1, ty2); GL.Vertex2(x, y + glyph.yOffset + glyph.rect.Height);
GL.TexCoord2(tx2, ty2); GL.Vertex2(x + glyph.rect.Width, y + glyph.yOffset + glyph.rect.Height);
GL.TexCoord2(tx2, ty1); GL.Vertex2(x + glyph.rect.Width, y + glyph.yOffset);
GL.End();

GL.PopMatrix();

QFont.End:

GL.MatrixMode(MatrixMode.Modelview);
GL.PopMatrix(); //pop modelview

GL.MatrixMode(MatrixMode.Projection);
GL.PopMatrix(); //pop projection

GL.MatrixMode(MatrixMode.Modelview);


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
james_lohr's picture

Hello,

Apologies for my recent inactivity, I've been rather busy at work.

I added a change to deal with this a few months ago, but haven't gotten round to releasing it.

I'll be releasing a new version this evening with this change along with numerous other bug fixes.

Regards,

James L.

james_lohr's picture

The latest release is available here:

http://www.opentk.com/node/3120

When you change the viewport, you have three options to make QFont aware of it:

  1. Call QFont.InvalidateViewport() . This invalidates the viewport cached by QFont, causing it to be read again on the next QFont.Begin()
  2. Call QFont.ForceViewportRefresh(). This forces QFont to refesh its cached viewport immediately.
  3. Call :

    QFont.PopSoftwareViewport()

    ...followed by:

    QFont.PushSoftwareViewport(Viewport viewport)

    Where Viewport is what you have just defined the new viewport to be at the application level.

The third option is the most efficient, because it skips an unnecessary call to GL.GetInteger. However, in practise (given that you are probably only doing this on resize events) either of the other two will do fine.