Skip to content

8. Blitting bitmaps

Adam Gorski edited this page Jul 8, 2021 · 3 revisions

Sometimes it is nice to have text drawn onto the buffer. Unfortunately renderXF does not directly support this, so a easy method was implemented to copy a bitmap onto the draw buffer, or copy the a portion of the draw buffer onto the bitmap.

New method

So, an existing bitmap must first me made:

Bitmap frameData = new Bitmap(400, 300);

In order to achieve perfect blending, the text must be drawn onto the draw buffer, however this is not possible, so first the draw buffer must be copied into the bitmap buffer:

GL.BlitIntoBitmap(frameData, new Point(0, 0), new Rectangle(0, this.ClientSize.Height - 100, 400, 100));

Depending on the method used, if you are copying an from a colorbuffer with an alpha component of zero, then you might have to set it manually to 255 with GL.DeleteTransparency otherwise you might run into a similar with black behind the text:

Alpha Problem

Next up you can draw anything you would like to your bitmap via using (Graphics g = Graphics.FromImage(frameData) and once you are done you can just blit it back into the renderX instance:

GL.BlitFromBitmap(frameData, new Point(0, this.ClientSize.Height - 100), new Rectangle(0, 0, 400, 100));  

Once complete your code should look like this:

void DrawText()
{
        GL.BlitIntoBitmap(frameData, new Point(0, 0), new Rectangle(0, this.ClientSize.Height - 100, 400, 100));
        GL.DeleteTransparency(frameData);

        using (Graphics g = Graphics.FromImage(frameData)){
                g.DrawString("renderXF v0.3.3", new Font("Consolas", 12), Brushes.White, new Rectangle(0, 0, 200, 200));
                g.DrawString("XF  : " + 0 + " FPS", new Font("Consolas", 12), Brushes.White, new Rectangle(0, 20, 200, 200));

        }
        GL.BlitFromBitmap(frameData, new Point(0, this.ClientSize.Height - 100), new Rectangle(0, 0, 400, 100));  
}

Old Method

Blitting bitmaps uses a class named BitmapUtility to help with all the blitting.

BitmapUtility uses an existing bitmap, because creating a new bitmap for each frame will not only be slow, it will also create memory leaks!!!

So, an existing bitmap must first me made:

Bitmap infoBitmap = new Bitmap(400, 300);

In order to achieve perfect blending, the text must be drawn onto the draw buffer, however this is not possible, so first the draw buffer must be copied into the bitmap buffer.

//Firstly, Copy pixels from the drawing buffer into the bitmap buffer
using (BitmapUtility bmpUtility = new BitmapUtility(infoBitmap))
{
    bmpUtility.CopyFrom(GL, 0, 0, 300, 100);
}
         
//Next, draw the text onto the bitmap buffer       
using (Graphics g = Graphics.FromImage(infoBitmap))
{
    g.DrawString("FPS: " + (1000f / deltaTime), this.Font, Brushes.White, 0, 0);
    g.DrawString("Drawtime: " + sw.Elapsed.TotalMilliseconds + "ms", this.Font, Brushes.White, 0, 24);
    g.DrawString("Frametime: " + deltaTime + "ms", this.Font, Brushes.White, 0, 12);
}

//Finally, copy the bitmap buffer back onto the drawing buffer
using (BitmapUtility bmpUtility = new BitmapUtility(infoBitmap))
{
    bmpUtility.BlitInto(GL, 0, 0, 300, 36, Color.Black);
}

Please note that bitmaps have the (0, 0) origin in the top left corner, while renderXF has its origin in the bottom left corner. renderXF uses the srcHeight int to calculate this offset.